File size: 3,524 Bytes
a1e4405
 
 
9e95393
 
 
775cbe6
 
 
 
 
 
 
 
a1e4405
 
9e95393
a1e4405
 
9e95393
a1e4405
9e95393
a1e4405
 
 
 
 
 
 
 
 
 
9e95393
 
 
a1e4405
9e95393
a1e4405
9e95393
 
 
775cbe6
 
 
 
a1e4405
 
9e95393
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
775cbe6
9e95393
 
 
775cbe6
9e95393
775cbe6
9e95393
 
 
775cbe6
9e95393
775cbe6
9e95393
 
 
775cbe6
9e95393
775cbe6
9e95393
 
 
 
 
 
a1e4405
9e95393
 
 
 
 
 
 
 
 
 
 
 
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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
from __future__ import annotations

from dataclasses import dataclass

import httpx

from .hf_client import (
    HFChatClient,
    HF_CHAT_API_ADVERSARIAL,
    HF_CHAT_API_CONSTRUCTIVE,
    HF_CHAT_API_EVIDENCE,
    HF_MODEL_4B,
    HF_MODEL_8B,
)
from .integration import DialogueIntegrator
from .internal_core import CustomerAIInternalCore
from .kb_search import LocalHybridKnowledgeStore
from .knowledge import GroundingPlanner
from .quality import CompletionGate
from .schemas import RoleName
from .search_planner import SearchPlanner
from .shared_head import ThreeRoleModelPool
from .skill_runtime import SkillRegistry
from .state import StateStore
from .task_decomposition import TaskDecomposer
from .writing_skills import default_writing_skills


@dataclass(frozen=True)
class InternalRuntimeDependencies:
    live_state_provider: object
    japanese_skill_pack: object
    canonical_store: object | None = None
    kb_snapshot_path: str | None = None
    kb_generation_id: str | None = None
    hf_token: str | None = None
    role_pool: object | None = None
    max_targeted_retry: int = 1
    constructive_model_id: str = HF_MODEL_4B
    adversarial_model_id: str = HF_MODEL_4B
    evidence_model_id: str = HF_MODEL_8B
    constructive_api_url: str = HF_CHAT_API_CONSTRUCTIVE
    adversarial_api_url: str = HF_CHAT_API_ADVERSARIAL
    evidence_api_url: str = HF_CHAT_API_EVIDENCE
    timeout_seconds: float = 600.0


def _canonical_store(deps: InternalRuntimeDependencies):
    if deps.canonical_store is not None:
        return deps.canonical_store
    if deps.kb_snapshot_path:
        return LocalHybridKnowledgeStore.from_jsonl(
            deps.kb_snapshot_path,
            generation_id=deps.kb_generation_id,
        )
    raise ValueError("canonical_store_or_kb_snapshot_required")


def _role_pool(deps: InternalRuntimeDependencies):
    if deps.role_pool is not None:
        return deps.role_pool
    if deps.constructive_model_id != HF_MODEL_4B:
        raise ValueError("constructive_model_drift")
    if deps.adversarial_model_id != HF_MODEL_4B:
        raise ValueError("adversarial_model_drift")
    if deps.evidence_model_id != HF_MODEL_8B:
        raise ValueError("evidence_model_drift")

    shared_http = httpx.AsyncClient(timeout=deps.timeout_seconds)
    clients = {
        RoleName.CONSTRUCTIVE: HFChatClient(
            token="",
            model_id=deps.constructive_model_id,
            api_url=deps.constructive_api_url,
            client=shared_http,
        ),
        RoleName.ADVERSARIAL: HFChatClient(
            token="",
            model_id=deps.adversarial_model_id,
            api_url=deps.adversarial_api_url,
            client=shared_http,
        ),
        RoleName.EVIDENCE_BOUND: HFChatClient(
            token="",
            model_id=deps.evidence_model_id,
            api_url=deps.evidence_api_url,
            client=shared_http,
        ),
    }
    return ThreeRoleModelPool(clients)


def build_internal_core(deps: InternalRuntimeDependencies) -> CustomerAIInternalCore:
    return CustomerAIInternalCore(
        decomposer=TaskDecomposer(),
        search=SearchPlanner(),
        grounding=GroundingPlanner(_canonical_store(deps), deps.live_state_provider),
        skills=SkillRegistry(default_writing_skills()),
        roles=_role_pool(deps),
        integrator=DialogueIntegrator(),
        gate=CompletionGate(),
        state=StateStore(),
        japanese=deps.japanese_skill_pack,
        max_targeted_retry=deps.max_targeted_retry,
    )