FastAPI + Celery + Next.js + Postgres/Redis app with company monitoring, source collection, LLM-based change analysis, enrichment, and account security (Turnstile, escalating lockout, email verification).
34 lines
1.1 KiB
Python
34 lines
1.1 KiB
Python
"""LLM provider interface. Every analysis task (app/prompts/*.py) is written
|
|
against this Protocol, never against a specific vendor SDK - swapping
|
|
`LLM_PROVIDER` changes which class `get_llm_provider()` returns and nothing
|
|
else has to change. `generate_structured` is the primary method: it always
|
|
returns a validated instance of the caller's Pydantic response model, never
|
|
raw text, so a malformed model response can never propagate un-typed data
|
|
into the rest of the app (see `LLMResponseError` / the repair loop in
|
|
anthropic_provider.py).
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import Protocol
|
|
|
|
from pydantic import BaseModel
|
|
|
|
|
|
class LLMResponseError(Exception):
|
|
"""Raised when a provider can't produce a response matching the
|
|
requested schema, even after any repair attempts."""
|
|
|
|
|
|
class LLMProvider(Protocol):
|
|
provider_name: str
|
|
|
|
async def generate_structured[T: BaseModel](
|
|
self,
|
|
system_prompt: str,
|
|
user_prompt: str,
|
|
response_model: type[T],
|
|
) -> T: ...
|
|
|
|
async def generate_text(self, system_prompt: str, user_prompt: str) -> str: ...
|