Files
data-ge/app/providers/base.py
2025-10-29 00:38:57 +08:00

45 lines
1.5 KiB
Python

from __future__ import annotations
from abc import ABC, abstractmethod
from typing import Any
import httpx
from app.exceptions import ProviderConfigurationError
from app.models import LLMRequest, LLMResponse
class LLMProviderClient(ABC):
"""Base class for provider-specific chat completion clients."""
name: str
api_key_env: str | None = None
supports_stream: bool = False
def __init__(self, api_key: str | None):
if self.api_key_env and not api_key:
raise ProviderConfigurationError(
f"Provider '{self.name}' requires environment variable '{self.api_key_env}'."
)
self.api_key = api_key or ""
@abstractmethod
async def chat(
self, request: LLMRequest, client: httpx.AsyncClient
) -> LLMResponse:
"""Execute a chat completion call."""
@staticmethod
def merge_payload(base: dict[str, Any], extra: dict[str, Any] | None) -> dict[str, Any]:
"""Merge provider payload with optional extra params, ignoring None values."""
merged = {k: v for k, v in base.items() if v is not None}
if extra:
merged.update({k: v for k, v in extra.items() if v is not None})
return merged
def ensure_stream_supported(self, stream_requested: bool) -> None:
if stream_requested and not self.supports_stream:
raise ProviderConfigurationError(
f"Provider '{self.name}' does not support streaming mode."
)