Skip to content

会话上下文维持功能修复总结

字数
1375 字
阅读时间
7 分钟

问题描述

用户报告在与AI对话时,即使传递了正确的conversation_id,两次连续对话仍然不在同一个会话上下文中,导致AI无法记住之前的对话内容。

根本原因分析

问题1:conversation_id未被传递到Dify API ⚠️ 核心问题

文件: cloudfunctions/ask/index.js

原因:

javascript
// ❌ 原函数签名缺少conversation_id参数
async function proxyChatWithDify({
  query,
  user,
  inputs = {},
  response_mode = 'blocking',
  auto_generate_name = true,
  apiKey = null,
  agentId = null,
  endpoint = DIFY_CHAT_ENDPOINT
}) {
  // ...
  const body = {
    inputs,
    response_mode: finalResponseMode,
    auto_generate_name,
    query,
    user: user || 'anonymous'
    // ❌ 缺少 conversation_id 字段
  };
}

影响: 即使前端正确传递了conversation_id,ask云函数也会忽略它,导致每次请求都创建新会话。

问题2:Agent查找失败导致response_mode错误

文件: cloudfunctions/ask/index.js

原因:

javascript
// ❌ isAgentChatApp函数只支持通过_id查找
async function isAgentChatApp({ apiKey, agentId }) {
  const agentDoc = await db.collection('ask_agents').doc(agentId).get();
  // 当agentId是agent_key(如"cbt_specialist")时查找失败
}

影响:

  • 当传入agent_key而非_id时,查找失败
  • 默认使用streaming模式,导致response_mode意外切换
  • 日志显示错误:document with _id cbt_specialist does not exist

修复方案

修复1:添加conversation_id支持 (cloudfunctions/ask/index.js)

1.1 修改函数签名

位置: 行 423-432

