음성 재생과 운영 배포 정리
This commit is contained in:
parent
8ed185ce6c
commit
ac7db95542
1020 changed files with 46863 additions and 2175 deletions
1
apps/api/app/contracts/__init__.py
Normal file
1
apps/api/app/contracts/__init__.py
Normal file
|
|
@ -0,0 +1 @@
|
|||
"""Cross-runtime contracts for replaceable service boundaries."""
|
||||
82
apps/api/app/contracts/engine_gateway.py
Normal file
82
apps/api/app/contracts/engine_gateway.py
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
"""Engine gateway HTTP and SSE contract.
|
||||
|
||||
Keep this module adapter-neutral. The Python API client, the current Python
|
||||
gateway, and a future Node.js gateway must preserve these shapes.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
from typing import Any, Literal, Optional
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
AIRole = Literal["client", "counselor", "evaluator"]
|
||||
EngineMessageRole = Literal["system", "user", "assistant"]
|
||||
EngineGatewaySseEvent = Literal["token", "done", "error"]
|
||||
|
||||
ENGINE_GATEWAY_SSE_TOKEN: EngineGatewaySseEvent = "token"
|
||||
ENGINE_GATEWAY_SSE_DONE: EngineGatewaySseEvent = "done"
|
||||
ENGINE_GATEWAY_SSE_ERROR: EngineGatewaySseEvent = "error"
|
||||
ENGINE_GATEWAY_SSE_EVENTS: tuple[EngineGatewaySseEvent, ...] = (
|
||||
ENGINE_GATEWAY_SSE_TOKEN,
|
||||
ENGINE_GATEWAY_SSE_DONE,
|
||||
ENGINE_GATEWAY_SSE_ERROR,
|
||||
)
|
||||
|
||||
|
||||
class EngineMessage(BaseModel):
|
||||
role: EngineMessageRole
|
||||
content: str
|
||||
cache: bool = False
|
||||
|
||||
|
||||
class GenerateRequest(BaseModel):
|
||||
ai_role: AIRole = "client"
|
||||
messages: list[EngineMessage]
|
||||
model: Optional[str] = None
|
||||
max_tokens: int = 1024
|
||||
temperature: float = 0.7
|
||||
structured_schema: Optional[dict[str, Any]] = None
|
||||
session_id: Optional[str] = None
|
||||
metadata: dict[str, Any] = Field(default_factory=dict)
|
||||
|
||||
|
||||
class StreamRequest(GenerateRequest):
|
||||
"""SSE stream request for live client AI turns."""
|
||||
|
||||
|
||||
class GenerateResponse(BaseModel):
|
||||
text: str
|
||||
model: str
|
||||
provider: str
|
||||
tokens_in: int = 0
|
||||
tokens_out: int = 0
|
||||
cost_usd: float = 0.0
|
||||
inference_geo: Optional[str] = None
|
||||
structured: Optional[dict[str, Any]] = None
|
||||
|
||||
|
||||
class StreamTokenEvent(BaseModel):
|
||||
text: str
|
||||
|
||||
|
||||
class StreamDoneEvent(BaseModel):
|
||||
provider: str
|
||||
model: str
|
||||
tokens_in: int = 0
|
||||
tokens_out: int = 0
|
||||
cost_usd: float = 0.0
|
||||
turns: int = 0
|
||||
|
||||
|
||||
class StreamErrorEvent(BaseModel):
|
||||
detail: str
|
||||
|
||||
|
||||
def sse_frame(event: EngineGatewaySseEvent, payload: BaseModel | dict[str, Any]) -> str:
|
||||
if isinstance(payload, BaseModel):
|
||||
body = payload.model_dump()
|
||||
else:
|
||||
body = payload
|
||||
return f"event: {event}\ndata: {json.dumps(body, ensure_ascii=False)}\n\n"
|
||||
Loading…
Add table
Add a link
Reference in a new issue