
做过研发项目申报的人都知道,光是文档就能把人搞崩溃。
一个研发项目从立项到结题,需要准备的文档包括:立项评审报告、研发项目任务书、项目建议书,然后每个月还要交月度会议纪要、试验试制通知单、验证报告……如果项目周期是一年,试制周期 8 个月,光是这些过程文档就接近 30 份。
每一份都要结合项目实际情况来写,结构固定但内容不能复制粘贴,否则审计一眼就看出来了。
这是一个典型的"结构固定、内容差异化、工作量巨大"的场景——非常适合 AI 来做。

我们在 RDAgent Cloud 平台上,基于现有的 AI 工作流引擎,开发了一个研发过程文档智能生成功能。
用户只需要:
- 填写公司名称、项目名称、项目周期、试制周期
- 上传项目计划书(立项素材,1个Word文件)
- 可选上传各月的研发阶段文档(每月最多3个)
- 点击"生成研发过程文档"
系统会自动生成一整包文档,打包成 zip 发到任务中心,用户直接下载。
输出内容:
- 立项阶段:项目建议书 + 立项评审报告 + 研发项目任务书(共3份)
- 试制阶段:每月 月度会议纪要 + 试验试制通知单 + 验证报告(最后月额外生成验收会议纪要)
一个 8 个月试制周期的项目,一次生成 27 份文档,打包下载。

整个系统的核心思路是"先理解,再分发,再并行":
① 前置理解轮
↓ 读取立项素材,提炼 materialSummary
↓ 所有后续文档节点共享这份摘要,无需传递完整原文
② 立项阶段并行生成
↓ 3份立项文档同时生成(parallel 节点)
↓ 等待全部完成(merge waitAll)
③ 月度文档流水线
↓ 按试制月份逐月处理
↓ 每月:先生成"本月问题+解决方案",再生成3份文档
↓ 有月度上传文档 → 结合文档生成;无文档 → 纯靠素材摘要生成
最终所有文档渲染为 docx,打包 zip,上传 OSS,用户在任务中心下载。

这是整个项目最难的问题。
如果让 AI 对 8 个月都用同一份 systemPrompt 生成,结果几乎一模一样,一眼就能看出是批量生成的。
我们的解法分两层:
第一层:月度问题预生成
在生成会议纪要、通知单、验证报告之前,先让 AI 生成"本月遇到的问题 + 解决方案"。这个问题缓存(issueSummary)会作为后续3份文档的上下文注入。
- 如果用户上传了当月的研发阶段文档,AI 会结合文档生成问题(有真实依据)
- 如果没上传,AI 会基于项目素材摘要和月份信息推断合理问题
第二层:会议类型差异化
月度会议纪要不是每个月都一样的——
- 第一个月:项目首次会议(项目评审会)
- 中间月:月度试制推进会
- 最后月(且是项目结题月):验收会议
每种类型对应不同的提示词,生成的内容角度完全不同。
这两层设计,让每个月的文档在结构相同的前提下,内容具备足够的差异性。

为了封装月度文档生成逻辑,我们开发了一个自定义节点 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 完全不变,节点数固定。

文档生成完之后还有一个问题:原来的智能体只输出单个 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,在任务中心直接提供下载链接。

这是一个容易忽视但非常重要的设计细节。
Word 模板里有很多固定字段(项目名称、项目编号、开始/结束时间、负责人等),这些字段不需要 AI 生成,直接从用户输入的 state 中读取填入。
AI 只负责生成正文内容字段,比如:
| 文档 | AI生成字段 |
|---|---|
| 立项评审报告 | 评审内容(5个要点)、评审意见 |
| 研发项目任务书 | 项目简介、开发要求、进度计划要求、负责人建议 |
| 月度会议纪要 | 会议内容、会议结论、执行计划 |
| 试验试制通知单 | 试验试制要求、试验试制目的、变更内容 |
| 验证报告 | 试验目的、研发资源使用情况、试制情况及问题、指标对比、分析意见 |
这样做有两个好处:一是 AI 不用生成格式化的表头数据(减少幻觉),二是渲染器可以精确控制每个字段的格式(字体、段落、间距)。

研发过程智能体是在项目计划书智能体基础上扩展的,两者复用了大量基础设施:
| 对比项 | 项目计划书 | 研发过程 |
|---|---|---|
| 输出格式 | 单个 Word | zip 包(多个 Word) |
| LLM调用 | 1轮理解 + 8路并行 | 1轮理解 + 3路并行 + N轮月度串行 |
| 月度文档 | 无 | 有,按月生成 |
| 耗时估计 | ~75秒 | 2~5分钟(6个月约3分钟) |
复用的组件包括:MultiFileParserNode、DataValidationNode、ExportNode、页眉Logo嵌入逻辑、任务中心接入、计费服务等。
新增的只有 MonthlyProcessorNode、ZipPackageNode 和 4 个新的文档渲染器。

坑1:验证报告字段比想象中多
初稿设计时,验证报告只规划了"试制情况及问题"和"分析意见"2个字段。对着实际模板仔细看之后,发现还有"试验试制目的"、"研发资源使用情况"(还分人力/仪器设备/物料耗材三类)、"指标对比"共3个字段被遗漏了。
这类问题的根本原因是先设计节点、后看模板。正确的顺序应该是:先把每份模板的每个字段列清楚,再设计 LLM 输出结构和提示词。
坑2:月度文档内容容易趋同
前几次测试的 8 份月度会议纪要几乎是一样的,只有月份不同。后来在提示词中明确加入"每个月生成的内容相对独立"的约束,并且把当月问题和解决方案作为差异化上下文注入,才明显改善。
坑3:LLM 调用次数比预估多
6个月试制周期:立项 3 次 + 每月 4 次(问题 + 会议 + 通知单 + 报告)= 27 次 LLM 调用。12个月就是 51 次。这对超时控制和计费预估都有影响,需要单独设置超时上限。

研发过程文档这个场景有一个特点:结构高度标准化,内容需要差异化。这正是 AI 工作流最擅长的领域——用节点编排解决结构问题,用提示词设计解决内容质量问题。
我们的经验是:从模板出发设计,而不是从功能出发设计。先把每份文档的每个字段搞清楚,哪些由 AI 生成、哪些固定填入,然后再设计节点和提示词。这样做出来的系统,后期维护和调整都容易得多。
下一步我们计划支持:
- 月度文档并行化(当前月内是串行,可以优化为同月3份文档并行)
- 实时进度反馈(SSE 流式输出每月生成进度,让用户知道"正在生成第3个月的文档")
- 后台可配置的文档标签管理
如果你们公司也有类似的"批量结构化文档生成"需求,欢迎交流。
夜雨聆风