- Replaced direct FastGPT client usage with a backend-neutral chat interface, allowing for improved flexibility and maintainability. - Introduced a new `ChatBackend` protocol and implemented `FastGPTBackend` to handle chat operations. - Updated the chat endpoint to utilize the new backend structure, enhancing the handling of chat requests and responses. - Added comprehensive tests to ensure compatibility and functionality of the new backend integration.
73 lines
1.8 KiB
Python
73 lines
1.8 KiB
Python
"""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."""
|