File size: 2,745 Bytes
a89a7f1
e75684b
db3d901
a89a7f1
 
 
 
 
e75684b
 
 
 
 
220e208
 
 
e75684b
 
 
f4259c0
a89a7f1
 
 
 
 
 
 
 
 
f4259c0
 
 
a89a7f1
 
 
 
 
 
 
f4259c0
a89a7f1
 
a9950fb
a89a7f1
 
f4259c0
a89a7f1
 
99c28ab
 
f4259c0
a89a7f1
 
 
 
 
 
 
 
 
 
 
 
e75684b
a89a7f1
 
 
 
 
eb41f91
a89a7f1
 
 
 
db3d901
a89a7f1
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import json
from dataclasses import asdict, is_dataclass
from datetime import UTC, datetime
from pathlib import Path

from utils.helpers import slugify


def _serialise_message(message: dict[str, object]) -> dict[str, object]:
    payload: dict[str, object] = {
        "role": message["role"],
        "content": message["content"],
    }
    contrast = message.get("_contrast")
    if contrast is not None:
        payload["_contrast"] = asdict(contrast) if is_dataclass(contrast) else contrast
    return payload


def save_chat_export(
    *,
    model_name: str,
    dataset_source: str,
    persona_id: str,
    persona_name: str | None,
    prompt_mode: str,
    system_prompt: str | None,
    messages: list[dict[str, str]],
    generation: dict[str, object],
    panel_label: str | None = None,
) -> Path:
    """Save the current chat session to ``artifacts/chats`` as JSON.

    Args:
        model_name: Model identifier used for the chat.
        dataset_source: Human-readable dataset source label.
        persona_id: Selected persona id.
        persona_name: Selected persona display name, if available.
        prompt_mode: Active system prompt mode.
        system_prompt: Current system prompt text, if any.
        messages: Conversation messages without the system prompt.
        generation: Generation settings used for the chat.
        panel_label: Optional side label (e.g. "left"/"right") for compare-mode exports.

    Returns:
        The path the export was written to.
    """

    from persona_data.environment import get_artifacts_dir

    payload = {
        "model_name": model_name,
        "dataset_source": dataset_source,
        "persona": {
            "id": persona_id,
            "name": persona_name,
        },
        "panel_label": panel_label,
        "prompt_mode": prompt_mode,
        "generation": generation,
        "messages": (
            [{"role": "system", "content": system_prompt}] if system_prompt else []
        )
        + [_serialise_message(message) for message in messages],
    }

    export_dir = (
        get_artifacts_dir()
        / "chats"
        / "__".join(slugify(part) for part in model_name.split("/"))
        / slugify(persona_id)
    )
    export_dir.mkdir(parents=True, exist_ok=True)

    timestamp = datetime.now(UTC).strftime("%Y%m%dT%H%M%SZ")
    filename_parts = [
        timestamp,
        slugify(persona_name or persona_id),
        slugify(prompt_mode),
    ]
    if panel_label:
        filename_parts.append(slugify(panel_label))
    export_path = export_dir / f"{'__'.join(filename_parts)}.json"
    export_path.write_text(
        f"{json.dumps(payload, indent=2, ensure_ascii=False)}\n",
        encoding="utf-8",
    )

    return export_path