feat(writer): add WriteOrchestrator.generate (vertical slice, real DocxInjector.inject)

This commit is contained in:
lhl
2026-08-13 10:32:35 +08:00
parent f175203a23
commit 08e311b0a1
5 changed files with 183 additions and 0 deletions
+76
View File
@@ -0,0 +1,76 @@
"""Phase 5 垂直切片运行脚本(CLI)。
用法:
python scripts/run_phase5_slice.py --template <PATH> --output <PATH> [--fake]
- --fake: 使用内置 FakeEngine(无需 LLM 客户端/API Key),用于验证管线打通。
- 不带 --fake: 使用真实 InferenceEngine(),需先配置 LLM 客户端(人工质量门禁)。
管线: WordTemplateParser → StructuredSource → WriteOrchestrator.generate → docx。
"""
from __future__ import annotations
import argparse
from types import SimpleNamespace
from docx import Document
from genesis.data_models import StructuredSource
from genesis.parsers.word_template_parser import WordTemplateParser
from genesis.writer.orchestrator import WriteOrchestrator
class FakeEngine:
"""切片验证用假引擎:返回固定章节内容,避免真实 LLM 调用。"""
def chat_structured(self, *, session_id, prompt, variables, schema, retry_count=2):
return SimpleNamespace(
data={
"title": variables.get("title", ""),
"blocks": [{"type": "paragraph", "text": f"{variables.get('title','')}】自动生成的内容(fake 模式)"}],
},
status="ok",
)
def _build_source(template_path: str) -> StructuredSource:
parsed = WordTemplateParser().parse(template_path)
return StructuredSource(
tables=[],
template=parsed,
rule_docs=[],
image_analyses=[],
existing_system=None,
comments=[],
)
def _main() -> None:
parser = argparse.ArgumentParser(description="Phase 5 垂直切片运行脚本")
parser.add_argument("--template", required=True, help="概要设计模板 docx 路径")
parser.add_argument("--output", required=True, help="输出 docx 路径")
parser.add_argument("--fake", action="store_true", help="使用 FakeEngine(无 LLM")
parser.add_argument("--samples-dir", default="samples", help="RAG 样本目录")
args = parser.parse_args()
source = _build_source(args.template)
engine = FakeEngine() if args.fake else None # None → 真实 InferenceEngine()(需客户端配置)
orch = WriteOrchestrator()
contents = orch.generate(
source,
args.output,
samples_dir=args.samples_dir,
engine=engine,
template_path=args.template,
)
loaded = Document(args.output)
joined = "\n".join(p.text for p in loaded.paragraphs)
print(f"[slice] 生成章节数: {len(contents)}")
print(f"[slice] 输出路径: {args.output}")
print(f"[slice] 注入校验: {'OK' if any('自动生成' in p.text for p in loaded.paragraphs) else 'EMPTY'}")
print(f"[slice] 文本内容预览:\n{joined[:200]}")
if __name__ == "__main__":
_main()