Skip to content

[Bug] 工具调用场景下的历史上下文还原不完整 #514

@aiesst

Description

@aiesst

问题描述
当前系统在工具调用过程中对历史消息的还原存在两个关键缺陷:

  1. 助手消息结构异常
    工具调用返回内容被强制包装成包含response的 <function_call> 格式,而非保持真实的fc调用结构:

    // addContextMessages 方法中,这种结果会让大模型下次调用工具后自己去模拟这种返回格式,因为它参考了历史有这种返回结构(被误导了)
    return (
      '<function_call>' +
      JSON.stringify({  
        function_call_result: {
          name: block.tool_call.name,
          arguments: parsedParams,
          response: parsedResponse
        }
      }) +
      '</function_call>'
    )
  2. 缺失关键用户消息
    上下文遗漏了工具执行后的用户消息:

    // 当前被忽略的系统消息
    '以下是刚刚执行的工具调用响应,请根据响应内容更新你的回答:\n' +
    JSON.stringify({
      role: 'tool', 
      content: ...,  
      tool_call_id: toolCall.id  
    })

预期行为
历史上下文应该是完整且真实的历史消息,如果缺失或者特意构造出历史消息,会误导大模型后续的问答。

个人建议
在 addContextMessages 方法的 contextMessages 参数中,用个字段context数组存储对话上下文,其中当 role='assistant' 时的context里面可能包含user的被丢失的消息、可能的 tool 的<function_call>真实消息。** addContextMessages** 方法中不再使用content字段去拼接上下文,而是使用记录的context去做拼接。可以每次在requestParams和返回的消息去更新sqlite的context字段,这里有完整的消息请求和消息的回复数据。

/**
 * SQLite 消息类型定义
 */
type SQLITE_MESSAGE = {
  id: string;
  conversation_id: string;
  parent_id?: string;
  role: MESSAGE_ROLE;
  content: string;
  created_at: number;
  order_seq: number;
  token_count: number;
  status: MESSAGE_STATUS;
  metadata: string;
  is_context_edge: number;
  is_variant: number;
  variants?: SQLITE_MESSAGE[];
  context?: string;  // 用于存储对话上下文的JSON字符串
};


/**
 * 建议示例-user类型:
 * 在user角色的消息中,context 字段存储的是用户输入的问题
 */
const userMessageExample = {
  //...
  role: "user",
  //....
  context: JSON.stringify([
    {
      role: "user",
      content: "帮我做....."
    },
  ])
};

/**
 * 建议示例-assistant类型:
 * 在 assistant 角色的消息中,context 字段存储单个回复的对话上下文,
 * 包括可能的用户消息丢失片段和工具调用信息
 */
const assistantMessageExample = {
  //...
  role: "assistant",
  //....
  context: JSON.stringify([
    { role: 'assistant', tool_calls: [Array] },
    {
      role: 'tool',
      content: 'success',
      tool_call_id: 'call_0_97ac4257-e304-4b1f-8432-8d870d569e58'
    },
    {
      role: "user",
      content: `以下是刚刚执行的工具调用响应,请根据响应内容更新你的回答:
        ${JSON.stringify({
          role: "tool",
          content: "...",
          tool_call_id: "xxxx"
        })}`
    },
    {
      role: "assistant",
      content: "tool调用成功,结果为xxx"
    }
  ])
};

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions