openJiuwen DeepSearch 来源匹配(source_matching)Prompt 契约与实现解析:从评分规则到片段级引用溯源落地

发布时间:2026/10/13 2:30:17
openJiuwen DeepSearch 来源匹配(source_matching)Prompt 契约与实现解析:从评分规则到片段级引用溯源落地
人工智能大模型AI AgentRAG深度研究搜索引擎后端代码智能体【免费下载链接】deepsearchopenJiuwen DeepSearch是一款知识增强的深度搜索与研究框架有业界领先的片段级引用和溯源推理能力提供精准Agentic搜索与研究能力项目地址https://gitcode.com/openJiuwen/deepsearch点击查看免费下载本篇技术指南以 openJiuwen DeepSearch 全局溯源链路中的核心 Prompt 模板source_matching/system.md为主体系统讲解来源匹配Source Matching这一能力它如何把内容识别阶段产出的待引用句子与预处理后的搜索记录逐一比对并打分最终输出可被下游参考文献生成与 Citation 校验直接消费的 JSON 匹配结果。读完本文你将掌握该 Prompt 的完整数据契约输入变量、评分体系、输出 Schema、约束条件、它如何被message_builder渲染注入、match_sources调用链的源码级实现以及 exact/fuzzy/classify 三类辅助匹配算法与搜索记录预处理的底层原理可直接用于理解或复现 openJiuwen DeepSearch 的片段级引用溯源能力。一、来源匹配在溯源链路中的定位来源匹配source_matching是 openJiuwen DeepSearch 全局溯源流程中承上启下的关键环节。其上游是溯源内容识别content recognition下游是参考文献生成reference generation与Citation 校验citation checking。从 SourceTracer 入口实现 可以还原完整链路preprocess_report移除报告文末的参考文献章节保留可溯源正文preprocess_search_record将搜索记录清洗、去重、裁剪并分配索引recognize_content_to_cite通过content_recognitionPrompt 识别报告中需要添加引用的句子match_sources将待引用句子列表与预处理后的搜索记录连接起来执行来源匹配即本主题generate_source_datas依据匹配结果生成引用数据add_source_references把引用标记插入句末最后经 Citation 校验与参考文献追加完成整篇报告的溯源。可见来源匹配决定了哪句话能获得哪个来源的引用是整个片段级引用能力的核心决策点。若此处匹配为空或错误下游不会伪造引用边界处理明确空 source list 时返回空匹配不应伪造引用因此匹配质量直接影响报告的可信度。二、source_matching Prompt 契约详解关联文档 system.md 定义了模型扮演的角色与硬性规则user.md 定义了单次请求的输入变量。两者共同构成完整 Prompt 模板。2.1 系统角色与任务目标system.md 将模型设定为专业的来源匹配助手professional source matching assistant核心职责是将研究报告中需要引用的内容与搜索记录进行精确匹配只选择最相关的来源。这与 openJiuwen DeepSearch 追求精准 Agentic 搜索与研究、提供片段级引用的产品定位一致——引用不是随便贴一个来源而是逐句找到支撑它的证据片段。2.2 匹配算法评分体系1-10 分system.md 规定按相关性评分1-10 分制对匹配进行排序共三档匹配类型分值区间判定语义Exact Match精确匹配10 分文本完全一致Semantic Match语义匹配8-9 分含义相同但措辞不同Keyword Match关键词匹配6-7 分核心事实一致该评分体系是 Prompt 层面的排序语言它指导 LLM 在多个候选来源中优先输出文本重合度最高、语义最贴近的记录。需要注意此处的 1-10 分是给 LLM 内部排序用的语义化分值与 辅助算法 中面向引用质量打分的 0.0-1.0 连续分值exact ≥ 0.85、fuzzy ∈ [0.3, 0.7]是两个独立体系后者用于代码侧的引用片段质量判断二者职责解耦。2.3 输出格式契约source_traced_resultssystem.md 要求模型严格输出如下 JSON 结构{ source_traced_results: [ { sentence: Sentence requiring citation, matched_source_indices: [matching record index 1, matching record index 2, matching record index 3] } ] }字段语义sentence需要引用的句子原文必须与输入保持一致见 2.4 约束matched_source_indices命中的搜索记录索引数组索引对应预处理后搜索记录在各自来源类型列表中的位置index字段。2.4 硬性约束Important Notessystem.md 明确列出的约束是解析与后处理代码得以稳定工作的前提每条句子最多 3 个matched_source_indices——防止单句引用来源过多保证引用精度与版面可读性sentence字段必须与输入句子保持一致——这是后续validate_trace_results能通过句子是否存在于内容识别结果来过滤的关键见第四节matched_source_indices必须对应搜索记录中的索引——索引语义由预处理阶段写入的index字段保证见第五节无法匹配任何搜索记录时matched_source_indices置为[]——即宁缺毋滥不伪造引用直接输出正确格式的 JSON不得附带任何额外字符包括json标记——配合代码侧的normalize_json_output清洗确保可被json.loads直接解析。2.5 输入变量user.mduser.md 只定义了两个 Jinja 变量也是 Prompt 契约测试 中source_matching的 required vars{{ content_recognition_result }}内容识别结果即需要引用的句子列表{{ search_record }}搜索记录JSON 形式。从 source_matcher.py 调用处 可见实际构建上下文时search_record会先json.dumps(..., ensure_asciiFalse)序列化为字符串再注入模板content_recognition_result直接传入列表。两者顺序与 user.md 一致渲染后即为发送给 LLM 的 user 消息。三、Prompt 如何被渲染与注入message_builder 源码剖析source_matching 模板由统一的 message_builder.py 加载渲染。关键机制如下build_prompt_messages(prompt_name, context)按prompt_name定位prompts目录下的子目录先渲染system.md纯静态模板不允许任何运行时变量再按需渲染user.mdJinja 变量来自传入的 context_assert_static_template_tree会递归校验 system 模板及其静态 include不包含运行时变量——这正是 source_matching/system.md 全文没有{{ }}占位符的原因系统级指令必须恒定只有 user 消息携带当次输入渲染结果组装为[{role: system, content: ...}, {role: user, content: ...}]的消息列表供ainvoke_llm_with_stats调用模板名必须匹配^[A-Za-z0-9_-]$上下文不得占用messages/history/prior_messages/images等预留键。仓库通过 test_deepresearch_prompt_contracts.py 以参数化方式对全部 Prompt 目录做契约校验断言source_matching/system.md不含任何模板变量、user.md的变量集合恰为{content_recognition_result, search_record}并且每个有system.md的目录都必须在契约表中注册test_contracts_cover_every_directory_prompt。这意味着若有人误改 system.md 引入变量或改动 user.md 的输入字段测试会立即失败从而保证 Prompt 契约与调用方代码长期稳定。四、match_sources 调用链从输入到校验后的匹配结果核心实现位于 source_matcher.py由match_sources作为入口依次经历四个阶段。4.1 按来源类型分组处理match_sourcesasync def match_sources(content_recognition_result, preprocessed_search_record, chunk_size, llm_model_name): # 空输入直接返回 [] for source_type, source_list in preprocessed_search_record.items(): source_results await process_source_type(...) all_trace_results.extend(source_results) merged_results merge_trace_results(all_trace_results) validated_results validate_trace_results(merged_results, content_recognition_result) return validated_results预处理后的搜索记录是按来源类型组织的字典如web_page_search_record、web_image_search_record、local_text_search_record、local_image_search_record参见 测试夹具。match_sources遍历每种类型分别匹配再统一合并与校验。这样设计的好处是不同来源类型的记录相互隔离索引只在各自列表内有效避免跨类型引用错位。4.2 分片与 LLM 调用process_source_type / call_llm_for_traceprocess_source_type当len(source_list) chunk_size时整体处理process_single_chunk否则按chunk_size切片逐个处理process_chunked_source分片结果最终合并。在 SourceTracer 默认参数 中_chunk_size 40即单批最多 40 条搜索记录call_llm_for_trace构建source_tracer_contextsearch_record序列化 content_recognition_result调用build_prompt_messages(source_matching, context)再经ainvoke_llm_with_stats发起调用统计代理名使用AgentLlmName.SOURCE_TRACER_SOURCE_MATCHING定义于 node_constants.py。异常被抑制并返回空列表保证单类型匹配失败不影响整篇报告流程。4.3 响应解析parse_trace_responseLLM 原始输出先经normalize_json_output清洗剥离json等围栏再json.loads。解析逻辑做了三层防御顶层必须是 dict且必须含source_traced_results键否则返回空source_traced_results必须是 list每个元素必须是 dict过滤非 dict 项随后统一注入result[source] source_type即给每条结果标注其来源类型。这正好呼应 system.md 第 5 条约束即使模型输出带了多余字符代码侧也能容错清洗但契约要求模型自身直接输出纯 JSON。4.4 合并去重与有效性校验merge_trace_results / validate_trace_resultsmerge_trace_results以f{sentence}|{source}为唯一键把分片或多次调用产生的同句同源结果合并matched_source_indices取并集、去重并升序排列同时只保留纯 int 索引过滤 bool 等误类型validate_trace_results仅保留sentence确实存在于content_recognition_result中的结果其余丢弃并告警。这一步把 system.md sentence 必须与输入一致的约束落到了工程校验上防止 LLM 幻觉出报告中不存在的句子。对应测试见 test_source_matcher.py覆盖成功解析、非法 JSON 抛错、缺失键返回空、多结果解析、重复句源对合并去重等场景。五、搜索记录预处理索引从何而来要让matched_source_indices语义成立搜索记录必须先被预处理并写入index字段。实现位于 source_tracer_preprocessors.pypreprocess_search_record仅处理值为 list 的来源类型非 list 原样保留process_search_record_list对每条记录执行三道过滤必填字段必须同时包含title、url、content三字段has_required_fields缺一即丢弃去重以url/title/content三元组做全等比较is_duplicate_record重复项仅保留首条长内容分片content长度超过max_content_lenSourceTracer 默认_search_record_max_content_len 3000时按 3000 字符为单位切分为多条记录每条继承原url/title每条通过校验的记录被追加item[index] len(processed_list)即预处理后列表内的位置下标就是 Prompt 中matched_source_indices所指向的索引。SourceTracer.transform_search_record负责把子报告生成阶段的 top-K 证据含passage_text或original_content转换为{url, title, content}格式且优先采用非空passage_text片段而非父文档全文避免把整篇文档重复塞入匹配上下文测试用例 明确验证了这一降级规则。六、辅助匹配算法代码侧的精确/模糊/分类匹配除 LLM 匹配外仓库还提供不依赖模型的辅助算法 source_match_algo.py用于事实与引用内容的精确/模糊匹配及引用片段质量判断exact_match将 fact 按中文标点分句逐句剥离末尾标点后在 citation_content 中做子串精确搜索命中片段取 citation 原文而非 fact 原文消除标点差异覆盖率映射为score 0.85 coverage_rate × 0.15恒 ≥ 0.85fuzzy_match基于difflib.SequenceMatcher做句子级模糊匹配非字符级滑动窗口默认阈值threshold 0.8覆盖率映射为score coverage_rate × 0.7有命中时钳制在[0.3, 0.7]无命中为 0.0classify_and_match综合策略——先 exact覆盖率 ≥ 0.85 判为exact否则 fuzzy有任何命中判为fuzzy均无命中返回no_match。模块设计上明确与防篡改用途的citation_verify_research.py#find_matches解耦并复用split_into_sentences与content_analyzer.py保持一致的分句口径。该模块与 Prompt 评分体系的关系可以这样理解Prompt 让 LLM 在句子 → 来源层面做语义取舍对应 8-9 分语义匹配辅助算法则在引用片段 → 来源正文层面做确定性的质量校验exact/fuzzy 分数二者共同构成LLM 语义匹配 确定性算法校验的双保险这也是 openJiuwen DeepSearch 片段级引用能力的技术底色。七、匹配结果的下游消费与整体编排匹配结果离开match_sources后进入 add_source.pygenerate_source_datasSourceReferenceProcessor.extract_source_info依据source类型定位对应记录列表按matched_source_indices逐个extract_source_item_info提取 title/url/content/score 等字段构建标准引用数据项并做索引越界与字段缺失校验匹配索引必须落在对应来源列表范围内的工程落实merge_source_datas把溯源新生成的数据与报告原文自带的引用数据合并按 chunk 在报告中的位置过滤、排序add_source_references以句末插入[source_tracer_result]标题的形式把引用写回报告插入前会对 title/url 做 HTML 实体转义与 URL scheme 校验仅允许 http/https见 add_source.py。整体编排由 SourceTracer 类 完成research_trace_source产出_trace_source_datasadd_source_to_report完成引用注入其pre_check_origin_coverage还以_min_origin_coverage_count 10、_min_origin_coverage_ratio 0.3两个阈值做前置判定——若原文引用覆盖已达标则跳过溯源避免无效算力消耗。八、配置开关与局部溯源场景来源匹配不仅服务于整篇报告的全局溯源还被用户反馈局部溯源复用。在 local_source_trace.py 中改写后的段落文本会走同一套recognize_content_to_cite(0.9) → match_sources(chunk_size40) → generate_source_datas → add_source_references → CitationCheckerResearch流程参数与全局溯源保持一致相似度阈值 0.9、单记录内容上限 3000、分片 40保证两种场景行为一致。此外config.py 提供source_tracer_research_trace_source_switch溯源功能开关默认True在 SourceTracerNode 中当search_mode research且开关为 False 时直接跳过溯源可用于按需关闭引用生成以节省调用成本。九、测试与验证仓库为来源匹配提供了多层次测试保障推荐按 source-matching 文档 给出的命令执行uv run pytest deepsearch/tests/source_tracer/test_source_matcher.py uv run pytest deepsearch/tests/source_tracer/test_source_match_algo.py uv run pytest deepsearch/tests/algorithm/prompts/test_deepresearch_prompt_contracts.py关键覆盖点Prompt 契约source_matching的 user 变量恰为content_recognition_result、search_recordsystem 模板必须零变量test_deepresearch_prompt_contracts.py匹配主流程成功路径、异常传播、空输入返回空、空内容识别返回空test_source_matcher.py响应解析source_traced_results缺失、非法 JSON、围栏包裹 JSON 的容错test_source_matcher.py结果合并同句同源多批结果的索引并集去重排序test_source_matcher.py整体链路匹配失败时_trace_source_datas保持空、异常包装为CustomValueException(SOURCE_TRACER_TRACE_SOURCE_ERROR)test_source_tracer.py。十、总结source_matching Prompt 是 openJiuwen DeepSearch 片段级引用能力的决策契约它以 1-10 分的匹配评分体系指导 LLM 做句子到来源的语义取舍以严格的 JSON Schemasource_traced_results和五条硬性约束保证输出可解析、可校验、不越界再由message_builder静态渲染、match_sources分片调用与合并校验、辅助算法兜底打分、下游引用注入完成闭环。理解这一契约及其源码实现是深入 openJiuwen DeepSearch 溯源体系、乃至二次定制引用精度策略的最佳切入点。赞分享人工智能大模型AI AgentRAG深度研究搜索引擎后端代码智能体【免费下载链接】deepsearchopenJiuwen DeepSearch是一款知识增强的深度搜索与研究框架有业界领先的片段级引用和溯源推理能力提供精准Agentic搜索与研究能力项目地址https://gitcode.com/openJiuwen/deepsearch点击查看免费下载相关推荐openJiuwen DeepSearch如何实现片段级溯源引用匹配与校验算法完整解析openJiuwen DeepSearch如何实现片段级溯源引用匹配与校验算法完整解析 openJiuwen DeepSearch 是一款知识增强的深度搜索与人工智能大模型AI AgentRAG深度研究搜索引擎后端代码智能体openJiuwen DeepSearch 的 Prompt 模板与 Workflow 节点工程规范从 prompt-workflow 规则文件到源码级落地openJiuwen DeepSearch 的 Prompt 模板与 Workflow 节点工程规范从 prompt workflow 规则文件到源码级落地人工智能大模型AI AgentRAG深度研究搜索引擎后端代码智能体openJiuwen DeepSearch 来源匹配Source Matching从提示模板到引用落地的完整技术解析openJiuwen DeepSearch 来源匹配Source Matching从提示模板到引用落地的完整技术解析 导读 本文聚焦 openJiuwe人工智能大模型AI AgentRAG深度研究搜索引擎后端代码智能体上一篇expo-navigation-bar 完全指南在 Android 上控制与监听系统导航栏下一篇Gofile批量下载工具深度解析高效自动化文件获取实战指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考