第1793篇:需求文档的AI解析——从PRD自动生成技术设计文档
第1793篇:需求文档的AI解析——从PRD自动生成技术设计文档
做了这么多年开发,我越来越相信一件事:技术问题往往是沟通问题的下游结果。
一个模糊的需求文档,产品经理以为说清楚了,开发理解的是另一回事,最后做出来对接不上,就开始互相甩锅。这种场景我见过太多次了。
更根本的问题是:从PRD到技术设计文档,中间这个翻译过程,完全依赖开发工程师的个人能力和经验。有的工程师能把需求里的模糊点全部挖出来,然后逼着产品补充清楚;有的工程师看到需求,觉得「大概能做」就开始动手,结果做到一半发现根本没考虑某些边界情况。
用AI来辅助这个过程,是我近一年实践下来觉得ROI最高的应用场景之一。
为什么这个场景很适合AI
从PRD到技术设计这个过程,本质上是一个「翻译+补全+推断」的过程:
- 翻译:把产品语言转成技术语言(「用户可以快速登录」→「需要OAuth2.0或短信验证码,Session超时时间多长」)
- 补全:发现PRD里没写但必须做的事(「删除商品」→「关联的订单怎么处理?在途物流怎么处理?」)
- 推断:从业务逻辑推断技术约束(「秒杀活动」→「必然高并发,需要库存扣减的原子性保证」)
这三件事,AI在有足够上下文的情况下可以做得很好。它不会像人一样因为「这个功能看起来很简单」就跳过边界情况分析。
构建PRD解析系统
先看整体流程:
第一步:PRD文档结构化解析
现实中的PRD文档格式千奇百怪,有Confluence的、有Notion的、有Word的,还有直接发微信的(我没夸张)。做这个工具的第一步是把各种格式统一处理。
@Service
public class PrdParser {
private final ClaudeApiClient claudeClient;
public StructuredPrd parse(String rawPrdContent, String documentFormat) {
String structurePrompt = String.format("""
你是一个需求分析专家。请将以下产品需求文档解析为结构化格式。
文档格式:%s
请提取以下内容,以JSON格式返回:
{
"product_background": "产品/功能背景描述",
"target_users": ["用户角色列表"],
"feature_list": [
{
"id": "F001",
"name": "功能名称",
"description": "功能描述",
"priority": "P0/P1/P2",
"user_stories": ["用户故事列表"],
"acceptance_criteria": ["验收标准列表"],
"dependencies": ["依赖的其他功能ID"],
"constraints": ["业务约束条件"]
}
],
"non_functional_requirements": {
"performance": "性能要求",
"security": "安全要求",
"compatibility": "兼容性要求",
"availability": "可用性要求"
},
"out_of_scope": ["明确排除在外的内容"],
"open_questions": ["文档中提到的待定事项"]
}
原始文档:
%s
""", documentFormat, rawPrdContent);
String response = claudeClient.complete(structurePrompt);
return parseStructuredPrd(response);
}
private StructuredPrd parseStructuredPrd(String jsonResponse) {
try {
String cleanJson = cleanJsonResponse(jsonResponse);
ObjectMapper mapper = new ObjectMapper();
return mapper.readValue(cleanJson, StructuredPrd.class);
} catch (JsonProcessingException e) {
log.error("PRD解析失败: {}", e.getMessage());
// 降级:返回只包含原始文本的结构
StructuredPrd fallback = new StructuredPrd();
fallback.setProductBackground(jsonResponse);
return fallback;
}
}
private String cleanJsonResponse(String response) {
return response
.replaceAll("(?s)```json\\s*", "")
.replaceAll("(?s)```\\s*", "")
.trim();
}
}第二步:技术设计文档生成
有了结构化的PRD,下一步是生成技术设计文档的各个部分。我把这个过程拆分成几个独立的生成步骤,每步聚焦一个方面:
@Service
public class TechDesignDocGenerator {
private final ClaudeApiClient claudeClient;
public TechDesignDoc generate(StructuredPrd prd, TechContext techContext) {
TechDesignDoc doc = new TechDesignDoc();
// 并行生成各个部分
CompletableFuture<String> apiDesignFuture =
CompletableFuture.supplyAsync(() -> generateApiDesign(prd, techContext));
CompletableFuture<String> dataModelFuture =
CompletableFuture.supplyAsync(() -> generateDataModel(prd, techContext));
CompletableFuture<String> sequenceDiagramFuture =
CompletableFuture.supplyAsync(() -> generateSequenceDiagrams(prd, techContext));
CompletableFuture<List<String>> clarificationFuture =
CompletableFuture.supplyAsync(() -> generateClarificationQuestions(prd));
try {
doc.setApiDesign(apiDesignFuture.get(30, TimeUnit.SECONDS));
doc.setDataModel(dataModelFuture.get(30, TimeUnit.SECONDS));
doc.setSequenceDiagrams(sequenceDiagramFuture.get(30, TimeUnit.SECONDS));
doc.setClarificationQuestions(clarificationFuture.get(30, TimeUnit.SECONDS));
} catch (Exception e) {
throw new RuntimeException("技术设计文档生成失败", e);
}
return doc;
}
private String generateApiDesign(StructuredPrd prd, TechContext context) {
String prompt = String.format("""
基于以下需求,设计RESTful API接口。
技术栈:%s
认证方式:%s
需求功能列表:
%s
请设计API,包含:
1. 接口路径和HTTP方法
2. 请求参数(Path/Query/Body)
3. 响应数据结构
4. 错误码定义
5. 关键业务规则对应的接口约束
输出格式:
- 用OpenAPI/Swagger风格的YAML描述
- 每个接口加注释说明对应的需求点
- 标注哪些接口需要认证
需求详情:
%s
""",
context.getTechStack(),
context.getAuthMethod(),
formatFeatureList(prd.getFeatureList()),
toJson(prd));
return claudeClient.complete(prompt);
}
private String generateDataModel(StructuredPrd prd, TechContext context) {
String prompt = String.format("""
基于以下业务需求,设计数据库模型。
数据库类型:%s
业务需求:
%s
请提供:
1. 核心实体列表(表名和用途)
2. 每个实体的字段定义(字段名、类型、约束、说明)
3. 实体间关系(一对一/一对多/多对多)
4. 索引建议(基于查询场景)
5. 关键业务规则对应的数据库约束
特别注意:
- 考虑软删除需求
- 考虑审计字段(创建人、创建时间、修改人、修改时间)
- 对多租户场景加租户ID字段
- 考虑数据量增长后的分表策略
用SQL DDL格式输出,加详细注释。
""",
context.getDatabaseType(),
toJson(prd));
return claudeClient.complete(prompt);
}
private String generateSequenceDiagrams(StructuredPrd prd, TechContext context) {
// 只对P0功能生成时序图
List<Feature> p0Features = prd.getFeatureList().stream()
.filter(f -> "P0".equals(f.getPriority()))
.collect(Collectors.toList());
if (p0Features.isEmpty()) {
p0Features = prd.getFeatureList().stream().limit(3).collect(Collectors.toList());
}
StringBuilder diagrams = new StringBuilder();
for (Feature feature : p0Features) {
String diagram = generateSingleSequenceDiagram(feature, context);
diagrams.append("### ").append(feature.getName()).append("\n\n");
diagrams.append(diagram).append("\n\n");
}
return diagrams.toString();
}
private String generateSingleSequenceDiagram(Feature feature, TechContext context) {
String prompt = String.format("""
为以下功能生成Mermaid sequenceDiagram格式的时序图。
功能名称:%s
功能描述:%s
用户故事:%s
验收标准:%s
技术架构:%s
要求:
1. 使用sequenceDiagram格式
2. 参与者用英文缩写,在描述中用中文说明
3. 展示主流程和最重要的异常流程
4. 标注关键的异步操作
5. 只返回Mermaid代码块,不要其他内容
示例格式:
```mermaid
sequenceDiagram
participant U as 用户
participant API as API网关
participant SVC as 业务服务
participant DB as 数据库
U->>API: 发起请求
API->>SVC: 转发请求
SVC->>DB: 查询数据
DB-->>SVC: 返回结果
SVC-->>API: 响应
API-->>U: 返回结果
```
""",
feature.getName(),
feature.getDescription(),
String.join("; ", feature.getUserStories()),
String.join("; ", feature.getAcceptanceCriteria()),
context.getArchitectureDescription());
return claudeClient.complete(prompt);
}
private List<String> generateClarificationQuestions(StructuredPrd prd) {
String prompt = String.format("""
你是一位资深后端工程师,正在评审产品需求文档。
请识别以下PRD中对技术实现有重大影响的模糊点和缺失信息,
生成需要向产品经理确认的问题列表。
每个问题需要:
1. 说明这个问题对应哪个功能点
2. 描述为什么需要澄清(影响什么技术决策)
3. 给出2-3个可能的答案选项(帮助PM更快回答)
重点关注:
- 边界情况处理(比如:某字段为空时如何处理)
- 数量/频率限制(比如:用户最多可以有多少个收藏)
- 并发冲突处理(比如:同时有人编辑同一条记录怎么办)
- 历史数据处理(比如:老数据在新功能上线后如何展示)
- 权限边界(比如:A用户能看到B用户的哪些数据)
PRD内容:
%s
返回JSON格式:
[
{
"feature_id": "F001",
"question": "问题描述",
"impact": "影响的技术决策",
"options": ["选项A", "选项B", "选项C"]
}
]
""", toJson(prd));
String response = claudeClient.complete(prompt);
return parseClarificationQuestions(response);
}
}第三步:非功能需求推断
PRD通常对非功能需求写得很模糊,「要快」「要稳定」之类的描述对技术设计毫无帮助。这里可以用AI帮我们从业务逻辑推断出具体的非功能需求:
@Service
public class NonFunctionalRequirementsInferrer {
private final ClaudeApiClient claudeClient;
public NonFunctionalRequirements infer(StructuredPrd prd, BusinessContext bizContext) {
String prompt = String.format("""
基于以下产品需求和业务背景,推断具体的非功能需求指标。
业务背景:
- 用户规模:%s
- 使用场景:%s
- 运营时间:%s(是否有明显的流量峰值)
- 数据敏感度:%s
产品功能:
%s
请推断以下维度的具体指标:
## 性能要求
- 核心接口响应时间(P50/P95/P99)
- 系统吞吐量(QPS/TPS)
- 并发用户数
- 推断依据说明
## 可用性要求
- SLA目标(99.9% vs 99.99%)
- 可接受的最大故障时间
- 数据一致性级别
- 推断依据说明
## 扩展性要求
- 预期6个月/1年后的用户增长
- 数据量增长预估
- 需要支持的扩展方向
## 安全要求
- 数据加密要求
- 敏感数据处理
- 审计日志要求
- 合规要求(如果有)
对每个指标,说明推断依据,便于与产品确认。
""",
bizContext.getUserScale(),
bizContext.getUsageScenario(),
bizContext.getOperationTime(),
bizContext.getDataSensitivity(),
formatFeatureList(prd.getFeatureList()));
String response = claudeClient.complete(prompt);
return parseNonFunctionalRequirements(response);
}
}一个完整的生成案例
让我展示一个真实的案例。输入是一段典型的产品需求:
PRD片段(原文):
用户可以收藏商品,在个人中心查看收藏列表。支持取消收藏。收藏的商品下架后在列表里用灰色显示。
看起来很简单对吧?AI解析后生成的澄清问题清单(部分):
Q1. [F001-商品收藏] 收藏数量是否有上限?
影响:需要决定是否在数据库层面添加约束,以及超出上限时的错误处理。
选项A:有上限(如最多500个),超出后弹窗提示
选项B:无上限
选项C:无上限,但超过一定数量后给出提示引导用户整理
Q2. [F001-商品收藏] 商品更新后(比如价格变化、库存变化),收藏列表是否实时展示最新信息?
影响:决定收藏表存储商品快照还是只存商品ID,以及列表接口的实现复杂度。
选项A:实时展示最新价格和库存(需要联表查询)
选项B:展示收藏时的价格快照,加"价格已变动"标记
选项C:展示最新信息,但价格相比收藏时的历史价格有变化时高亮
Q3. [F001-商品收藏] 用户删除账号后,收藏数据如何处理?
影响:数据清理策略和GDPR合规要求。
选项A:立即物理删除
选项B:软删除,保留一段时间
选项C:匿名化处理
Q4. [F001-商品收藏] 同一商品能否被多次收藏?如果用户在不同设备上同时操作,如何处理重复收藏?
影响:数据库唯一索引设计和并发控制。
选项A:数据库层面保证唯一
选项B:允许重复,由业务层去重这4个问题,在产品文档里全都没有明确答案,但每一个都会直接影响数据库设计和接口实现。
AI生成的数据模型草稿:
-- 商品收藏表
CREATE TABLE `user_product_favorite` (
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
`user_id` BIGINT NOT NULL COMMENT '用户ID',
`product_id` BIGINT NOT NULL COMMENT '商品ID',
`product_snapshot` JSON COMMENT '收藏时的商品快照(价格、图片等)[待PM确认是否需要]',
`status` TINYINT(1) NOT NULL DEFAULT 1 COMMENT '状态: 1-有效 0-已取消',
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '收藏时间',
`updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`deleted_at` DATETIME COMMENT '软删除时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_user_product` (`user_id`, `product_id`), -- 防止重复收藏
KEY `idx_user_status_created` (`user_id`, `status`, `created_at` DESC) -- 列表查询优化
) ENGINE=InnoDB COMMENT='用户商品收藏';
-- 注:如果需要支持收藏上限,在应用层检查,不在数据库添加约束
-- 注:product_snapshot字段是否需要,取决于PM对Q2的回答这个数据模型草稿里还保留了「待确认」的注释,非常好用——不是给你一个假装完整的方案,而是明确标注了哪里还有决策需要做。
与Confluence/Notion集成
做成工具要有落地能力,我们最后把这个系统集成到了Confluence:
@RestController
@RequestMapping("/api/prd-to-design")
public class PrdToDesignController {
private final PrdParser prdParser;
private final TechDesignDocGenerator designGenerator;
private final ConfluenceApiClient confluenceClient;
@PostMapping("/generate")
public ResponseEntity<GenerationResult> generateDesignDoc(
@RequestBody GenerationRequest request) {
// 1. 从Confluence获取PRD
String prdContent = confluenceClient.getPageContent(request.getPrdPageId());
// 2. 解析PRD
StructuredPrd structuredPrd = prdParser.parse(prdContent, "confluence");
// 3. 生成技术设计文档
TechContext context = TechContext.builder()
.techStack(request.getTechStack())
.databaseType(request.getDatabaseType())
.authMethod(request.getAuthMethod())
.architectureDescription(request.getArchDescription())
.build();
TechDesignDoc designDoc = designGenerator.generate(structuredPrd, context);
// 4. 创建技术设计文档页面
String confluenceContent = formatForConfluence(designDoc);
String newPageId = confluenceClient.createPage(
request.getParentPageId(),
"技术设计文档 - " + structuredPrd.getProductBackground().substring(0, 20) + "...",
confluenceContent
);
// 5. 创建澄清问题页面
if (!designDoc.getClarificationQuestions().isEmpty()) {
String questionsContent = formatQuestionsForConfluence(designDoc.getClarificationQuestions());
confluenceClient.createPage(
newPageId,
"待澄清问题清单",
questionsContent
);
}
return ResponseEntity.ok(new GenerationResult(newPageId, designDoc.getClarificationQuestions().size()));
}
private String formatForConfluence(TechDesignDoc doc) {
// 将Markdown格式转为Confluence存储格式
StringBuilder sb = new StringBuilder();
sb.append("<h2>API接口设计</h2>\n");
sb.append("<ac:structured-macro ac:name=\"code\">\n");
sb.append("<ac:parameter ac:name=\"language\">yaml</ac:parameter>\n");
sb.append("<ac:plain-text-body><![CDATA[").append(doc.getApiDesign()).append("]]></ac:plain-text-body>\n");
sb.append("</ac:structured-macro>\n");
sb.append("<h2>数据模型设计</h2>\n");
sb.append("<ac:structured-macro ac:name=\"code\">\n");
sb.append("<ac:parameter ac:name=\"language\">sql</ac:parameter>\n");
sb.append("<ac:plain-text-body><![CDATA[").append(doc.getDataModel()).append("]]></ac:plain-text-body>\n");
sb.append("</ac:structured-macro>\n");
sb.append("<h2>核心流程时序图</h2>\n");
sb.append(doc.getSequenceDiagrams());
return sb.toString();
}
}实际效果与局限
用了三个月,团队的反馈是:
好的方面:
- 以前从PRD到技术设计文档要2-3天,现在1个小时出草稿,剩下时间用来补充和review
- 澄清问题清单帮助我们在开发前就把需求漏洞堵上,减少了返工
- 数据模型草稿虽然不是最终版,但给了一个很好的讨论基础
不好的方面:
- AI生成的API设计风格和团队现有API风格不一致,需要人工对齐
- 对业务领域特有的规则理解不够深,需要人工补充很多注释
- 生成的内容有时候太详细,反而让工程师懒得再思考,直接把草稿当结论了
最后这条是个心理学问题。我后来做了一个调整:生成文档时明确标注「AI草稿版,所有结论需要工程师确认」,并且要求工程师修改了至少30%的内容才算完成技术设计。这个规则有点强制,但确实让大家保持了主动思考的习惯。
工具辅助思考,不能代替思考。
