diff --git a/renderer/public/iconfont.css b/renderer/public/iconfont.css index 2f0615f..dee1de8 100644 --- a/renderer/public/iconfont.css +++ b/renderer/public/iconfont.css @@ -1,8 +1,8 @@ @font-face { font-family: "iconfont"; /* Project id 4870215 */ - src: url('iconfont.woff2?t=1744276722320') format('woff2'), - url('iconfont.woff?t=1744276722320') format('woff'), - url('iconfont.ttf?t=1744276722320') format('truetype'); + src: url('iconfont.woff2?t=1744289078529') format('woff2'), + url('iconfont.woff?t=1744289078529') format('woff'), + url('iconfont.ttf?t=1744289078529') format('truetype'); } .iconfont { @@ -13,6 +13,10 @@ -moz-osx-font-smoothing: grayscale; } +.icon-openmcp:before { + content: "\e666"; +} + .icon-double-loading:before { content: "\e8fc"; } diff --git a/renderer/public/iconfont.woff2 b/renderer/public/iconfont.woff2 index fad5f13..9ed60a0 100644 Binary files a/renderer/public/iconfont.woff2 and b/renderer/public/iconfont.woff2 differ diff --git a/renderer/src/components/main-panel/chat/index.vue b/renderer/src/components/main-panel/chat/index.vue index bd716db..9db42a9 100644 --- a/renderer/src/components/main-panel/chat/index.vue +++ b/renderer/src/components/main-panel/chat/index.vue @@ -5,7 +5,7 @@
- +
@@ -90,7 +90,14 @@
-
Agent
+
+ Agent + + 正在生成答案 + + + +
@@ -268,6 +275,12 @@ watch(streamingContent, () => { } }, { deep: true }); +watch(streamingToolCalls, () => { + if (autoScroll.value) { + scrollToBottom(); + } +}, { deep: true }); + let loop: TaskLoop | undefined = undefined; const handleSend = () => { @@ -278,36 +291,37 @@ const handleSend = () => { const userMessage = userInput.value.trim(); - loop = new TaskLoop( - streamingContent, - streamingToolCalls, - // onerror - (msg) => { - ElMessage({ - message: msg, - type: 'error', - duration: 3000 - }); + loop = new TaskLoop(streamingContent, streamingToolCalls); - tabStorage.messages.push({ - role: 'assistant', - content: `错误: ${msg}` - }); + loop.registerOnError((msg) => { + ElMessage({ + message: msg, + type: 'error', + duration: 3000 + }); - isLoading.value = false; - }, - // onchunk - (chunk) => { - scrollToBottom(); - }, - // ondone - () => { - isLoading.value = false; - scrollToBottom(); + tabStorage.messages.push({ + role: 'assistant', + content: `错误: ${msg}` + }); + + isLoading.value = false; + }); + + loop.registerOnChunk((chunk) => { + scrollToBottom(); + }); + + loop.registerOnDone(() => { + isLoading.value = false; + scrollToBottom(); + }); + + loop.registerOnEpoch(() => { + isLoading.value = true; + scrollToBottom(); + }); - loop = undefined; - } - ); loop.start(tabStorage, userMessage); userInput.value = ''; diff --git a/renderer/src/components/main-panel/chat/task-loop.ts b/renderer/src/components/main-panel/chat/task-loop.ts index 2aeee59..9a3b1af 100644 --- a/renderer/src/components/main-panel/chat/task-loop.ts +++ b/renderer/src/components/main-panel/chat/task-loop.ts @@ -22,9 +22,10 @@ export class TaskLoop { constructor( private readonly streamingContent: Ref, private readonly streamingToolCalls: Ref, - private readonly onError: (msg: string) => void = (msg) => {}, - private readonly onChunk: (chunk: ChatCompletionChunk) => void = (chunk) => {}, - private readonly onDone: () => void = () => {}, + private onError: (msg: string) => void = (msg) => {}, + private onChunk: (chunk: ChatCompletionChunk) => void = (chunk) => {}, + private onDone: () => void = () => {}, + private onEpoch: () => void = () => {}, private readonly taskOptions: TaskLoopOptions = { maxEpochs: 20 }, ) {} @@ -166,6 +167,21 @@ export class TaskLoop { this.streamingToolCalls.value = []; } + public registerOnError(handler: (msg: string) => void) { + this.onError = handler; + } + + public registerOnChunk(handler: (chunk: ChatCompletionChunk) => void) { + this.onChunk = handler; + } + + public registerOnDone(handler: () => void) { + this.onDone = handler; + } + + public registerOnEpoch(handler: () => void) { + this.onEpoch = handler; + } /** * @description 开启循环,异步更新 DOM @@ -176,6 +192,8 @@ export class TaskLoop { for (let i = 0; i < this.taskOptions.maxEpochs; ++ i) { + this.onEpoch(); + // 初始累计清空 this.streamingContent.value = ''; this.streamingToolCalls.value = []; diff --git a/service/tabs.json b/service/tabs.json index 4ea9883..65687a3 100644 --- a/service/tabs.json +++ b/service/tabs.json @@ -1,5 +1,5 @@ { - "currentIndex": 1, + "currentIndex": 2, "tabs": [ { "name": "交互测试", @@ -115,17 +115,100 @@ { "name": "multiply", "description": "对两个数字进行实数域的乘法运算", - "enabled": false + "enabled": true }, { "name": "is_even", "description": "判断一个整数是否为偶数", - "enabled": false + "enabled": true }, { "name": "capitalize", "description": "将字符串首字母大写", - "enabled": false + "enabled": true + } + ], + "enableWebSearch": false, + "temperature": 0.7, + "contextLength": 10, + "systemPrompt": "" + } + } + }, + { + "name": "交互测试", + "icon": "icon-robot", + "type": "blank", + "componentIndex": 3, + "storage": { + "messages": [ + { + "role": "user", + "content": "什么是斐波那契数列?" + }, + { + "role": "assistant", + "content": "斐波那契数列(Fibonacci sequence)是以意大利数学家**列昂纳多·斐波那契**(Leonardo Fibonacci)命名的一个经典数列。其定义如下:\n\n### **定义**\n- **前两项**: \n \\( F_0 = 0 \\), \\( F_1 = 1 \\)(部分定义从 \\( F_1 = 1 \\), \\( F_2 = 1 \\) 开始)。\n- **递推关系**: \n 从第三项开始,每一项等于前两项之和: \n \\( F_n = F_{n-1} + F_{n-2} \\) (\\( n \\geq 2 \\))。\n\n### **数列示例**\n前几项为: \n0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, ...\n\n### **关键特性**\n1. **黄金分割**: \n 当 \\( n \\) 趋近于无穷大时,相邻两项的比值 \\( \\frac{F_{n+1}}{F_n} \\) 趋近于**黄金比例** \\( \\phi \\approx 1.618 \\)。\n\n2. **通项公式(比奈公式)**: \n \\[\n F_n = \\frac{\\phi^n - (-\\phi)^{-n}}{\\sqrt{5}}, \\quad \\phi = \\frac{1+\\sqrt{5}}{2}\n \\]\n 该公式通过无理数精确计算整数项。\n\n3. **应用领域**: \n - 自然界:如花瓣排列、松果螺旋、鹦鹉螺壳的生长模式。 \n - 计算机科学:动态规划、递归算法(需注意重复计算的优化)。 \n - 金融:斐波那契回调线用于技术分析。\n\n### **扩展知识**\n- **负数项**:递推关系可反向延伸,如 \\( F_{-n} = (-1)^{n+1}F_n \\)。\n- **变体**:卢卡斯数列(Lucas sequence)以 \\( L_0=2 \\), \\( L_1=1 \\) 开始,同样满足递推关系。\n\n斐波那契数列因其简洁的递推定义与广泛的自然关联性,成为数学和科学中的经典研究对象。" + }, + { + "role": "user", + "content": "add 1 2" + }, + { + "role": "assistant", + "content": "", + "tool_calls": [ + { + "id": "call_0_4eeb1c2f-8345-4b75-b002-af252af0728f", + "index": 0, + "type": "function", + "function": { + "name": "add", + "arguments": "{\"a\":1,\"b\":2}" + } + } + ] + }, + { + "role": "tool", + "tool_call_id": "call_0_4eeb1c2f-8345-4b75-b002-af252af0728f", + "content": "[{\"type\":\"text\",\"text\":\"3\"}]" + }, + { + "role": "assistant", + "content": "1 + 2 = 3" + }, + { + "role": "user", + "content": "nihao" + }, + { + "role": "assistant", + "content": "你好!有什么可以帮您的吗?😊" + } + ], + "settings": { + "modelIndex": 0, + "enableTools": [ + { + "name": "add", + "description": "对两个数字进行实数域的加法", + "enabled": true + }, + { + "name": "multiply", + "description": "对两个数字进行实数域的乘法运算", + "enabled": true + }, + { + "name": "is_even", + "description": "判断一个整数是否为偶数", + "enabled": true + }, + { + "name": "capitalize", + "description": "将字符串首字母大写", + "enabled": true } ], "enableWebSearch": false,