fix: validate retrieval-only chat questions before dispatch

This commit is contained in:
2026-10-17 12:17:52 +08:00
parent 1398938437
commit 4efcf83e4c
9 changed files with 217 additions and 16 deletions
+1 -1
View File
@@ -14,7 +14,7 @@ FastAPI + Pydantic
|-- 来源获取 -> 人工核验 -> 文本切分 -> 生成向量 -> 发布版本
```
当前后端实现健康/数据库就绪检查、来源与文档管理、知识增删改查、分页筛选、人工审核、历史快照、认证会话/角色权限、文本/向量快照及独立关键词/向量/RRF 检索;问答仍为占位接口。数据库由 Alembic 显式迁移并启用 pgvector,DeepSeek RAG 待明确恢复后实现。前端已接入登录/注册、个人中心、账户设置、会话恢复、路由守卫和角色菜单,以及来源、文档的创建、编辑、软删除、分页搜索与历史快照;实验页不伪造数据,知识审核与浏览器 Cookie/PostgreSQL 联调仍需验收。
当前后端实现健康/数据库就绪检查、来源与文档管理、知识增删改查、分页筛选、人工审核、历史快照、认证会话/角色权限、文本/向量快照及独立关键词/向量/RRF 检索;`/api/chat` 为独立条目关键词检索适配,返回检索状态与来源,不调用生成模型(见 [CHAT_API.md](CHAT_API.md))。数据库由 Alembic 显式迁移并启用 pgvector,DeepSeek RAG 待明确恢复后实现。前端已接入登录/注册、个人中心、账户设置、会话恢复、路由守卫和角色菜单,以及来源、文档的创建、编辑、软删除、分页搜索与历史快照;实验页不伪造数据,知识审核与浏览器 Cookie/PostgreSQL 联调仍需验收。
## 阶段 2 数据边界
+30
View File
@@ -0,0 +1,30 @@
# 检索式聊天接口
`POST /api/chat` 是已核验知识的条目级关键词检索适配,不调用生成模型。它与问答页面直接使用的 chunk/RRF 接口不同,也不会创建 Responses 准备快照。生成模型与真实服务接入继续延期。
## 请求
```json
{"question":"那拉提示例关键词"}
```
接口公开可用,无需登录;只接受 question。服务端去除首尾空白后校验1–500个字符,与底层 RetrievalRequest 共用同一字段约束;字符数不代表模型token数。缺失、空白、错误类型、超长输入或额外字段(包括 model、messages、凭据)均返回422,不写检索记录。只有停用词或标点、没有有效检索词时同样返回422。错误不包含原始输入值。
原适配曾允许2000字符,内层检索只允许500字符,导致501–2000字符请求返回500。现在该范围在HTTP入参处明确返回422,不截断问题,也不绕过原检索限制。
## 响应与证据
成功返回 answer、status、sources 和 retrieval_run_id。answer 为固定的检索状态说明,**不是生成式回答**。
- status=retrieval_only:返回最多5条来源预览(title/source_url),来自同一条目关键词检索历史的排名结果。说明中的命中总数可以大于来源预览数;完整排名、正文片段、来源/知识版本、配置、语料指纹和耗时保存在原检索记录中。
- status=no_evidence:没有命中的有效已核验依据,sources为空;仍保存该次真实无命中检索的run ID。
待审核、拒绝、软删除、来源/文档失效或修订后等待重新审核的条目不作为来源。资料修订影响后续请求,不重写已经保存的历史快照。没有LLM调用量、生成答案或费用字段,不能把固定说明用于领域质量评分。
检索历史及JSONL导出仍要求管理员权限;公开获取run ID不授予历史读取权限。该run的mode=keyword、证据粒度为knowledge_item,不能传入只接收chunk检索的 `POST /api/rag/contexts`。需要Responses准备时先使用chunks/vector/hybrid检索。
容量超限/数据库不可用保留503,历史保存约束冲突返回409;错误不会伪装成200无命中,也不会保存部分历史。仅成功完成检索与历史事务后返回来源。无额外数据库迁移。
## 验证边界
测试使用合成条目、真实隔离PostgreSQL和默认应用HTTP生命周期,覆盖500字符边界、501字符HTTP失败复现与修正、参数拒绝不写记录、公开调用与历史权限、审核筛选、资料修订/历史不变、容量与事务失败,以及进程重启后的历史和导出。没有模型调用或新增浏览器验收。
+1 -1
View File
@@ -2,7 +2,7 @@
本阶段按用户要求先实现通用请求格式,生成模型选择和真实调用延期。新准备请求采用非流式 **Responses API**(服务端点为 `<base_url>/responses`):`model/instructions/input/max_output_tokens`,从结构化 `output` 读取 assistant 文本。依据 [OpenAI Responses 迁移说明](https://developers.openai.com/api/docs/guides/migrate-to-responses)、[DeepSeek Responses 兼容表](https://api-docs.deepseek.com/guides/responses_api/) 与[百炼 Responses 文档](https://help.aliyun.com/zh/model-studio/qwen-api-via-openai-responses)。当前仍为纯组包和解析,不绑定实际服务地址、密钥或模型,不发出 HTTP 生成请求。
本阶段提供管理员上下文准备与历史接口、完整证据快照、固定提示词及纯响应解析器。`POST /api/chat` 仍保留原占位状态,尚未成为生成式问答接口;准备记录固定为 `kind=prepared_request, model_called=false`,不能作为实际模型回答、耗时、费用或领域实验结果。
本阶段提供管理员上下文准备与历史接口、完整证据快照、固定提示词及纯响应解析器。`POST /api/chat` 是独立的条目级关键词检索适配,返回检索状态和来源,尚未成为生成式问答接口(见 [CHAT_API.md](CHAT_API.md));准备记录固定为 `kind=prepared_request, model_called=false`,不能作为实际模型回答、耗时、费用或领域实验结果。
## 准备与读取
+10 -2
View File
@@ -11,9 +11,9 @@
| T05 | 知识库 | 设计 sources/documents/chunks/version 表 | 范涵宇 | 已完成(迁移、发布快照和接口已合入;待 Docker 联调) |
| T06 | 检索 | 实现关键词检索基线 | 范涵宇 | 已完成(已核验知识 BM25 与检索历史已合入) |
| T07 | 向量 | 评估 Embedding 并实现 pgvector | 范涵宇 | 已完成(本地模型、精确向量和 RRF 已合入;待真实领域评测) |
| T08 | RAG | 集成 LLM 与来源展示 | 范涵宇 | 协议基础已合入(Responses 请求/解析调整已在独立分支通过验证,待审;生成模型选型与实际调用延期) |
| T08 | RAG | 集成 LLM 与来源展示 | 范涵宇 | Responses 协议已合入(请求/解析与旧快照兼容已完成;生成模型选型与实际调用延期) |
| T09 | 实验 | 构建可核验问题集及评分规范 | 杨星萱 | 待办 |
| T10 | 工程 | 补充测试、Alembic、鉴权与部署 | 范涵宇(主)、全员 | 进行中(迁移、认证、CSRF、224项回归及浏览器核心流程已通过;Docker/HTTPS/部署待验收) |
| T10 | 工程 | 补充测试、Alembic、鉴权与部署 | 范涵宇(主)、全员 | 进行中(迁移、认证、CSRF及浏览器核心流程已通过;聊天边界修正和312项分支回归待审,Docker/HTTPS/部署待验收) |
## 2026-10-15 首次联调记录
@@ -126,3 +126,11 @@
- 本轮 `pytest -q backend/tests/test_rag.py backend/tests/test_exports.py` **113 passed**;完整 `pytest -q backend/tests` **294 passed, 1 skipped**。skip 为显式启用的真实 Embedding 专项,本轮不运行模型。ruff检查/格式检查及前端类型/生产构建通过;未修改页面交互,不宣称新增浏览器验收。
- PR #44 合入后同步最新 dev,保留两份阶段记录并解决本文件追加冲突。此次同步后重新执行前端时区6项、会话3项及类型/生产构建,均通过;backend树与此前294项回归时一致,本次未重复运行全量后端测试,也未新增模型调用或浏览器验收。
## 2026-10-17 T10:检索式聊天边界与后端验收
- PR #45 的 head/merge 均已核对进入 dev,再从最新 dev 创建 `fix/backend-chat-validation`。新合入 PR #46 已实现 `/api/chat` 的检索式适配,本轮补上后端边界修正和集成验收,不重复实现检索、不接入生成模型。
- 已复现501字符问题返回500:外层ChatRequest允许2000字符,内层RetrievalRequest只允许500字符。现在两者共用QueryText与输入规范,问题去首尾空白后1–500字符,超长/空白/错误类型/额外字段在HTTP边界返回422,不静默截断,也不写检索历史。
- 补充有效审核来源筛选、资料修订后重新审核、公开聊天/私有历史权限、历史与导出持久化、容量503及写入409完整回滚验证;真实HTTP重启后检索历史保持一致。Chat仅生成固定检索状态说明,条目级记录不能传给chunk级Responses准备。完整契约见 [CHAT_API.md](CHAT_API.md)。
- 专项 `pytest -q backend/tests/test_chat.py backend/tests/test_retrieval.py` **35 passed**;完整 `pytest -q backend/tests` **312 passed, 1 skipped**,skip为显式启用的真实Embedding专项,本轮未运行模型。ruff检查/格式检查、diff检查和最新前端类型/生产构建通过。API路径、响应字段和数据库迁移不变;README/架构文档更正已过期的聊天占位说明。无新增浏览器验收或领域分数。