Files
2026Technology-Competition/docs/design.md
T
lhl becd3e1f57 chore(assets): 参赛提交规范红线修复(ASCII 化 + 相对路径)
按《参赛成果物提交规范·赛道一》§6 红线:
- samples/ 目录改名 sample/(git mv,保留历史)
- 10 个中日文样本文件 + docs 参赛手册 PDF 重命名为 ASCII
  (requirements_*/template_*/rules_*/contestant-handbook.pdf)
- tests/test_zh_template.py 硬编码绝对路径 D:\00_project\Genesis 改为相对路径
- 全局更新 21 个活动文件引用;历史日志/审查文档不改(追加说明记录)
全量 pytest 431 passed / 99.15%
2026-08-26 14:15:52 +08:00

1807 lines
78 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 概要设计书自动生成 Agent 设计文档
> 版本: v1.0 | 日期: 2026-07-21 | 状态: 初版
---
## 目录
1. [项目概述](#1-项目概述)
2. [整体架构](#2-整体架构)
3. [Parser Agent 详细设计](#3-parser-agent-详细设计)
4. [Impact Agent 详细设计](#4-impact-agent-详细设计)
5. [RAG 基础设施层](#5-rag-基础设施层)
6. [Writer Agent 详细设计](#6-writer-agent-详细设计)
7. [QA Agent 详细设计](#7-qa-agent-详细设计)
8. [Web UI 设计](#8-web-ui-设计)
9. [数据模型与 Provenance 层](#9-数据模型与-provenance-层)
10. [异常处理策略](#10-异常处理策略)
11. [通信语言与文档规范](#11-通信语言与文档规范)
12. [Phase 5Writer / QA 子系统](#12-phase-5writer--qa-子系统)
---
## 1. 项目概述
### 1.1 目标
开发一个 Web 服务形态的 Agent,能够读取以下输入资料:
- Excel 版要件定义(核心数据源)
- Word 版概要设计模板(输出章结构与样式)
- Word 版概要设计做成说明书(各章作成指引)
- Word 版记入规则 / 图表规则等规则文档
- (可选) 现有系统的源代码与设计书(追加/改修场景)
自动生成符合规范的 **Word 版概要设计书**
### 1.2 成功标准
1. **格式精确** — 输出文档的样式、字体、表格格式严格符合模板
2. **内容准确** — 生成的所有信息必须来源于要件定义,不能捏造
3. **可追溯** — 每一段生成内容都能追溯到原始数据来源(单元格/行/列)
### 1.3 开发范式
本项目的开发遵循 5 个步骤,对应 AI 使用日志的"范式步骤"列:
1. **需求理解** — 分析大赛规则,理解概要设计书生成需求
2. **架构设计** — AI 生成方案,人工审核设计
3. **Agent 实现** — AI 编码实现各 Agent 模块
4. **测试验证** — 单元测试与集成测试验证
5. **反馈迭代** — 基于测试结果反馈修正
---
## 2. 整体架构
### 2.1 Agent 构成
系统由 4 个 Agent + 1 个基础设施层构成:
```
┌─────────────────────────────────────────────────────────────┐
│ Web UI (React) │
│ 上传资料 | 确认解析 | 确认影响调查 | 启动生成 | 预览结果 │
└──────────────────────┬──────────────────────────────────────┘
│ REST API
┌──────────────────────▼──────────────────────────────────────┐
│ Orchestrator (流程协调器) │
│ 职责: 编排整个流程、管理会话状态、处理异常、人工介入点 │
└────┬──────────┬──────────┬──────────┬───────────────────────┘
│ │ │ │
┌────▼───┐ ┌───▼────┐ ┌──▼────┐ ┌──▼──────────┐
│ Parser │ │ Impact │ │ Writer│ │ QA │
│ Agent │ │ Agent │ │ Agent │ │ Agent │
├────────┤ ├────────┤ ├───────┤ ├──────────────┤
│ 解析 │ │ 要素 │ │ 章节 │ │ 校验 │
│ 全部 │ │ 抽出 │ │ 生成 │ │ 格式/内容/ │
│ 输入 │ │ 关联 │ │ 模板 │ │ 可追溯性 │
│ 资料 │ │ 推論 │ │ 填充 │ │ │
└────────┘ └────────┘ └───────┘ └──────────────┘
│ │ │
└──────────┴─────────────────────┘
┌──────▼──────┐
│ RAG Layer │
│ (基础设施) │
│ 规则检索服务 │
└─────────────┘
```
### 2.2 处理流程
```
① Parser Agent — 解析所有输入资料
├── Excel要件定义 → 结构化数据(各单元格带Provenance)
├── Word模板 → 章结构、占位符、样式
├── 规则文档 → Markdown化 + 分类(设计规则/写入规则)
├── 图像/图形式 → Vision LLM识别
└──(可选)现系统代码/设计书 → 现系统结构数据
② 用户确认 — Web界面
├── 确认Excel解析结果(Sheet类型判定、数据预览)
├── 确认模板章结构
└── 确认现系统探索结果(如有)
③ Impact Agent — 影响调查
├── Step 1: 要素抽出
├── Step 2: 批注分析(先理解,不明再问)
├── Step 3: 关联推理(细粒度 + 证据 + 置信度)
├── Step 4: 影响矩阵构建
└── Step 5: 影响调查书输出(中间成果物)
④ 用户确认 — 影响调查结果
├── 逐条确认・修正(追加/删除/种类变更/证据修正)
├── 不确定处由用户判断
└── 点击「确认完成」按钮进入 Writer
⑤ Writer Agent — 逐章生成(每章循环)
├── 从RAG检索相关规则(写入规则)
├── 从设计规则检出约束
├── 从StructuredSource提取数据
├── 从ImpactReport提取关联关系
└── LLM生成 → 注入模板对应章节
⑥ QA Agent — 全量校验
├── 格式校验(vs 模板样式)
├── 内容校验(vs 源数据)
├── 规则遵守校验(vs RAG规则)
└── 可追溯性校验(每个断言有来源)
⑦ 输出最终文档
```
### 2.3 共通工具层
为了避免 Parser Agent 过于臃肿,以下功能拆分为独立工具服务:
| 工具 | 职责 | 输出 | 复用者 |
|------|------|------|--------|
| **FileReader** | 读取任意格式文件为统一内存结构 | UnifiedDocument(元数据+内容+格式特有信息) | Parser, QA |
| **CodeParser** | 解析 Java 项目结构 | CodeStructure(类+注解+依赖) | Parser, Impact |
| **ImageAnalyzer** | Vision LLM 封装,识别图片内容 | ImageDescription(类型+文本+关系) | Parser, Impact |
---
## 3. Parser Agent 详细设计
### 3.1 职责
解析所有输入资料为结构化数据(StructuredSource),作为后续 Agent 的唯一数据来源。
### 3.2 两阶段策略
```
Phase 1: Probe(探查)
快速扫描所有文件,返回概览信息 → 用户确认
- Sheet列表(名称、行数列数)
- 各Sheet表头(前3行)
- 自动识别的Sheet类型(機能/画面/帳票/DB/IF
- Word模板的章结构与使用样式
- 规则文档的章结构
Phase 2: Extract(深度提取)
用户确认后,按需深度解析
- 全表数据提取(每个单元格带Provenance)
- 规则文档的Markdown转换 + 分类
- 现系统代码/设计书解析
```
### 3.3 输入资料清单
| 输入 | 格式 | 用途 | 解析难度 |
|------|------|------|---------|
| 要件定义 | .xlsx | 核心数据源 | ★★★(合并单元格・层级表头・自由记述混在) |
| 概要设计模板 | .docx | 输出结构与样式 | ★★☆(标题层级・占位符・书签) |
| 做成说明书 | .docx | 各章作成指引 | ★☆☆(纯文本+标题结构) |
| 记入规则 | .docx/.xlsx/.pptx | 写法规范 | ★★☆(多格式跨文档) |
| 图表规则 | .docx/.xlsx/.pptx | 图表书写规范 | ★★☆ |
| (可选)现系统源码 | .java/.xml/.yml | 现系统结构把握 | ★★★(Spring Boot解析) |
| (可选)现系统设计书 | .docx/.xlsx | 现系统功能把握 | ★★☆ |
### 3.4 内部模块
```
Parser Agent
├── ExcelParser(要件定义解析)
│ ├── SheetDetector — 自动识别Sheet类型
│ ├── TableExtractor — 表格提取 + 合并单元格处理
│ ├── FreeTextParser — 自由记述型Sheet的LLM结构化
│ ├── FormattingDetector — 取消线检测、背景色检测
│ ├── CommentExtractor — 批注提取
│ └── ProvenanceAnnotator — 来源标注
├── WordParser(模板+规则文档解析)
│ ├── TemplateParser — 章结构、占位符、样式提取
│ └── RuleDocParser — 规则文档解析、Markdown化
├── PPTXParserPPT规则文档解析)
│ └── TextExtractor — 幻灯片文本提取
├── ExistingSystemExplorer(现系统探索)
│ ├── DirectoryScanner — 目录结构遍历
│ ├── JavaParser — Java代码解析(Controller/Service/Entity/Repository
│ ├── AnnotationAnalyzer — Spring Boot注解解析
│ └── ExistingDocParser — 现系统设计书解析
├── SourceAggregator(汇总器)
│ └── 统一输出为StructuredSource
└── 调用 → 共通工具层
├── FileReader(文件读取)
├── CodeParser(代码解析)
└── ImageAnalyzer(图像识别)
```
### 3.5 Excel 解析详细策略
#### 3.5.1 Sheet 类型自动识别
```python
def detect_sheet_type(sheet_name, headers):
"""
判断依据(优先级高→低):
1. Sheet名关键词
2. 表头关键词
3. 数据类型分布
"""
```
> 说明:关键词为日文,用于匹配日文要件定义文件中的实际 Sheet 名/表头(技术必要保留)。
| 关键词模式 | 判定类型 |
|-----------|---------|
| "機能" in name / "機能ID" in headers | FUNCTION |
| "画面" in name / "画面ID" in headers | SCREEN |
| "帳票" in name / "帳票ID" in headers | REPORT |
| "DB" in name / "テーブル" in name / "TABLE" in headers | DATABASE |
| "IF" in name / "インターフェース" in headers | INTERFACE |
| "バッチ" in name / "ジョブ" in name | BATCH |
| "コード" in name / "マスタ" in name | MASTER |
| 都不符合 | GENERIC |
#### 3.5.2 Sheet 性质判定(表格型 vs 自由记述型 vs 混合型)
```
判断指标:
1. 空行比率 > 30% → 自由记述型可能性
2. "・""■"开头行多 → 条目型可能性
3. 全部单元格为字符串类型 → 非表形式可能性
4. 没有表头行 → 自由记述型可能性
5. 仅使用 A 列、其他列几乎为空 → 自由记述型可能性
综合评分判定:
text_score > 阈值 → 自由记述型 / 混合型
table_score > 阈值 → 结构化表格型
```
- **结构化表格型** → openpyxl 行列解析
- **自由记述型** → 全部单元格文本合并 → 通过 LLM 结构化
- **混合型** → 先进行段落分割 → 各段落最优解析
#### 3.5.3 合并单元格处理
```python
def forward_fill(rows, merged_cells):
"""
下行填充策略:
1. 识别合并单元格范围(r1, c1, r2, c2
2. 遍历数据行,如果在合并范围内且为空值 → 填充主单元格值
3. 记录 Provenance(来自合并单元格的主位置)
"""
```
#### 3.5.4 取消线处理
```python
if cell.font.strike:
row_meta["excluded"] = True
row_meta["exclude_reason"] = "strikethrough"
# 值保留但不参与后续处理
```
#### 3.5.5 批注处理
```python
comment = cell.comment
if comment:
cell_meta["comment"] = {
"author": comment.author,
"text": comment.text,
"source_uri": f"file#sheet!{cell.coordinate}/comment"
}
# Impact Agent 侧「先分析,不明再问」
```
#### 3.5.6 图像/图形处理
```python
1. ZIP 中提取全部图像xl/media/
2. 定位图像锚点位置单元格位置
3. 图像数 < 10 通过 Vision LLM 识别
4. 图像数 >= 10 仅记录存在
5. 图形自动形状)→ 提取文本
```
#### 3.5.7 公式单元格处理
```python
# 同时保留公式字符串与计算值
cell_meta = {
"value": cell.value, # 计算值
"formula": cell.formula, # 公式字符串(from openpyxl
"has_formula": True,
"provenance": provenance
}
```
### 3.6 Excel 解析风险一览
| 风险 | 影响度 | 频率 | 应对 |
|-------|--------|------|------|
| 字符编码(Shift-JIS/UTF-8 | 高 | 中 | chardet 自动判别 |
| 隐藏行/列 | 高 | 中 | 检测→排除标记,可用户确认 |
| 公式单元格 | 高 | 高 | formula + value 同时保持 |
| 巨大文件 | 高 | 低 | read_only 模式 / 切换 Polars |
| 密码保护 | 高 | 低 | 检测后通知 |
| .xls 旧格式 | 高 | 低 | 错误通知 / LibreOffice 转换 |
| 多行单元格(Alt+Enter | 中 | 高 | 保留换行 |
| 多级表头 | 中 | 高 | 分析开头 N 行进行扁平化 |
| Sheet 间相互引用 | 中 | 中 | 作为上下文传给 LLM |
| 打印范围设置 | 中 | 中 | 记录到 Provenance |
| 大纲(分组) | 中 | 中 | 记录分组层级 |
| 单元格内多种字体混在 | 低 | 中 | 仅获取纯文本 |
| 条件格式 | 低 | 中 | 现阶段忽略 |
| 外部引用链接 | 低 | 低 | 检测后警告 |
| VBA/宏 | 低 | 低 | 检测存在(不执行) |
### 3.7 现有系统探索
#### 3.7.1 对应技术栈
| 技术 | 解析内容 |
|------|---------|
| Java / Spring Boot | Controller/Service/Repository/Entity + 注解 + API 端点 |
| MyBatis | 从 Mapper XML 提取 SQL + 表名 |
| Python / FastAPI | Router/Route/Model |
| C# / .NET | Controller/DTO/Entity |
| HTML/JSP | 画面文件一览/跳转链接 |
| Word/Excel 设计书 | 提取现有构成信息 |
#### 3.7.2 探索深度
```
优先级1: 目录信息(文件名、类名、API 端点)
方法: 目录遍历 + 正则表达式 / CodeParser
精度: 高
优先级2: Schema 信息(DB 表、DTO 结构)
方法: 解析 Entity/Model 文件
精度: 中〜高
优先级3: 依赖信息(Controller→Service 调用关系)
方法: 解析 import/调用关系
精度: 低
```
### 3.8 Parser Agent 的输出:StructuredSource
```python
@dataclass
class Provenance:
file_name: str
sheet_name: str
row: int
column: str
column_header: str
@dataclass
class CellValue:
value: Any
provenance: Provenance
formatting: CellFormatting | None = None
comment: CellComment | None = None
@dataclass
class CellFormatting:
strikethrough: bool = False
font_color: str | None = None
bg_color: str | None = None
@dataclass
class CellComment:
author: str
text: str
source_uri: str
@dataclass
class ExcelTable:
name: str
detected_type: SheetType
extraction_method: str # "openpyxl" | "llm_from_free_text"
headers: list[str]
rows: list[dict[str, CellValue]]
@dataclass
class ParsedTemplate:
file_name: str
sections: list[ChapterMarker]
placeholders: dict[str, str]
styles: dict
@dataclass
class ChapterMarker:
type: str # "heading" | "bookmark" | "placeholder"
name: str
level: int
@dataclass
class ExistingSystemInfo:
controller_layer: list[ControllerInfo]
service_layer: list[ServiceInfo]
entity_layer: list[EntityInfo]
api_endpoints: list[EndpointInfo]
source_path: str
@dataclass
class StructuredSource:
tables: list[ExcelTable]
template: ParsedTemplate
rule_docs: list[RuleDocument]
image_analyses: list[ImageAnalysis]
existing_system: ExistingSystemInfo | None
comments: list[CellComment]
```
---
## 4. Impact Agent 详细设计
### 4.1 职责
接收 Parser Agent 的 StructuredSource,分析要素间的关联关系,输出影响调查书(中间成果物)。
### 4.2 处理步骤
```
Step 0: 变更点定位(仅新增/改修时)
→ 从 Parser 的解析结果中识别「新增/追加/变更/删除」的各行
→ 从现有系统信息与要件定义的差异中定位变更范围
Step 1: 要素抽取
→ LLM 从各 Sheet 数据中识别「功能/画面/账票/DB/IF/批处理」
→ 取消线行除外、批注进行分析
→ 确认抽取精度(置信度)
Step 2: 批注分析
→ 先用 LLM 理解・分类批注内容
→ 提取应反映到设计书中的内容
→ 仅对不明点向用户提问(先分析、后提问)
Step 3: 关联推理(核心)
→ 从业务描述中推理要素间的关联
→ 关联类型: 利用 / 参照 / 更新 / 输出 / 输入 / 依赖
→ 证据(evidence)必须附带根据原文
→ 交叉检查进行置信度补正
→ 设计规则(来自 RAG)也作为考虑材料使用
Step 4: 影响矩阵构建
→ 双向矩阵(该要素影响什么 / 什么影响该要素)
Step 5: 影响调查书输出
→ JSON(供 Writer Agent 使用)+ 摘要(供 UI 确认用)
```
### 4.3 关联推理详情
#### 4.3.1 关联类型定义
| 类型 | 含义 | 例 |
|-------|------|-----|
| 利用 | 功能利用画面/账票 | F001 → SC001 |
| 参照 | 功能/画面读取 DB/IF 数据 | F001 → TB001SELECT |
| 更新 | 功能/画面写入 DB/IF 数据 | F001 → TB001INSERT/UPDATE |
| 输出 | 功能生成账票 | F001 → RP001 |
| 输入 | 画面接受输入并传给功能 | SC001 → F001 |
| 依赖 | 功能依赖其他功能/模块 | F001 → AUTH001(必须认证) |
#### 4.3.2 置信度定义
| 置信度 | 条件 | 证据要求 | 用户确认 |
|-------|------|---------|------------|
| high | 有明确记载(关联画面=SC001 等) | 证据明确 | 默认折叠显示 |
| medium | 关键词一致・ID 名一致 | 证据可引用 | 展开显示 |
| low | 仅根据名称相似性推理 | 证据弱 | 强调显示 |
#### 4.3.3 交叉检查
```python
def cross_validate(candidates):
"""从多个根据推理出同一关联时,置信度升级"""
same_relation = [r for r in candidates if r.from_id==x and r.to_id==y]
if len(same_relation) >= 2:
# 例: 明示 + 准明示 → high
upgrade_confidence(relation)
```
#### 4.3.4 矛盾检测
```python
def check_consistency(relations):
"""
- 循环引用的检测(A→B→C→A)
- 类型不一致(功能→功能的「利用」)
- 孤立要素(不与任何要素关联)
"""
```
### 4.4 影响调查书的结构(完整版)
```json
{
"metadata": {
"version": "v1",
"session_id": "genesis-xxx",
"created_at": "2026-07-21",
"llm_model": "deepseek-chat",
"parser_version": "1.0"
},
"change_analysis": {
"project_type": "new_development" | "enhancement",
"new_elements": [...],
"modified_elements": [...],
"deleted_elements": [...],
"unchanged_elements": [...]
},
"extracted_elements": [
{
"element_id": "F001",
"element_type": "功能",
"name": "用户注册",
"description": "业务描述的摘录",
"source_uris": ["file#sheet!A3"],
"comments_related": [...],
"images_nearby": [...],
"coverage": "complete" | "partial" | "speculative",
"provenance_chain": [...]
}
],
"relations": [
{
"from_id": "F001",
"from_type": "功能",
"to_id": "SC001",
"to_type": "画面",
"relation_type": "利用",
"confidence": "high",
"evidence": "evidence text",
"source_uri": "file#sheet!D3",
"cross_validated": true,
"user_corrected": false
}
],
"impact_matrix": {
"F001": {
"name": "用户注册",
"type": "功能",
"impacts": [
{"to_id": "SC001", "to_type": "画面", "relation_type": "利用",
"confidence": "high", "source_uri": "file#sheet!D3"}
],
"impacted_by": [
{"from_id": "TB001", "from_type": "DB", "relation_type": "参照",
"confidence": "high", "source_uri": "file#sheet!E4"}
]
}
},
// 注: impact_matrix 的元素与 relations[] 使用同一关系对象结构
// from_id/to_id [+type]、relation_type、confidence、evidence、source_uri),
// impacts = 该要素影响什么(to 方向),impacted_by = 什么影响该要素(from 方向)
// Writer 消费时以此为章内引用与“影响范围”描述的依据
"comments_analysis": [
{
"source_uri": "...",
"summary": "摘要",
"category": "review_feedback" | "supplementary" | "clarification" | "status_mark" | "question",
"importance": "must" | "should" | "nice_to_have" | "irrelevant",
"actionable_content": "...",
"confidence": "high",
"uncertainty": null
}
],
"uncertainties": [
{
"element_id": "F004",
"issue": "不明点的说明",
"source_uri": "...",
"suggested_question": "向用户提问的语句"
}
],
"quality_indicators": {
"provenance_chain": {...},
"coverage_markers": [...],
"orphan_warnings": [...],
"risk_flags": [
{"element": "F001", "risk": "high", "reason": "若删除将影响 5 个要素"}
],
"user_corrections": [...]
},
"summary": {
"total_elements": 45,
"total_relations": 128,
"by_type": {"功能": 12, "画面": 10, ...},
"high_confidence_relations": 85,
"medium_confidence_relations": 32,
"low_confidence_relations": 11,
"uncertainties_count": 2,
"orphan_count": 1
}
}
```
### 4.5 影响调查书的生命周期
```
v1(初版): Impact Agent 生成 → 保存
↓ 用户确认・逐条修正
v2(确认版): 应用用户修正 → 保存 ← Writer Agent 使用此版本
↓ 设计书生成完成
在设计书的元数据中记录「使用的影响调查书: v2」
```
### 4.6 用户确认界面方针
- 显示所有关联(无 auto-pass
- 证据(evidence)默认折叠、可展开
- 用户可以对各关联进行追加・删除・种类变更・证据修正(逐条修正)
- 保存修正履历(correction_history
- 责任在于「用户已确认并批准」这一点
---
## 5. RAG 基础设施层
> **详细设计见 [docs/rag-layer-design.md](rag-layer-design.md)**。本章为概要。
### 5.1 定位
RAG 不是独立 Agent,而是 Parser 和 Writer/QA 之间的基础设施层。
### 5.2 为什么需要 RAG
| 条件 | 结论 |
|------|------|
| 规则分散在 Word/Excel/PPT 多种格式 | 需要统一检索入口 |
| 规则本身没有按设计书章节整理 | 无法用静态索引做到 1:1 映射 |
| 同一个主题的规则散落在不同文档 | 需要跨文档的语义检索 |
| 目标:用户无感遵守规则 | 规则必须理解后精准注入生成过程 |
| 规则变化频率低但会变 | 需要持久化 + 版本管理 |
### 5.3 规则文档的分类
```
Parser 处理时分为:
1. 写入规则(记入规则、图表规则、字体指定)
→ RAG Layer → Writer Agent 参考
→ 每章生成时检索该章相关规则
2. 设计规则(架构约束、安全要求、设计方针)
→ 影响调查的关联推理也参考
→ 传递给 Impact Agent 作为补充信息
3. 参考设计文档(可选增强)
→ 过往概要设计书、设计决策记录
→ Impact Agent 改修场景参考
```
### 5.4 规则手册的生命周期
```
初期设定(首次):
用户上传规则文档
Parser + RAG 处理 → 规则手册 v1(持久化保存)
通常使用:
用户只上传要件定义与模板
Writer Agent 自动参照规则手册
规则更新时:
用户点击 Web UI 的「规则更新」按钮
上传新规则文档
Parser + RAG 再处理 → 规则手册 v2(文档级增量,只重建变化文档)
旧版本保留(用于与历史设计书关联)
```
### 5.5 关键设计决策(概要)
| 设计点 | 决策 |
|--------|------|
| 向量数据库 | Chromav1 唯一;Qdrant 切换为 v2 预留,Scope 缩减裁定)|
| Embedding | bge-m3(多语言,适配日文语料;OV2/T11)|
| 实现方式 | 手写(chromadb + rank_bm25 + sentence-transformers|
| 分割策略 | 按格式适配(Word 标题层级 / Excel 规则块 / PPT 1-2 页)|
| 检索策略 | 双通道(向量 top-10 + BM25 top-10+ RRF 融合 + rerank 精排(bge-reranker-v2-m3|
| 分类存储 | 分 Collection 隔离(rules-write / rules-design / ref-docs|
| 版本管理 | 文档级增量 + 版本组合(hash 对比,只重建变化文档)|
| 版本路由 | 会话开始锁版本 |
| 规则冲突 | 检测到矛盾时由用户确认采用哪条规则 |
---
## 6. Writer Agent 详细设计
### 6.1 职责
逐章节生成设计书内容,并注入 Word 模板中对应的位置。
### 6.2 各章生成时的输入
```
Writer Agent(每章循环)
├── ① 从 RAG 检索该章相关的写入规则
├── ② 从设计规则中检出约束条件
├── ③ 从 StructuredSource 提取该章所需的数据
├── ④ 从 ImpactReport 提取关联关系
├── ⑤ 从模板获取该章的样式定义
└── LLM 生成内容 → 注入模板对应位置
```
### 6.2.1 输出语言控制(output_language2026-08 新增)
- 参数:`--output-language {auto,zh,ja}`config `WriterConfig.output_language`,默认 `auto`
- 贯通链路:`run_trial → orchestrator.generate → build_contexts → GenerationContext.output_language
→ to_vars()["language_instruction"]`(prompt 的【语言约束】段引用该变量)
- **auto 推导规则**`src/genesis/writer/language.py::resolve_expected_language`,单一事实来源):
1. 显式 zh/ja → 直接采用
2. 标题含日文假名 → ja(纯汉字标题不可靠,跳过)
3. 规则文档(write_rules/design_rulesRAG 自作成说明书/记入规则)主导脚本
4. 均无法推导 → ""unverifiable,不强制)
- **生成期强制**`WriterAgent.generate_chapter` 用 `find_language_violations` 校验正文块
paragraph/note/listheading/table 不检——标题跟随模板、表格照抄源),违规按生成失败重试
max_retries 默认 2),耗尽抛 `WriterGenerationError` 硬失败
- 影响调查标签按 output_language 本地化(`_format_impact`):zh=新建/变更/删除/警告,ja=新規/変更/削除/警告
- 中文输出需配合中文模板 `sample/template_design_zh.docx`(日文模板镜像,锚点 id 原样保留)
### 6.3 模板注入策略
- 章位置识别:模板中的 Heading 层级 / 书签 / 占位符
- 内容注入:python-docx / docxtpl
- 样式保持:继承模板定义样式,LLM 只生成内容不控制格式
### 6.4 LLM 输出格式(JSON 内容块)
**决策**LLM 不直接输出 HTML 或 Word 格式,而是输出**结构化 JSON 内容块**ContentBlock)。渲染器统一将内容块转换为 `chapter_html`(前端预览)与 docx(最终下载)。
```json
{
"chapter_id": "db_design",
"version": 2,
"title": "DB設計",
"blocks": [
{
"block_id": "b-001",
"type": "paragraph", // paragraph | heading | table | list | note
"level": 2, // 仅 heading 使用(对应模板 Heading 层级)
"text": "本システムのDBは以下の通り。",
"source_uris": ["要件定義.xlsx#DB定義!A1"]
},
{
"block_id": "b-002",
"type": "table",
"caption": "テーブル一覧",
"headers": ["テーブルID", "テーブル名", "概要"],
"rows": [
["TB001", "ユーザー", "ユーザー情報"],
["TB002", "注文", "注文情報"]
],
"source_uris": ["要件定義.xlsx#DB定義!A3", "要件定義.xlsx#DB定義!B3"]
},
{
"block_id": "b-003",
"type": "list",
"style": "bullet", // bullet | numbered
"items": ["PK は ユーザーID とする", "外部キー制約を設定する"],
"source_uris": ["rules_entry_ja.docx#見出し!5.1"]
}
]
}
```
**设计原则**
- LLM 只负责**内容**(文本/表格/列表),**不控制格式**(字号/字体/颜色由模板样式决定)
- 每个 block 携带 `source_uris` → 满足「可追溯」成功标准,QA 第8项可追溯性校验据此执行
- `block_id` 全局唯一 → 幂等重写(runtime §7)按 (chapter_id, version) 覆盖时定位
- 表格结构天然支持 docx 表格渲染与 `chapter_html` 预览
### 6.5 章节 ↔ 模板映射规则
模板解析(Parser §3.8 `ParsedTemplate`)产出 `ChapterMarker` 列表。Writer 生成时按以下规则映射:
```
模板 ChapterMarker: Writer 内容块:
─────────────────────── ───────────────────────
heading level 1 (章) ────► chapter(1 个章节 = 1 次生成循环)
heading level 2 (节) ────► blocks[].type="heading" level=2
heading level 3 (小节) ───► blocks[].type="heading" level=3
bookmark / placeholder ──► blocks[].type="paragraph"(占位锚点)
```
**映射规则细化**
| 模板元素 | Writer 处理 |
|---------|------------|
| `## 3. DB設計`H1 | 生成循环入口:`chapter_id = "db_design"` |
| `### 3.1 テーブル一覧`H2 | 生成 `heading level=2` block,随后为该节内容块 |
| `{{section:db_tables}}` 占位符 | 定位到该占位符处,注入内容块渲染结果 |
| 书签(bookmark) | 作为内容块的插入锚点,渲染器在其后插入 |
| 模板自带示例文本 | 替换为生成内容(不保留示例) |
**生成顺序控制**:按模板章节顺序逐章生成。章间引用(如「3.2 画面一覧」引用「2. 機能一覧」的表)通过 WriterState 记录已生成章节的摘要与关键表结构,后章生成时引用(详见 6.9)。
### 6.6 docxtpl 占位符语法规范
模板中使用 docxtpl 语法定义占位符。支持两种模式:
```
模式 A: 章节级占位符(整章内容注入)
{{section:db_design}}
→ 渲染器将「db_design」章节的全部内容块渲染为 docx 元素序列,
替换该占位符
模式 B: 行内占位符(单值注入,用于封面/元信息)
{{doc_title}} {{version}} {{created_at}}
→ 从会话元数据取值填充
```
**规范约束**
- 占位符命名:`section:<chapter_id>` 用于章节;其余为元信息字段
- 模板中未找到占位符时,回退到「按 Heading 层级定位」(§6.5 规则),在对应 Heading 后插入
- 渲染器输出后做一次「占位符残留检查」:若存在未替换的 `{{...}}` 视为渲染失败,报错
### 6.7 渲染链路(ContentBlock → chapter_html / docx
```
ContentBlockJSONLLM 输出)
统一渲染器(Writer 内)
├──► chapter_html (每章生成后即时产出,供前端「生成执行」页实时预览)
│ 渲染: blocks → HTML 元素(p/h2/h3/table/ul
│ 样式: 内联基础样式 + 标记「该元素样式继承模板」
└──► docx 元素序列(全章完成后统一注入模板)
渲染: blocks → python-docx 元素(add_paragraph/add_table/add_heading
样式: 从模板对应样式定义继承(模板样式名映射表)
注入: 按 §6.6 占位符 / §6.5 Heading 定位写入模板
```
> **T17 docx 注入原型(OV8,已落地 `src/genesis/writer/docx_injector.py`**
> 将最难的「格式精度」成功标准提前验证。原型用原生 python-docx 实现 §6.6 占位符注入:
> - 章节级 `{{section:id}}` → 替换为内容块渲染的 docx 元素序列(heading/paragraph/table
> - 行内 `{{meta}}` → 元信息填充
> - **残留检查**:未替换 `{{...}}` 视为渲染失败(抛 `DocxInjectError`),与 §6.6 规范约束一致
> - **格式精度**:注入 heading 继承模板对应 Heading 样式(如 `Heading 2`),原有模板内容样式不被破坏
>
> 该原型在 Writer 完整实现前即可独立验证 docx 注入关键路径,规避「格式精度排末尾导致返工」的风险。
**模板样式映射表**(渲染器配置):
```yaml
style_map:
paragraph: "Normal" # 模板中的段落样式名
heading_1: "Heading 1"
heading_2: "Heading 2"
heading_3: "Heading 3"
table: "Table Grid" # 表格样式名
list_bullet: "List Bullet"
list_number: "List Number"
```
**预览与最终文件的一致性**`chapter_html` 与 docx 渲染自**同一份 ContentBlock**,内容一致;差异仅在格式载体(HTML 内联样式 vs docx 模板样式)。
### 6.8 每章生成流程(详细时序)
```
┌──────────────────────────────────────────────────────────┐
│ WriterAgent.generate_chapter(chapter_id, state) │
│ │
│ ① 组装输入: │
│ RAG.search(query=章标题+要素ID, category="write") │
│ → rules: list[RuleChunk] │
│ DataGate.load(structured_source, selector=该章数据) │
│ ImpactReport 中该章相关要素/关联 │
│ ParsedTemplate 中该章的样式定义 │
│ │
│ ② 冲突检测: │
│ ConflictDetector(rules) → 有冲突则阻塞该章,等用户决策 │
│ (已决策的冲突直接采用,不重复询问) │
│ │
│ ③ Prompt 组装: │
│ [系统指令] 你是概要设计书撰写助手…(固定文本) │
│ [用户数据] ┌─边界─┐ 规则/要件/要素描述 └─边界─┐ │
│ [任务] 生成该章内容,输出 JSON 内容块(schema 约束) │
│ │
│ ④ InferenceEngine.chat_structured( │
│ prompt="writer_chapter", │
│ variables={chapter_id, rules, data, relations, style},│
│ schema=ContentBlockSchema, │
│ retry_count=2) │
│ │
│ ⑤ 校验输出: │
│ 内容块结构校验(schema 校验)→ 失败则重试 │
│ source_uris 存在性校验(引用的 URI 必须能在输入中定位, │
│ T12 resolver.validate_source_uris → unresolved 非空即失败)│
│ │
│ ⑥ 渲染: │
│ 产出 chapter_html → 前端实时预览 │
│ 暂存 ContentBlock(按 chapter_id + version 幂等写入) │
│ │
│ ⑦ 更新 WriterState: │
│ 记录该章摘要 + 关键表结构(供后续章引用) │
└──────────────────────────────────────────────────────────┘
```
#### 6.8.1 串行生成约束(T10 文档化,I14)
> 架构审查 I14 裁定:**Writer 各章必须串行生成,不得并行**。本约束为设计基线,
> 而非实现细节,需在编排层与 UI 显式体现。
**理由**
1. **章间引用依赖**:后章(如「3.2 画面一覧」)需引用前章(「2. 機能一覧」)的
表结构与摘要,串行保证前章 `WriterState` 已就绪(§6.9),避免竞态或空引用
2. **并行收益低、复杂度高**:单章生成 3-5 分钟,并行需解决状态回写锁与
跨章引用一致性,复杂度远超收益(编审查 OV 一致结论)
3. **Token 友好**:前章摘要注入后章 prompt 的方式(§6.9)天然要求前章先完成
**约束落地点**
- 编排层:`POST /generate` 投递任务后,同一会话的逐章任务**严格按模板章节顺序串行消费**
(共享 orchestrator/,状态机 `writing` 态内顺序推进;单章失败可独立 retry,不影响其他章)
- UI:生成按钮触发后展示**预估总时长**(章数 × 单章 ~3-5 分钟)与逐章进度
(「第 3/12 章生成中」),让用户对串行等待有预期
- 实现反模式(禁止):同一会话并发投递多章生成任务、跳过 WriterState 直接全量重载
### 6.9 章间引用机制(WriterState
```
WriterState(会话级,跨章节共享):
{
"chapter_states": {
"function_list": {
"status": "completed",
"summary": "全15機能、一覧表あり",
"tables": [{"id": "機能一覧", "headers": ["機能ID", "機能名", "概要"], "row_count": 15}],
"key_elements": ["F001", "F002", ...]
},
"screen_list": {"status": "generating", ...},
...
},
"cross_refs": [ // 章间引用记录
{"from": "screen_list", "to": "function_list", "ref_type": "table", "table_id": "機能一覧"}
]
}
```
**引用规则**
- 后章需要前章数据时,**不重新加载全量数据**,而是从 WriterState 读取前章的摘要/表结构
- 引用内容在 prompt 中以「前章摘要」形式注入(token 友好,符合 runtime §2.6 Token 管理)
- 跨章引用关系记录到 `cross_refs`,供 QA 第4项「关联一致性」校验
---
## 7. QA Agent 详细设计
### 7.1 职责
生成后的全量校验,覆盖格式、内容、规则遵守、可追溯性四个维度。校验在**全章生成完成后**执行,发现问题时反馈给 Writer Agent 修正该章节,形成「QA 校验 → Writer 修正 → 重新校验」循环。
### 7.2 校验清单(11 项)
| # | 校验项 | 维度 | 方法 | 判定标准 |
|---|--------|------|------|---------|
| 1 | 格式一致性 | 格式 | 与模板逐项对比(字号/字体/字色/行距/段距/表样式)| 与模板定义一致 |
| 2 | 内容准确性 | 内容 | 与要件定义源数据对比 | 所有信息可追溯到源,无缺失 |
| 3 | 幻觉检测 | 内容 | LLM 语义校验「是否写了源数据中没有的内容」| 无凭空生成 |
| 4 | 关联一致性 | 内容 | 与影响调查书对比 | 生成的关联与 ImpactReport 一致 |
| 5 | 写入规则遵守 | 规则 | via RAG 检索写入规则并对比 | 符合记入规则/图表规则 |
| 6 | 设计规则遵守 | 规则 | via RAG 检索设计规则并对比 | 符合设计约束 |
| 7 | 矛盾检测 | 规则 | 全文扫描自相矛盾的描述 | 无矛盾表述 |
| 8 | 可追溯性 | 可追溯 | 每段内容检查 source_uri 标注 | 每个断言有来源 |
| 9 | 术语一致性 | 规则 | 与统一术语表对比 | 无术语混用 |
| 10 | 章节完整性 | 内容 | 与模板章结构对比 | 所有章节已生成且无缺章 |
| 11 | 语言一致性 | 语言 | 脚本检测正文与期望语言是否一致(`language_consistency`,确定性) | 期望语言可推导时正文不混入他语言;不可推导记满分(unverifiable |
> 第 11 项为 2026-08 新增(输出语言一致性保障)。期望语言由显式 `--output-language zh/ja` 或 auto 推导
> (标题假名 → 规则文档主导脚本)得到,单一事实来源为 `src/genesis/writer/language.py`
> 表格/标题不检(表格照抄源、标题跟随模板);Writer 生成阶段同源强制(违规重试、耗尽硬失败)。
### 7.3 校验方法
```
双重校验策略:
1. 确定性校验(代码)
- 格式校验(python-docx 对比模板样式)
- 可追溯性校验(正则检查 source_uri
- 章节完整性校验(章结构对比)
2. LLM 语义校验(推理引擎)
- 内容准确性(源数据逐条核对)
- 幻觉检测(对比源数据与生成内容)
- 规则遵守(注入 RAG 检索的规则,LLM 判断是否符合)
- 矛盾/术语检测
```
### 7.4 校验结果与反馈
```
QA 输出:
{
"version": "v1",
"total_items": 10,
"results": [
{"item": "格式一致性", "status": "pass"},
{"item": "内容准确性", "status": "fail",
"details": [{"chapter": "DB設計", "issue": "TB003 的列名与源数据不一致", "source_uri": "要件定義.xlsx#DB!D5"}]},
...
],
"summary": {"pass": 8, "fail": 2, "warnings": 1}
}
反馈循环:
QA 发现错误 → 将问题列表反馈给 Writer
→ Writer 只修正错误章节(不重新生成全部)
→ 重新 QA 校验
> **QA 护栏(T15 机制化,对应审查 OV6)**:
> 1. **循环边界**:「QA 校验 → Writer 修正 → 重新校验」循环受 `QALoopController`
> `DEFAULT_MAX_QA_ROUNDS=3`)约束,超过上限必须停止并上报人工/降级处理,
> 禁止无限重试(`src/genesis/qa/guardrails.py`)。
> 2. **独立校验模型(防自校验盲区)**:QA 校验强制走 `resolve_qa_model()` 返回的
> **fallback 模型**(如 qwen-max),不得与生成主模型(deepseek-chat)同源;
> 否则「DeepSeek 生成 + DeepSeek 校验」会形成同族模型盲点,难以发现自身偏误。
> 无 fallback 配置时返回 None,迫使调用方显式指定独立校验模型,而非静默回退主模型。
> 实现调用示例:`engine.chat(session_id=..., prompt=..., model=resolve_qa_model(models))`。
### 7.5 黄金集与评分器(T13 机制化,OV4)
> OV4 裁定:成功标准须有量度 → 建立黄金集 + 评分器(已实现于 `src/genesis/eval/`)。
- **评分器(ChapterScorer**:按 §7.2 指标体系输出各维度 `DimensionScore(score, passed)` 与总分 `EvalReport`。
- 确定性维度(代码可验证,无需 LLM):
- `traceability`:所有 `source_uri` 经 `resolver.validate_source_uris` 定位(不可解析 → 扣分,防 QA#8 作弊)
- `placeholder_residue`:渲染文本无 `{{...}}` 残留(残留即 fail
- `chapter_completeness`:生成章节覆盖模板期望集合(覆盖率)
- LLM 语义维度(内容准确性/幻觉/规则遵守):通过 `llm_evaluators` 钩子注入,默认中性分,待 Phase5 接入真实推理
- **黄金集(GoldenSet**:从 YAML 加载回归基线,`sample/` 真实脱敏样本作 `input_ref`(审查报告 §8.2 已确认 7 个样本为黄金集基础);每条 `GoldenCase` 标注 `expected_min_score`Phase5 后用于端到端回归
- 评分器作为 CI 质量门禁:生成结果总分 < 阈值 → 阻断合并(与 fail_under=99 覆盖率门禁同级)
→ 重复至全部通过或用户确认放行
```
### 7.5 与 RAG 的交互
- QA 校验规则遵守时,通过 RagService 检索写入规则/设计规则(category="write" 或 "design"
- 对已由用户决策的规则冲突(conflict_resolve 记录),以已决策规则为准,不再告警
### 7.6 输出
- 设计书附带 QA 报告(JSON,可下载)
- 前端「结果预览」页面展示 QA 结果(全10项 pass/fail + 警告)
---
## 8. Web UI 设计
### 8.1 概述
概要设计书自动生成 Agent 的 Web UI 是用户与系统交互的唯一界面,承担以下功能:
- 文件上传(要件定义、模板、规则文档、现系统文件)
- 各步骤的确认与修正(解析结果、影响调查结果、生成结果)
- 生成进度实时展示
- 最终设计书的预览与下载
- 规则手册管理(更新、版本查看)
- 多用户支持(数据隔离)
### 8.2 页面结构
**全局布局:**
```
┌─────────────────────────────────────────────────────────────┐
│ Genesis [上传] [解析] [影响调查] [生成] [结果] [历史] [设置] │ ← 顶部导航
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌─ 对话区域 ──────────────────────────────────────────┐ │
│ │ 🤖 ...(状态信息、进度、结果) │ │
│ │ 🧑 ...(用户输入、文件拖拽、回答) │ │
│ └──────────────────────────────────────────────────────┘ │
│ │
│ ┌─ 组件区域 ──────────────────────────────────────────┐ │
│ │ (根据当前步骤切换: 表格/确认画面/进度等) │ │
│ └──────────────────────────────────────────────────────┘ │
│ │
│ 状态栏: [📤已上传] [✅完成] [⏳进行中] [⏸未开始] │
└─────────────────────────────────────────────────────────────┘
```
**导航步骤:**
```
① 上传 → ② 解析确认 → ③ 影响调查确认 → ④ 生成执行 → ⑤ 结果预览
(文件选择) (Sheet判定等) (关联・不确定处) (进度显示) (设计书浏览/下载)
```
### 8.3 各页面详细设计
#### 页面1: 文件上传
```
┌─────────────────────────────────────────────┐
│ 1. 上传文件 │
├─────────────────────────────────────────────┤
│ │
│ 📁 要件定义 (必须) │
│ ┌─────────────────────────────────────┐ │
│ │ .xlsx, .xls, .docx, .pptx 拖放即可 │ │
│ │ 或 [选择文件] │ │
│ └─────────────────────────────────────┘ │
│ │
│ 📁 设计书模板 (必须) │
│ ┌─────────────────────────────────────┐ │
│ │ .docx (Word) │ │
│ └─────────────────────────────────────┘ │
│ │
│ 📁 记入规则 (推荐, 可多个) │
│ 📁 图表规则 (推荐) │
│ 📁 做成说明书 (推荐, 独立类型) │
│ │
│ 📁 现有系统文件 (任意, 追加/改修场景使用) │
│ │
│ [更新规则] ← 规则手册再构建按钮 │
│ │
│ [上传完成 → 进入解析] │
└─────────────────────────────────────────────┘
```
上传规则:
- 要件定义文件至少一个
- 模板文件必须是一个 .docx
- 做成说明书 / 记入规则 / 图表规则 均可多个,也可零个(规则手册已存在时);做成说明书使用独立 `file_type=write_instruction`api-design §2.2
- 现系统文件仅在追加/改修场景时需要
- 文件大小限制:最大100MB
- 支持拖拽上传、点击上传、取消上传
#### 页面2: 解析结果确认
```
┌─────────────────────────────────────────────┐
│ 2. 确认解析结果 │
├─────────────────────────────────────────────┤
│ │
│ ▶ Excel要件定义 - Sheet类型判定 │
│ ┌────────┬────────────┬────────┬─────────┐ │
│ │ Sheet名│ 类型判定 │ 修正 │ 行数/列数│ │
│ ├────────┼────────────┼────────┼─────────┤ │
│ │ 功能一览 │ ✅ FUNCTION │ [修正]│ 150x5 │ │
│ │ 画面一览 │ ✅ SCREEN │ [修正]│ 30x4 │ │
│ │ 账票一览 │ ✅ REPORT │ [修正]│ 12x6 │ │
│ │ DB定义 │ ✅ DATABASE │ [修正]│ 20x8 │ │
│ │ 自由记述 │ ⚠ 自由记述型│ [修正]│ 45行 │ │
│ └────────┴────────────┴────────┴─────────┘ │
│ ※ 取消线行将从生成对象中排除 │
│ │
│ ▶ Word模板 - 章节构成 │
│ 检测到的章节: │
│ 1. 目的 │
│ 2. 功能一览 │
│ ...(全部章节一览) │
│ [修改章节] │
│ │
│ ▶ 现有系统探索结果 (仅追加/改修场景显示) │
│ 检测: Controller / Service / Entity / API │
│ [查看详情] [要修正吗?] │
│ │
│ [确认并进入影响调查] │
└─────────────────────────────────────────────┘
```
交互说明:Sheet类型判定由 AI 自动完成,但用户可点击修正。章节构成同理。
#### 页面3: 影响调查确认
```
┌─────────────────────────────────────────────┐
│ 3. 确认影响调查结果 │
├─────────────────────────────────────────────┤
│ │
│ ── 影响调查概要 ── │
│ 要素数: 45件 | 关联数: 128件 | 高置信度: 85件 │
│ 不确定处: 2件 │
│ │
│ ── 要素一览(可折叠) ── │
│ ▸ F001 用户注册 (功能) │
│ 关联: SC001(利用/h) SC002(利用/h) TB001(更新/h) │
│ [编辑] [删除] │
│ │
│ ── 未确定项目 ── │
│ ❓ F004 → TB007 的关联不明 │
│ 根据: 仅名称相似 │
│ → [追加] [否决] [修正] │
│ │
│ ── 质量指标 ── │
│ ⚠ 孤立要素: F012 与任何要素均无关联 │
│ ⚠ 风险: 删除 F001 将影响 5 个要素 │
│ │
│ [确认完成 → 进入生成] │
└─────────────────────────────────────────────┘
```
交互说明:一栏显示全部关联(无 auto-pass)。仅高亮关注未确定项目。
#### 页面4: 生成执行
```
┌─────────────────────────────────────────────┐
│ 4. 概要设计书生成中... │
├─────────────────────────────────────────────┤
│ │
│ 进度: │
│ │
│ ✅ 功能一览 - 完成 (23秒) │
│ ✅ 画面一览 - 完成 (18秒) │
│ ⠋ DB设计 - 生成中... │
│ ⬜ 账票一览 - 等待 │
│ ⬜ IF定义 - 等待 │
│ ⬜ 非功能要件 - 等待 │
│ │
│ 已过时间: 41秒 / 预计时间: ~3分 │
│ │
│ ────────────────────────────────────── │
│ DB设计章 生成中: │
│ 关联要素: F001, F003, TB001, TB002 │
│ 适用规则: 写入规则_v3 │
│ │
│ [中途中断] [查看日志] │
│ │
│ ┌─ 规则冲突 (浮动卡片) ───────────────────┐ │
│ │ ⚠ 检测到规则冲突(DB设计章) │ │
│ │ 记入规则 2.3「表头仅加粗」 │ │
│ │ 图表规则 2.3「表头加粗+下划线」 │ │
│ │ [采用「记入规则」] [采用「图表规则」] [标注] │ │
│ └──────────────────────────────────────┘ │
└─────────────────────────────────────────────┘
```
交互说明:用户可保持此画面打开同时进行其他工作。生成完成时通知。选择中断时,已完成的章节保留。规则冲突由 WS 事件 `conflict_pending` 触发浮动卡片,决策后调用 `/api/rules/conflicts/{id}/resolve` 继续生成。
#### 页面6: 设置
>
> 简版:规则手册版本管理(versions / 更新 / 回滚)+ LLM 配置只读摘要(脱敏)。见 `docs/web-ui-design.md` §3.6。
#### 页面7: 会话历史
>
> 简版:会话列表(恢复 / 删除 / 新建),对应 `GET /api/sessions`。见 `docs/web-ui-design.md` §3.7。
#### 页面5: 结果预览与下载
```
┌─────────────────────────────────────────────┐
│ 5. 生成完成 │
├─────────────────────────────────────────────┤
│ │
│ ┌─ QA报告 ──────────────────────────┐ │
│ │ ✅ 全部10项检查通过 │ │
│ │ 警告 1件: 「功能概要应包含影响范围」 │ │
│ └────────────────────────────────────────┘ │
│ │
│ ┌─ 预览 ──────────────────────────┐ │
│ │ (ContentBlock → HTML 渲染) │ │
│ │ [章标题] [段落] [表] ... │ │
│ └────────────────────────────────────────┘ │
│ │
│ ┌─ 下载区域 ──────────────────────────┐ │
│ │ 📥 下载设计书 (.docx) │ │
│ │ 📥 下载QA报告 (.json) │ │
│ │ 📥 下载影响调查书 (.json) │ │
│ └────────────────────────────────────────┘ │
│ │
│ [修正后重新生成] [进行新生成] │
└─────────────────────────────────────────────┘
```
### 8.4 技术设计
#### 8.4.1 任务管理
```
TaskQueue(抽象接口,v1 仅 PersistentTaskQueueRedis/Valkey 为 v2 预留,Scope 缩减裁定)
├── task:generate-chapter-1
│ status: completed
│ result: {chapter: "功能一览", html: "...", time_ms: 23000}
├── task:generate-chapter-2
│ status: running
│ started_at: 2026-07-21T12:01:00Z
└── task:generate-chapter-3
status: pending
```
#### 8.4.2 会话管理(SQLite
**会话表设计:**
```sql
CREATE TABLE sessions (
id TEXT PRIMARY KEY,
user_id TEXT NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME,
status TEXT,
current_step TEXT,
metadata JSON
);
CREATE TABLE session_snapshots (
id INTEGER PRIMARY KEY AUTOINCREMENT,
session_id TEXT NOT NULL REFERENCES sessions(id),
step TEXT NOT NULL,
data BLOB,
version INTEGER DEFAULT 1,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE session_files (
id INTEGER PRIMARY KEY AUTOINCREMENT,
session_id TEXT NOT NULL REFERENCES sessions(id),
file_type TEXT NOT NULL,
file_name TEXT NOT NULL,
file_path TEXT NOT NULL,
file_size INTEGER,
mime_type TEXT,
uploaded_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
```
**为什么用 SQLite**
- 单一文件,无需额外安装
- 通过 SQL 查询即可轻松搜索会话
- ACID 事务保证数据一致性
- 进程重启后数据仍保留
- 迁移到 PostgreSQL 也容易(表定义兼容性高)
#### 8.4.3 多用户
```
工作区结构:
/data/users/{user_id}/
├── uploads/ # 用户上传的文件
│ ├── session_001/
│ │ ├── requirements.xlsx
│ │ └── template.docx
│ └── session_002/
├── outputs/ # 生成的设计书
│ ├── session_001.docx
│ └── session_002.docx
└── config/
共享数据(所有用户通用):
/data/shared/
├── rules-handbook/ # 规则手册(所有用户通用)
│ ├── v1/
│ └── v2/ # 规则更新版本
└── templates/ # 模板(所有用户通用)
```
#### 8.4.4 斜杠命令
```
/upload → 聚焦到文件上传区域
/probe → 跳转到解析结果画面
/impact → 跳转到影响调查画面
/generate → 跳转到生成执行画面
/result → 跳转到结果画面
/history → 跳转到历史会话页
/settings → 跳转到设置画面
/status → 显示当前生成任务的状态
/cancel → 取消当前生成
/help → 显示帮助
```
### 8.5 异常处理UX
#### 生成出错时
```
DB设计 生成过程中发生错误
┌─────────────────────────────────────────┐
│ ⚠ DB设计章生成时发生错误 │
│ 错误详情: LLM API调用失败 │
│ 错误码: LLM_TIMEOUT │
│ │
│ [重试] [跳过并继续] [中断] │
└─────────────────────────────────────────┘
```
#### 会话恢复
浏览器关闭后再次打开时:
```
「要恢复上次的会话吗?」
上次的状态: Step 3 (影响调查确认)
・解析结果: ✅ 完成
・影响调查: ✅ 完成(以上述v2确认)
・Writer: 未开始
[恢复并继续] [开始新会话]
```
---
## 9. 数据模型与 Provenance 层
### 9.1 核心概念
```
每个数据元素携带 Provenance(来源信息):
Excel哪个文件 → 哪个Sheet → 哪行哪列 → 哪个字段
```
### 9.2 Citation URI 格式
```
格式: file.xlsx#SheetName!ColumnRow
例: "要件定義.xlsx#機能一覧!C3"
```
> **T12 机制化(OV3**:URI 的解析/存在性验证已落地为 `src/genesis/parsers/resolver.py`
> - `parse_source_uri(uri)`:解析为 SourceRef(格式非法 → `URIError`
> - `provenance_to_uri(prov)`:从 Provenance 还原 URI(与 build 互逆)
> - `resolve_source_uri(uri, source)`:在 StructuredSource 内定位真实单元格
> - `validate_source_uris(uris, source)` → ValidationResult(resolved, unresolved)
>
> 该机制支撑 design.md §6.8 第五步「source_uris 存在性校验」——QA 校验时
> 所有引用的 URI 必须能在输入源中定位,否则落入 unresolved(防 QA#8 编造 URI 作弊)。
### 9.3 Provenance Chain
```
记录「该信息如何被加工」:
[
{"step": "raw", "source_uri": "...", "content": "原始值"},
{"step": "llm_extracted", "model": "deepseek-chat", "prompt_version": "v2"},
{"step": "user_corrected", "user": "田中", "date": "2026-07-21"}
]
```
### 9.4 完整数据模型定义
> 本节为编码所需的**字段级完整定义**,是阶段1.2(`data_models.py`)的直接实现依据。凡 `§3.8` 引用但未展开的类型,均在此定义。
#### 9.4.1 枚举与基础类型
```python
from enum import Enum
from typing import Any, Optional
from dataclasses import dataclass, field
class SheetType(Enum):
"""Excel Sheet 的类型(Parser SheetDetector 判定结果)"""
FUNCTION = "FUNCTION" # 功能一览
SCREEN = "SCREEN" # 画面一览
REPORT = "REPORT" # 账票一览
DATABASE = "DATABASE" # DB 定义
INTERFACE = "INTERFACE" # IF 定义
BATCH = "BATCH" # 批处理一览
MASTER = "MASTER" # 主数据定义
GENERIC = "GENERIC" # 无法归类
class ElementType(Enum):
"""Impact Agent 抽取的构成要素类型"""
FUNCTION = "機能" # 功能
SCREEN = "画面" # 画面
REPORT = "帳票" # 账票
DB = "DB" # 数据表
IF = "IF" # 接口
BATCH = "バッチ" # 批处理
class RelationType(Enum):
"""关联类型(Impact Agent 推理结果)"""
USE = "利用" # 功能利用画面/账票
REFER = "参照" # 读取 DB/IF 数据
UPDATE = "更新" # 写入 DB/IF 数据
OUTPUT = "输出" # 生成账票
INPUT = "输入" # 画面接受输入传给功能
DEPEND = "依赖" # 依赖其他功能/模块
class Confidence(Enum):
"""置信度等级"""
HIGH = "high"
MEDIUM = "medium"
LOW = "low"
class ExtractionMethod(Enum):
"""Excel 表的抽取方式"""
OPENPYXL = "openpyxl" # 结构化表格解析
LLM_FROM_FREE_TEXT = "llm_from_free_text" # 自由记述 → LLM 结构化
```
#### 9.4.2 Parser 相关类型补全
```python
@dataclass
class RuleDocument:
"""规则文档(Parser 解析后传给 RAG 的中间形态)"""
file_name: str # 源文件名
category: str # "write" | "design" | "ref"(写入规则/设计规则/参考文档)
markdown_content: str # 规则文档的 Markdown 化文本
source_path: str # 源文件路径
file_type: str # "word" | "excel" | "ppt"
hash: str # 内容 hash(版本管理用,RAG 层 §5)
@dataclass
class ImageAnalysis:
"""图片/图形的分析结果(Parser 输出,供 Writer 参考)。
区分 ImageDescription(§9.4.3):
- ImageDescription = ImageAnalyzer 的**原始识别输出**(仅 image_ref/description/confidence/model
- ImageAnalysis = Parser 在原始输出基础上**组装**,追加 sheet_name/anchor_cell/nearby_text/
source_uri/status 等解析上下文(写入 StructuredSource.image_analyses
调用方(Writer/Impact)只消费 ImageAnalysis,不应直接消费 ImageDescription。
"""
image_ref: str # 图片引用(ZIP 内路径 或 提取后的文件路径)
description: str # Vision LLM 的识别描述
confidence: float # 0.0 ~ 1.0
source_uri: str # 来源(如 file.xlsx#Sheet1!A1 附近图片)
sheet_name: str # 所属 Sheet
anchor_cell: str # 锚点单元格坐标
status: str # "recognized" | "recorded_only" | "failed"
nearby_text: str = "" # 图片附近文本(上下文)
# ExistingSystemInfo 的 4 个子类型
@dataclass
class ControllerInfo:
name: str
class_name: str
path: str # 类所在文件路径
base_path: str # @RequestMapping 等类级路径
endpoints: list[str] # 端点列表(如 ["GET /api/users"]
source_uri: str # 溯源(file#类名!行号)
@dataclass
class ServiceInfo:
name: str
class_name: str
path: str
methods: list[str] # 公开方法名
source_uri: str
@dataclass
class EntityInfo:
name: str
class_name: str
path: str
table_name: str | None # 对应 DB 表名(有 @Table 注解时)
fields: list[str] # 字段名列表
source_uri: str
@dataclass
class EndpointInfo:
method: str # GET/POST/PUT/DELETE
path: str
controller: str | None # 所属 Controller
description: str # 功能描述
source_uri: str
```
#### 9.4.3 共通工具层输出类型补全
```python
@dataclass
class UnifiedDocument:
"""FileReader 的统一输出(多格式归一化)"""
file_name: str
file_type: str # "excel" | "word" | "ppt" | "text"
source_path: str
content_type: str # 按格式的内容载体类型
# 按 file_type 填充不同字段(未命中的为 None)
tables: list[list[list[Any]]] | None = None # excel: [sheet][row][col]
sheet_names: list[str] | None = None # excel
paragraphs: list[dict] | None = None # word: [{style, text}]
slides: list[dict] | None = None # ppt: [{title, body, notes}]
text: str | None = None # text / 兜底
encoding: str | None = None # 检测到的编码(chardet
@dataclass
class CodeStructure:
"""CodeParser 的解析输出"""
root_path: str
language: str # "java" | "python" | "csharp" | ...
modules: list[dict] # 模块/包列表 [{name, path}]
classes: list[dict] # 类列表 [{name, kind, path}]
controllers: list[ControllerInfo]
services: list[ServiceInfo]
entities: list[EntityInfo]
endpoints: list[EndpointInfo]
raw_imports: list[dict] # import 关系(依赖分析用)[{from, to}]
@dataclass
class ImageDescription:
"""ImageAnalyzer 的原始识别输出(工具层)。
区分 ImageAnalysis(§9.2):Parser 会将本类型**组装**为带 Sheet 锚点与状态的
ImageAnalysis 后写入 StructuredSource;业务层不应直接消费本类型。
"""
image_ref: str
description: str
objects: list[str] # 识别出的对象标签
ocr_text: str | None # OCR 文本(若有)
confidence: float
model: str # 使用的 Vision 模型
```
#### 9.4.4 运行时层类型汇总(引用关系)
运行时层(`docs/agent-runtime-design.md`)已定义的类型,此处列出**与业务数据模型的衔接点**,不重复定义:
| 类型 | 定义位置 | 与业务模型的衔接 |
|------|---------|----------------|
| `ChatResult` / `StructuredResult` / `TokenUsage` | agent-runtime §2.2 | InferenceEngine 输出,各 Agent 消费 |
| `Prompt` / `PromptRegistry` | agent-runtime §2.7 | Prompt 模板库 |
| `ArtifactRef` / `MemoryService` | agent-runtime §4.4 | StructuredSource/ImpactReport 存取的引用 |
| `ToolResult` / `ToolExecutor` | agent-runtime §5.3 | UnifiedDocument/CodeStructure/ImageDescription 经此返回 |
| `LLMCallEvent` / `ToolCallEvent` | agent-runtime §6.1 | 可观测性事件 |
| `VectorStoreAdapter` / `VectorHit` | rag-layer §9.2 | RAG 存储适配 |
#### 9.4.5 数据模型引用关系图
```
生产方 消费方
──────── ────────
FileReader ── UnifiedDocument ──► ParserExcel/Word/PPT 解析)
CodeParser ── CodeStructure ────► ParserExistingSystemExplorer
ImageAnalyzer ── ImageDescription ► ParserImageAnalysis 组装)
Parser ── StructuredSource ─────────────► Impact(要素抽取)
└─ 内含: ExcelTable / ParsedTemplate / RuleDocument /
ImageAnalysis / ExistingSystemInfo / CellComment
Impact ── ImpactReport(影响调查书 JSON)► Writer(章节生成)
RAG ── RuleChunk ───────────────────────► Writer / Impact / QA(规则检索)
Writer ── ContentBlockJSON 内容块)────► 渲染器(chapter_html / docx
QA ── QAReport(校验结果 JSON)──────────► UI / 反馈 Writer
```
#### 9.4.6 实现落地说明(P0-1 修复:前向引用与定义顺序)
§3 与 §9.4 的类型存在**交叉引用**(如 §3 的 `ExcelTable.detected_type: SheetType`、`CellValue.formatting: CellFormatting` 等引用 §3 或 §9.4 中后置定义的类型)。实现时须遵守以下约定,避免类定义时的 NameError:
1. **全部数据模型统一放置于 `src/genesis/data_models.py`**(或按包拆分但共用同一模块边界),不散落各 Agent。
2. 该文件(及引用数据模型的任何文件)**首行启用 `from __future__ import annotations`**,使注解惰性求值,类定义顺序与引用顺序无关。
3. 枚举(`SheetType`/`ElementType`/`RelationType`/`Confidence`/`ExtractionMethod`)与 `EventType` 等,建议在文件后部集中定义;dataclass 内部可前向引用(依赖 future.annotations)。
4. `ExtractionMethod` 的取值字符串(`"openpyxl"` / `"llm_from_free_text"`)用于 `ExcelTable.extraction_method`,与 settings 中 `ExtractionMethod` 枚举保持同一常量来源,避免魔法字符串。
```python
# src/genesis/data_models.py(示意开头)
from __future__ import annotations
from enum import Enum
from dataclasses import dataclass, field
from typing import Any, Optional
```
---
## 10. 异常处理策略
### 10.1 基本方针
参考 OpenCode / Claude Code 模式:
- 出错时显示错误信息
- 用户可选择「重做」「继续」「中断」
- 已处理的 Step 保留结果,恢复时从中途继续
### 10.2 具体模式
```
Step 1(要素抽取)中 LLM 调用失败:
画面: 「要素抽取时发生错误」
选择: [重试] [取消]
Step 3(关联推理)中部分功能推理失败:
画面: 「F005, F008 的推理失败。其余已完成」
选择: [继续(跳过对应功能)] [重试] [中断]
```
### 10.3 恢复保证
- 各 Step 完成时保存中间结果
- 中断后,以相同会话 ID 恢复 → 从已完成的 Step 继续
- 未完成的 Step 从头执行
---
## 11. 通信语言与文档规范
### 11.1 通信语言
本项目的所有 AI 交流、文档、注释、代码中的文本,**统一使用中文**。不得使用日文、英文或其他语言进行交流(专有名词、技术术语、代码关键字等不可避免的情况除外)。
### 11.2 文档保存位置
所有设计文档、方案、报告等内容,必须保存到 `docs/` 目录下。
### 11.3 信息安全
- 不得将客户数据、公司信息上传至外部公开仓库
- API Key 配置在环境变量或配置文件中,不得硬编码在源码
- 确认所有依赖的许可证类型,禁止使用盗版软件
---
## 12. Phase 5Writer / QA 子系统
> 本章记录在 phase5/writer-qa 分支上落地的「Writer / QA 子系统」实现,作为设计 §6(Writer Agent 详细设计)与 §7(QA Agent 详细设计)的工程落地补充。实现严格遵循设计基线,并诚实标注了范围边界与推后项。
### 12.1 目标与范围
**目标**:打通「结构化源 → 单章内容生成 → 渲染 → 注入 Word 模板 → QA 校验 → 闭环仅重失败章」的最小可用链路。
**范围内**
- 单章内容生成(WriterAgent 调用 InferenceEngine 产出 `ChapterContent`)。
- 内容块渲染(`render_chapter_blocks` 将 `ChapterContent` 转 `Block` 序列)。
- Word 注入(`DocxInjector.inject` 将章节内容写入模板对应 `{{section:id}}` 占位符)。
- QA 校验(确定性维度:`traceability` / `placeholder_residue` / `chapter_completeness`)。
- QA 闭环(`QALoop` 仅对失败章重新生成,受 `QALoopController(DEFAULT_MAX_QA_ROUNDS=3)` 约束)。
> **确定性维度生效说明(Phase 5 现状)**:章节级「章节完整性(`chapter_completeness`)」维度当前因 `template_sections_expected` 恒为空而实质为空操作(恒满分),生效的确定性维度为**可追溯性(`traceability`+ 占位符残留(`placeholder_residue`**。待模板期望章节集合回填后,`chapter_completeness` 方才参与校验。
**范围外(诚实标注)**
- **语义 QA 为探针**:内容准确性 / 幻觉检测 / 规则遵守等 LLM 语义维度,经 `ChapterScorer.llm_evaluators` 钩子注入,默认中性分,尚未接入真实推理(设计 §7.5 已声明待 Phase5)。
- **图表生成**:本实现不生成图形/图表,仅支持表格/列表/段落/提示框等文本型 Block(设计 §6.4 的 table/list/paragraph/note)。
- **跨章引用一致性**:设计 §7.2 第 4 项「关联一致性」由 `WriterState.cross_refs` 记录,但端到端语义校验(与 ImpactReport 逐条比对)超出本实现范围,留待人工质量门禁与后续里程碑。
### 12.2 组件与数据流
```
StructuredSource
│ build_contexts(structured_source, samples_dir)
list[ChapterContext] (每章:chapter_id / 数据选择器 / 模板标记)
│ WriterAgent.generate_chapter(ctx) 逐章串行
ChapterContentblocks: list[ContentBlock] + source_uris
│ render_chapter_blocks(content)
list[Block]DocxInjector.Blockparagraph/heading/table/list/note
│ DocxInjector(template_path).inject(sections, meta)
Document(注入后 Word 文档)
│ QALoopDEFAULT_MAX_QA_ROUNDS=3
│ ├─ QAValidator 校验各章(仅确定性维度)
│ └─ 仅对失败章:WriterAgent.generate_chapter → render → 重新注入
最终 Document + QAReport
```
关键约定:
- 逐章**串行**生成(设计 §6.8.1 基线约束),`WriterState` 跨章共享摘要与关键表结构供后章引用。
- QA 闭环**仅重失败章**,不重新生成全部,受最大轮次护栏约束,禁止无限重试(设计 §7.4 护栏)。
### 12.3 实现期发现的真实 API 适配(避坑记录)
实现过程中,以下真实接口与设计/规范文档存在偏差,已按真实接口落地,此处统一记录供后人避坑:
1. **`DocxInjector` 真实接口**:为 `DocxInjector(template_path).inject(sections: dict[section_id, list[Block]], meta) -> Document`。**不存在** `inject_blocks` 方法;`sections` 字典的键是 `{{section:id}}` 中的 `id`(不含 `section:` 前缀)。
2. **`InferenceEngine.chat_structured`** 签名为 `chat_structured(*, session_id, prompt, variables, schema, retry_count=2) -> StructuredResult`,返回对象含 `.data`(解析后的 dict)与 `.status`ok / parse_error / failed)。调用时必须关键字传参。
3. **`RagService.retrieve_*`** 为**同步**方法(非 async)。调用方在同步编排链路中直接调用即可,无需 `await`。
4. **`map_template`** 消费真实的 `ParsedTemplate.sections`(元素类型为 `ChapterMarker`,含 `type` / `name` / `level`)。映射按文档顺序:遇到 `heading` 起一章;其后的 `section:<id>` 占位符归属该章 → `chapter_id = id`、`section_placeholder = "section:<id>"`。
5. **`ChapterScorer.score(chapters: list[ChapterArtifact], source: StructuredSource)`**QA 层需要 `ChapterContent → ChapterArtifact` 适配器(由 `ChapterContent.blocks` 拼接得到 `text`,并从各 block 收集 `source_uris`);设计 §7.5 的 `ChapterArtifact` 并非直接由 Writer 产出,需经适配。
6. **真实 `DocxInjector.Block`** 支持 `paragraph` / `heading` / `table``list` / `note` 当前按 `paragraph` 降级渲染(原型范围,无列表/提示框样式)。表格注入会渲染 `caption` 段落(caption 非空时在其上方/下方生成说明段落),非空 caption 不应被丢弃。
### 12.4 垂直切片状态
**FakeLLM 模式已打通(可回归)**:
- 运行 `python scripts/run_phase5_slice.py --fake`,使用 `FakeLLMClient` 驱动整条链路,产出 `sample/phase5-slice/output.docx`。
- 该切片覆盖:build_contexts → 逐章生成 → 渲染 → 注入 → QA 闭环(仅重失败章),并附带 `QAReport`。
**真实 LLM 生成 + 人工质量门禁(待人工执行项,P5-T10 推后)**:
- 真实推理接入(DeepSeek / Qwen 等)与端到端人工质量门禁(内容准确性 / 格式精度 / 规则遵守的人工判读)不在本自动实现范围内,标记为推后项。
- 真实 LLM 接入点已预留(`InferenceEngine` 默认实例 + `PromptRegistry` 注入),人工执行时仅需提供可用模型配置与 `scripts/run_phase5_slice.py` 的非 `--fake` 路径。