项目实训博客记录8 这个博客记录用于记录agent流的完善。在完成各个任务服务和知识服务的开发后平台已经具备了自然语言交互能力。用户输入问题后系统能够自动完成任务路由、参数解析、任务执行以及结果解释形成了一套完整的 Chat 工作流。但是在实际使用过程中发现这种流程本质上仍然属于固定 Workflow。整个执行过程由程序提前定义好当路由完成后就按照固定顺序依次执行参数解析、任务调用和结果返回各模块之间不存在自主规划能力。对于单轮任务这种方式已经能够满足需求但面对复杂问题时其局限性逐渐显现。首先当前系统一次只能执行一个任务。虽然 Router 能够识别用户意图但只能返回单个task type例如知识问答、修饰预测或二级结构预测而无法将一个复杂需求拆分成多个子任务依次执行。例如用户提出预测该 RNA 的修饰位点并结合文献分析其生物学功能时现有流程只能选择其中一个任务执行而无法自动完成预测→知识检索→综合分析这样的多阶段任务。其次当前各个 Service 之间相互独立任务执行结束后立即返回结果并不会根据执行结果继续决定下一步操作。虽然系统增加了上一轮结果记忆使用户可以继续追问为什么或详细解释一下但这种能力仍然属于固定流程下的结果复用而不是 Agent 根据当前状态自主规划后续动作。另外当前 Memory 的作用主要是保存上一轮任务结果为结果解释服务提供上下文支持。它记录了上一轮任务类型、执行结果和回复内容使系统能够完成连续追问解释但并没有参与任务规划也不能根据历史执行状态动态调整执行策略。因此现有 Chat 系统实际上更接近Router Workflow Memory的组合模式而不是完整的 Agent。它能够根据用户意图选择不同服务但整个执行链路仍然是预定义的固定流程缺乏任务拆解、自主规划、多工具协同和动态决策能力。因此为了让RNAInsight的Agent更加完善智能我开始开发第二代的chat service。并且想到chat service v1版本可以用于满足用户轻量级的请求需要而v2版本用于满足客户更加复杂的需要比如多轮任务规划等。首先是 Service 层的修改。在项目初期由于尚未形成统一的 Service 开发模板motif 模块的 single 服务与另外三个 Service 在返回结构上存在一定差异这导致 Java 端需要针对不同任务分别编写解析逻辑增加了接口维护成本。另一方面原有 Service 在完成预测后仅仅是将结果直接塞入 task_result 中进行返回不同任务的 task_result 内部结构完全不同。例如有的任务直接返回预测结果有的返回列表还有的附带额外统计信息缺乏统一的数据协议。这种设计虽然能够满足单任务调用但无法支撑后续 Agent 的多任务规划因为多个 Service 返回结果无法进行统一组织和解析。因此本次重构首先从任务返回结构入手。首先设计了统一的 TaskItem 数据结构每一个输入样本都对应一个独立的 TaskItem其中统一包含输入信息、预测结果、生成文件、警告信息以及扩展元数据等内容。这样无论底层执行的是家族分类、修饰预测还是结构分析对于上层来说一个样本始终对应一个标准化对象。在 TaskItem 之上又进一步增加了 TaskEnvelope 层将同一次任务中的多个 TaskItem 封装到统一任务对象中同时增加 task_type、status、params、summary 等任务级信息使每个 Service 返回的不再只是预测结果而是具有完整生命周期描述的任务实体。最后在最外层构建统一的 TaskResult 协议将一个或多个 TaskEnvelope 统一封装到 tasks 数组中并增加 schema_version、整体执行状态、统计信息和全局元数据等字段。由于所有 Service 都遵循同一协议因此无论底层任务类型如何变化Java 端和 Chat 服务都只需要按照统一格式解析即可大幅降低了系统耦合度。更重要的是这种设计天然支持多任务规划。当 Agent 将复杂问题拆分成多个子任务后每个 Service 可以独立生成自己的 TaskResult再通过统一的合并接口将多个任务对象组合到同一个 tasks 列表中。这样多任务执行与单任务执行拥有完全一致的返回格式上层无需增加新的解析逻辑只需要遍历任务列表即可完成结果整合为后续 Agent 的自主规划和多工具协同提供了统一的数据基础。然后是 Route Service 的改造。在最初版本中路由模块仅根据当前用户输入判断任务类型返回 task_type、need_sequence 等简单信息。这种设计能够完成单轮任务分发但缺乏上下文理解能力无法支持 Agent 场景下的连续对话和多任务规划。因此在重构过程中首先对 Router 的输入进行了扩展。除了保留用户当前输入外又增加了历史对话History、请求附加信息Extra以及 Agent Context 三部分内容并统一构造成 Prompt 输入大语言模型。其中History 用于保存最近几轮对话内容Extra 用于描述当前输入模式如文本输入或 FASTA 文件输入而 Agent Context 则保存上一轮任务类型、是否存在可解释结果以及上一轮回复摘要等状态信息。这样Router 不再依赖当前一句话进行判断而是能够结合整个上下文进行决策。与此同时对 Prompt 本身也进行了重新设计。Prompt 不再只是简单询问“当前属于什么任务”而是明确规定了各类任务的定义、FASTA 文件处理规则、任务判定优先级以及边界案例并要求模型严格按照统一 JSON 格式输出路由结果。这种方式减少了模型自由发挥带来的不稳定性使路由结果更加稳定和可控。在得到模型输出后系统并没有直接采用结果而是增加了一层结果校验机制。程序首先检查返回 JSON 是否符合规定格式再统一校验布尔字段和任务类型是否合法对于模型误判的情况还会根据规则进行自动修正。例如当用户询问“m6A 是什么”时即使模型误判为修饰预测任务也会根据知识问答规则自动修正为 knowledge_qa而对于“为什么”“解释一下”等模糊短句则结合 Agent Context 中保存的上一轮执行状态判断究竟属于知识问答还是结果解释实现了上下文感知路由。除此之外为保证系统稳定运行还设计了规则路由作为兜底方案。当大语言模型返回非法 JSON、输出异常或者调用失败时系统不会直接报错而是进入规则路由流程根据关键词匹配和 Agent 状态重新判断任务类型保证路由服务始终能够返回合法结果。通过这种“LLM 路由 规则校验 规则兜底”的三级机制Route Service 的稳定性和鲁棒性得到了进一步提升。经过上述改造Route Service 已经从最初的单轮关键词路由演进为结合历史对话、输入模式和 Agent 状态的上下文感知路由模块为后续 Agent 的连续对话、多任务规划以及自主决策提供了统一的入口。然后是 Parser Service 的改造。在原有架构中Parser 的职责主要是根据路由结果提取参数例如提取 RNA 序列、修饰类型或模型参数并直接生成对应任务的参数对象。这种设计能够满足单任务执行但无法支持 Agent 的多任务规划因为整个解析过程始终只围绕单个 task_type 展开。因此在新版 Parser 中首先保留了原有的参数解析逻辑将序列提取、模型参数解析以及 FASTA 文件解析统一封装使不同任务都能够通过相同入口完成输入解析。同时增加了输入来源自动识别机制系统会优先判断是否使用上传的 FASTA 文件如果不存在文件输入则自动从自然语言中提取序列并根据序列数量自动识别为单序列输入或批量输入实现了不同输入模式的统一管理。在此基础上为了支持多任务规划对 Parser 的返回结构进行了扩展。当检测到用户请求中同时包含多个任务意图时Parser 不再只返回一个解析结果而是在保留原有解析结果的基础上增加 execution_mode 和 task_plan 字段。其中execution_mode 用于标识当前任务执行模式而 task_plan 则保存多个待执行子任务的信息。随后系统会根据识别出的多个任务类型为每个子任务分别构建独立的 parsed_result。构建过程中并不会重新解析输入而是复用父任务已经解析好的序列、文件路径以及输入模式等公共信息仅根据不同任务补充对应的业务参数例如家族分类参数、修饰预测参数、结构预测参数或 motif 分析参数。这样既避免了重复解析又保证了多个子任务拥有相互独立的执行参数。最终Parser 返回的已经不再是单一任务参数而是一个包含多个子任务解析结果的任务规划对象。后续 Agent 只需要按照 task_plan 中定义的顺序依次调度各个 Service 即可完成复杂请求的执行而无需再次进行参数解析。这使得 Parser 从传统的参数提取模块演进为任务规划的生成模块为 Agent 的多任务协同执行提供了统一的任务描述接口。在完成 Service 返回结构、Router 和 Parser 的改造后最后一步是构建真正的 Agent Service。相比原来的 Chat WorkflowAgent Service 不再只是按照固定顺序调用模块而是在内部维护状态、观察执行质量、根据任务计划调用不同 Skill并支持多轮结果追问。首先是 Skill 注册。代码中通过TASK_HANDLERS将任务类型和具体 Service 绑定起来例如classification对应 family servicemodification_prediction对应 modification service。这样 Agent 主流程不需要写死每个任务的调用逻辑只需要根据task_type查表执行。SkillRegistry {classification: FamilyService,modification_prediction: ModificationService,motif_analysis: MotifService,structure_prediction: StructureService}handler SkillRegistry[task_type]result handler(parsed_result)然后是多任务规划执行。Parser 如果判断用户请求中包含多个任务会在parsed_result中加入task_plan。Agent 检测到task_plan后不再走单任务分支而是依次读取每个子任务取出对应的task_type和parsed_result再调用注册好的 Skill。每个子任务执行完成后结果会被收集起来最后合并成统一的 v2task_result。results []for step in task_plan:task_type step.task_typechild_parsed step.parsed_resulthandler SkillRegistry[task_type]result handler(child_parsed)results.append(result)task_result MergeTaskResults(results)这里没有把多任务设计成新的multi_task类型而是把它看成多个已有任务的组合。这样可以复用原有四类任务服务也方便后续继续扩展新 Skill。接着是质量检查。Agent 内部增加了Observation和AgentState。每经过一个阶段例如 Router、Parser、Precheck、Task、Explain都会调用 observe 记录当前阶段是否正常。这个信息不会返回给前端但会写入日志用于判断系统运行状态。Observe(stage, ok, code, message)if Router 成功:Observe(router, true, router_ok)if Parser 缺少 input_mode:Observe(parser, false, missing_input_mode)if Precheck 不通过:Observe(precheck, false, precheck_failed)更进一步Agent 还会对任务结果做质量观察。比如 family 分类会检查 top1 置信度是否偏低、top1 和 top2 差距是否过小modification 预测会检查概率是否接近阈值。如果结果处在边界区域Agent 会记录 warning说明结果需要谨慎解释。if task_type classification:if top1_score 0.50:Warning(classification_low_confidence)if top1_score - top2_score 0.10:Warning(classification_small_margin)if task_type modification_prediction:if abs(probability - threshold) 0.05:Warning(modification_near_threshold)然后是 fallback。对于融合模型来说Qwen embedding、checkpoint、显存等都可能出问题。如果任务首次执行失败并且错误信息与llm_fusion、embedding、cuda out of memory等有关Agent 会自动把model_mode改成base再执行一次。这样不会因为一个增强分支失败就导致整个任务失败。try:result ExecuteTask(parsed_result)except error:if model_mode llm_fusion and error 可降级:parsed_result.model_mode baseresult ExecuteTask(parsed_result)else:raise error最后是多轮记忆。Agent 每次完成可解释任务后会把上一轮的任务类型、解析结果、任务结果、解释文本保存到 memory 中。当用户继续问“为什么”“详细解释一下”时Router 会结合agent_context判断这是结果追问而不是新的知识问答。随后 Agent 读取上一轮结果调用 followup explain 进行增量解释并将新的解释继续写回 memory。SaveMemory(task_type, parsed_result, task_result, explanation, reply)if user asks follow-up:last_result LoadMemory()explanation ExplainFollowUp(current_question,last_result.task_result,last_result.reply)SaveMemory(explanation)return explanation通过这些改造Agent Service 相比原来的 Chat Workflow 多了几个关键能力它可以注册并调用不同 Skill可以执行多任务规划可以观察每个阶段的执行质量可以在模型异常时自动降级也可以基于上一轮结果进行连续追问解释。这样整个系统才真正从“固定流程调用”过渡到了更接近智能体的执行方式。然后展示新的chat service现在命名为agent service的效果展示。可以看到现在在聊天框中输入两种任务类型家族识别和修饰识别任务service完成了多轮任务规划和多轮任务规划的结果生成。