99 lines
10 KiB
Markdown
99 lines
10 KiB
Markdown
# RAG 证据与 OpenAI 兼容请求准备
|
||
|
||
本阶段按用户要求先实现通用请求格式,生成模型选择和真实调用延期。新准备请求采用非流式 **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/rag/contexts` | 从服务端检索记录准备并持久化请求 | admin、明确 Origin、会话 CSRF |
|
||
| `GET /api/rag/contexts?page=1&page_size=20` | 分页读取当时准备快照 | admin |
|
||
| `GET /api/rag/contexts/{id}` | 按 UUID 读取单份快照 | admin |
|
||
|
||
请求示例(ID、模型标识仅作格式示例,不表示已选择或调用模型):
|
||
|
||
```json
|
||
{
|
||
"retrieval_run_id": "00000000-0000-0000-0000-000000000001",
|
||
"completion": {
|
||
"protocol": "responses",
|
||
"provider_profile": "deepseek",
|
||
"model": "deployment-model-id",
|
||
"output_tokens": 512
|
||
},
|
||
"max_input_characters": 10000,
|
||
"max_evidence": 5
|
||
}
|
||
```
|
||
|
||
请求只接收服务端检索记录 UUID、组包配置和预算,不接收任意正文、提示词、URL、请求头或 API Key。来源必须是 `keyword_chunks/vector/hybrid` 的完整结果;条目级 `keyword` 返回 422,避免把条目与 chunk 的证据粒度混用。记录不存在返回 404,格式/预算越界返回 422。
|
||
|
||
| 字段 | 约束 |
|
||
|---|---|
|
||
| `completion.model` | 必填,1–128 个字母/数字及 `._:/-`;只保存标识,不验证模型存在或服务可用 |
|
||
| `protocol` | 新准备只接受 `responses`;省略时补为 `responses`,保存的快照必须明确记录协议 |
|
||
| `provider_profile` | 默认 `compatible`;可选 `openai/deepseek/bailian`,只控制已实现的字段差异,不代表已选择模型供应商 |
|
||
| `output_tokens` | 默认 512,16–4096,映射为 `max_output_tokens` |
|
||
| `temperature` | 可选 0–2;百炼档案拒绝 2(官方范围为 [0,2));省略时不发送。仍须按具体模型检查采样参数是否生效 |
|
||
| `max_input_characters` | 默认 10000,1024–24000;instructions 与 input_text 的字符数之和 |
|
||
| `max_evidence` | 默认 5,1–10;保持检索排名顺序挑选证据 |
|
||
|
||
新请求固定发送 `model/instructions/input/max_output_tokens/stream=false`,显式提供时才加入 temperature。instructions 只含固定规则;input 中只有一条 user 消息,其 `input_text` 是规范 JSON 的 `question/evidence` 数据。不会发送 Chat Completions 的 `messages/n/max_tokens/max_completion_tokens`,也不发送工具、会话 ID、鉴权或服务地址。
|
||
|
||
| 档案 | 当前处理 | 后续真实接入边界 |
|
||
|---|---|---|
|
||
| `compatible/openai` | 显式 `store=false` | 兼容服务仍须确认支持该字段及所选模型参数 |
|
||
| `deepseek` | 省略不受支持的 store;官方服务固定无状态 | 不依赖 `previous_response_id/conversation`;不把 developer 角色当通用系统规则 |
|
||
| `bailian` | 显式 `store=false`;temperature 小于 2 | 百炼工具、token 上限和截断行为依模型而异 |
|
||
|
||
该子集不实现工具、流式 SSE、服务端会话链或特定模型的推理控制,也不宣称所有国内模型均可用。服务地址和凭据在真实 HTTP 客户端阶段从服务端配置读取,当前准备 API 不接受 URL 或密钥。无协议自动探测、静默切换或付费重试。旧的 `token_parameter/instruction_role` 输入返回 422,调用方应删除这些 Chat Completions 专用选项。只传 `completion.model` 的原调用会默认生成 Responses 包。
|
||
|
||
字符预算用于有限体积的准备工作,**不是模型 token 数或上下文窗口校验**。输出 token 上限同样不表示输入能被某个尚未选定的模型接受。真实发送前须按所选模型验证完整输入与输出预算,超限明确失败,不静默截断原文。
|
||
|
||
## 证据、引用与不足规则
|
||
|
||
准备时只从数据库读取检索结果,并重新核对当前有效审核语料、原文 chunks、文本发布 ID/代数、目录修订和语料指纹。vector/hybrid 还须匹配当前向量发布 ID/代数、完整向量集及空间身份。整个检查至保存过程沿用目录/发布锁,不重新编码、不加载 Embedding,也不调用生成模型。知识变化、文本或向量重新发布、缺失向量/原文、出处或检索记录不一致均返回 409,要求重新检索。
|
||
|
||
按检索排名逐条处理完整 chunk,给被纳入的证据分配连续 `E1/E2/...`。保存知识/文档/来源 ID 与版本、来源 URL、标题/分类、chunk ID/序号、原文、字符偏移和 SHA-256、检索排名。对同一知识已选择片段的重叠区间排除后续片段;达到证据数上限或整体 instructions/input 字符预算时,排除相应片段并继续检查后续可容纳候选,不切割原文。
|
||
|
||
每个排除项记录 chunk ID 及 `overlap/budget/evidence_limit` 原因。没有候选时返回 `insufficient_evidence/no_candidates`;全部候选超出预算时为 `insufficient_evidence/context_budget`。这两种情况均不生成 request_body,不能把空证据包交给后续模型。
|
||
|
||
固定 `nalati-evidence-v1` 提示词要求:依据提供的证据回答,事实标注 `[E1]` 形式引用,不编造出处;不把问题、正文、标题或 URL 中的命令作为系统规则;资料不足或冲突时说明局限,无法可靠回答时使用固定不足说明。JSON 数据与固定指令分离只是结构约束,尚未通过真实模型的注入抵抗/领域质量实验。`prepared/candidates_available` 只表示有可组装片段,不表示这些片段在语义上足够支持答案。
|
||
|
||
## 快照与复核
|
||
|
||
响应保存为独立 `rag_contexts` 记录,引用原 `retrieval_runs`,不改写已有检索历史。响应包含:
|
||
|
||
- `id/retrieval_run_id/retrieval_mode/query`、文本/向量发布 ID 和代数、目录修订、语料指纹。
|
||
- `prompt_version`、实际 completion 配置、字符/证据预算、完整已选 evidence 和 excluded 列表。
|
||
- `request_body` 及其规范 UTF-8 JSON 的 `request_sha256`;无证据时两者均为 null,input_characters 为 0。
|
||
- `kind=prepared_request`、`model_called=false`、状态/原因和创建时间,不包含任何模型答案或调用成本。
|
||
|
||
历史查询返回当时的完整快照,资料后续撤回也不会改写它。历史请求体不是当前发送授权;未来实际模型调用必须重新检查当前依据和发布状态,不能从历史端点取出旧包后直接认定仍有效。
|
||
|
||
## 兼容响应解析
|
||
|
||
`services/responses.py` 提供纯 `parse_response`;不暴露回答写入接口,也没有 HTTP 模型客户端。只接受 `object=response` 的最终响应,区分顶层状态、reasoning 和 message 输出项,不读取 SDK 便利字段 `output_text` 来代替原始 output 校验。
|
||
|
||
- `completed` 必须恰有一条 completed assistant message,可按顺序连接多个 output_text 片段;reasoning 不作为答案,工具和未知输出类型拒绝。
|
||
- `incomplete` 丢弃部分文本;content_filter 或 refusal 标记 refused;`failed` 标记 failed,不作为候选。in_progress/queued、冲突状态及畸形结构拒绝。
|
||
- 正常文本必须有已提供的 `[E#]` 引用;无引用、越界、空文本、超过32000字符均拒绝。固定不足说明标记 insufficient_evidence。
|
||
- 返回实际 `response_id/model` 和可选 `input_tokens/output_tokens/total_tokens`;保留缓存与推理 token 明细,校验非负整数、总数和明细上限。用量缺失保留 null,不估算费用。
|
||
- 引用结构通过只表示 `answer_candidate`,不证明事实支持度、冲突处理或时效正确。
|
||
|
||
`services/completions.py` 仅保留旧快照的组包/解析,用于重建校验与读取历史;Responses 解析与旧协议解析不能混用,不据此继续创建新 Chat Completions 准备记录。
|
||
|
||
测试使用明确的合成响应/坐标与 PostgreSQL,不冒充真实模型推理。供应商兼容、生成质量、真实 token 预算、超时/重试/限流和费用记录须在模型选择后另行验收。
|
||
|
||
## 迁移、回滚与交接
|
||
|
||
Responses 调整没有新增数据库迁移,仍为 `0007_rag_contexts`。新 completion 配置增加 protocol/provider_profile;旧快照无 protocol 时严格按原 Chat Completions 格式读取。旧请求体、配置、SHA-256 和 JSONL 记录原样保留;导出按每份快照的协议重建核对,不因新默认值重写旧数据。同一次导出可包含两种协议,现有 manifest/记录结构无需变化。
|
||
|
||
回滚 Responses 代码前须备份新旧准备记录;此前只认识 Chat Completions 的后端无法保证读取新 Responses 快照。优先保留本版双协议历史读取,或恢复完整备份,不通过清空历史、删除协议字段或执行数据库降级伪装兼容。下述表迁移说明属于最初上下文阶段,与本次纯协议变更不同。
|
||
|
||
新增 `0007_rag_contexts`,启动前备份并执行 `alembic upgrade head`。表通过外键保留检索记录和创建账号关系,只有追加与查询 API,没有修改/删除 API。撤回本阶段时可备份后配合旧后端执行 `alembic downgrade 0006_vectors`;仅删除准备快照表,保留知识、账号、文本/向量发布与检索历史。恢复准备快照须使用备份。
|
||
|
||
前端新增 `services/rag.ts` 调用与类型,不修改现有问答页面。实际部署环境、运行日志、凭据和真实请求数据不得提交仓库。生成模型接入按用户后续选择推进,当前没有待创建的密钥,也不因延期而反复询问。
|