Notes · 2025.09.20

空结果也是结果

问答接口联调。

1 min · rag · code

模型总想说点什么。问到一份你没权限看的制度,它仍能编出一段听起来像制度的话。企业场景里,说不出比乱说安全。Humanitelligence 的检索与问答接口联调,空结果、超时、权限提示都要核对。我是张恒基。成功问答是演示。空结果是产品。

空有好几种,不能共用一句「未找到」

检索没召回,是一种空。召回了但权限过滤后为零,是一种空。超时没等到向量服务,是一种空。输入本身空,又是一种。四种如果都回「未找到」,使用者无法决定下一步:改问法、去申请权限、等一等,还是别再点。下一步不同,文案就得不同。文案从接口字段来。字段没有,前端会编。前端一编,口径散。

我在 TextGuard 的 FastAPI 里写过超时和空输入。那边空的是不配打分的文本。这边空的是不能答的问题。不能答,要带着原因。原因短到能画在对话框里。长原因进日志。日志给联调用。使用者不看日志。不看的东西,不要指望它救人。救人的是页面上那一句人话。

权限提示尤其不能软。软了,人会以为库里没有。库里有、你看不见,和库里没有,业务含义相反。相反的含义用同一句,会把申请权限的流程掐死。掐死之后,他要么放弃,要么找人要一份导出。导出绕过系统,系统就白做。白做的 RAG,切片再细也没用。

乱说比空更贵

企业库里的错答,可能变成一次按错制度执行。执行比聊天机器人的幻觉贵。贵的场景下,低置信、无引用、权限不足,都该走空或走「需人工」。人工两个字不好看,比一段无引用的流畅段落安全。流畅是模型的本能。本能要在接口层拦住。拦不住,提示词里写「不要编」往往不够。不够的时候,用空。

我协助排查联调问题、同步接口变更,并回归内部查询路径。回归的意思是:改完错误码,把空、超时、权限、成功四条路径都点一遍。只点成功,演示能过,工单会在下午来。下午来的工单通常是权限。权限最不像 demo。demo 用的账号什么都看得见。什么都看得见的账号,测不出空。测不出空的发布,会在真用户那里第一次遇见空。第一次遇见如果表现为乱说,信任结束。

引用字段在空的时候也要有行为。没有引用,就不要假装有来源编号。假编号比假段落更像系统在说谎。说谎一次,业务方会改回自己搜 PDF。自己搜 PDF 是图谱和向量存在之前的世界。世界倒回去,评测表上的提升没有意义。

内部查询路径要能复现空

空如果只在生产出现、内部环境永远成功,联调是假的。假联调来自权限被放开、超时被加长、评测问题都选有答案的。有答案的问题该有。没有答案的问题也要进一套固定名单。名单上的问法,每次回归必跑。必跑的结果必须是空或权限,不能是一段很像的话。很像的话在名单上出现,算回归失败。失败要修接口或修过滤,不修文案把空说得更诗意。诗意救不了错答。

同步接口变更时,把错误码表一起同步。前端、检索、问答三处对同一码。对不上,空会在某一层被当成 500。500 会触发重试。重试在超时场景会把慢变成更慢。更慢之后,用户刷新。刷新再打一次贵的推理。贵的推理仍可能空。空应该便宜。便宜的空,才配当产品。

我是实习生。产品决策不写我的名字。名字能写的是:这三条失败路径我核对过,内部查询能复现,变更有回归。回归记录能给人看。给人看的记录比「接口已经通了」有用。通了只覆盖成功。成功是演示。演示不是企业库的日常。日常充满空。

说不出是合格输出

我收到的限制来自模型那句本能:问答接口必须允许什么都不说。空结果、超时、权限提示与成功答案同级。同级之后,乱说才有地方被按回去。按回去的系统,切片和图谱才值得继续调。不按回去,调得越准,编得越像。越像,越贵。