
RD-Agent 数据科学实验生成策略draft / idea / merge / router 与 select 机制设计解析【免费下载链接】RD-AgentResearch and development (RD) is crucial for the enhancement of industrial productivity, especially in the AI era, where the core aspects of RD are mainly focused on data and models. We are committed to automating these high-value generic RD processes through RD-Agent, which lets AI drive>项目地址: https://gitcode.com/GitHub_Trending/rd/RD-Agent本文围绕 RD-Agent 数据科学场景中的实验生成exp_gen模块设计文档展开系统讲解其“draft新建解、idea改进假设、merge合并解”三种核心优化策略与 router元策略路由的设计思想以及 select 工具中 expand扩展点选择与 submit最终方案挑选两类能力。读完本文你可以理解该模块的完整策略分层、各策略在源码中的落地位置rdagent/scenarios/data_science/proposal/exp_gen/目录并掌握max_trace_num、merge_hours、sota_count_window等关键配置项的默认值与作用机制。1. 背景数据科学场景下的“方案优化”在 RD-Agent 的数据科学Kaggle 式竞赛场景中Agent 会不断生成、执行、评估实验。所有历史实验及反馈被组织成一棵 DAG 形式的DSTrace定义于 base.py其中记录了hist已提交的实验-反馈序列dag_parent每个节点实验的父节点索引支持多分支并行探索sota_exp_to_submit当前用于提交的全球最优实验uncommitted_experiments已生成但尚未完成未提交的实验键为 loop_id。在此基础上DSTrace提供了若干被所有策略共用的“查询原语”例如sota_experiment()/last_successful_exp()按search_typeall或ancestors检索最优/最近成功实验next_incomplete_component()按COMPLETE_ORDER (DataLoadSpec, FeatureEng, Model, Ensemble, Workflow)base.py判断流水线还缺哪个组件get_leaves()返回 DAG 的叶子节点即当前所有可扩展的分支末端。设计文档 exp_gen/README.md 开篇即点明了核心问题“优化方案是一段漫长旅程Optimization is a long journey我们可能会在不同策略之间切换”。本文的其余部分正是围绕这一判断展开。2. 三种优化策略与 router 元策略设计文档将“优化解”的过程归纳为三种策略外加一种用于在它们之间切换的元策略router策略文档定义源码落地位置draft创建一个新的初始方案draft/draft.pyidea提出改进现有方案的假设proposal.py、idea_pool.pymerge合并不同的方案merge.pyrouter在策略之间路由的元策略可有多实现router/init.py2.1 draft从零构建首个可运行方案“draft”策略的目标是当尚无有效基线时先把流水线搭起来。源码中对应两个实现均在 draft/draft.pyDSDraftExpGen面向“组件分解”模式。gen()按固定配置表依次为DataLoadSpec、FeatureEng、Model、Ensemble、Workflow生成任务分别实例化DataLoaderTask、FeatureTask、ModelTask、EnsembleTask、WorkflowTask并注入最近一次成功实验的工作区代码使新实验站在已有代码基础上继续。它还特别处理了“连续失败”的情况若上一次对同一组件的实现抛出异常会把异常信息一并写入 prompt提示模型“换一种方法避免死循环”。DSDraftV2ExpGen面向整条流水线的草案生成流程为“生成领域 tag → 组装通用知识 → 基于知识生成假设 → 生成CodingSketch任务描述”最终统一输出一个DSExperiment。调用侧的入口是 proposal.py 中的draft_exp_in_decomposition()def draft_exp_in_decomposition(scen: Scenario, trace: DSTrace) - None | DSDraftExpGen: next_missing_component trace.next_incomplete_component() if next_missing_component is not None: return DSDraftExpGen(scenscen).gen(componentnext_missing_component, tracetrace) else: return None即只要DSTrace里还缺组件就直接走 draft 路径补组件而不进入“改进假设”流程。值得注意的是proposal.py顶部保留了一条 TODO 注释proposal.py“DSDraftExpGen should be moved to router in the further”这与设计文档“router 负责策略调度”的定位完全一致。2.2 idea提出并筛选改进假设“idea”策略是 exp_gen 的主体。当前仓库的主实现是DSProposalV2ExpGenproposal.py其gen()方法约 proposal.py#L1300-L1499构成一个多步流水线问题识别identify_problem分为两类问题源SCENARIO_PROBLEM从场景描述与 SOTA 描述中识别数据驱动/领域驱动的挑战Pydantic 模型ScenarioChallenges约束“最多五个挑战、宁少而精”FEEDBACK_PROBLEM从历史实验反馈、代码实现审查与 trace 历史中提炼问题TraceChallenges。 两类问题按scen_prob_multiplier max(0, 3 - weighted_exp_num // 4)的权重动态配比——实验积累越多场景类问题权重越低反馈类问题权重越高避免 Agent 在已有充分反馈后仍泛泛地谈场景。想法池采样Step 1.5若DS_RD_SETTING.enable_knowledge_base开启trace.knowledge_base.sample_ideas()会从知识库中采样历史想法注入问题集数据结构见 idea_pool.py 的DSIdea。假设生成hypothesis_genLLM 为每个问题产出一条对应假设并自带五维自评对齐度、影响力、新颖度、可行性、风险收益比见HypothesisEvaluation模型可选的 RAG 检索enable_research_rag会补充社区讨论与公开代码知识。假设批判与重写可选enable_hypo_critique_rewrite开启时先hypothesis_critique找缺陷再hypothesis_rewrite产出改进版失败时回退到原始假设保证主流程鲁棒。假设选择Step 3两条路径二选一加权打分compute_top_scores()采用固定权重proposal.py#L859-L891alignment 0.2、impact 0.4、novelty 0.2、feasibility 0.1、risk_reward_balance 0.1取前五随后select_hypothesis()对“来自想法池的假设 3 倍加权”“场景类/反馈类问题按 multiplier 线性衰减加权”并用 MD5 哈希生成可复现的伪随机数从中挑选LLM 直接选择llm_select_hypothesisTrue时改由hypothesis_select_with_llm()结合剩余时间、历史 SOTA 分数、按余弦相似度采样的历史假设_prob_dis_torch等上下文做决策。任务生成task_gen将选定假设转成CodingSketch含current_state、modifications、structure、sketch、packages字段并实例化为具体任务如ModelTask、PipelineTask同时按需追加WorkflowTask更新工作流若任务声明了packages还会通过get_packages()查询运行时环境并缓存。此外还有一个更朴素的基线实现NaiveExpGennaive.py不区分组件直接让 LLM 基于 SOTA 描述与完整 trace 描述生成一个PipelineTask假设即任务描述本身便于对照实验。2.3 merge合并不同分支的方案设计文档将merge定义为“合并不同的方案”。merge.py 中提供两级实现MergeExpGen最直接的合并——取 trace 前两棵子树的 SOTAtrace.get_leaves()得到叶子后分别取sota_experiment_fb用模板渲染“当前最优解 其反馈 待合并解 其成功迭代过程”生成一个PipelineTask其假设固定为“合并两个版本的方案可兼得双方优点”merge.py#L26-L96。ExpGen2Hypothesis继承DSProposalV2ExpGen的增强版。它会遍历除当前选中分支外的所有叶子按max_sota_retrieved_num * 2 // 叶子数的配额从各分支收集 SOTA 实验merge.py#L148-L200再通过定制 promptmerge.yaml让 LLM 从多个分支的成功迭代中“提出合并假设”而不是机械拼贴。若sota_exp_to_submit已存在还会优先选择与其最终分数最接近的其他分支参与合并get_exp_index。2.4 router在 draft / idea / merge 之间路由设计文档指出“router 是一个在策略间路由的元策略可以有多实现”。当前仓库的核心 router 实现是 router/init.py 中的ParallelMultiTraceExpGen它同时持有三个“子策略”self.exp_gen DataScienceRDLoop.default_exp_gen(self.scen) # idea 策略默认实验生成 self.draft_exp_gen DSDraftV2ExpGen(self.scen) # draft 策略 self.merge_exp_gen ExpGen2Hypothesis(self.scen) # merge 策略 self.trace_scheduler: TraceScheduler import_class(DS_RD_SETTING.trace_scheduler)(...) self.planner import_class(DS_RD_SETTING.planner)(self.scen)其async_gen()的路由决策router/init.py#L104-L125可以概括为draft 分支计时器未启动或剩余时间 ≥merge_hours且当前子 trace 还没有 SOTA 实验且enable_draft_before_first_sotaTrue→ 走 draftmerge 分支计时器已启动、剩余时间 merge_hours进入“收尾合并期”、且叶子数 ≥ 2 → 走 merge其余情况→ 走默认 idea 策略。在进入收尾期前router 还会用调度器选定的叶子把current_selection固化到 trace 上并在返回前trace.register_uncommitted_exp(exp, loop.loop_idx)登记新实验。从源码结构看这个“基于剩余时间 SOTA 状态 分支数”的路由器正是文档中“优化是长旅程、需要切换策略”的直接工程化。3. select 工具expand 与 submit 两种能力文档将select定位为“供其他策略或步骤使用的能力”并列出两种典型用法submit结束优化前必须选出一个方案提交expand可以选择一个点作为下一次扩展的起点。这两点在 select/ 目录下各有一个对应文件。3.1 expand决定“下一次从哪个节点扩展”select/expand.py 实现了四个CheckpointSelector它们的返回值语义一致(-1,)表示继续在最新试验上扩展空元组trace.NEW_ROOT表示开一条新子 trace(idx,)表示回跳到第 idx 个历史节点扩展LatestCKPSelector始终返回(-1,)即线性迭代是最简单的默认选择器LimitTimeCKPSelector按“总时长扣除merge_hours后除以max_trace_num”计算每条子 trace 的时间预算超时就跳到新子 trace达到max_trace_num上限则继续当前 traceSOTAJumpCKPSelector以sota_count_window为窗口统计最近试验中feedback.decisionTrue的次数若低于sota_count_threshold判定“当前分支陷入瓶颈”跳到新子 traceBackJumpCKPSelector在同样触发条件下以 50% 概率开新 trace50% 概率回跳到“倒数第二个 SOTA”节点认为最新的 SOTA 未必是好的扩展点。与之配合的是 trace_scheduler.py 中的并发调度器RoundRobinScheduler、SOTABasedScheduler、MCTSScheduler等它们解决的是并行多 trace 场景下“下一个空闲执行槽该扩哪条分支”的问题BaseScheduler.next()采用“先提交 pending 选择、再原子选择父节点选不到就asyncio.sleep等待”的写法保证多循环并发下的选择一致性。3.2 submit从整棵 trace 中挑出唯一提交方案select/submit.py 实现了四个SOTAexpSelector对应“结束前选出一个方案”这一能力GlobalSOTASelector直接取全 trace 的sota_experiment(search_typeall)即全局分数最优实验AutoSOTAexpSelector先从各分支叶子按配额收集 SOTA 候选受max_sota_retrieved_num约束、按分数排序去重再让 LLM 阅读每个候选的描述与最终分数返回selected_SOTA_idxLLM 输出非法时回退到“最新的 SOTA 实验”。候选数超过上下文时通过build_messages_and_calculate_token()提前截断BestValidSelector纯分数排序的 Top-N 选择器支持use_decision决策为正的实验优先与each_trace按分支各取 Top-k两种模式ValidationSelector最重的“元选择器”。它在/tmp/mock/competition下用 LLM 生成或复用已验证的data.py从原始数据采样、固定随机种子与grade.py本地评分然后对每个候选实验多进程重跑main.py并按统一口径打分最终按验证集分数排序选出最佳——从源码结构看这是为缓解“离线分数与线上排名不一致”而设计的重新验证机制。文件底部还提供了select_on_existing_trace()fire.Fire入口离线评估脚本可对已有 trace 的 pickle 或日志目录回放上述四种选择器统计“命中奖牌 loop”的命中率check_hit输出result_selector.json汇总。这为选择器策略的调优提供了可复现的评测手段。4. 建议目录结构与源码对照设计文档给出的目标结构如下原文档“Suggest folder structure”- router/ - idea/ - samll_step(or refine?).py - normal.py - draft/ - merge/ - select/ - expand.py - submit.py对照当前仓库exp_gen/的实际布局可以整理出如下映射文档建议实际仓库状态router/已落地router/init.pyParallelMultiTraceExpGen路由器idea/samll_step(or refine?).py、idea/normal.py从源码结构看尚无独立的idea/子目录idea 策略由 proposal.pyDSProposalV1ExpGen/DSProposalV2ExpGen承载“normal”整轮改进与“small step”组件级微调的区分体现在coder_on_whole_pipeline开关与组件分解模式上文档中的设想尚未拆分为独立文件draft/已落地draft/draft.py draft/prompts_draft.yamlmerge/以单文件 merge.py merge.yaml 形式落地未拆为目录select/expand.py已落地select/expand.pyselect/submit.py已落地select/submit.py目录之外模块还包含若干支撑文件base.pyDSTrace/DSHypothesis、planner/init.py实验计划、trace_scheduler.py并行调度、idea_pool.py、diversity_strategy.py跨 trace 多样性注入、naive.py朴素基线以及提示词文件 prompts.yaml、prompts_v2.yaml、naive.yaml。总体上看文档建议的“策略目录化”已实现约一半router / draft / select 完全对应idea 与 merge 待进一步拆分。5. planner为每次实验生成附加计划planner/init.py 定义了DSExperimentPlan与DSExpPlannerHandCraft。计划默认包含三个键exp_gen.draft是否需要生成初始草案exp_gen.suggest_model_architecture是否建议新的模型架构exp_gen.suggest_model_ensemble是否建议模型集成当前按时间比例触发的分支被注释掉仅保留键。DSExpPlannerHandCraft.plan()的规则planner/init.py#L27-L45trace 中还没有 SOTA 时置draftTrue已有 SOTA 且剩余时间比例大于model_architecture_suggestion_time_percent时开启“模型架构建议”。路由器在enable_plannerTrue时才会调用它否则使用空计划DSExperimentPlan()计划随后通过exp_gen.gen(trace, plands_plan)传入各策略供 prompt 消费。6. 关键配置项一览DS_RD_SETTING上述策略的行为主要由 rdagent/app/data_science/conf.py 中的DS_RD_SETTING控制与本文主题强相关的配置项及默认值如下以当前仓库源码为准配置项默认值作用coder_on_whole_pipelineTrue组件分解 vs 整条流水线生成True时任务统一走PipelineTask否则按组件生成且 draft 补组件逻辑被跳过spec_enabledTrue是否读取工作区内spec/*.md规格文件作为任务规格否则用内置component_spec模板max_trace_num1并行子 trace 上限expand 选择器与 trace 调度器均以此为界sota_count_window5SOTAJump/BackJump 选择器统计 SOTA 密度的窗口长度sota_count_threshold1窗口内 SOTA 次数低于该值即触发“跳新 trace / 回跳”merge_hours0收尾合并期时长剩余时间低于该值时 router 切换到 merge 策略expand 选择器也据此分配子 trace 时间预算max_sota_retrieved_num10submit/merge 侧收集 SOTA 候选的总配额enable_draft_before_first_sotaFalse是否在首个 SOTA 出现前允许走 draft 策略enable_plannerFalse是否启用DSExpPlannerHandCraft生成实验计划model_architecture_suggestion_time_percent0.75剩余时间比例高于该值时开启模型架构建议llm_select_hypothesisFalse假设选择走 LLM 决策还是加权打分trace_scheduler/planner/scheduler_temperature见 conf.py以字符串类路径方式被import_class动态加载便于切换 RoundRobin / SOTA / MCTS 等调度实现需要说明的适用前提merge_hours、sota_count_window等参数依赖全局计时器RD_Agent_TIMER_wrapper.timer已启动即任务设定了总时长限制在max_trace_num1的默认单 trace 配置下多分支 expand/submit 逻辑不会触发模块退化为“线性迭代 全局最优提交”。7. 小结exp_gen模块的设计文档虽然篇幅不长但它给出的“draft / idea / merge 三策略 router 元路由 selectexpand / submit工具”分层在源码中得到了相当完整的对应draft负责冷启动补组件DSDraftExpGen/DSDraftV2ExpGenidea负责核心假设工程问题识别 → 想法池 → 生成 → 批判重写 → 加权或 LLM 选择 →CodingSketch任务merge负责收尾期跨分支融合MergeExpGen/ExpGen2HypothesisrouterParallelMultiTraceExpGen按“剩余时间 / SOTA 状态 / 分支数”把执行流分发给上述策略并借助 trace 调度器实现并行多分支select把“从哪扩展”四个 CheckpointSelector 调度器与“最终交哪个”四个 SOTAexpSelector 离线评估脚本拆成两个可独立替换的能力。如果你想继续深入建议按如下顺序阅读先看 base.py 理解DSTrace的数据模型再看 router/init.py 的路由决策然后分别对照 select/expand.py 与 select/submit.py 的策略实现最后用 conf.py 中的默认值核对各开关的实际生效条件。【免费下载链接】RD-AgentResearch and development (RD) is crucial for the enhancement of industrial productivity, especially in the AI era, where the core aspects of RD are mainly focused on data and models. We are committed to automating these high-value generic RD processes through RD-Agent, which lets AI drive>项目地址: https://gitcode.com/GitHub_Trending/rd/RD-Agent创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考