关于 grounded-citations
Grounded Citations 是一款用于研究和写作的引用管理技能,为外部来源登记编号并生成来源列表。它还支持原文证据、未核实声明标记和引用校验,适用于聊天答复及文档交付。
主要功能
- 01登记来源并分配稳定编号
- 02生成多种格式的来源列表
- 03检查草稿中的引用与来源
- 04附加并核验逐字证据
- 05标记未核实的知识声明
适用场景
- 01为研究答复添加逐句引用
- 02核对报告中的来源与引用编号
- 03为高风险事实核查保留原文证据
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ nousresearch/ hermes-agent --skill grounded-citations安装后在 Claude Code 中输入/grounded-citations确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/citation-formats.mdgrounding-rationale.mdscripts/_hermes_home.pysources.py详细介绍
有依据的引文
每条取自外部来源的陈述都要添加行内编号引文和 Sources: 列表,格式类似 Perplexity。由台账脚本管理 url → [n] 的映射,因此编号和 URL 均来自检索,而非记忆——模型只会输出交给它的小整数。
对于高风险工作,同一台账还可作为事实核查链:每个来源都附有逐字引文(除非引文确实出现在抓取的页面文本中,否则会被拒绝),来自模型知识的陈述会标记为 [unverified],而 verify --evidence 会使任何引用的来源不含证据的草稿验证失败。
此技能适用于聊天答复、书面文档(markdown、PDF、docx、幻灯片)和研究报告。不适用于学术 BibTeX 工作流——会议论文请使用 arxiv 技能,此技能会为其提供支持(参见 references/citation-formats.md)。
适用场景
只要答复或成品依赖于检索到的信息,而非你已知的信息,就使用此技能:
- 研究、比较、新闻摘要、“X 的当前情况如何”
- 任何写入磁盘、引用、转述或报告外部事实的交付物——报告、简报、文档、演示文稿、Wiki 页面
- 用户会希望核查结果的事实调查
- 必须标注相互矛盾来源的多来源综合分析
如果检索只是另一项任务中的辅助步骤,则无需添加行内引文——例如编码时快速查找语法或版本、日常对话、创意写作。只有当用户很可能需要链接时,才提及 URL。
先决条件
除标准工具集外,无其他要求。scripts/sources.py 是仅使用 Python 3 标准库的脚本。
检索使用当前已配置的工具:web_search、web_extract、browser_exec 或 terminal(curl、CLI)。
台账位置:$HERMES_HOME/cache/citations/ledger.json(按配置文件区分)。
可通过 --ledger <path> 或 HERMES_CITATION_LEDGER 为每项任务指定其他位置。
运行方式
S=~/.hermes/skills/research/grounded-citations/scripts/sources.py
python "$S" reset # start a clean ledger
python "$S" add https://example.com/a --title "A" # prints: [1]
python "$S" add https://example.com/b --title "B" # prints: [2]
python "$S" list # ledger table
python "$S" render # Sources: block
python "$S" verify draft.md # catch bad citations
add 操作具有幂等性,并会规范化 URL:同一页面在同一台账中始终返回相同 ID,因此经过多轮搜索和提取后,ID 仍保持稳定。
快速参考
| 操作 | 命令 |
|---|---|
| 为新任务创建空白台账 | sources.py reset |
| 注册来源并获取其 ID | sources.py add <url> [--title T] |
| 一次注册多个来源 | sources.py add <url1> <url2> ... |
| 从 JSON 工具输出中注册来源 | sources.py ingest results.json |
| 为来源附加逐字证据 | sources.py quote <id> --text "exact wording" --from page.txt |
| 显示台账 | sources.py list [--json] |
| 生成 Sources 区块 | sources.py render [--style markdown|plain|footnotes|bibtex|evidence] [--only 1,3] |
| 仅生成草稿引用的来源 | sources.py render --cited-in draft.md |
| 就地重写草稿的 Sources 区块 | sources.py render --replace-in draft.md |
| 检查草稿中的引文 | sources.py verify draft.md [--strict] [--min-coverage 0.6] [--evidence] |
流程
① 在将生成有依据的回答或文档的任务开始时,重置台账。继续处理草稿中已有编号的工作时,跳过重置——复用台账可保持编号稳定。
② 在检索时注册每个来源。 每次 web_search /
web_extract / browser_exec / fetch 后,将 URL 传给 sources.py add
(或通过管道将原始 JSON 传给 sources.py ingest)。务必在撰写正文之前完成。事后凭记忆注册,正是这项技能要避免的失败模式。
③ 边写边引用。 将方括号括起的编号紧跟在来源所支持的每个句子之后:
Ice floats because it is less dense than liquid water.[1][2]
- 编号前不加空格;每个编号单独放在一组方括号中。
- 每个句子最多引用 3 个编号。按句引用,不要把所有引用都堆在末尾。
- 只能使用台账返回的编号。切勿编造编号或 URL。
- 自身知识中的说法无需引用。
- 来源之间存在冲突时,呈现双方观点,并分别标注对应编号。
- 按来源原样引用具体数字、日期和名称;明确标出缺失信息(“未找到关于 X 的来源”),不要含糊带过。
④ 使用 sources.py render --cited-in <draft> 追加 Sources 区块,从台账以机械方式生成编号 → URL 映射,不要手动重输。对于非 Markdown 格式的目标,选择对应的 --style,并按照 references/citation-formats.md 处理位置(docx 中使用脚注,PDF/LaTeX 中使用尾注,演示文稿中添加 Sources 幻灯片,wiki 输出中按页面列出来源)。
⑤ 交付前进行验证——sources.py verify <draft> 遇到未知编号、Sources 区块与台账不一致,或(使用 --min-coverage 时)正文引用过少,都会以非零状态码退出。修正后重新运行。
⑥ 聊天回答也遵循相同步骤,草稿就是你的回复:注册来源、在正文中引用,并以生成的 Sources: 列表结尾。简短回答可以使用 sources.py render --only <ids> 生成区块,无需写入文件。
多平台调查
“大家对 X 有什么看法”/“在网上研究 X”不能只用一次
web_search。应按来源类型扩展搜索范围,并行收集,然后综合整理,同时将每项说法归于其所属平台:
| 来源类型 | 路径 | 可补充的信息 |
|---|---|---|
| 开放网络 | web_search → web_extract | 官方文档、文章、公告 |
| 社区讨论 | reddit-reading(search、thread) | 用户实际体验、投诉、变通方法 |
| 博客/发布说明/变更日志 | rss-feeds(read、discover) | 带日期的原始帖子、版本历史 |
| 视频 | youtube-content | 操作演示、演示视频、演讲 |
| 代码 | 使用 gh search repos / gh search issues 的 terminal | 实现、未解决的问题 |
| X/Twitter | xurl(需要 API 访问权限) | 公告、开发者讨论 |
reddit-reading 和 rss-feeds 技能为可选项。如果尚未安装,请先运行
hermes skills install official/social-media/reddit-reading 或
hermes skills install official/research/rss-feeds,再使用。
每条路径返回的所有 URL 都要在收到时注册到台账中(步骤 ②)。将观点与测量结果分开:Reddit 讨论串只能证明用户报告了某种情况,不能证明其属实;应与一手来源搭配,或将其标注为用户情绪。报告各平台的覆盖缺口(“Reddit 搜索未返回 3 月之后的新内容”),不要悄悄缩小范围,只呈现有效的搜索结果。
事实核查模式
对于读者必须能够核查证据链的工作——例如医疗、法律、金融、安全、存在争议的主张,或用户要求事实核查时——应从引用来源升级为提供证据:
① 为每个来源附上一段逐字引文。 提取网页后,将其文本保存到文件中,并附上支撑每项主张的句子:
python "$S" quote 1 --text "Ice is about 9% less dense than liquid water." --from page1.txt
除非引文逐字出现在证据文本中,否则会被拒绝(不区分空白、大小写和 Markdown 标记——提取文本中的内联链接,如 _[ERAP1](https://…)_,会与读者看到的纯文本匹配),因此改写或记错的数据不能冒充证据。
从抓取的文本中复制粘贴;切勿重新输入。按照读者看到的样子引用句子——匹配器会自动识别提取器添加的标记,因此你不必在引文中复现链接语法或转义的星号。
② 用 [unverified] 标记基于模型知识的主张。 对于无法找到来源、但又是论证关键的主张,应明确标记,而不是添加引用:
The refactor likely predates the 2.0 release.[unverified]
verify --min-coverage 会将 [unverified] 句子计为已覆盖——目标是为每项主张注明来源,而不是为每个句子都添加引用。如果关键主张可以核查,就应进行核查;[unverified] 仅用于确实无法核查的内容。如果事实核查交付内容中大多数标记都是 [unverified],应在摘要中说明这一点。
③ 针对有争议的事实,使用第二个独立来源交叉核查。 如果两个来源存在分歧,应分别引用其内容,并注明各自的 ID 和引文,同时说明你更采信哪一方以及原因。一个来源是报道;两个独立来源才构成佐证。
④ 通过证据门槛验证,并呈现证据块:
python "$S" verify report.md --evidence --min-coverage 0.5
python "$S" render --style evidence --replace-in report.md
如果任何被引用的来源都没有附上引文,--evidence 就会判定草稿不通过。evidence 渲染样式会在每个来源的 URL 下方列出其引文,因此交付内容会清楚展示“主张 → 来源 → 确切的支撑文本”,不要求读者盲目信任。使用 --replace-in <draft> 可就地重写现有的 Sources 块(幂等操作——附加更多引文后可以安全地再次运行);--cited-in 则会将内容打印到 stdout。两者都会输出标题 ## Sources(--style plain 会输出 Sources:)。
--min-coverage 的统计方式。 覆盖率 =
已注明来源的句子数 / 正文句子数。正文句子是 Sources 块、标题(#)、表格行(|)和围栏代码移除后,由 4 个或更多单词组成的非空行片段;引用块标记会被去除。来源通过 [n] 引用或 [unverified] 标记注明,因此同时包含两者的句子只计一次。先在不设置阈值的情况下运行 verify,并查看 info: stats: 行中的统计数据,再选择数值。
注意事项
- 写完后才登记。 台账必须根据工具输出填充,而不是从草稿中重建——那会重新引入编号所要消除的 URL 幻觉风险。
- 任务中途重新编号。 切勿在草稿中手动编辑 ID。ID 是台账中的标识;如果草稿引用了
[4],那么[4]就必须始终对应那个来源。仅在任务之间运行reset。 - 将 URL 重新输入到 Sources 块中。 始终使用
render。手动输入的 URL 是未经验证的声明。 - 引用搜索摘要,仿佛你读过页面。
web_search描述仅能支持其字面所述内容。如果某项主张需要页面正文作为依据,请引用提取的页面——先运行web_extract。 - 引用过多。 每句话最多引用 3 个 ID;每个分句都加引用会让文本难以阅读,也会掩盖究竟由哪个来源支撑论点。
- 在代码/配置产物中引用台账。 来源注释应放在散文类交付物和文档头部中,而不是生成的代码里。
- 并行子 Agent。 每个子 Agent 都有自己的工作目录;如果要合并输出,请用
--ledger(或HERMES_CITATION_LEDGER)让它们都指向同一个台账,否则它们的 ID 会冲突。 - 引用搜索摘要,而不是页面内容。 证据引文必须来自提取的页面文本,而不是搜索结果描述——先运行
web_extract,保存文本,然后使用quote --from引用该文件。 - 将内容改写后传入
quote --text。 原文逐字校验会拒绝这种做法;正确的解决办法是找到实际句子,而不是反复改写,直到出现匹配项。 - 把
[unverified]当作逃避手段。 它用于标记确实无法找到来源的少数主张;如果大多数句子都带有此标记,说明任务需要更多检索,而不是更多标记。 - 手动编辑 Sources 块。 使用
render --replace-in <draft>;自行截取文件内容有导致块过时或重复的风险,之后会被verify标记。
验证
python "$S" verify report.md --strict --min-coverage 0.5
通过表示:草稿中的每个 [n] 都存在于台账中,Sources 块列出的 ID 与引用的 ID 完全一致,且 URL 与台账中的 URL 一致;带有来源的句子中,已引用的比例达到阈值。即使退出代码为 0,也要阅读警告——已登记但未引用的来源通常意味着某项主张在编辑过程中丢失了归属。