会话上下文维持功能修复总结
字数
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
- createSession修复: 将
dify_conversation_id初始值从随机生成的UUID改为null,等待首次对话后从Dify API获取真实ID - 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
}部署步骤
上传ask云函数
- 右键
cloudfunctions/ask目录 - 选择"上传并部署:云端安装依赖"
- 右键
验证部署
- 在云开发控制台查看云函数版本
- 查看日志确认新代码已生效
测试对话
- 在小程序中开始新对话
- 发送至少两条消息
- 验证AI能记住之前的对话内容
预期效果
- ✅ conversation_id在首次对话后正确获取并存储
- ✅ 后续对话正确使用已有conversation_id
- ✅ AI能够记住同一会话中之前的对话内容
- ✅ Agent查找正确,response_mode按预期工作
- ✅ 日志中可以清晰追踪conversation_id的使用情况
注意事项
conversation_id生命周期
- 由Dify API生成和管理
- 存储在
ask_sessions.dify_conversation_id字段 - 会话有效期由Dify API控制
数据一致性
- 前端从ask云函数响应中提取conversation_id
- 通过askMessageManager的update_session更新到数据库
- 后续对话从数据库读取并传递给ask云函数
错误处理
- 如果conversation_id失效,Dify API会返回错误
- 前端应捕获错误并创建新会话