Files
ZNJJ-api-server/src/backends/chat.py
T

73 lines
1.8 KiB
Python
Raw Normal View History

"""Backend-neutral chat contract."""
from collections.abc import AsyncIterator
from dataclasses import dataclass, field
from typing import Any, Protocol
@dataclass(frozen=True)
class ChatInput:
"""Input shared by all chat backend implementations."""
session_id: str
text: str
need_form_update: bool = False
@dataclass(frozen=True)
class TextDelta:
"""A piece of raw model text.
The text may contain a partial ``<state>...</state>`` prefix. Parsing that
public protocol remains the responsibility of the FastAPI layer.
"""
text: str
@dataclass(frozen=True)
class FormUpdate:
"""A structured form update produced alongside model text."""
data: Any
ChatStreamEvent = TextDelta | FormUpdate
@dataclass(frozen=True)
class ChatResult:
"""Backend-neutral result for a non-streaming chat request."""
content: str
status_code: str | None = None
form_update: Any = field(default_factory=dict)
class ChatBackend(Protocol):
"""Contract implemented by FastGPT today and LangGraph later."""
def stream(self, chat_input: ChatInput) -> AsyncIterator[ChatStreamEvent]:
"""Stream raw text and structured side-channel events."""
...
async def complete(self, chat_input: ChatInput) -> ChatResult:
"""Return one complete backend-neutral chat result."""
...
class ChatBackendError(Exception):
"""Base error raised by a chat backend adapter."""
class ChatBackendAuthenticationError(ChatBackendError):
"""The backend rejected its configured credentials."""
class ChatBackendRateLimitError(ChatBackendError):
"""The backend rejected the request because of rate limiting."""
class ChatBackendAPIError(ChatBackendError):
"""The backend API failed or returned an invalid response."""