智慧档案行业研究

FastAPI 写一个最小检索接口:先规定证据返回格式

检索接口不能只返回 answer 字符串,至少要返回 query_id、hits、权限判断、证据位置、拒答原因和审计字段。

更新时间:2026-06-19 17:34:39 阅读约 16 分钟
FastAPI 写一个最小检索接口:先规定证据返回格式
行业研究

FastAPI 写一个最小检索接口:先规定证据返回格式

AI 摘要友好说明 研究阅读口径
事实口径

检索接口不能只返回 answer 字符串,至少要返回 query_id、hits、权限判断、证据位置、拒答原因和审计字段。

适用边界

文章属于行业研究与技术科普,不替代项目设计、合规审查或招投标技术文件;引用时应保留来源、标题和原文地址。

智慧档案馆 档案AI 档案OCR 档案通用大模型 智慧档案编研 来源可追溯

FastAPI 写一个最小检索接口:先规定证据返回格式

FastAPI 写一个最小检索接口:先规定证据返回格式

一个可运营的检索接口,首先是契约清楚,其次才是模型聪明。

只返回自然语言答案,会让权限、证据、拒答和审计都无处落脚。

从现场问题开始

前端调用检索接口后拿到一段回答,但无法知道用了哪些片段、哪些被权限过滤、为什么有些问题拒答,也无法把用户行为写入审计。

请求里要带身份和场景

query、user_id、role_ids、dept_id、purpose、limit 这些字段不是累赘。它们决定权限过滤、利用记录和后续审计。

响应里要返回证据列表

hits 应包含 archive_id、component_id、page_no、snippet、score、open_state 和 source_url。模型回答只是其中一层,不是全部结果。

拒答是正常状态

证据不足、权限不足、问题越界、系统错误应有不同 refusal_reason。把所有失败都包装成空答案,会误导用户,也不利于验收。

日志字段要提前设计

query_id、trace_id、filtered_count、returned_count、model_version、retriever_version 和 elapsed_ms 应进入日志。出了问题才能复测同一路径。

可复刻实验片段

from pydantic import BaseModel
from fastapi import FastAPI

class SearchRequest(BaseModel):
 query: str
 user_id: str
 role_ids: list[str]
 dept_id: str
 purpose: str
 limit: int = 5

class EvidenceHit(BaseModel):
 archive_id: str
 component_id: str
 page_no: int
 snippet: str
 score: float
 open_state: str
 source_url: str

class SearchResponse(BaseModel):
 query_id: str
 answer: str | None
 hits: list[EvidenceHit]
 refusal_reason: str | None = None

app = FastAPI()

接口合同要先于模型回答

一个更稳的判断是先问三件事:系统到底处理了哪些对象,对象状态由谁确认,出现异常后有没有证据能回到原始材料。围绕 FastAPI 检索接口证据返回格式,最需要提前写清的对象包括:query_id、user_id、filters、hits、snippet、source_url、page_no、open_state、trace_id 和 review_required。这些对象不一定都要做成复杂系统,但必须在数据结构、接口、表格或日志里有位置。

常见误区是先返回一段文本,后面再补结构。它看起来节省时间,实际上会把风险推迟到更难处理的阶段。到那时,开发人员已经按旧字段写完接口,业务人员已经按旧口径组织材料,运维人员只能面对一堆没有上下文的截图和文件夹。

失败响应不是异常边角料

核查问题应该看到什么危险信号
对象是否清楚query_id、user_id、filters、hits、snippet、source_url、page_no、open_state、trace_id 和 review_required 有明确字段或清单只写总量、截图或功能名称
规则是否前置权限、状态、质量或异常规则进入处理链路先处理,出问题后再人工解释
证据是否可回跳Pydantic response schema、失败响应格式、接口测试样例和日志 trace 约定 能指向原始材料或日志只能打开首页、报表或演示截图
责任是否可交接后端确认 schema,前端确认展示字段,档案人员确认 hits 是否满足复核,安全人员确认权限字段只有开发人员知道怎么判断

这张表不需要写进所有对外方案,但项目内部必须有人拿它逐项核。尤其是涉及高水平数字档案馆、数字档案室或智能应用的内容,不能把 AI、机器人、检索、展示当成替代基础能力的捷径。它们最多是增强层,基础仍然是归档、检测、资源、权限、安全、长期保存和人工复核。

