乐于分享
好东西不私藏

我们用AI工作流做了一个"研发过程文档自动生成"智能体

我们用AI工作流做了一个"研发过程文档自动生成"智能体
背景:企业研发文档是一场持续的"纸质马拉松"

做过研发项目申报的人都知道,光是文档就能把人搞崩溃。

一个研发项目从立项到结题,需要准备的文档包括:立项评审报告、研发项目任务书、项目建议书,然后每个月还要交月度会议纪要、试验试制通知单、验证报告……如果项目周期是一年,试制周期 8 个月,光是这些过程文档就接近 30 份。

每一份都要结合项目实际情况来写,结构固定但内容不能复制粘贴,否则审计一眼就看出来了。

这是一个典型的"结构固定、内容差异化、工作量巨大"的场景——非常适合 AI 来做。

我们做了什么

我们在 RDAgent Cloud 平台上,基于现有的 AI 工作流引擎,开发了一个研发过程文档智能生成功能。

用户只需要:

  1. 填写公司名称、项目名称、项目周期、试制周期
  2. 上传项目计划书(立项素材,1个Word文件)
  3. 可选上传各月的研发阶段文档(每月最多3个)
  4. 点击"生成研发过程文档"

系统会自动生成一整包文档,打包成 zip 发到任务中心,用户直接下载。

输出内容

  • 立项阶段:项目建议书 + 立项评审报告 + 研发项目任务书(共3份)
  • 试制阶段:每月 月度会议纪要 + 试验试制通知单 + 验证报告(最后月额外生成验收会议纪要)

一个 8 个月试制周期的项目,一次生成 27 份文档,打包下载。

架构设计:三阶段流水线

整个系统的核心思路是"先理解,再分发,再并行"

① 前置理解轮
   ↓ 读取立项素材,提炼 materialSummary
   ↓ 所有后续文档节点共享这份摘要,无需传递完整原文

② 立项阶段并行生成
   ↓ 3份立项文档同时生成(parallel 节点)
   ↓ 等待全部完成(merge waitAll)

③ 月度文档流水线
   ↓ 按试制月份逐月处理
   ↓ 每月:先生成"本月问题+解决方案",再生成3份文档
   ↓ 有月度上传文档 → 结合文档生成;无文档 → 纯靠素材摘要生成

最终所有文档渲染为 docx,打包 zip,上传 OSS,用户在任务中心下载。

最核心的设计决策:月度文档怎么做差异化?

这是整个项目最难的问题。

如果让 AI 对 8 个月都用同一份 systemPrompt 生成,结果几乎一模一样,一眼就能看出是批量生成的。

我们的解法分两层:

第一层:月度问题预生成

在生成会议纪要、通知单、验证报告之前,先让 AI 生成"本月遇到的问题 + 解决方案"。这个问题缓存(issueSummary)会作为后续3份文档的上下文注入。

  • 如果用户上传了当月的研发阶段文档,AI 会结合文档生成问题(有真实依据)
  • 如果没上传,AI 会基于项目素材摘要和月份信息推断合理问题

第二层:会议类型差异化

月度会议纪要不是每个月都一样的——

  • 第一个月:项目首次会议(项目评审会)
  • 中间月:月度试制推进会
  • 最后月(且是项目结题月):验收会议

每种类型对应不同的提示词,生成的内容角度完全不同。

这两层设计,让每个月的文档在结构相同的前提下,内容具备足够的差异性。

一个新节点:MonthlyProcessorNode

为了封装月度文档生成逻辑,我们开发了一个自定义节点 MonthlyProcessorNode

它的核心逻辑是:

for (YearMonth month : trialMonths) {
    // 1. 生成本月问题+解决方案
    String issueSummary = generateIssueSummary(state, month, monthlyFiles, materialSummary);
    
    // 2. 判断会议类型(首次/中间/验收)
    String meetingType = isFirstMonth ? "first" : (isProjectLastMonth ? "final" : "middle");
    
    // 3. 依次生成:月度会议纪要 + 通知单 + 验证报告
    monthDoc.put("meeting", generateMeeting(..., meetingType));
    monthDoc.put("notice",  generateNotice(...));
    monthDoc.put("report",  generateReport(...));
    
    // 4. 最后月额外生成验收会议纪要
    if (isProjectLastMonth) monthDoc.put("finalMeeting", generateMeeting(..., "final"));
}

