乐于分享
好东西不私藏

VFP AI 插件开发花絮13:会话管理和多轮会话

VFP AI 插件开发花絮13:会话管理和多轮会话

插件之前对会话管理并没有处理。所有的消息存储在DBF中。虽然对于多轮会话有粗糙的处理,但是如果要适用于所选择的模型,在原有代码上修改会麻烦很多。
所以构建了这个会话管理和多轮会话的组件,以便更好的对它们进行处理。
ClearSet Classlib To jsonhelper.vcx ADDITIVE Set Classlib To session.vcx ADDITIVE LOCAL loJsonHelper, loSessionMgr, loSession1, loSession2, loMsg, loHistory, loSummary, loList, loLoaded, lcJson, loEx*---------------------------------------------------------------------* 1. 初始化 JSON 辅助对象和会话管理器*---------------------------------------------------------------------? "=== 1. 初始化环境 ==="loJsonHelper = CREATEOBJECT("jsonhelper")IF ISNULL(loJsonHelper) OR VARTYPE(loJsonHelper.oWindow) != "O"    ? "错误: 无法创建 jsonhelper 对象"    RETURNENDIF? "jsonhelper 初始化成功"loSessionMgr = CREATEOBJECT("sessionmanager", loJsonHelper)IF ISNULL(loSessionMgr)    ? "错误: 无法创建 sessionmanager 对象"    RETURNENDIF? "sessionmanager 初始化成功,会话目录: " + loSessionMgr.cSessionPath? ""*---------------------------------------------------------------------* 2. 创建第一个会话 (技术支持工作区)*---------------------------------------------------------------------? "=== 2. 创建会话并添加消息 ==="loSession1 = loSessionMgr.createsession("tech_support", "thread_001", "技术支持_打印机问题")? "创建会话: " + loSession1.Name + " (ID: " + loSession1.csessionid + ")"* 添加用户消息loMsg = CREATEOBJECT("chatmessage", "user", "打印机无法连接,错误代码 0x80070002", loJsonHelper)loMsg.ntokensused = 12loSession1.addmessage(loMsg)* 添加助手回复loMsg = CREATEOBJECT("chatmessage", "assistant", "请检查 USB 线缆并重启打印服务。", loJsonHelper)loMsg.ntokensused = 18loSession1.addmessage(loMsg)* 添加第二条用户消息loMsg = CREATEOBJECT("chatmessage", "user", "重启后仍然不行,驱动显示黄色感叹号", loJsonHelper)loMsg.ntokensused = 14loSession1.addmessage(loMsg)? "已添加 3 条消息,总 Token: " + TRANSFORM(loSession1.ntotaltokens)? ""*---------------------------------------------------------------------* 3. 创建第二个会话 (销售工作区)*---------------------------------------------------------------------loSession2 = loSessionMgr.createsession("sales", "thread_002", "产品咨询")? "创建会话: " + loSession2.Name + " (ID: " + loSession2.csessionid + ")"loMsg = CREATEOBJECT("chatmessage", "user", "请问 VFP 9.0 运行时是否需要授权?", loJsonHelper)loMsg.ntokensused = 8loSession2.addmessage(loMsg)loMsg = CREATEOBJECT("chatmessage", "assistant", "VFP 9.0 运行时是免费的,可以随应用程序分发。", loJsonHelper)loMsg.ntokensused = 22loSession2.addmessage(loMsg)? "已添加 2 条消息,总 Token: " + TRANSFORM(loSession2.ntotaltokens)? ""*---------------------------------------------------------------------* 4. 保存会话到文件*---------------------------------------------------------------------? "=== 4. 保存会话 ==="IF loSessionMgr.savesession(loSession1)    ? "会话1 保存成功"ELSE    ? "会话1 保存失败"ENDIFIF loSessionMgr.savesession(loSession2)    ? "会话2 保存成功"ELSE    ? "会话2 保存失败"ENDIF? ""*---------------------------------------------------------------------* 5. 从内存中清除所有活动会话,然后重新加载*---------------------------------------------------------------------? "=== 5. 清空内存并重新加载会话 ==="loSessionMgr.oActiveSessions.Remove(-1)   && 清空内存集合? "内存中活动会话数: " + TRANSFORM(loSessionMgr.oActiveSessions.Count)* 尝试获取不存在的会话(触发从文件加载)loLoaded = loSessionMgr.getsession(loSession1.csessionid)IF ISNULL(loLoaded)    ? "错误: 无法加载会话 " + loSession1.csessionidELSE    ? "成功加载会话: " + loLoaded.Name    ? "  消息数量: " + TRANSFORM(loLoaded.nmessagecount) &&m.loJsonHelper oWindow._api("loLoaded", "nmessagecount")     ? "  总 Token: " + TRANSFORM(loLoaded.ntotaltokens)    ? "  第一条消息内容: " + LEFT(loLoaded.oMessages.Item(1).ccontent, 50)ENDIF? ""*---------------------------------------------------------------------* 6. 测试会话摘要和最近消息*---------------------------------------------------------------------? "=== 6. 测试会话方法 ==="IF !ISNULL(loLoaded)    loSummary = loLoaded.getsummary()    ? "摘要 - 会话名: " + loSummary.Name    ? "      消息数: " + TRANSFORM(loSummary.nMessageCount)    ? "      总Token: " + TRANSFORM(loSummary.nTotalTokens)    * 获取最近 2 条消息    loRecent = loLoaded.getrecentmessages(2)    ? "最近 2 条消息:"    FOR EACH loMsg IN loRecent        ? "  " + loMsg.crole + ": " + LEFT(loMsg.ccontent, 40)    ENDFOR    * 获取 API 格式历史(跳过系统消息)    loHistory = loLoaded.getchathistory(10)    ? "API 历史记录 (" + TRANSFORM(loHistory.Count) + " 条):"    FOR EACH loMsg IN loHistory        ? "  " + loMsg.role + ": " + LEFT(loMsg.content, 40)    ENDFORENDIF? ""*---------------------------------------------------------------------* 7. 列出所有会话*---------------------------------------------------------------------? "=== 7. 列出所有会话 ==="loList = loSessionMgr.listsessions()IF VARTYPE(loList) = "O" AND loList.Count > 0    ? "找到 " + TRANSFORM(loList.Count) + " 个会话:"    FOR EACH loItem IN loList        ? "  " + loItem.cSessionId + " | " + loItem.Name + " | 消息:" + TRANSFORM(loItem.nMessageCount)    ENDFORELSE    ? "没有找到任何会话文件"ENDIF? ""*---------------------------------------------------------------------* 8. 删除一个会话并验证*---------------------------------------------------------------------? "=== 8. 删除会话 ==="lcDeleteId = loSession2.csessionid? "准备删除会话: " + lcDeleteIdIF loSessionMgr.deletesession(lcDeleteId)    ? "删除成功"    * 再次列出,确认消失    loListAfter = loSessionMgr.listsessions()    ? "剩余会话数: " + TRANSFORM(loListAfter.Count)ELSE    ? "删除失败"ENDIF? ""*---------------------------------------------------------------------* 9. 清理*---------------------------------------------------------------------? "=== 9. 测试完成 ==="loSessionMgr = .NULL.loJsonHelper = .NULL.? "所有测试结束,请检查会话目录 '" + ADDBS(SYS(5+ SYS(2003)) + "AnythingLLM_Session' 下的文件"RETURN
输出:
存储的会话1:
{  "SessionId": "20260407_7FR1DI1WR",  "threadSlug": "thread_001",  "workspaceSlug": "tech_support",  "Name": "技术支持_打印机问题",  "createdAt": "2026.04.07 23:05:43",  "updatedAt": "2026.04.07 23:05:43",  "totalTokens": 44,  "messageCount": 3,  "Messages": [    {      "role": "user",      "content": "打印机无法连接,错误代码 0x80070002",      "timestamp": "2026.04.07 23:05:43",      "tokensUsed": 12    },    {      "role": "assistant",      "content": "请检查 USB 线缆并重启打印服务。",      "timestamp": "2026.04.07 23:05:43",      "tokensUsed": 18    },    {      "role": "user",      "content": "重启后仍然不行,驱动显示黄色感叹号",      "timestamp": "2026.04.07 23:05:43",      "tokensUsed": 14    }  ]}
尽管组件是基于 AnythingLLM 的聊天端点创建,但是,这就是一个良好的开端。