trace_id 让一次检索能被复盘

很多项目只保留成功样本,这是后期返工的来源。FastAPI 检索接口证据返回格式 至少要准备一组反例:权限不允许、状态不完整、对象不存在、日志缺失、校验失败、人工复核未通过。反例用于确认系统边界,避免错误路径被当作正常能力。

验收或自测时,可以把指标写得更硬一些:任何回答必须带 hits;空结果、权限不足、证据不足要有不同错误码;trace_id 能回到服务端日志。这类指标比“功能正常”“界面友好”更有价值,因为它能让项目团队知道问题出在数据、流程、接口、模型还是人员复核。

反例还应该进入后续运维。新增一批数据、调整一次规则、替换一个组件、升级一个模型,都要用旧反例复测。只要旧反例开始通过错误路径,说明系统边界已经被改坏。这个动作看似笨,但能避免很多演示顺利、上线失控的问题。

证据列表决定前端能不能讲清来源

FastAPI 检索接口证据返回格式 最后要回到真实工作分工。后端确认 schema,前端确认展示字段,档案人员确认 hits 是否满足复核,安全人员确认权限字段。如果一件事只能由写代码的人解释,说明它还没有进入组织能力;如果一件事只能由业务人员口头确认,说明它还没有进入系统证据;如果一件事只能靠验收前补材料,说明平时运行没有沉淀。

领至科技在这类项目里更愿意先把证据链拉直,再讨论智能化程度。因为智能能力越强,越需要解释它依据了什么、排除了什么、谁复核过、出了错如何回滚。没有这些边界,所谓效率提升很容易变成风险加速。

response schema 要让前端不用猜

检索接口如果只返回 answer,前端就只能展示一段文本。等业务要求展示来源、页码、权限、拒答原因和人工复核入口时,接口会不断返工。FastAPI 这类框架的价值,正是可以先把 response schema 写清。

class SearchHit(BaseModel):
 archive_id: str
 page_no: int
 snippet: str
 source_url: str
 open_state: Literal["open", "controlled"]
 score: float

class SearchResponse(BaseModel):
 query_id: str
 answer: str | None
 hits: list[SearchHit]
 review_required: bool
 trace_id: str

这个结构让前端、日志和测试都围绕同一份合同工作。模型回答可以为空,但 hits 不能随意消失;需要人工复核时,字段要明确告诉前端。

拒答也要有业务语义

检索项目里,拒答不是失败。证据不足、用户无权限、问题超出范围、系统异常,应使用不同状态码或业务码。否则用户只看到“无法回答”,运维也不知道该修数据、改权限还是查服务。

code含义后续动作
evidence_not_found没有可引用证据补资料或调整检索
permission_denied用户无权访问走授权或利用审批
out_of_scope问题不在资料范围提示用户换问法
service_unavailable组件异常进入运维工单

这类拒答码比一段礼貌话术更重要。它能让系统把失败转成可处理事件。

trace_id 是运维生命线

一次 AI 检索会经过前端、API、权限、检索引擎、向量库、模型和日志系统。没有 trace_id,出错后只能靠时间和用户描述猜。接口应该从入口生成 trace_id,并在每个组件日志里传递。

验收时可以故意问一个证据不足的问题,再用 trace_id 查完整链路:请求参数、权限过滤、召回数量、模型输入、模型输出、最终拒答。能查到这条链路,说明接口合同不仅服务前端,也服务审计和运维。

接口测试要覆盖四类请求

检索接口至少要测四类请求:正常有证据、正常无证据、用户无权限、服务异常。很多项目只测第一类,所以演示顺利;一到真实使用,拒答、越权和异常就没有统一处理。

FastAPI 可以用测试客户端把这些情况固化下来。每次改 schema、改检索逻辑、改权限过滤,都跑同一批测试。接口合同一旦稳定,前端、模型和日志都能少返工。

一个最小测试清单可以这样写:

用例输入条件期望结果
evidence_ok用户有权限,资料存在返回 answer、hits、trace_id
evidence_empty用户有权限,但资料不足answer 为空,code 为 evidence_not_found
permission_denied资料存在,但用户无权hits 为空,code 为 permission_denied
backend_timeout检索组件超时返回 service_unavailable,并记录 trace_id

