visuddhinanda 4 месяцев назад
Родитель
Сommit
82b6574c07
1 измененных файлов с 98 добавлено и 39 удалено
  1. 98 39
      dashboard-v4/dashboard/src/hooks/useChatData.ts

+ 98 - 39
dashboard-v4/dashboard/src/hooks/useChatData.ts

@@ -7,6 +7,9 @@ import {
   PendingMessage,
   OpenAIMessage,
   TOpenAIRole,
+  ParsedChunk,
+  ToolCall,
+  CreateMessageRequest,
 } from "../types/chat";
 
 import { useActivePath } from "./useActivePath";
@@ -43,10 +46,11 @@ export function useChatData(chatId: string): {
   // 加载消息列表
   const loadMessages = useCallback(async () => {
     // 如果 chatId 为空或无效,不执行加载
+    /*
     if (!chatId || chatId.trim() === "") {
       return;
     }
-
+*/
     try {
       setIsLoading(true);
       setError(undefined); // 清除之前的错误
@@ -85,14 +89,12 @@ export function useChatData(chatId: string): {
   // 构建对话历史(用于AI API调用)
   const buildConversationHistory = useCallback(
     (baseMessages: MessageNode[], newUserMessage?: MessageNode) => {
-      const history: OpenAIMessage[] = activePath
-        .filter((m) => m.role !== "tool") // 排除tool消息
-        .map((m) => ({
-          role: m.role,
-          content: m.content || "",
-          tool_calls: m.tool_calls,
-          tool_call_id: m.tool_call_id,
-        }));
+      const history: OpenAIMessage[] = activePath.map((m) => ({
+        role: m.role,
+        content: m.content || "",
+        tool_calls: m.tool_calls,
+        tool_call_id: m.tool_call_id,
+      }));
 
       if (newUserMessage) {
         history.push({
@@ -110,18 +112,20 @@ export function useChatData(chatId: string): {
   const saveMessageGroup = useCallback(
     async (tempId: string, messages: MessageNode[]) => {
       try {
-        const savedMessages = await messageApi.createMessages(chatId, {
+        const data: CreateMessageRequest = {
           messages: messages.map((m) => ({
             uid: m.uid,
             parent_id: m.parent_id,
             role: m.role,
             content: m.content,
+            session_id: m.session_id,
             model_id: m.model_id,
             tool_calls: m.tool_calls,
             tool_call_id: m.tool_call_id,
             metadata: m.metadata,
           })),
-        });
+        };
+        const savedMessages = await messageApi.createMessages(chatId, data);
 
         // 更新本地状态:移除pending,添加到已保存消息
         setPendingMessages((prev) => prev.filter((p) => p.temp_id !== tempId));
@@ -146,7 +150,14 @@ export function useChatData(chatId: string): {
     },
     [chatId]
   );
-
+  // 一个安全 JSON 解析函数
+  function safeJsonParse(str: string): any {
+    try {
+      return JSON.parse(str);
+    } catch {
+      return str; // 返回原始字符串,避免崩溃
+    }
+  }
   // 发送消息给AI并处理响应
   const sendMessageToAI = useCallback(
     async (userMessage: MessageNode, pendingGroup: PendingMessage) => {
@@ -163,7 +174,7 @@ export function useChatData(chatId: string): {
           rawMessages,
           userMessage
         );
-        const adapter = getModelAdapter(currModel.name);
+        const adapter = getModelAdapter(currModel);
 
         // 处理Function Call的循环逻辑
         let currentMessages = conversationHistory;
@@ -173,7 +184,7 @@ export function useChatData(chatId: string): {
         while (maxIterations-- > 0) {
           // 流式处理AI响应
           let responseContent = "";
-          let functionCalls: any[] = [];
+          let functionCalls: ToolCall[] = [];
           let metadata: any = {};
 
           const streamResponse = await adapter.sendMessage(currentMessages, {
@@ -181,19 +192,64 @@ export function useChatData(chatId: string): {
             max_tokens: 2048,
           });
 
-          // 模拟流式输出处理
+          // 用于存储流式拼接的 tool_calls
+          const toolCallBuffer = new Map<number, ToolCall>();
+
+          // 流式输出处理
           await new Promise((resolve, reject) => {
             const processStream = async () => {
               try {
-                // 这里应该是实际的流处理逻辑
                 for await (const chunk of streamResponse) {
-                  const parsed = adapter.parseStreamChunk(chunk);
+                  const parsed: ParsedChunk | null =
+                    adapter.parseStreamChunk(chunk);
+
+                  // 处理内容流
                   if (parsed?.content) {
                     responseContent += parsed.content;
                     setStreamingMessage(responseContent);
                   }
-                  if (parsed?.function_call) {
-                    // 处理function call
+
+                  // 处理 tool_calls
+                  if (parsed?.tool_calls) {
+                    for (const call of parsed.tool_calls) {
+                      //console.info("ai chat call", call);
+                      const existing = toolCallBuffer.get(call.index);
+                      if (existing) {
+                        // 拼接 arguments
+                        existing.function.arguments +=
+                          call.function.arguments || "";
+                        //console.debug("ai chat 拼接 arguments", existing);
+                      } else {
+                        // 初始化新 tool_call
+                        //console.debug("ai chat 初始化新 tool_call", call);
+                        toolCallBuffer.set(call.index, {
+                          ...call,
+                          function: {
+                            ...call.function,
+                            arguments: call.function.arguments || "",
+                          },
+                        });
+                      }
+                    }
+
+                    console.info(
+                      "ai chat function call (buffer)",
+                      toolCallBuffer
+                    );
+                  }
+
+                  // 如果模型说明调用结束
+                  if (parsed?.finish_reason === "tool_calls") {
+                    // 在这里 arguments 已经拼接完整,可以解析
+                    const toolCalls: ToolCall[] = [];
+                    toolCallBuffer.forEach((value: ToolCall, key: number) => {
+                      toolCalls.push(value);
+                    });
+
+                    console.info("ai chat Final tool calls", toolCalls);
+
+                    // TODO: 在这里触发你实际的函数调用逻辑
+                    functionCalls = toolCalls;
                   }
                 }
                 resolve(undefined);
@@ -204,8 +260,8 @@ export function useChatData(chatId: string): {
             processStream();
           });
 
-          // 创建AI响应消息
-          const aiMessage: MessageNode = {
+          // 创建AI请求消息
+          const toolCallsMessage: MessageNode = {
             id: 0,
             uid: `temp_ai_${pendingGroup.temp_id}_${allAiMessages.length}`,
             temp_id: pendingGroup.temp_id,
@@ -226,32 +282,34 @@ export function useChatData(chatId: string): {
             updated_at: new Date().toISOString(),
           };
 
-          allAiMessages.push(aiMessage);
+          allAiMessages.push(toolCallsMessage);
 
           // 如果有function calls,处理它们
           if (functionCalls.length > 0) {
             const toolResults = await Promise.all(
               functionCalls.map((call) => adapter.handleFunctionCall(call))
             );
-
-            const toolMessages = functionCalls.map((call, index) => ({
-              id: 0,
-              uid: `temp_tool_${pendingGroup.temp_id}_${index}`,
-              temp_id: pendingGroup.temp_id,
-              chat_id: chatId,
-              session_id: pendingGroup.session_id,
-              parent_id: aiMessage.uid,
-              role: "tool" as const,
-              content: JSON.stringify(toolResults[index]),
-              tool_call_id: call.id,
-              is_active: true,
-              save_status: "pending" as const,
-              created_at: new Date().toISOString(),
-              updated_at: new Date().toISOString(),
-            }));
+            //ai相应消息
+            const toolMessages: MessageNode[] = functionCalls.map(
+              (call, index) => ({
+                id: 0,
+                uid: `temp_tool_${pendingGroup.temp_id}_${index}`,
+                temp_id: pendingGroup.temp_id,
+                chat_id: chatId,
+                session_id: pendingGroup.session_id,
+                parent_id: toolCallsMessage.uid,
+                role: "tool" as const,
+                content: JSON.stringify(toolResults[index]),
+                tool_call_id: call.id,
+                is_active: true,
+                save_status: "pending" as const,
+                created_at: new Date().toISOString(),
+                updated_at: new Date().toISOString(),
+              })
+            );
 
             allAiMessages.push(...toolMessages);
-
+            console.debug("ai chat allAiMessages", allAiMessages);
             // 更新对话历史,继续循环
             currentMessages.push(
               {
@@ -265,6 +323,7 @@ export function useChatData(chatId: string): {
                 tool_call_id: tm.tool_call_id,
               }))
             );
+            console.debug("ai chat currentMessages", currentMessages);
 
             continue;
           }