Repository navigation
Conversation
Issue helsome#13 要求 evidence 定位到原始 source 的具体 passage/span,而不是只保存 run/URL 级引用。此前 EvidenceRef 只记录产出该证据的 capability run,而一条 research.news 的 run 会带回多条新闻,从 claim 跳过去只能落到来源集合。 - 新增 SourcePassage / PassageLocation 契约:source/document identity、 逐字 excerpt、以及 start/end 字符偏移与 1-based line/column - 新增确定性定位器 locatePassage:只容忍空白差异,其余逐字匹配;定位不到 返回 undefined(fail-closed),绝不回退到相近偏移 - relocatePassage 在重载后按当前文本复算位置;来源变了如实返回 undefined - buildCapabilityPassages 只处理自带可检索文本的来源(当前 research.news), 结构化数据能力返回空,不把 Folio 自己生成的 summary 当 passage - assembleReport 接线,写入可选的 ResearchReport.evidencePassages
8 tasks
issue helsome#13 的验收项 7/8 要求真实 Deep Research E2E,只跑 fixture 不算完成。 本 PR 的切片是 passage 级证据定位,因此补一个只走生产路径的验收: - apps/electron/e2e/evidence-passage-live-acceptance.ts 真实模型(HTTP 流式)+ 真实 AgentKernel + 生产 createAgentSynthesizer + 生产 research.news 能力(仅注入 getNews fetcher)+ 生产 ResearchService。 断言四组:真实 retrieval 产出 evidencePassages;每条 passage 的 offset 能 relocate 回同一位置且 slice 等于 excerpt;每条 EvidenceRef 能经 passagesForEvidence 解析到 passage;换全新 repository 实例重载后仍成立。 没有凭据/没有可达检索源时直接失败,不留 fixture 退路。 - docs/acceptance/evidence-passage/ 真实运行产物:deepseek-v4-pro + 49 条实时新闻 → 49 条 passage 全部可重定位。 - docs/evidence-passage-test-report.md 验收报告。明确写出本切片**不覆盖** claim 身份、verifier 输出、双向 claim↔evidence 映射与报告 UI 跳转(分别依赖 helsome#67 / helsome#90 接线 / 未认领), 并如实记录注入 fetcher 时 provenance.provider 仍为 'longbridge' 的既有行为。 Related to helsome#13
Contributor
Author
|
请求批准合并 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
改动说明
为 Issue #13 补上证据的 passage/span 级定位——这是「claim → 具体原始 passage」跳转所缺的那层数据。
现状:
EvidenceRef只记录「哪个 capability run 产出了这条证据」(capabilityId+runId+fetchedAt)。而一次research.news的 run 会带回多条新闻,报告里却只有 run 级别的引用,因此从 claim 跳过去只能落到来源集合,落不到具体那一段话。本 PR 做了什么:
packages/core/src/evidence-passage.ts:SourcePassage/PassageLocation契约。定位信息包含 source/document identity(documentId、canonicalUrl)、逐字excerpt、以及location(start/end字符偏移 + 1-basedline/column)——即 issue 里要求的「source/document identity、excerpt 和 location metadata」三件套。packages/shared/src/research/evidence-passage.ts:locatePassage(sourceText, excerpt, { occurrence }):确定性定位。只容忍空白差异(换行/缩进不同仍能命中),其余字符必须逐字相同;偏移始终指向原始文本,所以sourceText.slice(start, end)就是那段证据本身。定位不到返回undefined(fail-closed),绝不回退到相近偏移——那正是要防的「编造引用」。relocatePassage(passage, sourceText):重载后按当前文本重新推导位置;来源已变则如实返回undefined,不使用存下来的旧偏移(旧偏移恰好仍在范围内会高亮到无关文字)。buildCapabilityPassages({ runId, capabilityId, result }):从能力结果构建 passage。只处理自带可检索文本的来源(当前是research.news),结构化数据能力返回[]——CapabilityResult.summary是 Folio 自己生成的散文,把它当 passage 会凭空制造出处。passagesForEvidence(passages, { runId, capabilityId }):evidence → passage 方向;passage 自身带runId/capabilityId,反向天然成立,无需额外索引。passageIdOf:id 由 run + capability + 文档身份 + span 派生,与数组位置无关(重排带 id 的新闻不会改 id;只有来源无文档身份时才用位置兜底)。assembleReport在组装报告时从 run outcome 派生 passage,写入ResearchReport.evidencePassages。因为派生自真实 run outcome 而不是模型输出的正文,位置不可能被模型编出来。字段可选,且仅在该 run 确实产出 passage 时写入。多对多:一条 evidence(一个 run)可以产出多条 passage;passage 上带
runId+capabilityId,所以「一个结论多条证据」「一条证据支撑多个结论」都天然成立,没有引入 1:1 schema。关联 Issue
Related to #13
测试报告(正式审核前必填)
环境
bun install --frozen-lockfile)upstream/main@ba5dcdf(fix(portfolio-risk): 打通「临近财报」信号与 research.events 的真实契约 (#178))实际执行命令与结果
已知失败 / Baseline
bun test packages/shared --isolate的 22 项失败全部与本 PR 无关,均可复现于当前main:packages/shared/src/providers/longbridge/longbridge.test.ts(LongbridgeFinancialDataProvider/LongbridgeBrokerAccountProvider):本机没有 Longbridge CLI 与凭据。langfuse backend > does not throw when Langfuse is down:依赖外部 Langfuse 端点。A/B 对照(同一命令,回退本 PR 的生产代码后再跑一遍):
与改动对应的验证(要点)
undefined;改写一个词的「近似句」不会被匹配上。sourceText.slice(start, end)回切即得到该 passage;多行来源的line/column有独立断言。runner.test.ts里keeps a passage jump valid after the report is persisted and reloaded走真实链路 ——ResearchRunner→assembleReport→ResearchReportRepository→JsonFileStore落盘 → 新的 store 实例重新读盘 →passagesForEvidence解出 passage →relocatePassage用原始来源文本复算位置并与落盘位置一致。对应验收项「claim → evidence 的跳转在报告重新加载后仍然有效,并定位到具体原始 passage」。market.quote)不产出 passage,报告里evidencePassages保持缺席。真实 Deep Research E2E(issue #13 验收项 7/8)
验收项 7 要求「至少完成 1 次真实 Deep Research E2E,走真实模型 + 实际 retrieval/search 路径;只跑 mock / fixture 不算完成」。本 PR 已补:
apps/electron/e2e/evidence-passage-live-acceptance.ts:只走生产路径 —— 真实模型(HTTP 流式)+ 真实AgentKernel+ 生产createAgentSynthesizer+ 生产research.news能力(只注入getNewsfetcher)+ 生产ResearchService/ResearchRunner/assembleReport+ 真实ResearchReportRepository。没有凭据或没有可达检索源时直接失败,不留 fixture 退路。docs/acceptance/evidence-passage/:本次真实运行的产物。docs/evidence-passage-test-report.md:验收报告。实测结果(2026-09-28,commit
963d0ff):deepseek-v4-pro,真实流式 API(2068 prompt + 2635 completion tokens)relocatePassage回到同一位置,且sourceText.slice(start, end)等于记录的 excerptEvidenceRef都解析到至少一条 passage如实披露两点:
getNewsfetcher,改用实时公开 RSS 源;生产 Longbridge fetcher 仍是该能力的默认值,并由 feat: 为 Deep Research 增加持久化检查点与崩溃恢复 #80 的research-recovery-kernel.ts端到端覆盖。另外createResearchNewsCapability把provenance.provider写死为'longbridge',所以这次运行的 checkpoint 里该字段仍显示longbridge—— 这是既有行为,不是本 PR 引入的。UI 截图(仅可见 UI 变化时必填)
Scope / 后续
本 PR 包含:
runId/capabilityId)本 PR 不包含(留给后续 PR):
claim ↔ evidence双向映射:PR feat: 为研究报告引入 claim 身份与 claim↔evidence 双向映射 #67 正在处理,本 PR 未复制其类型、也未与其重叠buildCapabilityPassages目前只认research.news,其余返回[],不会为结构化数据硬造一个位置与在途 PR 的关系(如实披露):本 PR 修改了
packages/core/src/research.ts与packages/shared/src/research/runner.ts,这两个文件 PR #67、#164 也在改。本 PR 对它们只做追加(新增一个可选字段 + 一处派生逻辑),没有改动任何既有字段、既有行为或既有导出。如果维护者希望避免同文件冲突,我可以把该字段改为独立的持久化产物,或等前置 PR 合并后 rebase。