Files
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

78 lines
3.1 KiB
Python
Raw Permalink 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.
"""#1/#2orchestrator 章级重试兜底测试。
问题:真实 LLM 输出有随机方差(如 ja 跑 function_list 单次输出疑似纯汉字被判违规),
WriterAgent 内部 max_retries=2 耗尽后抛 WriterGenerationError → 整次 run_trial 死亡。
修复:orchestrator.generate 增加章级管道重试(chapter_attempts),单章失败不连坐整次运行。
"""
from __future__ import annotations
from pathlib import Path
from types import SimpleNamespace
import pytest
from genesis.data_models import StructuredSource
from genesis.parsers.word_template_parser import WordTemplateParser
from genesis.writer.exceptions import WriterGenerationError
from genesis.writer.orchestrator import WriteOrchestrator
class _FlakyEngine:
"""前 N 次调用抛错(模拟随机硬失败),之后成功。"""
def __init__(self, fail_calls: int):
self.fail_calls = fail_calls
self.calls = 0
def chat_structured(self, *, session_id, prompt, variables, schema, retry_count=2):
self.calls += 1
if self.calls <= self.fail_calls:
raise RuntimeError(f"模拟第 {self.calls} 次调用失败")
return SimpleNamespace(
data={
"title": variables["title"],
"blocks": [{"type": "paragraph",
"text": "本機能はFakeLLMにより生成された十分な説明内容であり、書込規則を満たす。"}],
},
status="ok",
)
def _ss() -> StructuredSource:
template = Path("sample/phase5-slice/template.docx")
if not template.exists():
pytest.skip("样本模板缺失,跳过")
parsed = WordTemplateParser().parse(str(template))
return StructuredSource(template=parsed, tables=[], rule_docs=[],
image_analyses=[], existing_system=None, comments=[])
def test_generate_recovers_stochastic_single_chapter_failure(tmp_path):
"""前 3 次调用失败(跨章/章内重试),后续成功 → 整次生成不崩溃。"""
out = tmp_path / "o.docx"
engine = _FlakyEngine(fail_calls=3)
# chapter_attempts=3,内部 max_retries=2 → 单章最多约 3×2 次调用
contents = WriteOrchestrator().generate(
_ss(), str(out), samples_dir="nonexistent_dir_xyz",
engine=engine, template_path=str(Path("sample/phase5-slice/template.docx")),
)
assert contents, "应成功产出章节"
assert out.is_file()
def test_generate_hard_fails_after_chapter_attempts_exhausted(tmp_path):
"""始终失败 → 章级重试耗尽后仍抛 WriterGenerationError(不吞错)。"""
out = tmp_path / "o.docx"
class AlwaysFail(_FlakyEngine):
def chat_structured(self, *, session_id, prompt, variables, schema, retry_count=2):
self.calls += 1
raise RuntimeError("always fail")
with pytest.raises(WriterGenerationError):
WriteOrchestrator().generate(
_ss(), str(out), samples_dir="nonexistent_dir_xyz",
engine=AlwaysFail(0), template_path=str(Path("sample/phase5-slice/template.docx")),
chapter_attempts=1,
)