javascript
async function proxyChatWithDify({
  query,
  user,
  inputs = {},
  response_mode = 'blocking',
  auto_generate_name = true,
  conversation_id = null,  // ✅ 新增conversation_id参数
  apiKey = null,
  agentId = null,
  endpoint = DIFY_CHAT_ENDPOINT
}) {

1.2 将conversation_id添加到请求体

位置: 行 463-475

javascript
const body = {
  inputs,
  response_mode: finalResponseMode,
  auto_generate_name,
  query,
  user: user || 'anonymous'
};

// ✅ 如果提供了conversation_id,添加到请求体中以维持会话上下文
if (conversation_id) {
  body.conversation_id = conversation_id;
  console.log('[proxyChatWithDify] 使用已有conversation_id:', conversation_id);
}

1.3 增强日志输出

位置: 行 477-486

javascript
console.log('[proxyChatWithDify] 请求参数:', {
  endpoint,
  response_mode: finalResponseMode,
  user: user || 'anonymous',
  inputKeys: Object.keys(inputs || {}),
  queryLength: query?.length || 0,
  agentId,
  isAgentChatApp: needsStreaming,
  hasConversationId: !!conversation_id  // ✅ 添加conversation_id状态标识
});

修复2:支持agent_key查找 (cloudfunctions/ask/index.js)

位置: 行 318-366

javascript
async function isAgentChatApp({ apiKey, agentId }) {
  if (!agentId) {
    return false;
  }

  try {
    const db = ensureDb();
    let agentDoc;

    // ✅ 首先尝试通过_id查找
    try {
      agentDoc = await db.collection('ask_agents').doc(agentId).get();
    } catch (error) {
      // ✅ 如果通过_id查找失败,尝试通过agent_key查找
      console.log('[isAgentChatApp] 通过_id查找失败,尝试通过agent_key查找:', agentId);
      const queryResult = await db.collection('ask_agents')
        .where({
          agent_key: agentId,
          status: 'active'
        })
        .limit(1)
        .get();

      if (queryResult.data && queryResult.data.length > 0) {
        agentDoc = { data: queryResult.data[0] };
      }
    }

    if (agentDoc && agentDoc.data) {
      const isAgent = agentDoc.data.agent_origin === 'user_custom' ||
                     agentDoc.data.dify_agent_id ||
                     agentDoc.data.capability_tags?.includes('agent');

      // ✅ 添加详细的判断结果日志
      console.log('[isAgentChatApp] Agent类型判断结果:', {
        agentId,
        agent_key: agentDoc.data.agent_key,
        agent_origin: agentDoc.data.agent_origin,
        isAgent
      });
      return isAgent;
    }
  } catch (error) {
    console.log('[isAgentChatApp] 无法判断Agent类型,默认使用streaming模式:', error.message);
  }

  return true;
}

相关修复(已在前期完成)

askMessageManager云函数优化

文件: cloudfunctions/askMessageManager/index.js, package.json

  1. createSession修复: 将dify_conversation_id初始值从随机生成的UUID改为null,等待首次对话后从Dify API获取真实ID
  2. getSession性能优化:
    • 添加数据库超时配置(60秒)
    • 实现重试机制(3次,指数退避)
    • 只查询必要字段
    • 客户端缓存(5分钟)

前端askMessage服务

文件: miniprogram/services/askMessage.js

  • ✅ 已正确实现conversation_id提取和更新逻辑(lines 240-268)
  • ✅ 已实现会话缓存机制
  • ✅ 已正确传递conversation_id到ask云函数

测试验证

1. 验证conversation_id传递

在微信开发者工具控制台查看日志:

javascript
// 首次对话
[proxyChatWithDify] 请求参数: {
  hasConversationId: false  // ✅ 首次对话无conversation_id
}
// 返回: conversation_id: "xxxx-xxxx-xxxx-xxxx"

// 第二次对话
[proxyChatWithDify] 使用已有conversation_id: xxxx-xxxx-xxxx-xxxx
[proxyChatWithDify] 请求参数: {
  hasConversationId: true  // ✅ 后续对话有conversation_id
}

2. 验证会话上下文

测试对话:

用户: 你好,我叫小明
AI: 你好小明,很高兴认识你...

用户: 我叫什么名字?
AI: 你叫小明。  // ✅ AI记住了之前的对话

3. 验证Agent查找

检查日志中不再出现:

❌ document.get:fail document with _id cbt_specialist does not exist

应该看到:

✅ [isAgentChatApp] Agent类型判断结果: {
  agentId: "cbt_specialist",
  agent_key: "cbt_specialist",
  agent_origin: "system_default",
  isAgent: true
}

部署步骤

  1. 上传ask云函数

    • 右键 cloudfunctions/ask 目录
    • 选择"上传并部署:云端安装依赖"
  2. 验证部署

    • 在云开发控制台查看云函数版本
    • 查看日志确认新代码已生效
  3. 测试对话

    • 在小程序中开始新对话
    • 发送至少两条消息
    • 验证AI能记住之前的对话内容

预期效果

  • ✅ conversation_id在首次对话后正确获取并存储
  • ✅ 后续对话正确使用已有conversation_id
  • ✅ AI能够记住同一会话中之前的对话内容
  • ✅ Agent查找正确,response_mode按预期工作
  • ✅ 日志中可以清晰追踪conversation_id的使用情况

注意事项

  1. conversation_id生命周期

    • 由Dify API生成和管理
    • 存储在ask_sessions.dify_conversation_id字段
    • 会话有效期由Dify API控制
  2. 数据一致性

    • 前端从ask云函数响应中提取conversation_id
    • 通过askMessageManager的update_session更新到数据库
    • 后续对话从数据库读取并传递给ask云函数
  3. 错误处理

    • 如果conversation_id失效,Dify API会返回错误
    • 前端应捕获错误并创建新会话

参考文档

贡献者

The avatar of contributor named as Cai Hongyu Cai Hongyu

文件历史

撰写