Files
Mutual_Fund/api/chat/customer_agent.py
T

83 lines
2.9 KiB
Python

"""Anonymous customer-service Agent HTTP endpoints."""
from __future__ import annotations
import json
from fastapi import APIRouter, Request
from fastapi.responses import JSONResponse, StreamingResponse
from service.customer_agent.chat import QueryTooLongError
from agent.customer_agent.session import SessionOwnershipError
from utils.request_id import get_request_id, new_request_id
from utils.response import fail, success
router = APIRouter()
def _runtime(request: Request):
runtime = getattr(request.app.state, "customer_agent_runtime", None)
if runtime is None:
raise RuntimeError("customer agent runtime is not configured")
return runtime
@router.post("/session/create")
async def create_session(request: Request):
runtime = _runtime(request)
session_id = await runtime.session_service.create_session()
return success({"session_id": session_id, "customer_id": None})
@router.get("/chat")
async def chat(request: Request, session_id: str, query: str):
runtime = _runtime(request)
trace_id = request.headers.get("X-Trace-Id") or get_request_id() or new_request_id()
try:
await runtime.session_service.verify_session_ownership(session_id)
retry_after = await runtime.session_service.consume_chat_quota(session_id)
if retry_after is not None:
response = fail(429, "请求过于频繁", {"retry_after": retry_after})
return JSONResponse(
status_code=429,
headers={"Retry-After": str(retry_after)},
content=response.model_dump(),
)
result = await runtime.agent.handle(session_id, query, trace_id=trace_id)
except SessionOwnershipError as exc:
return JSONResponse(
status_code=exc.code,
content=fail(exc.code, exc.message).model_dump(),
)
except QueryTooLongError as exc:
return JSONResponse(
status_code=400,
content=fail(400, str(exc)).model_dump(),
)
async def events():
yield f"data: {json.dumps(result, ensure_ascii=False)}\n\n"
return StreamingResponse(
events(), media_type="text/event-stream", headers={"X-Trace-Id": trace_id}
)
@router.post("/session/end")
async def end_session(request: Request, body: dict):
runtime = _runtime(request)
session_id = body.get("session_id", "")
try:
await runtime.session_service.verify_session_ownership(session_id)
except SessionOwnershipError as exc:
return JSONResponse(
status_code=exc.code,
content=fail(exc.code, exc.message).model_dump(),
)
if hasattr(runtime.redis, "delete"):
await runtime.redis.delete(
f"session:{session_id}", f"session:{session_id}:messages",
f"rate:limit:anon:{session_id}:chat",
)
return success({"session_id": session_id, "archived": False})