런타임 계약과 학습자 흐름 보강
This commit is contained in:
parent
f456b8997a
commit
206018b088
56 changed files with 4306 additions and 1008 deletions
|
|
@ -24,6 +24,16 @@ ENGINE_GATEWAY_SSE_EVENTS: tuple[EngineGatewaySseEvent, ...] = (
|
|||
ENGINE_GATEWAY_SSE_DONE,
|
||||
ENGINE_GATEWAY_SSE_ERROR,
|
||||
)
|
||||
ENGINE_GATEWAY_DEFAULT_MODEL_SENTINEL = "gateway-default"
|
||||
|
||||
|
||||
def normalize_engine_gateway_model(model: Optional[str]) -> Optional[str]:
|
||||
"""Return an explicit model override, or None for gateway default routing."""
|
||||
|
||||
value = (model or "").strip()
|
||||
if not value or value == ENGINE_GATEWAY_DEFAULT_MODEL_SENTINEL:
|
||||
return None
|
||||
return value
|
||||
|
||||
|
||||
class EngineMessage(BaseModel):
|
||||
|
|
@ -58,6 +68,27 @@ class GenerateResponse(BaseModel):
|
|||
structured: Optional[dict[str, Any]] = None
|
||||
|
||||
|
||||
def structured_payload_from_response(resp: GenerateResponse) -> dict[str, Any] | None:
|
||||
"""Return structured output, or a JSON object embedded in legacy text."""
|
||||
|
||||
if isinstance(resp.structured, dict):
|
||||
return resp.structured
|
||||
|
||||
raw = (resp.text or "").strip()
|
||||
if not raw:
|
||||
return None
|
||||
raw = _strip_json_fence(raw)
|
||||
|
||||
parsed = _json_object_or_none(raw)
|
||||
if parsed is not None:
|
||||
return parsed
|
||||
|
||||
start, end = raw.find("{"), raw.rfind("}")
|
||||
if 0 <= start < end:
|
||||
return _json_object_or_none(raw[start : end + 1])
|
||||
return None
|
||||
|
||||
|
||||
class StreamTokenEvent(BaseModel):
|
||||
text: str
|
||||
|
||||
|
|
@ -188,6 +219,23 @@ def _to_stream_error_event(payload: Any) -> StreamErrorEvent:
|
|||
return StreamErrorEvent(detail="engine stream error")
|
||||
|
||||
|
||||
def _strip_json_fence(value: str) -> str:
|
||||
if not value.startswith("```"):
|
||||
return value
|
||||
text = value.split("```", 2)[1] if value.count("```") >= 2 else value.strip("`")
|
||||
if text.lstrip().lower().startswith("json"):
|
||||
text = text.lstrip()[4:]
|
||||
return text.strip()
|
||||
|
||||
|
||||
def _json_object_or_none(value: str) -> dict[str, Any] | None:
|
||||
try:
|
||||
parsed = json.loads(value)
|
||||
except (json.JSONDecodeError, ValueError):
|
||||
return None
|
||||
return parsed if isinstance(parsed, dict) else None
|
||||
|
||||
|
||||
def _safe_int(value: Any) -> int:
|
||||
try:
|
||||
return int(value or 0)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue