【JchatMind智能体 | 第三天】数据模型设计
前言:
本项目非原创,我也是作为一名初学者跟着一起学习。项目来源于:代码随想录-知识星球。
代码随想录-知识星球
https://wx.zsxq.com/group/88511825151142
在知识星球里看到卡哥分享这个项目 ,感觉还不错,于是想要学习一下这个项目怎么写。项目日记也会同步更新。(本人不分享本项目源码,支持项目付费)
本文由我学习该项目并结合AI整理总结而来,分享出来学习过程中的心得体会,由浅入深,用于日后的回顾,同时也希望能给你带来帮助。
目录
【JchatMind智能体 | 第二天】为何选 PostgreSQL + pgvector 而非 MySQL?
https://blog.csdn.net/h52412224/article/details/159018355【JchatMind智能体 | 第一天】从最原始的大模型调用开始
https://blog.csdn.net/h52412224/article/details/158881257
三类核心数据:数据模型设计的基础
在开始设计具体的数据库表结构之前,有一个非常重要的前提需要先明确。在 Agent 系统中,所有需要长久保存的持久化数据,其实都可以归纳为三类,这也是整个数据模型设计的起点。
-
第一类是Agent与对话状态本身,这类数据主要描述两个核心问题:谁在和模型进行交互,以及这次对话目前推进到了哪一步。
-
第二类是对话过程中产生的各类消息记录,不仅包含用户的输入和模型的输出,还包括工具执行的结果,以及过程中产生的各种辅助元信息。
-
第三类是Agent需要按需查阅的系统知识,这些知识并不是模型本身自带的,而是需要通过 RAG 技术,在Agent执行任务需要相关背景支撑时,再提供给模型。
Agent 表:抽离固化 Agent 配置
在很多简单的 Agent 示例中,Agent 往往只是代码里定义的一个类,系统指令是直接写死在代码里的,它能使用哪些工具、访问哪些知识,也全都是由开发者在编码阶段约定好的。
但只要系统稍微复杂一点,这种硬编码的方式就会很快失控,后续想要修改 Agent 的配置,都需要改动代码、重新部署,灵活性特别差。
所以这套数据模型设计的第一步,就是把 Agent 本身从代码中抽离出来,将它转化为一条明确的数据库记录,实现配置和代码的解耦。
Agent 表其实只描述三类核心信息,且这些信息都属于长期稳定的配置,并非Agent运行时的动态状态数据:
-
基础标识:名称、描述,方便区分不同的Agent
-
行为基调:系统指令,决定Agent的行事风格和核心准则
-
能力边界:默认使用的模型、允许调用的工具、允许访问的知识库,以及温度、top_p这类聊天相关配置项
这样设计的好处很直观:后续创建新Agent、修改已有Agent配置、禁用闲置Agent,都不需要改动任何代码,直接操作数据库即可;同时系统在运行时,也能清晰知晓当前Agent的能力范围,避免出现越权操作。
CREATE TABLE agent (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name TEXT NOT NULL, -- Agent 名称
description TEXT, -- 描述(用户可见)
system_prompt TEXT, -- 系统指令
model TEXT, -- 默认使用的模型
allowed_tools JSONB, -- 允许使用的工具列表
allowed_kbs JSONB, -- 允许访问的知识库
chat_options JSONB, -- 其它配置项(温度、top_p、最大token)
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
Chat Session 表:对话的锚点与归属
一次完整的Agent对话是一个持续推进的过程,而非单次的请求响应。所以chat_session表本身不会承载太多复杂信息,它的核心作用就是一个锚点:
-
把本次对话和对应的Agent进行绑定
-
为后续对话中产生的所有消息、操作提供统一的归属
CREATE TABLE chat_session (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
agent_id UUID REFERENCES agent(id) ON DELETE SET NULL, -- 绑定的 Agent
title TEXT, -- 自动生成的标题
metadata JSONB, -- 扩展(例如输入语言、设备类型)
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
Chat Message 表:全流程语义追溯
这张表的设计思路看似简单,却是实现Agent记忆和流程追溯的关键:对话过程中出现的所有语义片段,都要做到可追溯、可还原。
不管是用户输入、模型输出、系统规则提示,还是工具执行的返回结果,它们在语义上扮演着不同角色,但在时间线上是连续衔接的。因此设计时无需区分聊天消息和系统消息,而是将其统一抽象为message,通过role字段区分不同的语义角色即可。
两个核心字段的作用:
-
content:存储模型真正能理解和处理的主体内容
-
metadata:存储不适合直接拼接进prompt,但对系统运行至关重要的结构化信息,比如工具调用参数、RAG检索命中内容、本次模型调用的专属配置等
基于这张表,系统能在任何时刻根据session_id筛选出对应消息,重新拼接出完整的对话上下文,Agent的记忆功能,正是基于这个逻辑实现的。
CREATE TABLE chat_message (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
session_id UUID NOT NULL REFERENCES chat_session(id) ON DELETE CASCADE,
role TEXT NOT NULL, -- user / assistant / system / tool
content TEXT, -- 主体内容
metadata JSONB, -- 工具调用、RAG 片段、模型参数等
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
Knowledge Base 表:划清模型与系统的知识边界
学习Agent系统时,很容易混淆一个点:哪些信息是模型本身自带的,哪些信息是系统需要额外提供的。而这套数据模型中,knowledge_base表的存在,就是为了清晰划清这条边界。
知识库中的内容,并非用来教会模型新知识、让它永久记忆,而是在Agent执行相关任务需要背景支撑时,通过RAG技术把相关背景信息临时提取出来,提供给模型作为参考。
简单来说,知识库代表的是系统的私有知识、专属知识,而非模型本身的记忆,任务执行完成后,模型并不会保留这些临时提供的知识库内容。
CREATE TABLE knowledge_base (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name TEXT NOT NULL,
description TEXT,
metadata JSONB, -- 业务属性,如行业/标签
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
Document 表:管理原始资料
document表并不直接为模型提供服务,它的核心职责是管理RAG的原始资料层,简单来说,就是记录一个文件的基础信息和处理信息,比如文件名称、格式、大小、来源,以及被解析的方式、页数等。
CREATE TABLE document (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
kb_id UUID NOT NULL REFERENCES knowledge_base(id) ON DELETE CASCADE,
filename TEXT NOT NULL,
filetype TEXT, -- pdf / md / txt 等
size BIGINT, -- 文件大小
metadata JSONB, -- 页数、上传方式、解析参数等
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
Chunk Bge M3 表:RAG 的核心载体
模型并不会直接阅读和处理完整的原始文档,在RAG流程中,模型能看到的永远是被切分后的、语义相对完整的小文本片段,chunk就是这些片段的核心载体。
每一条chunk记录都包含三类关键信息,缺一不可:
-
可读文本内容:可供模型读取和理解的核心信息,后续会拼接进prompt
-
向量表示:用于和用户查询内容做相似度计算,实现快速检索
-
来源元信息:标注片段来自哪个文档、哪一页、哪一个段落,方便溯源
这里有一个RAG设计的重要原则:向量只负责找,文本才负责看。也就是说,embedding向量的唯一作用是计算相似度,帮助系统快速找到相关文本片段,不会直接交给模型;真正拼接进prompt、为模型提供参考的,是chunk中的content文本内容。
表名后的bge_m3后缀,代表这张表中的向量是通过bge_m3模型生成的,该模型生成的向量为1024维,因此embedding字段的类型定义为VECTOR(1024)。同时为了提升向量检索的效率,需要给embedding字段创建专属索引。
CREATE TABLE chunk_bge_m3 (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
kb_id UUID NOT NULL REFERENCES knowledge_base(id) ON DELETE CASCADE,
doc_id UUID NOT NULL REFERENCES document(id) ON DELETE CASCADE,
content TEXT NOT NULL, -- 切片后的文本内容
metadata JSONB, -- 页码、段落号、chunk index 等
embedding VECTOR(1024) NOT NULL, -- bge_m3 模型是 1024 维的向量
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
-- 给向量加索引,提升检索效率
CREATE INDEX idx_chunk_embedding
ON chunk_bge_m3
USING ivfflat (embedding vector_l2_ops)
WITH (lists = 100);
总结
这次梳理Agent数据模型设计,对Agent工程化开发有了更具象的理解:
-
数据分类是基础,将Agent系统的持久化数据分为状态、消息、知识库三类,能让整个模型设计的逻辑更清晰,避免混乱。
-
核心表各司其职,每个表都有明确的定位和作用,Agent表固化配置、chat_session表锚定对话、chat_message表实现追溯、知识库相关表支撑RAG能力,相互配合形成完整的数据体系。
-
解耦是关键思路,把Agent配置从代码中抽离为数据库记录,让系统的可维护性和灵活性大幅提升,符合工程化开发的要求。
-
RAG设计有原则,遵循向量负责检索、文本负责供模型参考的原则,能让RAG的实现更高效、更贴合模型的处理逻辑。
上述内容也同步在我的飞书,欢迎访问
https://my.feishu.cn/wiki/QLauws6lWif1pnkhB8IcAvkhncc?from=from_copylink
如果我的内容对你有帮助,请点赞,评论,收藏。创作不易,你们的支持就是我坚持下去的动力!
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)