智愿通

面向高考志愿咨询的智能决策 Agent 练习项目。把「录取事实查询」和「政策资料检索」放在同一条工作流里,由规则代码负责冲稳保分层与事实校验,大模型负责理解问题和组织语言。目前仍在学习中。

项目背景

高考志愿填报是个典型的高利害问答场景——用户问的「我这个分能不能上」必须给出有依据的答案,记错一个位次就可能误导一个真实的决策。同时,它的问题形态还很不统一:有人要查具体的录取数据,有人问政策概念,有人问某个专业怎么样。

这个项目想验证一件事:面对高风险事实型问答,怎么让大模型「有依据地说话」。核心思路是把职责拆开——

它也是我用来深入理解 Agent 编排、检索质量与评测体系的练习场。

技术栈

层次技术选型承担的角色
语言Python 3.13—
工作流LangGraph主图 + 子图、条件分支、断点中断、PostgreSQL Checkpointer
存储PostgreSQL 17 + pgvector结构化表 / 向量 / 全文索引 / 画像 / 会话状态同一个库
对话模型Qwen 系列意图理解与最终回答组织
嵌入text-embedding-v4(1024 维)子块向量化
中文检索jieba 预分词 + 领域词典解决 PG 原生全文检索不切中文词的问题
后端FastAPI + SSE接口服务与流式事件推送
前端React + Vite会话工作台
评测pytest + 自实现忠实度评测检索消融、忠实度与引用准确率

架构:两条查询链路

用户自然语言
├─ 结构化链路:模型抽条件 → 代码校验 → 参数化 SQL → 冲稳保规则打标签
└─ 检索链路:  pgvector 稠密 + tsvector 稀疏 → RRF 融合 → 回取父块
                    ↓
              统一证据上下文 → 最终模型组织回答 → 事实与来源校验 → SSE 返回

几个关键设计决定

不让模型写 SQL

模型只负责抽取结构化条件,SQL 由固定逻辑生成、参数化传值、条件受白名单约束。原因很直接:这是「够不够分」这类高利害问题,模型写错 SQL 不会报错,只会静默给出错误答案。

混合检索而不是纯向量

纯向量检索对高校名、专业名这类专名会漂移,纯关键词检索又扛不住口语改写。两路分数不是一个量纲,所以只融合排名——用 RRF。Recall@1 从 0.9231 提到 0.9487,提升集中在 Top-1,也就是最影响推荐结果的位置。

单库而不是多库

结构化表、向量、全文索引、画像、会话状态都放在一个 PostgreSQL 里。当前数据规模用 pgvector 完全够,单库能让这些数据共享事务与连接池,减少一致性问题。

先校验再展示

为避免「错误数字先展示、随后整段回退」这种比慢更伤体验的情况,采用的是先生成完整回答、校验通过、再分片发送。用户看到的是逐段呈现,但它不是模型首 token 实时流式——这是事实准确性与响应体验之间的取舍。

在幻觉治理上做的事

手段说明
来源严格匹配不取文件名后缀,走全路径匹配,避免错误归因
冲稳保确定性校验标签由代码依据位次规则计算,模型只解释不改写
事实保护结构化结果进入最终模型后,再做一遍事实一致性校验
忠实度评测自实现,评判回答断言是否被本轮检索上下文支持
评测指纹报告记录题集与被测代码哈希,不一致则强制全量重跑

当前状态

这是一个本地练习项目,仍在学习中。数据覆盖范围有限,功能在持续完善,没有对外提供服务,也不作为成熟产品对外运营。文中的技术选型与实测数据,来自我在练习过程中真实跑过的实验。

相关笔记:为什么纯向量检索不够用 · 38 个单测全绿,功能一次都没触发过 · 评测工具比业务代码更危险

← 返回首页