diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a63274b --- /dev/null +++ b/.gitignore @@ -0,0 +1,26 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.zip \ No newline at end of file diff --git a/assets/css/chat.css b/assets/css/chat.css new file mode 100644 index 0000000..4208333 --- /dev/null +++ b/assets/css/chat.css @@ -0,0 +1,58 @@ +#messages { + padding: 10px; + margin-bottom: 10px; + height: calc(100% - 140px); + overflow-y: auto; +} + +#messages div { + border: 2px solid #000000; + font-size: 14px; + color: #000; + margin-bottom: 10px; + padding: 10px; + border-radius: 5px; +} + +#messages>.message.loading { + border-color: #003cff; + animation: pulse 1s infinite; +} + +@keyframes pulse { + 0% { + border-color: #6e90ff; + } + 50% { + border-color: #002ec5; + } + 100% { + border-color: #6e90ff; + } +} + +#messages>.message.user { + border-color: #c90000; +} + +#messages>.message.assistant { + border-color: #06af2d; +} + +#input-container { + border-top: 2px solid #000000; + height: 100px; + width: 100%; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + + #input { + margin-bottom: 10px; + height: 50px; + width: 90%; + border: 1px solid #ccc; + border-radius: 5px; + } +} \ No newline at end of file diff --git a/assets/css/index.css b/assets/css/index.css index cac0ad0..522f140 100644 --- a/assets/css/index.css +++ b/assets/css/index.css @@ -1,5 +1,17 @@ +html { + height: 100%; + width: 100%; +} + +body { + height: 100%; + width: 100%; + margin: 0; + padding: 0; +} + #project-info-img { width: 64px; height: 64px; object-fit: cover; -} \ No newline at end of file +} diff --git a/assets/js/chat.js b/assets/js/chat.js index 0d23006..504a52f 100644 --- a/assets/js/chat.js +++ b/assets/js/chat.js @@ -1,59 +1,91 @@ const mujianSdk = new window.MujianUMD.MujianSdk(); +const stopController = new AbortController(); -async function chat( - query, - cb, -) { - let lastChunk = ''; - // 让缓冲区跨回调持久,防止分包导致的半行重复解析 - let buffer = ''; - await mujianSdk.ai.chat.complete(query, (data) => { - - // data 可能是块状字符串;避免逐字符遍历 - buffer += data; - const lines = buffer.split('\n'); - buffer = lines.pop() || ''; - - for (const line of lines) { - if (!line.startsWith('data: ')) continue; - const payload = line.slice(6); - try { - const parsedData = JSON.parse(payload); - if (parsedData?.isFinished) { - // 结束标志,交给外层 await 完成 - continue; - } - - let content = parsedData?.choices?.[0]?.delta?.content; - // if (content && typeof window !== 'undefined') { - // const username = localStorage.getItem(USERNAME_KEY) || 'User'; - // content = content?.replace(new RegExp(FAKE_USERNAME, 'g'), username); - // } - - if (content !== undefined && content !== null) { - if (content.length > 0) { - lastChunk += content; - cb && cb(lastChunk); - } - } else { - console.error('data', payload); - } - } catch (error) { - console.log('error', error); - throw error; - } - } - }); - - - // console.log('lastChunk', lastChunk); - return lastChunk; +async function send(query) { + const id = Date.now(); + addMessage("assistant", "等待回复中...", id); + startLoading(id); + await mujianSdk.ai.chat.complete( + query, + (res) => { + updateMessage(id, res.fullContent); + if (res.isFinished) { + stopLoading(id); + } + }, + stopController.signal, + { + parseContent: true, + }, + ); } +function stop() { + stopController.abort(); +} -mujianSdk.init().then(() => { - chat('你好', (res) => { - // console.log('res', res) - $('#message').text(res); - }) -}); \ No newline at end of file +async function renderAllMessages() { + const messages = await mujianSdk.ai.chat.message.getAll(); + renderMessages(messages); + scrollToBottom(); +} + +function updateMessage(id, message) { + if ($(`#message-assistant-${id}`).length === 0) { + return; + } + $(`#message-assistant-${id}`).text("assistant: " + message); + scrollToBottom(); +} + +function addMessage(role, message, id = null) { + const _id = id || Date.now(); + $("#messages").append( + `
`, + ); +} + +function startLoading(id) { + $(`#message-assistant-${id}`).addClass("loading"); +} + +function stopLoading(id) { + $(`#message-assistant-${id}`).removeClass("loading"); +} + +function clearMessages() { + $("#messages").empty(); +} + +function scrollToBottom() { + $("#messages").animate( + { scrollTop: $("#messages").prop("scrollHeight") }, + 100, + ); +} + +function renderMessages(messages) { + // console.log("messages", messages); + messages.forEach((message) => { + addMessage(message.role, message.content, message.id); + }); +} + +$("#send").click(async () => { + const query = $("#input").val(); + console.log("query", query); + if (!query) { + return; + } + $("#input").val(""); + addMessage("user", query, Date.now()); + await send(query); +}); + +$("#stop").click(stop); + +(async () => { + await mujianSdk.init().then(async () => { + await renderAllMessages(); + }); +})(); diff --git a/chat.html b/chat.html index 8228262..e654000 100644 --- a/chat.html +++ b/chat.html @@ -12,16 +12,22 @@ + - - - + +