from __future__ import annotations import argparse import json from pathlib import Path ROOT = Path(__file__).resolve().parents[1] DEFAULT_INPUT = ROOT / "plugins" / "1c" / "training" / "examples" / "instruction.examples.jsonl" DEFAULT_GENERATED_INPUT = ROOT / "plugins" / "1c" / "training" / "raw" / "generated.instruction.jsonl" DEFAULT_OUTPUT = ROOT / "plugins" / "1c" / "training" / "prepared" / "train.chat.jsonl" def iter_jsonl(path: Path) -> list[dict]: records: list[dict] = [] with path.open("r", encoding="utf-8") as handle: for line in handle: line = line.strip() if line: records.append(json.loads(line)) return records def normalize_record(record: dict) -> dict: messages = [] for message in record.get("messages") or []: messages.append( { "role": message["role"], "content": message["content"].strip(), } ) return { "messages": messages, "metadata": { "id": record.get("id"), **(record.get("metadata") or {}), }, } def dedupe_records(records: list[dict]) -> list[dict]: seen: set[str] = set() result = [] for record in records: record_id = str(record.get("id") or (record.get("metadata") or {}).get("id") or "") if record_id and record_id in seen: continue if record_id: seen.add(record_id) result.append(record) return result def main() -> int: parser = argparse.ArgumentParser(description="Prepare 1C training data in chat JSONL format.") parser.add_argument("--input", type=Path, action="append", help="Input JSONL file. Can be passed multiple times.") parser.add_argument( "--include-generated", action=argparse.BooleanOptionalAction, default=True, help="Include the generated local training JSONL when it exists.", ) parser.add_argument("--output", type=Path, default=DEFAULT_OUTPUT) args = parser.parse_args() input_paths = args.input or [DEFAULT_INPUT] if args.include_generated and DEFAULT_GENERATED_INPUT.exists() and DEFAULT_GENERATED_INPUT not in input_paths: input_paths.append(DEFAULT_GENERATED_INPUT) raw_records = [] for input_path in input_paths: raw_records.extend(iter_jsonl(input_path)) records = [normalize_record(record) for record in dedupe_records(raw_records)] args.output.parent.mkdir(parents=True, exist_ok=True) with args.output.open("w", encoding="utf-8") as handle: for record in records: handle.write(json.dumps(record, ensure_ascii=False) + "\n") print(f"Wrote {len(records)} training record(s) to {args.output}") return 0 if __name__ == "__main__": raise SystemExit(main())