
插件之前对会话管理并没有处理。所有的消息存储在DBF中。虽然对于多轮会话有粗糙的处理,但是如果要适用于所选择的模型,在原有代码上修改会麻烦很多。
所以构建了这个会话管理和多轮会话的组件,以便更好的对它们进行处理。
Clear
Set 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 对象"
RETURN
ENDIF
? "jsonhelper 初始化成功"
loSessionMgr = CREATEOBJECT("sessionmanager", loJsonHelper)
IF ISNULL(loSessionMgr)
? "错误: 无法创建 sessionmanager 对象"
RETURN
ENDIF
? "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 = 12
loSession1.addmessage(loMsg)
* 添加助手回复
loMsg = CREATEOBJECT("chatmessage", "assistant", "请检查 USB 线缆并重启打印服务。", loJsonHelper)
loMsg.ntokensused = 18
loSession1.addmessage(loMsg)
* 添加第二条用户消息
loMsg = CREATEOBJECT("chatmessage", "user", "重启后仍然不行,驱动显示黄色感叹号", loJsonHelper)
loMsg.ntokensused = 14
loSession1.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 = 8
loSession2.addmessage(loMsg)
loMsg = CREATEOBJECT("chatmessage", "assistant", "VFP 9.0 运行时是免费的,可以随应用程序分发。", loJsonHelper)
loMsg.ntokensused = 22
loSession2.addmessage(loMsg)
? "已添加 2 条消息,总 Token: " + TRANSFORM(loSession2.ntotaltokens)
? ""
*---------------------------------------------------------------------
* 4. 保存会话到文件
*---------------------------------------------------------------------
? "=== 4. 保存会话 ==="
IF loSessionMgr.savesession(loSession1)
? "会话1 保存成功"
ELSE
? "会话1 保存失败"
ENDIF
IF 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.csessionid
ELSE
? "成功加载会话: " + 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)
ENDFOR
ENDIF
? ""
*---------------------------------------------------------------------
* 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)
ENDFOR
ELSE
? "没有找到任何会话文件"
ENDIF
? ""
*---------------------------------------------------------------------
* 8. 删除一个会话并验证
*---------------------------------------------------------------------
? "=== 8. 删除会话 ==="
lcDeleteId = loSession2.csessionid
? "准备删除会话: " + lcDeleteId
IF 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 的聊天端点创建,但是,这就是一个良好的开端。