Code / services/llm_provider_service/api_models.py
services/llm_provider_service/api_models.py
1
"""API request/response models for LLM Provider Service.
2
3
This module contains LPS-internal models only.
4
Shared HTTP contracts are in common_core.api_models.llm_provider
5
"""
6
7
from __future__ import annotations
8
9
from datetime import date
10
from typing import Any
11
12
from pydantic import BaseModel, Field
13
14
15
class LlamaCppRuntimeStatus(BaseModel):
16
"""Configured and observed llama.cpp server identity."""
17
18
reachable: bool
19
configured_model: str
20
loaded_model: str | None = None
21
model_path: str | None = None
22
model_matches_configured: bool | None = None
23
context_size: int | None = None
24
total_slots: int | None = None
25
thinking_enabled: bool | None = None
26
generation_defaults: dict[str, str | int | float | bool | None] = Field(default_factory=dict)
27
error_type: str | None = None
28
29
30
class LLMProviderStatus(BaseModel):
31
"""Model for LLM provider status."""
32
33
name: str
34
enabled: bool
35
available: bool
36
circuit_breaker_state: str # "closed", "open", "half_open"
37
default_model: str | None = None
38
last_success: str | None = None
39
last_failure: str | None = None
40
failure_count: int = 0
41
average_response_time_ms: float | None = None
42
runtime: LlamaCppRuntimeStatus | None = None
43
44
45
class LLMProviderListResponse(BaseModel):
46
"""Response model for listing LLM providers."""
47
48
providers: list[LLMProviderStatus]
49
default_provider: str
50
selection_strategy: str
51
total_requests_today: int = 0
52
total_cost_today: float = 0.0
53
54
55
class HealthCheckResponse(BaseModel):
56
"""Health check response model."""
57
58
status: str = Field(description="Service status")
59
service: str = Field(description="Service name")
60
version: str = Field(description="Service version")
61
dependencies: dict[str, dict[str, Any]] = Field(
62
default_factory=dict, description="Status of service dependencies"
63
)
64
65
66
class UsageSummaryResponse(BaseModel):
67
"""Usage summary response model."""
68
69
period: str = Field(description="Time period for summary")
70
total_requests: int = Field(description="Total requests in period")
71
successful_requests: int = Field(description="Successful requests")
72
failed_requests: int = Field(description="Failed requests")
73
total_tokens: dict[str, int] = Field(description="Total tokens by type")
74
total_cost: float = Field(description="Total cost in USD")
75
provider_breakdown: dict[str, dict[str, Any]] = Field(description="Usage breakdown by provider")
76
77
78
class ModelInfoResponse(BaseModel):
79
"""Model information for API exposure.
80
81
Subset of ModelConfig fields relevant for external clients.
82
Internal manifest fields (parameter compatibility flags, etc.) are excluded.
83
"""
84
85
model_id: str = Field(description="Provider-specific model identifier")
86
provider: str = Field(description="Provider hosting this model")
87
display_name: str = Field(description="Human-readable model name")
88
model_family: str = Field(description="Model family identifier")
89
max_tokens: int = Field(description="Maximum output tokens supported")
90
context_window: int = Field(description="Total context window size")
91
supports_streaming: bool = Field(description="Supports streaming responses")
92
capabilities: dict[str, bool] = Field(description="Model capabilities")
93
cost_per_1k_input_tokens: float | None = Field(
94
default=None, description="Cost per 1000 input tokens in USD"
95
)
96
cost_per_1k_output_tokens: float | None = Field(
97
default=None, description="Cost per 1000 output tokens in USD"
98
)
99
is_deprecated: bool = Field(description="Model is deprecated")
100
release_date: date | None = Field(default=None, description="Model release date")
101
recommended_for: list[str] = Field(description="Use cases this model excels at")
102
103
104
class ModelManifestResponse(BaseModel):
105
"""Response model for model manifest endpoint.
106
107
Returns all available models grouped by provider.
108
"""
109
110
providers: dict[str, list[ModelInfoResponse]] = Field(
111
description="Models grouped by provider name"
112
)
113
total_models: int = Field(description="Total number of models across all providers")