From f175203a237dbf8dac37e23426ebea53f92ad5d4 Mon Sep 17 00:00:00 2001 From: lhl Date: Thu, 13 Aug 2026 10:14:03 +0800 Subject: [PATCH] feat(writer): add build_contexts (template+rules -> GenerationContext list) --- src/genesis/writer/context_builder.py | 31 +++++++++++++++++++++++++++ tests/test_phase5_context_builder.py | 30 ++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 src/genesis/writer/context_builder.py create mode 100644 tests/test_phase5_context_builder.py diff --git a/src/genesis/writer/context_builder.py b/src/genesis/writer/context_builder.py new file mode 100644 index 0000000..27bb7cb --- /dev/null +++ b/src/genesis/writer/context_builder.py @@ -0,0 +1,31 @@ +"""上下文装配:StructuredSource + 模板 + 规则 → 有序 GenerationContext 列表(Phase 5)。""" +from __future__ import annotations + +from genesis.data_models import StructuredSource +from genesis.services.rag_service import CannedRagService +from genesis.writer.models import ChapterSpec, GenerationContext +from genesis.writer.template_mapper import map_template + + +def build_contexts(structured_source: StructuredSource, samples_dir: str = "samples") -> list[GenerationContext]: + specs: list[ChapterSpec] = map_template(structured_source.template) + rag = CannedRagService(samples_dir=samples_dir) + out: list[GenerationContext] = [] + for spec in specs: + # RagService 方法为同步(P5-T3 裁定) + write_rules = rag.retrieve_write_rules(spec.chapter_id) + design_rules = rag.retrieve_design_rules(spec.chapter_id) + used = (structured_source.template.styles or {}).get("used", []) + out.append( + GenerationContext( + chapter_id=spec.chapter_id, + title=spec.title, + template_marker=spec, + structured_source=structured_source, + write_rules=write_rules, + design_rules=design_rules, + template_styles=set(used), + prior_state=None, + ) + ) + return out diff --git a/tests/test_phase5_context_builder.py b/tests/test_phase5_context_builder.py new file mode 100644 index 0000000..f77eb28 --- /dev/null +++ b/tests/test_phase5_context_builder.py @@ -0,0 +1,30 @@ +from types import SimpleNamespace + +from genesis.data_models import ParsedTemplate, ChapterMarker +from genesis.writer.context_builder import build_contexts +from genesis.writer.models import GenerationContext + + +def _ss(): + template = ParsedTemplate( + file_name="t.docx", + sections=[ + ChapterMarker(type="heading", name="はじめに", level=1), + ChapterMarker(type="placeholder", name="section:introduction", level=0), + ], + placeholders={}, + styles={"defined": ["Heading1"], "used": ["Heading1", "Normal"]}, + ) + return SimpleNamespace(template=template) + + +def test_build_contexts_maps_chapters(): + ctxs = build_contexts(_ss(), samples_dir="nonexistent_dir_xyz") + assert len(ctxs) == 1 + c = ctxs[0] + assert isinstance(c, GenerationContext) + assert c.chapter_id == "introduction" + assert c.write_rules == [] # 样本缺失 -> 空 + assert c.design_rules == [] + assert c.template_styles == {"Heading1", "Normal"} + assert c.template_marker.section_placeholder == "section:introduction"