Survey 检索与 Scorer 的整合边界¶
本文件说明 survey 与可编程 Scorer 共存时的接口边界。survey 不支持 Scorer DSL;两者保留各自的检索与评分规则。
两个入口各自做什么¶
接口 |
用途 |
排序控制 |
|---|---|---|
|
文本/身份检索,fused或multi,可选网页反喂 |
保留默认、 |
|
有界的多查询综述检索与作者/venue/年份/引用规则过滤 |
|
agentic: true 在 survey 中表示一次 LLM 查询规划,不是 /v1/search 的 agent: true 总结,也不是自定义 scorer。
Survey 请求示例¶
在微服务已经部署并可达时,可发送:
{
"goal": "surface code threshold",
"queries": ["surface code threshold", "surface code decoding"],
"sources": ["arxiv", "openalex"],
"rules": {
"year_from": 2020,
"min_citations": 10,
"sort": "citations"
},
"max_results": 10,
"agentic": false
}
goal为非空文本,最多4000字符。
queries可选,最多6条,每条非空且最多500字符;缺省用规则式规划产生查询。
sources缺省为semantic_scholar、arxiv、openalex,不使用search.default_tools。
rules可指定authors、venues、year_from、year_to、min_citations、sort。
max_results默认25,范围1~100,表示最终聚合数量,不是全局上游请求预算。
agentic=true且LLM配置齐全时,可扩展查询并建议有界权重;显式规则不能被LLM修改。
api_keys由可信调用方注入并在handler中裁剪,不回显在plan中,也不在SurveyRequest的repr中展示。
响应包含plan、usage、hits、queries、errors、coverage;不包含scorer元数据或score_explanation。
不支持的参数必须显式拒绝¶
survey请求的顶层不得出现以下字段,即使值为null或false:
ranking
scorer
explain
出现时返回400,例如:
{
"detail": {
"code": "unsupported_survey_parameter",
"field": "scorer",
"message": "survey-search does not support scorer; use /v1/search"
}
}
错误在规划、LLM和backend调用之前产生,不会忽略程序后执行默认排序。
需要自定义评分时使用 /v1/search,详见 Scorer 使用指南。其他普通未知字段按SurveyRequest的兼容策略忽略;survey模型并非整体设置为extra=forbid。
请求安全保护¶
/v1/search 和 /v1/survey-search 共享以下保护:
配置service_token时,在读取、解码请求体之前校验Bearer令牌。
实际请求体最多64KiB,不能通过省略/伪造Content-Length或分块传输绕过。
请求体必须为UTF-8 JSON,不接受字面NUL或UTF-16/32字节编码。
JSON容器嵌套最多64,在完整JSON解析前检查。
支持ASGI root_path和尾部斜杠路径;其他非搜索路由行为不变。
令牌未配置时接口仍开放。上述请求保护不能替代部署网络隔离、令牌配置或配置加载失败时的风险审查。
Survey 错误输出¶
情况 |
HTTP状态 |
|---|---|
缺少/错误令牌(配置了service_token) |
401 |
非法编码 |
400 |
顶层ranking/scorer/explain |
400 |
请求体超64KiB |
413 |
JSON过深、JSON语法错误、缺字段、字段类型/范围或规则验证失败 |
422 |
一般验证错误返回:
{
"detail": {
"code": "invalid_survey_request",
"message": "Invalid survey request; check the reported fields.",
"errors": [{"type": "missing", "loc": ["body", "goal"]}],
"truncated": false
}
}
最多列出20个验证错误;超出时truncated=true。保留静态字段路径和错误类型,不回显input、body、ctx或验证器原始message。api_keys中的动态键名在位置中替换为[key],避免把调用方输入作为错误路径泄漏。
仅survey使用这个新的安全验证错误协议;原有search、admin等路由的验证响应保持原样。搜索的ScorerError仍走它原来的安全错误处理。
保留而未改写的检索语义¶
survey对各源记录先执行rules,再合并;跨源互补的作者/引用信息不会救回先前已过滤的记录。
source/author/venue等缺失元数据不满足相应规则;作者规范化匹配不等于ORCID身份消歧。
queries顺序执行,单个查询的backends并行执行。
survey通过run_multi后自行rank,不使用普通fused搜索的网页reinject阶段。
coverage.exhaustive始终为false;返回的是有界取回集合,不是全部文献中的全局排序。
返回hit使用Paper.model_dump,不统一改成search的四位小数账单序列化。
这些差异需由调用方理解,不能把survey当作search的可互换替代接口。
Semantic Scholar 节流的行为变化¶
RequestSlots使同一S2 Key在一个进程内的请求发起至少间隔1秒;重试、身份查询、默认/auto/scorer、survey和reinject共享同一闸门。匿名调用共用anonymous槽。
空闲Key的首请求不必等待;并非每次固定增加1秒。
闸门等待发生在HTTP请求timeout之外;当前没有总等待deadline,也没有Key槽回收机制。
并发或多查询时,整个检索的等待时间可能超过request_timeout。
多进程/副本需要外部限流协调或同Key粘性路由。
只选择arxiv、openalex时不会直接进入S2闸门;这个节流不会解决OpenAlex的429。
若部署有严格并发或延迟要求,应另行评估并测试有界等待和槽回收,不能仅靠单次HTTP请求timeout推断总延迟上限。
验证与发布¶
tests/test_survey_service.py 覆盖进程内FastAPI/ASGI路径和模拟backend/LLM;默认测试同时回归scorer、survey及S2行为,不调用真实外部API。从仓库根目录执行:
uv sync --locked --extra dev
uv run --no-sync --offline python -m pytest -q
版本由本仓 pyproject.toml 与 Commitizen 流程管理,见 项目概览:版本与发布开发流程。不手改VERSION、重写旧tag或覆盖已发布产物。离线测试不证明qatlasd/网页的端到端透传与展示正确;选定版本仍需单独验证调用方兼容性。