用一个节点封装了所有月度逻辑,工作流拓扑保持干净简洁——无论试制周期是 1 个月还是 12 个月,工作流 JSON 完全不变,节点数固定。

另一个新节点:ZipPackageNode

文档生成完之后还有一个问题:原来的智能体只输出单个 Word 文件,现在要输出一批文件。

我们新增了 ZipPackageNode,把所有渲染好的 docx 打包成 zip:

try (ZipOutputStream zos = new ZipOutputStream(baos)) {
    for (Map<String, Object> file : renderedFiles) {
        zos.putNextEntry(new ZipEntry(file.get("fileName")));
        zos.write((byte[]) file.get("fileBytes"));
        zos.closeEntry();
    }
}
String downloadUrl = fileApi.uploadFile(zipFileName, baos.toByteArray());

文件名规则为 研发过程文件_{timestamp}.zip,在任务中心直接提供下载链接。

文档结构设计:AI写什么,渲染器填什么

这是一个容易忽视但非常重要的设计细节。

Word 模板里有很多固定字段(项目名称、项目编号、开始/结束时间、负责人等),这些字段不需要 AI 生成,直接从用户输入的 state 中读取填入。

AI 只负责生成正文内容字段,比如:

文档AI生成字段
立项评审报告评审内容(5个要点)、评审意见
研发项目任务书项目简介、开发要求、进度计划要求、负责人建议
月度会议纪要会议内容、会议结论、执行计划
试验试制通知单试验试制要求、试验试制目的、变更内容
验证报告试验目的、研发资源使用情况、试制情况及问题、指标对比、分析意见

这样做有两个好处:一是 AI 不用生成格式化的表头数据(减少幻觉),二是渲染器可以精确控制每个字段的格式(字体、段落、间距)。

与项目计划书智能体的对比

研发过程智能体是在项目计划书智能体基础上扩展的,两者复用了大量基础设施:

对比项项目计划书研发过程
输出格式单个 Wordzip 包(多个 Word)
LLM调用1轮理解 + 8路并行1轮理解 + 3路并行 + N轮月度串行
月度文档有,按月生成
耗时估计~75秒2~5分钟(6个月约3分钟)

复用的组件包括:MultiFileParserNodeDataValidationNodeExportNode、页眉Logo嵌入逻辑、任务中心接入、计费服务等。

新增的只有 MonthlyProcessorNodeZipPackageNode 和 4 个新的文档渲染器。

一些踩过的坑

坑1:验证报告字段比想象中多

初稿设计时,验证报告只规划了"试制情况及问题"和"分析意见"2个字段。对着实际模板仔细看之后,发现还有"试验试制目的"、"研发资源使用情况"(还分人力/仪器设备/物料耗材三类)、"指标对比"共3个字段被遗漏了。

这类问题的根本原因是先设计节点、后看模板。正确的顺序应该是:先把每份模板的每个字段列清楚,再设计 LLM 输出结构和提示词。

坑2:月度文档内容容易趋同

前几次测试的 8 份月度会议纪要几乎是一样的,只有月份不同。后来在提示词中明确加入"每个月生成的内容相对独立"的约束,并且把当月问题和解决方案作为差异化上下文注入,才明显改善。

坑3:LLM 调用次数比预估多

6个月试制周期:立项 3 次 + 每月 4 次(问题 + 会议 + 通知单 + 报告)= 27 次 LLM 调用。12个月就是 51 次。这对超时控制和计费预估都有影响,需要单独设置超时上限。

写在最后

研发过程文档这个场景有一个特点:结构高度标准化,内容需要差异化。这正是 AI 工作流最擅长的领域——用节点编排解决结构问题,用提示词设计解决内容质量问题。

我们的经验是:从模板出发设计,而不是从功能出发设计。先把每份文档的每个字段搞清楚,哪些由 AI 生成、哪些固定填入,然后再设计节点和提示词。这样做出来的系统,后期维护和调整都容易得多。

下一步我们计划支持:

  • 月度文档并行化(当前月内是串行,可以优化为同月3份文档并行)
  • 实时进度反馈(SSE 流式输出每月生成进度,让用户知道"正在生成第3个月的文档")
  • 后台可配置的文档标签管理

如果你们公司也有类似的"批量结构化文档生成"需求,欢迎交流。