Files
AIclinicalresearch/docs/03-业务模块/SSA-智能统计分析/07-统计专家配置/复杂分析分步执行架构评估报告.md
HaHafeng 52989cd03f feat(ssa): Agent channel UX optimization (Solution B) + Plan-and-Execute architecture design
SSA Agent channel improvements (12 code files, +931/-203 lines):
- Solution B: left/right separation of concerns (gaze guiding + state mutex + time-travel)
- JWT token refresh mechanism (ensureFreshToken) to fix HTTP 401 during pipeline
- Code truncation fix: LLM maxTokens 4000->8000 + CSS max-height 60vh
- Retry streaming code generation with generateCodeStream()
- R Docker structured errors: 20+ pattern matching + format_agent_error + line extraction
- Prompt iron rules: strict output format in CoderAgent System Prompt
- parseCode robustness: XML/Markdown/inference 3-tier matching + length validation
- consoleOutput type defense: handle both array and scalar from R Docker unboxedJSON
- Agent progress bar sync: derive phase from agentExecution.status
- Export report / view code buttons restored for Agent mode
- ExecutingProgress component: real-time timer + dynamic tips + step pulse animation

Architecture design (3 review reports):
- Plan-and-Execute step-by-step execution architecture approved
- Code accumulation strategy (R Docker stays stateless)
- 5 engineering guardrails: XML tags, AST pre-check, defensive prompts, high-fidelity schema, error classification circuit breaker

Docs: update SSA module status v4.1, system status v6.7, deployment changelist
Made-with: Cursor
2026-03-07 22:32:32 +08:00

9.5 KiB
Raw Permalink Blame History

架构委员会评估报告:复杂多步统计分析的 Agentic 分步执行方案

评估议题: 针对“描述 -> 单因素 -> 多因素 -> 敏感性”复杂流,大模型是否可以且应该“分步写代码、分步执行、分步展示”?

评估结论: 🌟 极度赞同! 这是经典的 "Plan-and-Solve (规划并逐步解决)" 智能体设计模式。它不仅解决了大模型的上下文窗口限制,更是解决“步骤间因果依赖”的唯一工程解法。

一、 为什么“一次性生成全部代码”注定失败?(The One-Shot Trap)

在你提供的这个 4 步分析法中,存在一个极其关键的**“因果悖论 (Causality Paradox)”**

步骤 3 (多因素分析) 明确要求: “将单因素分析中 P 值小于 0.1 的变量... 纳入多因素逻辑回归模型。”

  • 如果让大模型一次性写完所有代码:
    大模型在写代码的那一刻,根本不知道哪些变量的 P 值会小于 0.1
    为了实现这个需求,大模型必须在 R 代码里写出极度复杂的“动态提参和动态公式拼接”代码(例如:用 R 提取所有卡方和秩和检验的 P 值,动态过滤,然后 as.formula(paste("Yqol ~", paste(selected_vars, collapse="+"))))。
    在真实工程中,这种由大模型动态生成的元编程 R 代码,因为各种检验结果的数据结构不同,运行崩溃率高达 95% 以上
  • 如果采用“分步执行 (Agentic Step-by-Step)”:
    大模型先写步骤 1 和 2。R Docker 跑完后,大模型真真切切地看到了 P 值的输出结果。然后大模型做一个人脑决策:“哦,我看到 age (P=0.03) 和 smoke (P=0.08) 小于 0.1,所以我现在的步骤 3 代码可以直接写死glm(Yqol ~ age + smoke + bmi + sex, ...)”。
    这让代码生成变得极其简单、傻瓜、0 报错!

二、 架构实现方案:如何在无状态的 Docker 中实现“分步”?

R Docker 的 /execute-code 接口是无状态的 HTTP 请求(跑完就销毁内存)。要实现分步执行,我们在 Node.js 编排层有两套落地模式:

方案 A代码累加法 (Code Accumulation) —— 🌟 推荐 MVP 阶段使用

这种方式最简单,不需要改动基础设施。

  1. Turn 1 (描述与单因素)
    • LLM 生成 Code_A加载数据、Table 1、卡方、秩和检验
    • Node.js 发送 Code_A 给 R Docker拿到结果展示给用户。
  2. Turn 2 (多因素)
    • LLM 根据上一步结果,决定了纳入变量,生成 Code_BLogistic 回归)。
    • Node.js 在后台将代码拼接Final_Code = Code_A + "\n" + Code_B。
    • Node.js 把 Final_Code 发给 R Docker 重新跑一遍。虽然前两步被重复跑了但在小数据集下如1000行以内R 跑一次只需零点几秒,用户完全无感知。

方案 B环境快照法 (Workspace Snapshot) —— 适合大数据/耗时计算

如果单因素分析非常耗时(如海量基因数据),不能重复跑。

  1. 执行引擎改造
    在每次 R 脚本执行的最后,强制加上一句 save.image("/tmp/session_xxx.RData"),把当前处理好的清洗后数据、中间变量全部序列化存入本地或 OSS。
  2. 分步调起
    执行步骤 3 时LLM 生成的 R 代码第一句就是 load("/tmp/session_xxx.RData"),直接继承上一步的内存状态继续跑。

三、 对产品体验 (UX) 的降维打击

