File size: 3,889 Bytes
53587e2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
770a262
 
53587e2
770a262
 
 
 
 
 
53587e2
 
 
 
 
 
 
770a262
53587e2
 
 
 
 
 
 
 
 
770a262
53587e2
 
 
 
 
 
 
770a262
53587e2
 
 
 
 
770a262
 
 
 
 
 
 
 
 
 
53587e2
 
 
 
 
 
 
 
 
 
 
770a262
 
 
 
 
 
 
 
 
53587e2
 
 
 
 
 
 
 
 
 
770a262
53587e2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
770a262
53587e2
 
 
 
 
 
 
 
 
 
 
 
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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
from __future__ import annotations

import json
import os
import sys
from pathlib import Path
from typing import Any

import httpx
from fastapi import FastAPI
from pydantic import BaseModel, Field

ROOT = Path(__file__).resolve().parent
sys.path.insert(0, str(ROOT))

from escalation.patcher import repair  # noqa: E402
from harness.adapters import load  # noqa: E402
from harness.engine import run_harness  # noqa: E402

CONFIG: dict[str, Any] = json.loads((ROOT / "config.json").read_text(encoding="utf-8"))
ADAPTER = load(str(CONFIG.get("adapter") or "generic"))
# .get everywhere: ctx_compress has no tools, and a missing variable must not crash startup
SLM_URL = os.environ.get("MT_SLM_URL", "")
ROUTER_URL = os.environ.get("MT_ROUTER_URL", "")
TOOLS_URL = os.environ.get("MT_TOOLS_URL", "")
RELAY_URL = os.environ.get("MT_RELAY_URL", "")
ESCALATION = CONFIG.get("escalation") or {}
MODELS: list[str] = list(ESCALATION.get("models") or []) or [str(ESCALATION.get("preferred_model") or "")]
TAIL_CHARS = int(ESCALATION.get("session_tail_chars") or 0)
MAX_NEW = int((CONFIG.get("slm") or {}).get("max_new_tokens") or 3072)

app = FastAPI(docs_url=None, redoc_url=None, openapi_url=None)


class HarnessIn(BaseModel):
    item_id: str
    task: dict[str, Any]
    seed: int | None = None


class RepairIn(BaseModel):
    item_id: str
    task: dict[str, Any]
    draft: Any = None
    trace: str = ""
    errors: str = ""
    ticket: str = ""
    seed: int | None = None


class SystemIn(BaseModel):
    item_id: str
    task: dict[str, Any]
    floor: float = Field(ge=0.0, le=1.0)
    ticket: str = ""
    seed: int | None = None


def decide(query: str, draft: str) -> float:
    if not ROUTER_URL:
        return 1.0
    try:
        with httpx.Client(timeout=30.0) as http:
            response = http.post(
                ROUTER_URL.rstrip("/") + "/decide", json={"input": {"query": query, "draft": draft}}
            )
        response.raise_for_status()
        answers = response.json().get("answers") or []
        return float(answers[0]["probability"]) if answers else 0.0
    except Exception:
        return 0.0


def _repair(payload: RepairIn | SystemIn, draft: Any, trace: str, errors: str) -> Any:
    return repair(
        payload.task,
        draft,
        trace,
        errors,
        adapter=ADAPTER,
        relay_url=RELAY_URL,
        ticket=payload.ticket,
        model=MODELS,
        tail_chars=TAIL_CHARS,
        max_tokens=MAX_NEW,
    )


def _harness(task: dict[str, Any], seed: int | None):
    return run_harness(
        task, adapter=ADAPTER, slm_url=SLM_URL, tools_url=TOOLS_URL, config=CONFIG, seed=seed
    )


@app.get("/health")
def health() -> dict[str, str]:
    return {"status": "ok", "adapter": ADAPTER.name}


@app.post("/harness/run")
def harness_run(payload: HarnessIn) -> dict[str, Any]:
    result = _harness(payload.task, payload.seed)
    return {
        "answer": result.answer,
        "self_check": {"pass": result.verified},
        "trace": result.trace,
        "steps": result.steps,
    }


@app.post("/escalation/repair")
def escalation_repair(payload: RepairIn) -> dict[str, Any]:
    return {"answer": _repair(payload, payload.draft, payload.trace, payload.errors)}


@app.post("/system/run")
def system_run(payload: SystemIn) -> dict[str, Any]:
    result = _harness(payload.task, payload.seed)
    draft = result.answer
    probability = decide(ADAPTER.query(payload.task), ADAPTER.as_text(draft))
    if result.verified and probability >= payload.floor:
        return {"answer": draft, "route": "local", "p": probability}
    answer = _repair(payload, draft, result.trace, result.errors)
    return {"answer": answer, "route": "escalated", "p": probability}


if __name__ == "__main__":
    import uvicorn

    uvicorn.run(app, host="0.0.0.0", port=int(os.environ.get("MT_PORT", "8080")), log_level="warning")