人工智能大模型AI AgentRAG深度研究搜索引擎后端代码智能体【免费下载链接】deepsearchopenJiuwen DeepSearch是一款知识增强的深度搜索与研究框架有业界领先的片段级引用和溯源推理能力提供精准Agentic搜索与研究能力项目地址https://gitcode.com/openJiuwen/deepsearch点击查看免费下载导读本文围绕 openJiuwen DeepSearch 用户反馈处理器中的new_task动作展开系统讲解报告生成完成后如何根据用户新要求对已有报告进行章节级扩展的完整技术链路从前端选区定位目标章节、复用历史研究资料、评估资料充足性到触发增量采集、选择改写已有小节或追加新小节两种编辑策略再到改写结果的结构校验、offset 区间回传与局部溯源衔接。读完本文你将掌握new_task的输入输出数据契约、核心源码调用链、Prompt 契约与边界错误处理并能在实际部署与二次开发中直接定位对应实现文件与测试用例。1. 功能定位与维护范围new_task是 用户反馈处理 能力族中的章节级扩展动作。它解决的核心场景是报告已经完整生成用户选中报告中的某一段文字并提出一项新的撰写要求例如补充行业背景新增一节分析第二名城市差距系统需要在尽量复用已有研究资料的前提下对报告做局部、精确、可溯源的扩展。从 维护范围声明 看该文档覆盖user_feedback_processor中new_task动作的完整环节目标章节解析根据选区 offset 与报告标题结构定位目标小节及其所属编号大章节历史资料复用从当前大纲、历史计划和已有资料中收集可复用证据增量采集资料不足时执行增量研究编辑策略选择修改已有小节 / 追加新小节章节改写与新增小节的结构校验。同时文档明确声明了不覆盖的边界完整报告初始生成流程、通用 collector 内部实现、同义改写、补充检索与真实性核验——这些分别由 同义改写、补充检索与改写、真实性核验 子文档负责本文不再展开。2. 可见行为与整体执行路径当用户在报告编辑界面选中文本并提交新任务后系统对外可见的行为是后端根据start_offset/end_offset定位用户选区所在的目标章节根据用户指令判断如何编辑报告修改已有小节、在目标大章节下追加新小节或在资料不足时先执行增量采集再改写返回更新后的完整报告new_report、原始区间original_start_offset/original_end_offset、改写区间rewritten_start_offset/rewritten_end_offset、证据资料与增量研究信息若开启局部溯源enable_local_source_traceTrue改写结果继续进入 局部溯源 阶段更新 citation。从前端协议到后端执行的入口链路为前端传入 JSON payload含action: new_task→UserFeedbackProcessor.parse_feedback解析 →UserFeedbackProcessor.validate校验 →UserFeedbackProcessor.execute路由 →NewTaskProcessor.run_new_task执行 → 局部溯源可选→build_stream_result/send_result流式回传前端。2.1 Action 映射前端action字符串到统一动作定义的映射维护在 action_definitions.py 的USER_INPUT_ACTION_MAP中。new_task被映射为new_task: UserInputActionMapping( action_categoryUserFeedbackActionCategory.NEW_TASK, action_subcategoryNewTaskActionSubcategory.NEW_TASK, ),resolve_feedback_action会根据feedback[action]解析出ResolvedUserAction供后续流式结果构建_build_new_task_stream_result与发送_send_new_task_result使用——其中new_task的流式发送复用通用的_send_rewrite_stream_result逻辑即先下发局部替换区间再同步完整final_result快照。2.2 主入口分发在 user_feedback_processor.py 中execute对new_task的分发代码如下if action new_task: action_result await self._new_task_processor.run_new_task( feedbackfeedback, final_resultfinal_result, languagelanguage, ) return await apply_trace_if_enabled(action_result)其中apply_trace_if_enabledL850-L886根据enable_local_source_trace开关决定是否调用apply_local_source_trace_to_action_result对改写结果做差异感知的 citation 更新。3. 核心代码路径一览new_task的实现集中分布在以下文件路径以仓库根目录为基准职责文件Action 映射与校验action_definitions.py主入口与分发user_feedback_processor.pynew_task 核心实现new_task_processor.py章节定位工具section_locator.pymarkup 剥离工具report_edit_utils.py历史记录回写history.py评估 Promptnew_task_assessment/system.md改写 Promptnew_task_rewrite_section/system.md主要测试用例位于 test_new_task_processor.py1683 行覆盖定位、资产收集、评估解析、增量采集、两种编辑策略、markup 保护与错误兜底等场景、test_processor.py 与 test_history.py。4. 核心流程源码级原文档给出了 9 步核心流程结合 new_task_processor.py 的源码实现可以展开为如下完整链路步骤 1分发到 NewTaskProcessorUserFeedbackProcessor.execute将new_task分发给NewTaskProcessor。NewTaskProcessor继承UserFeedbackPromptInvoker定义于 common.py通过_invoke_prompt统一调用评估与改写两个 LLM 调用点对应的AgentLlmName分别为USER_FEEDBACK_PROCESSOR_NEW_TASK_ASSESSMENT与USER_FEEDBACK_PROCESSOR_NEW_TASK_REWRITE_SECTION见 node_constants.py。步骤 2resolve_target_section 定位目标章节resolve_target_section 是后续所有 offset 计算的基座。它同时完成两件事调用locate_section(report_content, start_offset, end_offset)section_locator.py在 Markdown 标题树中找到能包住选区且 span 最小、层级尽量深的小章节块返回LocatedSection调用locate_enclosing_numbered_major_blockL105-L135查找包含选区的一级数字编号大章节块标题匹配N.前缀。随后分别对 section、selected、major 三类文本范围调用_strip_markup_from_report_range剥离 citation / inference markup得到干净的改写上下文。关键点是三类范围分开清理避免 strip 后 offset 互相污染。返回的NewTaskTargetSection携带section_title、clean_section_text、clean_selected_text、major_section_title、major_heading_level以及各区间 offset。对应的单元测试test_resolve_target_section_strips_citation_and_infer_markup验证了选区文本原文[checked_citation: 1][[1]](https://a.com)[推理结论](#inference:3)会被清理为原文推理结论同时test_resolve_target_section_keeps_numbered_major_chapter_context验证了编号大章节上下文的完整保留。步骤 3collect_section_assets 收集历史资产collect_section_assets 基于_find_matched_sectionL360-L385将目标章节与结构化大纲中的 section 做匹配。匹配模式match_mode只有三种title_exact标题逐字精确匹配title_normalized标题归一化匹配容忍编号、空格、标点差异见_normalize_section_titlenone未命中。设计约束章节资产映射只接受标题匹配拒绝按章节顺序或正文相似度匹配以避免误用相邻章节的研究资料。test_collect_section_assets_does_not_match_by_section_order与test_collect_section_assets_does_not_match_by_content_similarity两个测试专门固化了这一约束。匹配到 section 后从该 section 的历史plans中逐层遍历steps → retrieval_queries → doc_infos聚合并去重得到historical_doc_infos。去重过程_deduplicate_doc_infos会先过滤缺少title或url的异常条目再复用报告侧deduplicate_doc_infos逻辑test_new_task_deduplicate_doc_infos_keeps_same_url_different_sources验证了同 URL 不同source_id的文档会被保留按来源去重而非按 URL 去重。步骤 4assess_section_assets 评估资料充足性assess_section_assets 调用new_task_assessmentPrompt让 LLM 在当前章节干净文本 用户指令 历史文档列表 支持的编辑策略上下文中输出严格 JSON{ edit_strategy: modify_existing_subsection, target_subsection_title: 1.2 Existing subsection title, subsection_title: , relevant_doc_indices: [1, 2], is_sufficient: false, missing_aspects: [aspect A, aspect B], reasoning_summary: short summary }源码对该响应的解析带有多级防御这一点是原文档未展开、但实践中极易踩坑的JSON 解析失败json.JSONDecodeError时降级为is_sufficientFalsemissing_aspects退化为用户指令返回非 dict 时同样降级为资料不足relevant_doc_indices必须是1 index len(historical_doc_infos)的 int显式排除 bool因为bool是int子类越界/非法索引被过滤并告警is_sufficient只接受真正的bool类型字符串false不会被 Python truthiness 误判为充足即使 LLM 判定is_sufficientTrue若没有有效相关文档也会被强制降级为资料不足downgraded sufficient assessment编辑策略只由 LLM 结构化字段决定_normalize_edit_strategy不再依赖用户指令关键词未知策略默认回退为modify_existing_subsection。对应测试包括test_assess_section_assets_logs_and_falls_back_when_llm_response_is_invalid_json、test_assess_section_assets_logs_filtered_invalid_relevant_doc_indices、test_assess_section_assets_downgrades_sufficient_result_without_valid_docs、test_assess_section_assets_treats_string_false_as_insufficient等。步骤 5资料不足时执行增量研究当assessment.is_sufficientFalse时build_incremental_plan 以missing_aspects缺失方面列表按语言用或;拼接构造一个标题为NEW_TASK incremental research、包含单个INFO_COLLECTING步骤的Planrun_incremental_collection 从 session / context 上下文变量解析采集配置实例化CollectorExecutionService并调用run_plan以section_idxnew_task传入CollectorRunPlanConfig含max_search_query_count、max_research_loops、max_tool_call_turns_per_query均来自 session 全局状态config.info_collector_*返回info_summary与新增doc_infos增量文档与历史相关文档合并去重后作为最终写作证据merged_doc_infos。若历史资料足够则跳过增量采集日志incremental collection skippedtest_run_new_task_skips_incremental_collection_when_historical_assets_are_sufficient验证了该路径下build_incremental_plan与run_incremental_collection均不会被调用。关键兜底当历史与增量都没有可用证据时merged_doc_infos为空直接抛出USER_FEEDBACK_PROCESSOR_REWRITE_ERRORNo evidence available for new_task rewrite...绝不进行无证据改写——见test_run_new_task_raises_when_no_historical_or_incremental_docs_available。步骤 6_apply_new_task_edit_strategy 应用编辑策略_apply_new_task_edit_strategy 按评估结果分发到两条策略路径modify_existing_subsection改写已有小节见 步骤 6.1append_new_subsection追加新小节见 步骤 6.2。步骤 7改写结果结构校验两条策略各自经过严格校验详见第 6 节确保 LLM 输出不破坏报告标题层级结构。步骤 8_build_new_task_result 组装返回结果_build_new_task_result 返回的字典字段如下这些字段同时服务前端替换区间、历史记录回写与局部溯源{ new_report: edit_result.new_report, original_text: edit_result.original_text, original_start_offset: edit_result.original_start_offset, original_end_offset: edit_result.original_end_offset, original_text_clean: edit_result.original_text_clean, rewritten_text: edit_result.rewritten_text, rewritten_start_offset: edit_result.rewritten_start_offset, rewritten_end_offset: edit_result.rewritten_end_offset, section_start_offset: edit_result.section_start_offset, section_end_offset: edit_result.section_end_offset, section_title: edit_result.section_title, matched_section_id: evidence.assets.section_id, match_mode: evidence.assets.match_mode, assessment_summary: evidence.assessment.reasoning_summary, used_historical_doc_count: len(evidence.assessment.relevant_doc_infos), used_new_doc_count: len(evidence.incremental_doc_infos), incremental_plan: evidence.incremental_plan, incremental_doc_infos: evidence.incremental_doc_infos, source_trace_doc_infos: evidence.merged_doc_infos, missing_aspects: evidence.assessment.missing_aspects, edit_strategy: evidence.assessment.edit_strategy, new_subsection_title: edit_result.new_subsection_title, }步骤 9局部溯源衔接返回结果经apply_trace_if_enabled进入局部溯源阶段默认开启由 local_source_trace.py 基于改写区间做差异感知的 citation 更新。5. 数据契约与依赖5.1 feedback 依赖字段new_task的feedback依赖字段类型说明actionstr固定为new_taskselected_textstr选区文本start_offset/end_offsetint选区在当前报告正文中的字符偏移user_instructionstr新增任务要求可为空字符串校验逻辑位于 user_feedback_processor.py 的validate_basicuser_instruction与rewrite_scope必须是 stroffset 必须满足0 start_offset end_offset len(report_content)且report_content[start_offset:end_offset]必须与selected_text逐字一致OFFSET_MISMATCH否则抛出对应CustomValueException。5.2 final_result 依赖final_result至少需要提供response_content当前报告正文即run_new_task中final_result.get(response_content, )。可能还包含历史研究资料、子报告与 metadata供局部溯源阶段使用。5.3 运行时依赖new_task的增量采集路径依赖以下运行时上下文当前大纲session.get_global_state(search_context.current_outline)见_load_current_outline历史计划section 的plans从其中聚合doc_infos工作流 session 中的采集配置config.info_collector_max_search_query_count等当前 collector model contextCollectorExecutionService位于 collector_execution_service.py。session 与 model context 通过 common.py 的resolve_session_collector/resolve_model_context_collector从上下文变量解析session 不可用时增量采集直接抛出改写异常NEW_TASK requires session.。5.4 Prompt 契约new_task依赖两个 Prompt 调用点new_task_assessmentsystem.md user.md输入变量current_date、language、user_instruction、selected_text、clean_section_text、section_title、historical_doc_infos1 基索引、supported_edit_strategies职责判断历史资料是否足够并输出编辑策略对modify_existing_subsection给出target_subsection_title可以不同于用户选中的小节若同大章节下另有语义更匹配的小节对append_new_subsection给出不带编号的subsection_title输出约束严格 JSON无 markdown fence、无额外文本is_sufficient为 bool不足时列出missing_aspects。new_task_rewrite_sectionsystem.md user.md输入变量language、user_instruction、edit_strategy、major_section_title、major_section_text、section_title、clean_section_text、selected_subsection_title、new_subsection_title、clean_selected_text、doc_infos职责按策略输出改写后的整个已有小节或仅新增小节禁止输出整段大章节或既有兄弟小节禁止输出 citation 标记与 inference 锚点链接数学公式须用标准 LaTeX 且成对闭合。改写结果必须保持目标标题层级和章节结构约束——这正是第 6 节校验逻辑的 Prompt 侧源头。6. 两种编辑策略的实现细节6.1 策略一修改已有小节modify_existing_subsection_apply_modify_existing_subsection_strategy的执行要点若评估给出的target_subsection_title指向同一大章节内另一个更匹配的小节_resolve_existing_subsection_targetL513-L537会把改写目标重定向到该小节重定向后会对实际被改写的小节重新收集历史资产并做第二次评估只刷新证据充足性与相关文档编辑策略与目标小节沿用第一次结果避免跨小节重定向反复漂移——见test_run_new_task_can_modify_existing_subsection_other_than_selection与test_run_new_task_retargets_assets_when_modifying_another_subsection改写前调用_strip_markup_from_target_sectionL261-L323只剥离即将被替换的小节内 markup报告其他部分的引用与前端定位不受影响测试test_run_new_task_modify_existing_subsection_cleans_only_rewritten_subsection_markup验证了兄弟小节[[1]](https://a.com)与后续章节[[3]](https://c.com)均被保留仅目标小节内的 checked_citation 与 inference 锚点被清理调用rewrite_section_with_assets生成改写文本并经_validate_rewritten_section校验_restore_original_section_separatorL450-L474恢复改写段与后续内容之间的原始换行分隔防止与下一章节标题粘连或空行漂移测试test_run_new_task_keeps_newline_before_next_heading验证改写内容与## 第二章之间保留\n\n。6.2 策略二追加新小节append_new_subsection_apply_append_new_subsection_strategy的执行要点追加模式不清理原大章节 markup避免破坏既有引用测试test_run_new_task_preserves_major_chapter_markup_before_appending_subsection与test_run_new_task_preserves_plain_trace_links_before_appending_subsection分别验证 checked_citation/inference 锚点与双中括号溯源链接在追加后原样保留_build_next_subsection_titleL580-L618生成稳定的N.x连续编号标题从大章节标题提取数字编号扫描下一层小节编号取最大值 1去掉 LLM/用户给出的旧编号后重新编号支持从用户指令中提取显式标题正则匹配标题为…/title as …/titled …英文报告使用Additional Analysis兜底中文使用新增补充分析见_fallback_subsection_title调用generate_new_subsection_with_assets生成新小节正文并经_validate_new_subsection校验_append_subsection_to_major_sectionL620-L645将新小节追加到所属大章节末尾major_section_end_offset处并保持章节边界的换行规范original_text为空字符串无被替换原文original_start_offset original_end_offset major_section_end_offsetnew_subsection_title记录新小节编号标题。对应的端到端测试test_run_new_task_appends_new_subsection_to_numbered_major_chapter验证了在## 1.2 目标小节之后正确追加## 1.3 第二名城市差距分析且不破坏# 2. 第二大章。6.3 改写结构校验规则整章改写校验_validate_rewritten_sectionL403-L448输出为空 → 拒绝输出中出现比原小节标题层级更高#数量更少的标题 → 拒绝防止 LLM 把小节扩写成更大的章节块首行必须是原章节标题原文标题缺失或首行不匹配 → 拒绝改写标题层级必须与原小节一致层级改变 → 拒绝。新增小节校验_validate_new_subsectionL647-L705输出为空 → 拒绝期望标题为major_heading_level 1层级的# ... {subsection_title}LLM 有时会返回整段大章节命中期望小节标题后只截取该小节块heading_block_end计算块边界丢弃兄弟小节测试test_validate_new_subsection_extracts_expected_block_from_full_major_output验证## 1.6 其他小节不会被保留LLM 返回的标题会被规范化覆盖为系统生成编号测试test_validate_new_subsection_normalizes_llm_heading_to_expected_title将## 第二名城市对比分析规范为## 1.5 第二名城市对比分析小节正文中不允许出现层级 expected_level的意外标题防止新增小节内混入大章节级标题。6.4 新增小节的标题编号生成规则_build_next_subsection_title的完整流程可归纳为从major_section_title提取数字编号N正则^(?Pnumber\d)\.\s*解析大章节内所有level major_heading_level 1的小节标题提取N.x中的x序号next_index max(indices) 1从 LLM 建议标题或用户指令中提取原始标题去编号、去显式标题包装输出f{N}.{next_index} {raw_title}无法提取大章节编号时直接返回裸标题。相关测试包括test_build_next_subsection_title_extracts_explicit_title_from_instruction从标题为第二名城市对比分析提取、test_build_next_subsection_title_renumbers_llm_numbered_title_under_major_chapter1.2.1会被重编号为1.3、test_build_next_subsection_title_uses_english_fallback_and_extracts_english_title英文报告兜底标题。7. 边界与错误处理原文档列出的边界约束在源码中均有对应实现边界约束源码实现位置无法定位目标章节时抛出用户反馈处理异常locate_section无标题时退回整篇报告选区不合法在validate_basic拦截user_feedback_processor.py资料不足且增量采集不可用时应返回明确错误不应生成无证据改写_prepare_rewrite_evidence末尾merged_doc_infos为空即抛USER_FEEDBACK_PROCESSOR_REWRITE_ERRORnew_task_processor.py改写结果为空、改变目标标题层级、缺失原章节标题或包含意外更高层级标题时应拒绝_validate_rewritten_section/_validate_new_subsection见 6.3追加新小节需生成稳定的小节标题并避免破坏后续章节_build_next_subsection_title_append_subsection_to_major_section敏感日志模式下不记录用户任务、证据全文或改写正文parse_feedback与validate_basic中LogManager.is_sensitive()时以*掩码输出user_feedback_processor.py错误码体系集中在 status_code.py 的USER_FEEDBACK_PROCESSOR_*系列错误码含义212400用户反馈处理器禁用212401超过最大交互次数212402选区文本超长212403选区文本与 offset 区间不匹配OFFSET_MISMATCH212404无效 action212405改写失败REWRITE_ERRORnew_task 的兜底错误212406用户反馈 JSON 格式非法212407参数类型非法212408offset 区间非法212409rewrite_scope非法所有异常统一通过CustomValueException/CustomRuntimeExceptionexception.py包装并经send_error以StreamEvent.ERROR流式回传前端。8. 历史记录与大纲回写new_task完成后还会同步更新 session 中的历史状态见 history.pybuild_current_outline_update当存在incremental_plan且能按matched_section_id命中大纲 section 时将增量计划追加到该 section 的plans使后续轮次可复用本轮新增研究资产build_rewrite_history_update/build_rewrite_history_item为每次new_task交互追加一条改写历史_add_new_task_history_fields额外记录section_title、matched_section_id、match_mode、assessment_summary、used_historical_doc_count、used_new_doc_count、missing_aspects、incremental_plan_title、edit_strategy、new_subsection_title等字段。9. 测试与验证原文档推荐的测试命令均以仓库根目录为基准uv run pytest tests/user_feedback_processor/test_new_task_processor.py uv run pytest tests/user_feedback_processor/test_processor.py uv run pytest tests/user_feedback_processor/test_history.py若改动影响 citation 更新还应运行uv run pytest tests/user_feedback_processor/test_local_source_trace.py从 test_new_task_processor.py 的测试矩阵看new_task的验证维度非常完整章节定位markup 剥离、编号大章节上下文保留、归一化匹配、拒绝顺序/相似度误匹配资产收集doc_infos 聚合、异常条目过滤、同 URL 不同 source 去重、None 列表字段兜底评估解析结构化 JSON 解析、非法 JSON 降级、非法索引过滤、字符串 false 处理、无有效文档降级、策略默认值增量采集缺失方面构造计划、采集结果合并、资料充足时跳过采集编辑策略改写整章、追加小节、跨小节重定向与资产重取、markup 选择性清理、换行分隔保留、证据不足拒绝改写标题编号显式标题提取、LLM 编号重编号、中英文兜底标题。10. 相关文档用户反馈处理总览同义改写补充检索与改写真实性核验局部溯源赞分享人工智能大模型AI AgentRAG深度研究搜索引擎后端代码智能体【免费下载链接】deepsearchopenJiuwen DeepSearch是一款知识增强的深度搜索与研究框架有业界领先的片段级引用和溯源推理能力提供精准Agentic搜索与研究能力项目地址https://gitcode.com/openJiuwen/deepsearch点击查看免费下载相关推荐openJiuwen DeepSearch 查询理解机制全解析从意图识别到大纲与章节研究计划openJiuwen DeepSearch 查询理解机制全解析从意图识别到大纲与章节研究计划 导读 查询理解Query Understanding是 op人工智能大模型AI AgentRAG深度研究搜索引擎后端代码智能体openJiuwen DeepSearch 主图节点全景解析从 StartNode 到 EndNode 的研究工作流实现openJiuwen DeepSearch 主图节点全景解析从 StartNode 到 EndNode 的研究工作流实现 本文围绕 openjiuwen_de人工智能大模型AI AgentRAG深度研究搜索引擎后端代码智能体openJiuwen-DeepSearch 产品技术解析基于 agent-core 的知识增强深度搜索与研究引擎openJiuwen DeepSearch 产品技术解析基于 agent core 的知识增强深度搜索与研究引擎 本文系统梳理 openJiuwen Deep人工智能大模型AI AgentRAG深度研究搜索引擎后端代码智能体上一篇Livebook数据可视化终极指南Vega-Lite图表与Maplibre地图集成下一篇Guardrails环境变量配置灵活管理LLM护栏参数创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考