from __future__ import annotations import json from dataclasses import asdict, dataclass from pathlib import Path @dataclass(frozen=True) class SyntheticExample: prompt: str response: str correction: str tags: list[str] source: str = "synthetic" def as_dict(self) -> dict: return asdict(self) def generate_synthetic_examples( topic: str, count: int, tag: str = "synthetic", ) -> list[SyntheticExample]: if count < 0: raise ValueError("count must be non-negative") cleaned_topic = topic.strip() or "local AI workflow" return [ SyntheticExample( prompt=f"Write a concise field note about {cleaned_topic} #{index}.", response=f"Draft note {index}: {cleaned_topic}.", correction=f"Corrected note {index}: {cleaned_topic} with concrete evidence.", tags=[tag, cleaned_topic.replace(" ", "-").lower()], ) for index in range(1, count + 1) ] def validate_synthetic_example(example: SyntheticExample) -> list[str]: errors = [] if not example.prompt.strip(): errors.append("prompt is required") if not example.response.strip(): errors.append("response is required") if not example.correction.strip(): errors.append("correction is required") if not example.tags: errors.append("at least one tag is required") return errors def quality_filter_examples(examples: list[SyntheticExample]) -> list[SyntheticExample]: return [ example for example in examples if not validate_synthetic_example(example) and example.prompt != example.response and example.response != example.correction ] def augment_examples( examples: list[SyntheticExample], extra_tag: str = "augmented", ) -> list[SyntheticExample]: augmented = list(examples) for example in examples: tags = list(dict.fromkeys([*example.tags, extra_tag])) augmented.append( SyntheticExample( prompt=f"{example.prompt} Include one verification detail.", response=example.response, correction=f"{example.correction} Verification detail recorded.", tags=tags, source=example.source, ) ) return augmented def export_synthetic_jsonl( examples: list[SyntheticExample], output_path: str | Path = "data/synthetic_examples.jsonl", ) -> Path: output = Path(output_path) output.parent.mkdir(parents=True, exist_ok=True) with output.open("w", encoding="utf-8") as f: for example in examples: f.write(json.dumps(example.as_dict(), ensure_ascii=False) + "\n") return output