这种分步执行模式,在前端交互上能带来无与伦比的体验(参考我们在 V12/V13 原型图中的设计):

  1. 进度条变“真”了 (Progressive Rendering)
    原来用户要看一个转圈看 30 秒。现在,系统可以在 5 秒时弹出 Table 1描述统计10 秒时弹出单因素 P 值表格20 秒时弹出 Logistic 回归森林图。用户像看瀑布流一样看着报告生成,极大地降低了等待焦虑。
  2. 极简自愈 (Micro-Healing)
    如果到了第 4 步(多重插补敏感性分析)时 R 引擎因为缺包报错了,系统只需要让大模型重写第 4 步的代码,前面的 3 步成果依然安然无恙地展示在界面上。
  3. 人类干预节点 (Human-in-the-loop)
    在步骤 2 跑完后,可以挂起流程。系统问医生:“基于 P<0.1 的规则AI 拟将 age, smoke 纳入回归模型。您是否需要强制纳入其他具有临床意义的变量?”医生勾选后,再执行步骤 3。这是顶级医疗软件的灵魂。

四、 针对 R 代码执行错误的诊断与防御机制补充 (R Docker Error Prevention)

针对日志中出现的 <text>:14:9: unexpected input 错误(通常由于大模型在 R 代码块中输出了非法的中文注释或未闭合的字符串/标签导致),在架构上需要增加以下防御机制:

1. Coder Agent 输出的预处理清洗 (Pre-Execution Sanitization)

大模型有时会在代码块中混入解释性文字(如“根据您的分析计划,”),如果这些文字没有被加上 # 注释符R 引擎就会报语法错误。

Node.js 侧 (CodeRunnerService) 的强制修正:

在将代码发给 R Docker 之前,执行一层纯正则或 AST 级别的清洗:

  • 提取有效块:只提取 r` 和 ` ` 之间的代码。
  • 过滤孤儿中文:如果存在不在引号内且不以 # 开头的中文字符,这极可能是大模型的解释文字泄漏到了代码块中。可以尝试用正则检测并自动给这些行加上 # ,或者直接截断。
  • (推荐)最简单暴力的方法:在 Coder Agent 的 System Prompt 中加入最严厉的指令:“除了代码块,你绝对不能输出任何解释性文字。必须直接输出纯 R 代码,第一行就是 library(),不要使用 Markdown 代码块标签。”

2. R Docker 端的语法预检 (Syntax Dry-Run)

R Docker 在真正执行计算(尤其是耗时计算)前,应该快速进行一次语法检查,这样能立即抛出友好的错误,而不是等跑了一半才崩溃。

R 端 (execute-code API) 的防御:

可以在 R 侧接收到代码字符串后,先用 parse() 函数尝试解析,如果解析失败,直接返回“语法错误”,不再交给 eval()。

# 在 R API 内部增加预检
tryCatch({
parsed_code <- parse(text = input_code)
}, error = function(e) {
# 这里捕获的就是 unexpected input 这种纯语法错误
stop(paste("R代码语法错误无法解析:", e$message))
})
# 解析通过后,再执行 eval(parsed_code)

3. 错误捕获的鲁棒性 (Robust Error Handling)

日志中显示的 (execResult.consoleOutput || []).slice is not a function 说明 Node.js 在尝试处理 R 的报错信息时,因为 execResult.consoleOutput 不是一个数组而导致了二次报错。这会让后续的自愈机制Self-Healing拿不到真实的错误信息。

后端侧的修正:

确保 CodeRunnerService 在捕获 R 的 HTTP 错误响应时,返回的数据结构永远符合约定,避免抛出 JS 层的 Type Error保证错误能够平稳地传给 Reviewer/Fixer Agent 让其重试。

4. Agent 职责的精细化拆分:引入独立的 Fixer Agent (专门改代码) 🌟

这是彻底解决 AI 陷入“修 Bug 死循环”的最优架构策略Actor-Critic 模式)。不要让原来的 Coder Agent 兼职改代码,必须将其拆分:

  • 📝 Coder Agent纯写代码
    它的职责是“从 0 到 1”专注于把统计学计划翻译成 R 代码。上下文中包含大量的分析需求和数据字典。
  • 🔧 Fixer Agent专门修 Bug
    当 CodeRunnerService 捕获到 R 报错时,唤醒专门的 Fixer Agent
    它拥有完全不同的 System Prompt内部被注入了丰富的“R 语言常见报错及修复指南 (Knowledge Base)”
    Fixer Agent 的 Prompt 示例:"你是一个顶尖的 R 语言 Debug 专家。
    刚才系统执行了这段代码:[原始代码]
    遇到了这个错误:[R 原始报错,如 unexpected input 或 computationally singular]排错指南:
    1. 如果是 unexpected input通常是因为代码块中混入了未注释的中文解释请剔除它们。
    2. 如果是 object not found请核对原始列名大小写是否拼错或者是否漏了引包如 library(dplyr))。
    3. 如果是 computationally singular说明存在严重的共线性或某列方差为0请在代码中添加自动剔除方差为0的变量的逻辑。

请分析错误原因,并输出修复后的纯 R 代码。"

优势: 这种职能拆分让修复动作更具靶向性,大幅降低了大模型面对冰冷的 R 错误日志时产生幻觉的概率,自愈成功率可提升 60% 以上。

五、 最终结论

你提出的分步思路不仅靠谱更是通往高级数据科学智能体Data Science Agent的核心秘籍。

行动建议:

请后端和 Agent 研发团队在接下来的开发中,将这个长流程拆解为一个 “多轮对话状态机 (Multi-turn State Machine)”

  • 设定一个管线数组:[Task1_Desc, Task2_Uni, Task3_Multi, Task4_Sens]。
  • 让 Node.js 控制 LLM 逐个 Task 生成代码 -> 跑 Docker -> 读取结果 -> 喂给下一个 Task 的 Context。

同时,针对本次 R 执行报错,请优先修复错误处理代码中的 slice is not a function Bug引入独立的 Fixer Agent 机制,以确保自愈循环能高效、精准地运转!