citation_id与source_span实战:教AI Agent逐字引用字节级证据
【免费下载链接】wigoloThe go-to web for your AI coding agent — local-first search, fetch, crawl & research over MCP. No API keys, no cloud, $0/query. Public beta.项目地址: https://gitcode.com/GitHub_Trending/wi/wigolo
用 AI Agent 做联网搜索时,它给出的答案往往"言之凿凿却无法核实"——到底引用了哪句话、来自哪个网页的哪个位置?wigolo 是一个本地优先的 AI 编码智能体 Web 搜索工具(MCP 协议),它的每条证据都自带citation_id(稳定引用编号)和source_span(字节级来源坐标),让 Agent 能够逐字引用、可验证到字符偏移,这是大多数云端搜索工具做不到的能力。
为什么需要"字节级证据"?
普通搜索工具返回的是"标题 + 摘要 + 链接",Agent 只能模糊地说"某网站提到……"。而 wigolo 返回的每条证据长这样(摘自 README.md 的真实结构):
{ "title": "Logical replication - PostgreSQL docs", "url": "https://www.postgresql.org/docs/current/logical-replication.html", "excerpt": "Logical replication is a method of replicating data objects…", "citation_id": "src-1", "source_span": { "start": 1042, "end": 1305 } // 字节级精确坐标 }这两个字段解决两个核心问题:
| 字段 | 作用 | 类比 |
|---|---|---|
citation_id | 一段证据的稳定"门牌号",Agent 引用时不用写长 URL | 图书馆的索书号 |
source_span | 引文在原文中的精确字符区间{start, end} | 书页码 + 行号 |
快速上手:三条引用方式
wigolo 的search工具默认返回evidence[](已按 ML 重排器打分排序)和citations[](编号到 URL 的映射),宿主模型(你的 AI Agent)拿到后有三种引用姿势,规则写在 skills/wigolo/rules/synthesis.md:
- 编号引用
[N]:citations数组把[1]、[2]映射到 URL,最接近人类阅读习惯; - ID 引用
{citation_id}:跨分页、跨查询保持稳定,适合长对话中反复指认同一来源; - span 校验:拿到
source_span后,可以回到原文 Markdown 的start~end区间核对引文是否逐字一致——这是防"幻觉引用"的最后一道闸门。
它是怎么做到的:从搜索到引文
证据管道分三步,核心实现在 src/search/evidence.ts 与 src/search/highlights.ts:
- 切段:把每个来源的 Markdown 正文切成候选段落,同时记录每段的字符偏移
charStart / charEnd; - 重排:本地 ONNX 重排器对段落打分,选出最相关的 Top 段落,并保留其偏移区间,写入
source_span; - 编号:
citation_id由url + '#' + span.start做 SHA-1 取前 12 位生成(见stableCitationId函数,src/search/evidence.ts)。
类型定义在 src/types.ts:SourceSpan就是{ start, end },EvidenceItem则把它和citation_id、score打包成一条完整证据。
💡 细节:证据片段会先过滤"太短(<40 字符)"或"链接占比超 50%"的段落——导航栏、页脚这类垃圾内容进不了证据区,Agent 引用的都是正文真话。
稳定性:翻页重查,编号不变
这是citation_id设计中最巧妙的一点:同一个 URL 的同一位置,无论查几次、分页大小是多少,ID 永远相同。因为它只依赖url + 起始偏移,与查询词、结果数量无关。
项目里的集成测试 tests/integration/citation-id-stability.test.ts 专门验证了这一点:用max_results: 10和max_results: 5各查一次,两次返回的证据citation_id重叠且source_span.start完全一致。
对 Agent 的实际意义:多轮对话中它可以直接说"如{src-1}所述……",而不用担心编号随查询漂移,下游程序也能据此做去重和溯源。
项目中的相关资料
- 工具响应契约:docs/tools.md —— "
evidence[]+citations[]:带citation_id和source_span(源文中精确字符区间)的可引用摘录,让 Agent 可以逐字引用" - 证据构建与预算控制:src/search/evidence.ts
- 高亮切段与 span 计算:src/search/highlights.ts
- 合成引用规范(官方 Skill 规则):skills/wigolo/rules/synthesis.md
- 稳定性测试:tests/integration/citation-id-stability.test.ts
- 证据过滤与预算单元测试:tests/unit/search/evidence.test.ts
常见问题(FAQ)
Q:source_span的 start/end 是什么单位?源文 Markdown 字符串中的字符偏移(README 称之为 byte-exact provenance,字节级精确来源)。markdown[start:end]即可取出对应原文。
Q:为什么有的citation没有citation_id?当某来源的证据段落被 token 预算裁掉时,编号会缺省——消费方可把"无 ID"理解为"仅来源级引用,无具体段落"(见 src/search/evidence.ts 的注释)。
Q:本地就能跑吗?可以。wigolo 主打 local-first:无需 API key、无云依赖,重排器走本地 ONNX 模型,search走 18 个直连搜索引擎适配器,每次查询零成本。
一句话总结:citation_id给证据发"稳定门牌号",source_span把它钉在原文的字符区间上——AI Agent 从此可以说出可逐字核验的引用,而不是"我好像记得某网站说过"。
【免费下载链接】wigoloThe go-to web for your AI coding agent — local-first search, fetch, crawl & research over MCP. No API keys, no cloud, $0/query. Public beta.项目地址: https://gitcode.com/GitHub_Trending/wi/wigolo
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考