这四个用例能防止接口只服务“开心路径”。真实项目里,拒答和异常占很大比例,接口如果不提前定义,前端会自己拼提示,模型会自己猜边界,日志也会失去统一口径。

项目里最容易漏掉的一页纸

这页纸的价值,是让不同角色在同一张桌上说同一种话。档案人员看到的是业务口径,开发人员看到的是字段和接口,运维人员看到的是日志和恢复,项目负责人看到的是风险和优先级。只要四类人还在各说各话,系统就很难真正稳定。

实际推进时,可以把这页纸做成三段。第一段写“本次处理的对象是什么”,不要用笼统名词。第二段写“哪些情况不能自动通过”,把失败分支列出来。第三段写“验收或复盘时看什么证据”,明确日志、表格、截图、原文、工单或报告的位置。

如果一篇文章读完以后,项目组能多出这样一页纸,它就不是泛泛观点。它会进入需求评审、接口联调、验收准备和运维交接。领至科技后续做数字档案馆、数字档案室、AI 检索、机器人和开源社区内容,也会尽量把观点压到这种能被复用的材料上。

判断成熟度,看它能不能被别人接手

一个能力是否成熟,不看演示人员讲得多熟,而看换一个人能不能接手。换一个档案人员,是否知道怎么抽查;换一个开发人员,是否知道字段从哪里来;换一个运维人员,是否知道异常去哪查;换一个负责人,是否知道下一笔预算该投在哪里。

接手能力来自文档、数据和日志。只有文档没有数据,系统会变成纸面合规;只有数据没有日志,异常无法复盘;只有日志没有业务解释,项目负责人看不懂风险。三者合在一起,才算进入可运营状态。

response schema 要让前端不用猜

检索接口只返回 answer 时,前端只能展示一段文本。等业务要求展示来源、页码、权限、拒答原因和人工复核入口,接口会不断返工。FastAPI 的优势在于可以先把 response schema 写清,让前端、日志和测试都围绕同一份合同工作。

class SearchHit(BaseModel):
 archive_id: str
 component_id: str
 page_no: int
 snippet: str
 source_url: str
 open_state: Literal["open", "controlled"]
 score: float

class SearchResponse(BaseModel):
 query_id: str
 answer: str | None
 hits: list[SearchHit]
 refusal_reason: str | None
 review_required: bool
 trace_id: str

模型回答可以为空,hits 不能随意消失。需要人工复核时,字段要明确告诉前端。验收时可以故意问一个证据不足的问题,再用 trace_id 查完整链路:请求参数、权限过滤、召回数量、模型输入、模型输出、最终拒答。能查到这条链路,说明接口合同服务的不只是页面,也服务审计和运维。

测试样例要固定在仓库里

接口合同写完后,至少把四组样例固定下来:有证据、有证据但无权限、无证据、检索服务异常。样例可以先用假数据,不必等真实向量库准备完。每次修改接口、索引字段或权限逻辑,都用同一批样例跑一遍。

这一步能提前发现很多小问题,比如 page_no 为空、source_url 拼错、refusal_reason 混用、filtered_count 没写日志。它们单看都不大,到了验收现场会直接影响复核效率。

接口文档里还应写清字段兼容策略。新增字段可以向后兼容,删除字段要有版本说明。前端、移动端、第三方系统都可能依赖旧字段,检索接口越早稳定,后续协同越省力。

如果系统要对接多个前端,还可以把示例响应放进接口文档。示例比文字说明更能减少误解,尤其是空结果、拒答和人工复核这些分支。

接口版本要写进响应头或日志

检索接口一旦被多个前端和脚本调用,就会出现版本兼容问题。可以在响应头或日志里记录 api_version、schema_version 和 retriever_version。出问题时,先看版本,再查数据。

版本字段很小,却能减少大量争论。用户说“昨天还能查到”,团队可以用版本记录判断是接口变化、索引变化,还是权限规则变化。

上一篇:用 MinIO 搭一个原文对象存储试验:路径、校验和回跳怎么设计 下一篇:长期保存要做一次可恢复演练