File size: 3,440 Bytes
9c84f9d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
"""JSONL file-based result store for local CLI runs."""

import json
import logging
from datetime import datetime, timezone
from pathlib import Path
from typing import Any
from uuid import uuid4

logger = logging.getLogger(__name__)


class JsonlStore:
    """Persist run results to JSONL files in a local directory.

    Directory structure:
        output_dir/
        β”œβ”€β”€ run.json          (run metadata)
        β”œβ”€β”€ results.jsonl     (inference results, one per line)
        β”œβ”€β”€ evaluation.json   (aggregated evaluation)
        └── eval_details.jsonl (per-sample eval details)
    """

    def __init__(self, output_dir: str | Path) -> None:
        self.output_dir = Path(output_dir)
        self.output_dir.mkdir(parents=True, exist_ok=True)

    async def update_run(self, run_id: str, data: dict[str, Any]) -> None:
        run_file = self.output_dir / "run.json"
        existing: dict[str, Any] = {}
        if run_file.exists():
            existing = json.loads(run_file.read_text())
        # Serialize datetimes
        for k, v in data.items():
            if isinstance(v, datetime):
                data[k] = v.isoformat()
        existing.update(data)
        existing["run_id"] = run_id
        run_file.write_text(json.dumps(existing, ensure_ascii=False, indent=2))

    async def insert_run_result(self, data: dict[str, Any]) -> str:
        result_id = str(uuid4())[:8]
        results_file = self.output_dir / "results.jsonl"
        data["id"] = result_id
        with open(results_file, "a") as f:
            f.write(json.dumps(data, ensure_ascii=False) + "\n")
        return result_id

    async def create_evaluation(self, data: dict[str, Any]) -> str:
        eval_id = str(uuid4())[:8]
        eval_file = self.output_dir / "evaluation.json"
        data["id"] = eval_id
        # Serialize datetimes
        for k, v in data.items():
            if isinstance(v, datetime):
                data[k] = v.isoformat()
        payload = json.dumps(data, ensure_ascii=False, indent=2)
        # tmp νŒŒμΌμ— λ¨Όμ € μ“°κ³  μ›μžμ μœΌλ‘œ κ΅μ²΄ν•œλ‹€(F3) -- μž¬κ³„μ‚° 도쀑 죽어도
        # evaluation.json 은 이전 λ‚΄μš© κ·ΈλŒ€λ‘œκ±°λ‚˜ μƒˆ λ‚΄μš© κ·ΈλŒ€λ‘œλ‹€. μ ˆλ°˜μ§œλ¦¬κ°€ μ•ˆ λ‚¨λŠ”λ‹€.
        tmp_file = eval_file.with_name(eval_file.name + ".tmp")
        tmp_file.write_text(payload)
        tmp_file.replace(eval_file)
        return eval_id

    def load_existing_results(self) -> list[dict[str, Any]]:
        """Load existing inference results from results.jsonl."""
        results_file = self.output_dir / "results.jsonl"
        if not results_file.exists():
            return []
        results = []
        for line in results_file.read_text().strip().split("\n"):
            if line:
                results.append(json.loads(line))
        return results

    def load_run_meta(self) -> dict[str, Any]:
        """Load run metadata from run.json."""
        run_file = self.output_dir / "run.json"
        if not run_file.exists():
            return {}
        return json.loads(run_file.read_text())

    async def insert_eval_details(self, details: list[dict[str, Any]]) -> int:
        if not details:
            return 0
        details_file = self.output_dir / "eval_details.jsonl"
        with open(details_file, "a") as f:
            for d in details:
                f.write(json.dumps(d, ensure_ascii=False) + "\n")
        return len(details)