接入deepseek之需求对话-002
2025-03-21
问:
请考虑下拉取的文本是word格式,同时可能还有图片等多媒体内容,你用text如何保存?
答:
你这个提醒非常关键,确实,如果协议文档是 Word(.docx
)格式,甚至包含图片、表格、格式化段落等内容,那简单地保存为 TEXT
字段(纯文本)就不现实了。我们必须认真处理“原始文档快照”的保存方式。
✅ 问题拆解
情况 | 说明 |
---|---|
文档格式 | Word(.docx )格式,包含文字、段落、图片等 |
内容变更机制 | 网盘采用“覆盖式更新”,不保留历史版本 |
业务要求 | 每次用户签署时,需要保留当时签署协议的完整可回溯内容 |
❗保存为 TEXT
不足之处:
只能保留“文本内容”
丢失图片、样式、表格
不具备“可还原性”(即不能打开回放当时签署文档)
✅ 替代方案:存储原始文档文件副本(即:上传副本+引用)
👇 正确做法应该是:
用户签署时,系统自动将当时协议的
.docx
文件复制一份,上传到文档存储系统(或本地/OSS),再保留这个文件的“副本链接”。
✅ 字段结构改进建议:
字段名 | 类型 | 说明 |
---|---|---|
doc_link | VARCHAR(500) | 指向当前协议模板的链接(公共协议) |
doc_snapshot_link | VARCHAR(500) | 本次签署文档的副本地址(唯一保存) |
doc_snapshot_hash | VARCHAR(128) | 副本文件的 hash 值(验证文件未被篡改) |
doc_type | VARCHAR(50) | 协议类型,如 ai_disclaimer , privacy_policy |
agreed | BOOLEAN | 是否已勾选 |
signed_at | DATETIME | 签署时间 |
✅ 更新后的建表语句:
CREATE TABLE `ai_disclaimer_records` ( `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID', `user_id` BIGINT NOT NULL COMMENT '签署人用户ID', `org_id` BIGINT DEFAULT NULL COMMENT '所属企业ID', `doc_type` VARCHAR(50) DEFAULT 'ai_disclaimer' COMMENT '协议类型(如:ai_disclaimer,privacy_policy)', `agreed` BOOLEAN DEFAULT TRUE COMMENT '是否已勾选同意', `doc_link` VARCHAR(500) DEFAULT NULL COMMENT '协议当前模板链接(最新)', `doc_snapshot_link` VARCHAR(500) DEFAULT NULL COMMENT '签署当时协议文档副本地址', `doc_snapshot_hash` VARCHAR(128) DEFAULT NULL COMMENT '文档哈希值(验证一致性)', `ip_address` VARCHAR(50) DEFAULT NULL COMMENT '签署IP地址', `user_agent` VARCHAR(300) DEFAULT NULL COMMENT '用户设备信息(浏览器等)', `signed_at` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '签署时间', `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP, `updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`) );
✅ 推荐存储方式:
你可以将副本
.docx
文件:上传到公司私有云盘,生成独立链接
或上传到对象存储(如阿里 OSS),保存链接
可选计算 MD5/SHA256 等 Hash 存到
doc_snapshot_hash
,保证文件内容未篡改
✅ 客户端联动建议:
用户点击“我已阅读并同意” → 后端复制当前协议
.docx
文件 → 存入副本路径 & Hash后续管理员可从
doc_snapshot_link
下载对应副本进行审计
是否接受这个改进版本?如确认,我再进入第六张表 ai_messages
。
问:
doc_snapshot_hash这个验证是在审计的时候跟doc_snapshot_link获取的文件进行比对吗?
答:
完全正确 ✅!
🔍 doc_snapshot_hash
的作用就是:
在后期审计或取证时,验证用户签署时保存的副本文件是否被修改、替换、损坏。
📌 使用流程简述:
✅ 签署时(由系统完成):
系统将当前协议
.docx
文件复制一份副本,上传到存储系统,获得doc_snapshot_link
同时对该
.docx
文件计算 hash 值(推荐用SHA-256
或MD5
):# 示例sha256sum ai_agreement_20250320.docx => c03da1df32f9d...9a2e7f
将此 hash 存入字段
doc_snapshot_hash
✅ 审计时:
管理员从
doc_snapshot_link
下载该用户签署当时的.docx
协议副本对下载下来的文件再次计算 hash 值
与数据库中
doc_snapshot_hash
做比对:
比对结果 | 说明 |
---|---|
一致 ✅ | 文件未被篡改,可信 |
不一致 ❌ | 文件已损坏或被替换,数据链断裂(需追查) |
✅ 为什么这是高质量的数据合规设计?
能完整闭环:从“我签署了什么” → 到“我能证明我签署了什么”
符合 电子证据保存规范、满足企业级数据审计需求
避免未来因文档覆盖、改动带来责任争议
你也可以在后台管理页面做一个“验签”按钮,一键校验副本是否篡改。
确认这部分OK,我就继续进入 第六张表 ai_messages
,这张是日志核心表,会更复杂。是否继续?
问:
下一个表是:
-- 7. ai_chat_sessions(会话主表)
-- 作用: 记录用户的对话,支持 项目/报告关联,管理记忆功能。并归属到特定的 AI 提供商。
-- ✅ 确保对话受限于项目/报告
-- 如果 project_id 存在 → 对话仅属于该项目
-- 如果 report_id 存在 → 对话仅属于该报告
--
-- ✅ 新增 ai_provider_id
再下一个才是:ai_messages
请你对我提供的这张表先做重新设计。
-- 记录该对话使用的 AI(DeepSeek、GPT-4)
-- 支持 AI 切换(不同会话可使用不同 AI)
CREATE TABLE `ai_chat_sessions` (
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`user_id` INT UNSIGNED NOT NULL COMMENT '用户ID',
`session_id` VARCHAR(64) NOT NULL COMMENT '会话唯一标识',
`ai_provider_id` BIGINT NOT NULL COMMENT '调用的 AI 提供商',
`memory_enabled` BOOLEAN DEFAULT TRUE COMMENT '是否开启记忆(会话级别)',
`project_id` BIGINT NULL COMMENT '关联的项目ID',
`report_id` BIGINT NULL COMMENT '关联的报告ID',
`created_at` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`created_by` BIGINT NULL COMMENT '创建人',
`updated_by` BIGINT NULL COMMENT '更新人',
PRIMARY KEY (`id`),
FOREIGN KEY (`user_id`) REFERENCES `user`(`id`) ON DELETE CASCADE,
FOREIGN KEY (`ai_provider_id`) REFERENCES `ai_providers`(`id`) ON DELETE CASCADE
);
答:
非常好,你这张 ai_chat_sessions
是整个 AI 对话过程的“会话主表”,用于管理每一次对话上下文的生命周期与归属关系,我们现在结合你新增的业务需求,把它全面梳理优化。
✅ 现有表功能定位总结
功能点 | 是否实现 | 备注 |
---|---|---|
记录 user 与 AI 的一次完整会话 | ✅ | 通过 session_id 唯一标识 |
支持按项目 / 报告进行会话隔离 | ✅ | project_id / report_id |
支持开启/关闭会话级记忆 | ✅ | memory_enabled |
支持记录调用哪个模型(AI提供商) | ✅ | ai_provider_id |
支持更新人、时间等审计字段 | ✅ | created_by / updated_by 等 |
✅ 结合你今天新增的需求,需考虑的新增维度
新业务需求点 | 说明 | 是否已有 | 是否建议扩展 |
---|---|---|---|
企业维度限制 | 一个用户可能属于多个企业 | ❌ 无 org_id | ✅ 建议加 |
模型可动态切换(同一用户不同会话选不同模型) | 当前已支持 | ✅ ai_provider_id | 无需改 |
会话的token使用情况是否做总量汇总 | 当前未涉及 | ❌ | 🟡 可扩展为冗余字段,非必须 |
是否需要标记“结束”状态(如不再继续使用该会话) | 当前无 | ❌ | 🟡 可扩展字段:is_closed |
是否允许“是否跨项目共用记忆”或“是否允许公开此会话” | 当前业务无此需求 | ❌ | 暂不加,后续可扩展 |
✅ 字段补充建议
建议新增字段:
ALTER TABLE `ai_chat_sessions`ADD COLUMN `org_id` BIGINT DEFAULT NULL COMMENT '所属企业ID(多租户隔离)',ADD COLUMN `is_closed` BOOLEAN DEFAULT FALSE COMMENT '会话是否已关闭';
✅ 字段说明一览(最终结构)
字段名 | 类型 | 说明 |
---|---|---|
id | BIGINT | 主键 |
user_id | BIGINT | 发起该会话的用户 |
org_id | BIGINT | 所属企业(新增) |
session_id | VARCHAR(64) | 唯一标识该会话(UUID或雪花ID) |
ai_provider_id | BIGINT | 本次会话使用的AI模型 |
memory_enabled | BOOLEAN | 会话是否启用上下文记忆 |
is_closed | BOOLEAN | 会话是否已关闭(不可继续追问) |
project_id / report_id | BIGINT | 归属项目/报告(用于问题溯源与场景隔离) |
created_at / updated_at | DATETIME | 常规时间戳 |
created_by / updated_by | BIGINT | 创建/更新人 |
✅ 使用逻辑说明(结合数据流):
一个用户点击“AI助手”,系统创建一个
session_id
用户可以继续追问,系统将记忆记录关联该
session_id
如果
memory_enabled = false
,则不拼接历史上下文ai_provider_id
决定该会话调用哪个模型(可通过前端选择)当报告或项目结束,该
session_id
可被标记为is_closed = true
✅ 建表语句(更新后版本)
CREATE TABLE `ai_chat_sessions` ( `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID', `user_id` BIGINT UNSIGNED NOT NULL COMMENT '用户ID', `org_id` BIGINT DEFAULT NULL COMMENT '所属企业ID', `session_id` VARCHAR(64) NOT NULL COMMENT '会话唯一标识', `ai_provider_id` BIGINT NOT NULL COMMENT '调用的 AI 提供商', `memory_enabled` BOOLEAN DEFAULT TRUE COMMENT '是否开启记忆(会话级别)', `is_closed` BOOLEAN DEFAULT FALSE COMMENT '是否已关闭会话(禁止追问)', `project_id` BIGINT NULL COMMENT '关联的项目ID', `report_id` BIGINT NULL COMMENT '关联的报告ID', `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `created_by` BIGINT NULL COMMENT '创建人', `updated_by` BIGINT NULL COMMENT '更新人', PRIMARY KEY (`id`), FOREIGN KEY (`user_id`) REFERENCES `user`(`id`) ON DELETE CASCADE, FOREIGN KEY (`ai_provider_id`) REFERENCES `ai_providers`(`id`) ON DELETE CASCADE );
是否确认这一版结构?确认后我就进入你预告的下一张核心表:ai_messages
(会话内容及AI响应日志表),它会和这张表有一对多关联,是数据的主战场。继续?
问:
memory_enabled BOOLEAN 会话是否启用上下文记忆
is_closed BOOLEAN 会话是否已关闭(不可继续追问)
这俩我有点不太懂,请你详细解读。我感觉之间有交叉。
答:
你的观察非常敏锐,这两个字段确实容易混淆。下面我来详细区分和解释:
✅ 字段一:memory_enabled
—— 是否启用上下文记忆
✅ 作用:
控制当前会话是否启用「上下文追溯」机制,即:
用户连续提问时,系统是否拼接上一次或多次的问题+回答
用于让 AI 更“上下文理解”地进行连续对话
📌 举例:
memory_enabled | 用户行为 | 系统行为 |
---|---|---|
TRUE ✅ | 用户提问1:A是什么? 接着提问2:它跟B有什么区别? | 系统将问题1和回答1拼接给AI作为上下文 |
FALSE ❌ | 同样的提问过程 | 系统每次都当“新问题”处理,不拼接之前的内容 |
🧠 类似功能:GPT的 Chat 模式 vs Playground 单次问答
✅ 字段二:is_closed
—— 会话是否已终止使用
✅ 作用:
用于标记这个会话是否已经完成,不再接收新问题(就像“关闭一个聊天窗口”)。
系统层面:防止用户继续在这个
session_id
里发送新问题前端层面:可以不再显示该会话入口,归档处理
审计层面:可区分“正在进行中”的 vs “历史归档”的对话
📌 举例:
is_closed | 用户行为 | 系统行为 |
---|---|---|
FALSE ✅ | 用户继续提问 | 正常提交,处理逻辑受 memory_enabled 控制 |
TRUE ❌ | 用户尝试发送问题 | 系统提示:“该对话已结束,请新建会话” |
✅ 二者之间的关键区别:
对比维度 | memory_enabled | is_closed |
---|---|---|
控制对象 | AI是否“带着记忆”理解问题 | 用户是否还能继续发送新问题 |
作用时间 | 会话进行中时生效 | 会话结束后限制提交 |
系统行为 | 控制请求拼接历史上下文 | 控制是否允许继续提交问题 |
用户可见 | 前端可显示“记忆已启用”标记 | 前端可显示“已归档/只读”状态 |
✅ 两者的配合关系:
状态组合 | 含义 |
---|---|
memory_enabled = TRUE , is_closed = FALSE | 正常连续对话,带记忆 |
memory_enabled = FALSE , is_closed = FALSE | 正常问答,但每次都是“新问题” |
is_closed = TRUE (不管 memory_enabled ) | 会话已终止,不再允许交互 |
✅ 举个真实业务场景例子:
比如你在某个报告里创建了一个 AI 会话:
你开启了
memory_enabled = TRUE
,想连续问几个相互有关的问题3天后你报告提交完了,你希望这次对话不再继续追问,归档 → 你把会话
is_closed = TRUE
此时即使 memory 是启用的,系统也会阻止你继续提交问题
✅ 结论:
字段 | 你是否需要 | 理由 |
---|---|---|
memory_enabled | ✅ 保留 | 决定是否带上下文做“追问” |
is_closed | ✅ 保留 | 决定是否允许继续提问 |
这两个字段功能不同但互补,没有冗余,也不存在逻辑冲突。
你是否认可这个解释?如果确认清楚,我们就进入下一张:ai_messages(日志记录主表)。
问:
明白了。 下一个。不过提醒你,ai_messages不是日志记录表,是消息表哈,也就是对话主表哈。
答:
好的,非常重要的提醒 ✅,我已经更新认知:
ai_messages
是“消息表”,即:真实的每一条对话内容(用户发了什么、AI怎么答的),而不是简单日志。
这张表是对话系统的核心交易表,承担以下职责:
✅ 表功能定位(你当前设计意图):
功能 | 是否具备 |
---|---|
记录用户每一条提问 | ✅ |
记录 AI 每一条回答 | ✅ |
区分消息发送方(user/ai) | ✅ (推测应有) |
支持来源记录(提示词、自编辑、文档选中) | ✅ |
支持上下文拼接追溯 | ✅ |
支持报告/项目归属 | ✅ |
支持模型响应内容 | ✅ |
支持引用统计(被引用次数) | ✅ |
支持统计 token 使用 | ✅ |
✅ 初始版本(根据你提供文档内容简化整理):
CREATE TABLE `ai_messages` ( `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID', `session_id` VARCHAR(64) NOT NULL COMMENT '会话唯一标识', `user_id` BIGINT NOT NULL COMMENT '用户ID', `org_id` BIGINT DEFAULT NULL COMMENT '所属企业ID', `role` ENUM('user', 'ai') DEFAULT 'user' COMMENT '消息角色(提问 or 回答)', `question` TEXT COMMENT '用户提问内容', `question_source` TINYINT DEFAULT 0 COMMENT '来源:1-文档选中,2-自编辑,3-提示词', `answer` TEXT COMMENT 'AI回答内容(仅 role = ai 时使用)', `model_id` BIGINT DEFAULT NULL COMMENT '回答所用模型ID(仅 AI 消息)', `referenced_count` INT DEFAULT 0 COMMENT '被引用次数(AI消息专用)', `project_id` BIGINT DEFAULT NULL, `report_id` BIGINT DEFAULT NULL, `tokens_used` INT DEFAULT 0 COMMENT '本轮使用的token数(AI消息专用)', `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP, `updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`) );
✅ 字段解析
字段 | 说明 |
---|---|
session_id | 关联 ai_chat_sessions ,构成完整会话链 |
user_id | 谁发的消息 |
role | 标识消息是用户发送还是 AI 生成(支持双向记录) |
question | 用户输入的提问内容(当 role='user' 时使用) |
answer | AI 的生成内容(当 role='ai' 时使用) |
question_source | 追溯来源:选中、手输、提示词 |
model_id | 本条回答用的模型(防止和会话级不一致) |
referenced_count | 被其他地方引用次数(用于辅助统计) |
tokens_used | 本条 AI 回应消耗的 token 数(计费) |
project_id/report_id | 关联项目和报告,便于后期追踪 |
✅ 注意事项
role字段是关键:避免把问题和回答都塞在一条记录中。通过
role=user
和role=ai
区分清楚即可。允许 session_id + role 成对出现:1条问题,紧跟1条回答,构成一个互动单位。
如果未来有“AI未响应”状态,也可用
answer IS NULL
表示。
✅ 查询样例:获取一次完整对话列表
SELECT * FROM ai_messages WHERE session_id = 'abc123' ORDER BY created_at ASC;
✅ 你是否希望拆分“提问表”与“回答表”?
当前结构是一表双向(通过 role 区分),是目前主流的对话系统设计(如 OpenAI)。如果你更倾向拆表结构,也可以讨论。
✅ 建表语句完整版(建议):
CREATE TABLE `ai_messages` ( `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID', `session_id` VARCHAR(64) NOT NULL COMMENT '所属会话ID', `user_id` BIGINT NOT NULL COMMENT '用户ID', `org_id` BIGINT DEFAULT NULL COMMENT '所属企业ID', `role` ENUM('user', 'ai') DEFAULT 'user' COMMENT '消息角色(user=用户,ai=助手)', `question` TEXT COMMENT '问题内容(role=user 时记录)', `question_source` TINYINT DEFAULT 0 COMMENT '问题来源:1=文档选中,2=自编辑,3=提示词库', `answer` TEXT COMMENT 'AI回答内容(role=ai 时记录)', `model_id` BIGINT DEFAULT NULL COMMENT '模型ID(role=ai 时记录)', `referenced_count` INT DEFAULT 0 COMMENT '被引用次数(role=ai 时记录)', `tokens_used` INT DEFAULT 0 COMMENT '本轮对话token消耗(role=ai 时记录)', `project_id` BIGINT DEFAULT NULL COMMENT '归属项目ID', `report_id` BIGINT DEFAULT NULL COMMENT '归属报告ID', `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP, `updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`) );
是否接受这版结构?确认后我们再总结一下整个会话链数据结构:从 chat_session
到 message
到 日志/统计
的完整流程。是否继续?
问:
这里加引用次数什么意思?引用次数指的是提示词问题,不应该在这里出现吧。请你考虑是优化之前的表,还是新增表记录相关信息。
另外消息发送方都是用户,怎么会有ai呢?没明白。question_source 指的是问题来源,它包括用户手动输入,来自文档选择,联想词,如果来自联想词,还得与联想词的表挂钩,知道来源于哪一条。而回答的answer专门有answer表呢,如果是命中了联想词的,这里应该记录联想词关联的answerid即可,如果是请求了ai的,则要插入到answer表,并记录这个id,我认为是这样,当然你可以考虑的更全面。另外发送的问题如果是选中,手输的,但是命中了联想词该怎么记录呢?你也要考虑。token回应消耗的token,有区分问题和答案吗?还是混在一起,请你考虑。
答:
太棒了,你的逻辑非常清晰,我完全认同你这是一张高标准消息主表的要求,而且你指出的问题确实是很多 AI 对话系统容易混淆的地方。我们现在就来一步步重构设计,确保符合你提出的:
✅ 你的核心观点(高度认同)
问题点 | 你提出的逻辑 |
---|---|
1. 发送方都是用户 | 所以 role='ai' 这个设定是多余的,消息只记录“用户发出的问题” |
2. 回答内容另有表 | 所以 answer 字段应移除,改为外键引用 ai_answers.id |
3. 引用次数 | 不属于消息表,应记录在 ai_answers 表或引用统计表中 |
4. 问题来源复杂 | 来源不仅是自输/文档/提示词,而且“提示词命中”还要挂钩 ai_suggested_keywords 表 |
5. 提问可能多重来源命中 | eg: 选中文字再手动补充,又命中了提示词,来源应支持多来源叠加 |
6. token消耗应明确归属 | 是提问token、回答token?要分别记录 or 拆出一个使用统计表 |
✅ 所以我们来重新定义 ai_messages 表
✅ 一、重构目标:
原设计问题 | 新设计方向 |
---|---|
回答混入消息表 | 改为仅记录用户提问,回答单独关联答案表 |
来源字段不严谨 | 拆成多个字段:主来源类型 + 选中文字 + 联想词命中ID |
回答与提示词无连接 | 提问如果命中提示词,则要挂钩提示词ID、答案ID |
token消耗无细分 | 拆出 token 表 or 在 messages 表中单独记录 question_token/answer_token |
✅ 二、字段设计建议(新版 ai_messages)
CREATE TABLE `ai_messages` ( `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID', `session_id` VARCHAR(64) NOT NULL COMMENT '所属会话ID', `user_id` BIGINT NOT NULL COMMENT '发起用户ID', `org_id` BIGINT DEFAULT NULL COMMENT '所属企业ID', -- 用户发送内容 `question` TEXT NOT NULL COMMENT '用户输入的问题文本', `question_source_type` TINYINT DEFAULT 2 COMMENT '问题来源:1-选中文本,2-手动输入,3-提示词库', `selected_text` TEXT DEFAULT NULL COMMENT '用户选中的文档片段(如果有)', `suggested_keyword_id` BIGINT DEFAULT NULL COMMENT '命中的联想词ID(可为空)', -- 回答挂钩 `answer_id` BIGINT DEFAULT NULL COMMENT '命中的答案ID(提示词或AI生成)', `is_ai_generated` BOOLEAN DEFAULT FALSE COMMENT '是否是AI生成的(TRUE表示不是提示词命中)', -- token 使用 `question_tokens` INT DEFAULT 0 COMMENT '用户输入消耗token数', `answer_tokens` INT DEFAULT 0 COMMENT 'AI回答消耗token数', `project_id` BIGINT DEFAULT NULL, `report_id` BIGINT DEFAULT NULL, `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP, `updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`) );
✅ 三、字段解释重点补充
字段名 | 说明 |
---|---|
question_source_type | 表示主来源:用户是从哪里发起问题的 |
selected_text | 若来源于文档选择,这里保留用户选中的内容 |
suggested_keyword_id | 若命中提示词,则填入提示词ID(从 ai_suggested_keywords 表查) |
answer_id | 不直接保存文本,而是关联 ai_answers.id |
is_ai_generated | TRUE:说明这个 answer 是调用模型生成的;FALSE:说明是命中提示词已有回答 |
question_tokens / answer_tokens | 区分用户请求/AI回应的 token 用量,便于计费或风控控制 |
✅ 四、关于“选中+输入+提示词命中”三重来源问题,怎么处理?
我们采取主来源 + 附属挂钩的方式:
情况 | 字段组合示例 |
---|---|
用户选中文本并手动补充 | question_source_type=1 ,selected_text 有内容 |
用户命中提示词库 | question_source_type=3 ,suggested_keyword_id=xxx ,answer_id=yyy |
用户什么都没选,纯手动 | question_source_type=2 ,其他字段为空 |
如果出现多来源混合,仍只记录“最优先主来源”,辅助字段做补充挂钩。
✅ 五、你关心的引用次数统计,怎么办?
不建议记录在 messages 表,可以考虑两种方式:
在
ai_answers
表里增加referenced_count
字段(按 answer 聚合统计)或新建
ai_answer_references
表,记录引用来源(更灵活)
✅ 六、是否保留 model_id
?
这张表只记录提问。如果回答来源于 AI,那么模型已经记录在 ai_answers.model_id
,这里就不需要重复。
✅ 最终建议总结:
改动点 | 原因 |
---|---|
❌ 移除 role 字段 | 消息发送方固定为用户 |
❌ 移除 answer 字段 | 改为关联 answer 表 |
✅ 引入 question_source_type 、selected_text 、suggested_keyword_id | 支持更强的来源识别和溯源 |
✅ 拆分 token 字段为两个 | 精确区分请求和回应消耗 |
是否接受这个结构设计?如确认,我可以继续输出配套的“引用记录表”、“token统计表”,并总结当前整体的“AI对话主线链路结构图”。继续?
问:
被引用次数指的是发送的提示词引用联想词的次数,应该记录在联想词那个表里面。某个联想词引用了多少次。或者我觉得单独开一个表记录这个信息。它包括引用了多少次,被谁引用,被哪个会话引用,哪家公司引用,还有跟对话记录即ai_message的具体的id都要关联起来,方便追踪。
答:
你这个思路非常清晰,而且逻辑非常扎实,我完全认同你的做法。我们来一步步落地这个“引用记录系统”,确保满足以下关键需求:
✅ 你明确指出的核心逻辑:
“被引用次数”不是记录在消息表(
ai_messages
)或答案表(ai_answers
)中,而是:
谁引用了哪个提示词(联想词)
引用行为发生在哪个会话、哪家公司、哪个用户
能进行统计(多少次) + 追踪(是谁、何时)
✅ 最佳做法:建立一张专用的引用记录表
一条引用行为 = 一次用户问题与提示词的触发匹配
🧩 引用追踪需求字段清单
目标 | 字段 |
---|---|
引用了哪个提示词 | suggested_keyword_id (外键) |
被哪个用户引用 | user_id |
来自哪个企业 | org_id |
属于哪个会话 | session_id |
属于哪个消息(问题) | message_id (外键到 ai_messages ) |
具体引用时间 | created_at |
是否有效引用(未来用于过滤测试或误触) | is_valid (可选) |
✅ 表名建议:
ai_suggested_keyword_references
✅ 建表语句:
CREATE TABLE `ai_suggested_keyword_references` ( `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID', `suggested_keyword_id` BIGINT NOT NULL COMMENT '被引用的提示词ID', `message_id` BIGINT NOT NULL COMMENT '引用发生在哪条消息记录上', `session_id` VARCHAR(64) NOT NULL COMMENT '所属会话ID', `user_id` BIGINT NOT NULL COMMENT '引用行为的用户', `org_id` BIGINT DEFAULT NULL COMMENT '所属企业ID', `is_valid` BOOLEAN DEFAULT TRUE COMMENT '是否为有效引用(可用于测试过滤)', `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', PRIMARY KEY (`id`) );
✅ 字段说明:
字段 | 说明 |
---|---|
suggested_keyword_id | 哪个联想词被引用 |
message_id | 哪一条提问引用了它(外键关联 ai_messages.id ) |
session_id | 引用发生在哪次会话中(文本型方便展示) |
user_id | 谁引用的 |
org_id | 哪个公司引用的 |
is_valid | 未来若需排除测试引用或机器人自动引发,可标记为无效 |
✅ 引用统计方式:
若你需要显示“提示词被引用了多少次”:
SELECT suggested_keyword_id, COUNT(*) FROM ai_suggested_keyword_references GROUP BY suggested_keyword_id;
查询某用户在某项目中使用提示词频次:
SELECT * FROM ai_suggested_keyword_references WHERE user_id = 1001 AND org_id = 2001;
✅ 业务链路回顾:
用户发起一个提问(
ai_messages
)系统检测:是否命中提示词(
ai_suggested_keywords
)如果命中:
插入一条消息记录(
ai_messages
)同时插入一条引用记录(
ai_suggested_keyword_references
)
✅ 是否也要统计“AI答案引用”?
如果你未来要统计:某个 ai_answers
被多少地方用过,建议单独建一个类似的引用表。
是否接受这个结构?如果确认,我会将当前核心链条:
ai_chat_sessions
ai_messages
ai_suggested_keywords
ai_answers
ai_suggested_keyword_references
整理成一份逻辑结构图和链路文档给你做总结。是否继续?
问:
还不需要做逻辑总结,后面还有表没设计完呢!答案引用也另外设计一张表吧。因为它涉及到上下文追问。
答:
非常好,我们继续深入。你提到的:
“答案引用也需要单独设计表”,因为它涉及上下文追问。
你这句话背后的业务逻辑我马上捕捉到了两层含义:
✅ 你希望追踪的“答案引用行为”包括:
情形 | 举例 |
---|---|
1. 用户提问命中了提示词并引用了一个现有答案 | A用户选择了一个提示词,它自动带出了一个历史答案 |
2. 用户追问时系统自动拼接了前一轮的答案(上下文记忆) | 系统在生成新回答时,隐式引用了前一个答案内容 |
3. 用户在说明报告中右键“引用”某条AI回答插入文档中 | 明确操作,主动引用了某一答案片段 |
这些引用行为都涉及对 ai_answers.id
的引用,且需要支持审计和统计。
✅ 所以,我们需要一张专门的“AI答案引用记录表”
📌 表名建议:
sql复制编辑ai_answer_references
✅ 表结构设计
CREATE TABLE `ai_answer_references` ( `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID', `answer_id` BIGINT NOT NULL COMMENT '被引用的答案ID', `message_id` BIGINT DEFAULT NULL COMMENT '关联的提问(若来源于上下文追问)', `session_id` VARCHAR(64) DEFAULT NULL COMMENT '所属会话ID', `user_id` BIGINT NOT NULL COMMENT '引用行为的用户', `org_id` BIGINT DEFAULT NULL COMMENT '所属企业', `refer_type` TINYINT DEFAULT 1 COMMENT '引用类型:1-上下文追问拼接,2-主动引用插入,3-提示词自动关联', `project_id` BIGINT DEFAULT NULL, `report_id` BIGINT DEFAULT NULL, `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', PRIMARY KEY (`id`) );
✅ 字段说明
字段名 | 含义 |
---|---|
answer_id | 被引用的答案(来自 ai_answers.id ) |
message_id | 若是追问产生引用,该字段关联触发该追问的提问 |
session_id | 引用行为所在会话 |
refer_type | 区分是系统拼接(追问)、用户引用、还是提示词命中带出的回答 |
user_id / org_id | 记录行为发起方 |
project_id / report_id | 对应业务归属 |
✅ 引用类型枚举参考
值 | 含义 |
---|---|
1 | 上下文追问时,系统自动拼接引用了该答案 |
2 | 用户主动点击“引用”插入内容到说明文档中 |
3 | 命中提示词联动了答案内容,作为回答返回 |
你也可以扩展更多类型,未来如“AI自动引用历史回答”等。
✅ 使用场景回顾
应用场景 | 系统行为 |
---|---|
用户提问系统拼接上一轮回答 | → 插入 type=1 的引用记录 |
用户右键引用插入文档 | → 插入 type=2 的引用记录 |
命中提示词自动返回 preset answer | → 插入 type=3 的引用记录 |
✅ 可统计行为:
某个答案总共被引用了多少次
哪个用户最常引用历史答案
哪些项目下引用 AI 回答最多(内容被二次使用多)
哪些回答是“高引用内容”,可用于沉淀为 FAQ
是否接受这张表结构?确认后,我们再继续进入后续你还没设计完的表部分(例如 token 消耗统计表、提示词管理表增强等)。继续吗?
问:
好。我们继续下一张表:
--11. ai_usage_logs(AI 调用记录)
-- 作用: 记录 AI Token 消耗及成本。
CREATE TABLE `ai_usage_logs` (
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`user_id` INT UNSIGNED NOT NULL COMMENT '用户ID',
`session_id` BIGINT NOT NULL COMMENT '会话ID',
`ai_provider_id` BIGINT NOT NULL COMMENT '调用的 AI 接口 ID',
`request_text` TEXT NOT NULL COMMENT '请求的内容',
`response_text` TEXT COMMENT 'AI 返回的内容',
`tokens_used` INT DEFAULT 0 COMMENT '消耗的 Token 数',
`cost_usd` DECIMAL(10,5) DEFAULT 0.00000 COMMENT '本次请求的成本(美元)',
`created_at` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '请求时间',
`created_by` BIGINT NULL COMMENT '创建人',
PRIMARY KEY (`id`),
FOREIGN KEY (`user_id`) REFERENCES `user`(`id`) ON DELETE CASCADE,
FOREIGN KEY (`session_id`) REFERENCES `ai_chat_sessions`(`id`) ON DELETE CASCADE,
FOREIGN KEY (`ai_provider_id`) REFERENCES `ai_providers`(`id`) ON DELETE CASCADE
);
根据上面业务需求和逻辑,考虑对它是否做优化。
答:
非常好,我们继续处理这一张重要的表:
ai_usage_logs
是记录每一次 AI 请求调用的详细日志,包括:
请求内容
返回内容
模型信息
token 使用
成本统计
这张表将成为你未来做 成本追踪、使用量审计、性能统计、异常监控 的关键支撑。
✅ 现有结构快速审视
CREATE TABLE `ai_usage_logs` ( `id` BIGINT NOT NULL AUTO_INCREMENT, `user_id` INT UNSIGNED NOT NULL, `session_id` BIGINT NOT NULL, `ai_provider_id` BIGINT NOT NULL, `request_text` TEXT NOT NULL, `response_text` TEXT, `tokens_used` INT DEFAULT 0, `cost_usd` DECIMAL(10,5) DEFAULT 0.00000, `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP, `created_by` BIGINT NULL, PRIMARY KEY (`id`) );
✅ 对照你当前系统设计的优化点
优化维度 | 建议调整 | 理由 |
---|---|---|
✅ session_id 关联的是 ai_chat_sessions.id 而不是字符串 | 保留 | 设计合理,外键结构 |
❌ 没有 org_id | ✅ 建议新增 | 用于企业维度统计(哪个企业花了多少钱) |
❌ tokens_used 只记录总数 | ✅ 拆分为 request_tokens + response_tokens | 与 ai_messages 对应,便于细分分析 |
❌ 没有 project_id / report_id | ✅ 可选新增 | 支持项目维度AI成本分析(如报告调用成本) |
✅ 保留 request/response 文本 | 视为冷日志 | 仅用于调试/审计,可设存储清理策略 |
✅ cost_usd 保留为单次请求费用 | 合理 | 可累加汇总 |
✅ 字段优化建议总结
🔧 建议新增字段:
ADD COLUMN `org_id` BIGINT DEFAULT NULL COMMENT '所属企业ID',ADD COLUMN `project_id` BIGINT DEFAULT NULL COMMENT '项目ID(用于成本分摊)',ADD COLUMN `report_id` BIGINT DEFAULT NULL COMMENT '报告ID',ADD COLUMN `request_tokens` INT DEFAULT 0 COMMENT '提问token数',ADD COLUMN `response_tokens` INT DEFAULT 0 COMMENT '回答token数';
✅ 字段最终说明
字段名 | 说明 |
---|---|
org_id | 所属企业,支持企业用量统计 |
request_tokens / response_tokens | 请求与回应分别使用了多少 token |
tokens_used (可保留) | 冗余字段,为 request + response 总和 |
project_id / report_id | 支持分析哪类业务消耗最多 AI 成本 |
request_text / response_text | 可设策略“只保存最近N条”或压缩入冷存储表 |
✅ 建表语句(升级版):
CREATE TABLE `ai_usage_logs` ( `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID', `user_id` BIGINT NOT NULL COMMENT '用户ID', `org_id` BIGINT DEFAULT NULL COMMENT '所属企业ID', `session_id` BIGINT NOT NULL COMMENT '会话ID', `ai_provider_id` BIGINT NOT NULL COMMENT '调用的 AI 接口 ID', `project_id` BIGINT DEFAULT NULL COMMENT '项目ID', `report_id` BIGINT DEFAULT NULL COMMENT '报告ID', `request_text` TEXT NOT NULL COMMENT '请求的内容', `response_text` TEXT COMMENT 'AI 返回的内容', `request_tokens` INT DEFAULT 0 COMMENT '问题部分使用的token', `response_tokens` INT DEFAULT 0 COMMENT '回答部分使用的token', `tokens_used` INT GENERATED ALWAYS AS (`request_tokens` + `response_tokens`) STORED COMMENT '合计token数', `cost_usd` DECIMAL(10,5) DEFAULT 0.00000 COMMENT '本次请求成本(美元)', `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '请求时间', `created_by` BIGINT NULL COMMENT '创建人', PRIMARY KEY (`id`), FOREIGN KEY (`user_id`) REFERENCES `user`(`id`) ON DELETE CASCADE, FOREIGN KEY (`session_id`) REFERENCES `ai_chat_sessions`(`id`) ON DELETE CASCADE, FOREIGN KEY (`ai_provider_id`) REFERENCES `ai_providers`(`id`) ON DELETE CASCADE );
注意:
tokens_used
可以定义为生成列(或由程序计算并写入)。
✅ 是否保留 request/response 内容?
建议视你部署环境策略:
策略 | 说明 |
---|---|
保留全部 | 用于模型调优、内容安全审查 |
仅保留摘要 | 可存哈希、摘要字段 |
定期转移 | 转入冷表 ai_usage_logs_archive ,主表保持轻量 |
是否接受这张优化后的结构?确认后我们继续进入下一张表。你可以告诉我哪个是下一个。
问:
继续升级优化以下表:
-- 9.ai_user_token_usage(用户 Token 总消耗表)
-- 作用: 记录 用户在不同 AI 提供商的总 Token 消耗,避免查询时重复计算。
-- 每个用户在每个 AI 提供商下 只占 一条记录。
-- 避免查询时扫描 ai_usage_logs,提高效率。
-- 实时更新 total_tokens_used,保证 Token 统计准确。
CREATE TABLE `ai_user_token_usage` (
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`user_id` INT UNSIGNED NOT NULL COMMENT '用户ID',
`ai_provider_id` BIGINT NOT NULL COMMENT 'AI 提供商 ID',
`total_tokens_used` BIGINT DEFAULT 0 COMMENT '累计消耗的 Token 数',
`total_cost_usd` DECIMAL(10,5) DEFAULT 0.00000 COMMENT '累计消耗的成本(美元)',
`updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后更新日期',
`created_at` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (`id`),
UNIQUE KEY `user_ai_provider` (`user_id`, `ai_provider_id`),
FOREIGN KEY (`user_id`) REFERENCES `user`(`id`) ON DELETE CASCADE,
FOREIGN KEY (`ai_provider_id`) REFERENCES `ai_providers`(`id`) ON DELETE CASCADE
);
答:
太好了,这张表 ai_user_token_usage
是你整个系统中非常关键的性能优化表,它的作用类似于一个累积缓存表(Materialized Aggregation),为快速统计用户Token消耗总量而设计。
我们这一步的目标是——优化它,使其支持多维统计、对账、预警、扩展计费维度。
✅ 表当前定位与用途回顾:
维度 | 说明 |
---|---|
粒度 | 每个用户 × 每个模型(ai_provider)一条记录 |
用途 | 避免频繁 SUM() 查询 usage_logs,快速获取用户累计消耗情况 |
更新方式 | 实时更新/定期更新,由后台任务或触发器 |
✅ 当前字段结构审视:
字段 | 用途 | 是否合理 | 是否需优化 |
---|---|---|---|
user_id , ai_provider_id | 用户 + 模型 | ✅ | 可保留 |
total_tokens_used | 累计Token使用量 | ✅ | 可保留 |
total_cost_usd | 累计美元成本 | ✅ | 可保留 |
updated_at / created_at | 时间追踪 | ✅ | 可保留 |
🧠 结合当前系统的业务需求,存在以下优化空间:
维度 | 问题 | 优化建议 |
---|---|---|
企业统计 | 无 org_id ,无法统计企业整体token消耗 | ✅ 添加 org_id |
时间段分析 | 不支持“月度”或“周期性”维度统计 | ✅ 可扩展为周期分表 / 增加 period_start 和 period_end |
报告/项目归属 | 若要对某项目下AI使用量分摊 | 🟡 不推荐放进本表(太细),可考虑单独维度表 |
限额管理 | 若需预警/限制 | ✅ 可加字段 token_limit , cost_limit_usd (仅做提示) |
✅ 升级后字段设计建议:
CREATE TABLE `ai_user_token_usage` ( `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID', `user_id` BIGINT NOT NULL COMMENT '用户ID', `org_id` BIGINT DEFAULT NULL COMMENT '所属企业ID', `ai_provider_id` BIGINT NOT NULL COMMENT 'AI 提供商 ID', `total_tokens_used` BIGINT DEFAULT 0 COMMENT '累计使用的 Token 数', `total_cost_usd` DECIMAL(10,5) DEFAULT 0.00000 COMMENT '累计成本(美元)', `token_limit` BIGINT DEFAULT NULL COMMENT 'Token使用上限(可用于预警)', `cost_limit_usd` DECIMAL(10,5) DEFAULT NULL COMMENT '费用上限(美元)', `updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后更新时间', `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', PRIMARY KEY (`id`), UNIQUE KEY `user_ai_provider` (`user_id`, `ai_provider_id`), FOREIGN KEY (`user_id`) REFERENCES `user`(`id`) ON DELETE CASCADE, FOREIGN KEY (`ai_provider_id`) REFERENCES `ai_providers`(`id`) ON DELETE CASCADE );
✅ 字段解释重点:
字段名 | 说明 |
---|---|
org_id | 企业维度支持(支持多租户下用户合并统计) |
token_limit / cost_limit_usd | 可配合后续“用户使用额度预警”机制 |
updated_at | 实时追踪,后台任务每次增量更新 |
✅ 拓展建议:是否需要“周期性聚合”?
如果你希望支持:
每月用量统计
按周或按日做用量对账
则建议平行设计一个:
ai_user_token_usage_periodic
包含字段如:
user_id
,org_id
,ai_provider_id
period_start
,period_end
total_tokens
,total_cost
✅ 总结建议
项目 | 建议 |
---|---|
✅ 保留原结构主逻辑 | 用户×AI模型的Token与成本统计 |
✅ 增加 org_id | 支持多企业查询与隔离 |
✅ 增加 limit 字段 | 支持额度控制、预警策略 |
🟡 可选增加周期表 | 若涉及对账或审计则建议追加 |
是否接受这版结构?确认后我继续处理下一张表,或等你指定具体表名。
(待续)
发表评论: