routeur_ia_api / domain /models.py
Cyril Dupland
Add sources parameter to completion requests and update documentation: Enhance the CompletionRequest model to include an optional sources field for document filtering. Update related API examples and documentation to reflect this change, ensuring clarity on usage and implications for project document retrieval.
686df05
raw
history blame
7.61 kB
"""Pydantic models for request/response schemas."""
from pydantic import BaseModel, Field
from typing import Optional, List, Dict, Any, Literal
from datetime import datetime, timezone
from .enums import ModelName
# ============ Auth Models ============
class TokenRequest(BaseModel):
"""Request for JWT token (can be extended with username/password)."""
# Pour l'instant, on pourrait juste retourner un token
# Plus tard, on peut ajouter username/password
pass
class TokenResponse(BaseModel):
"""JWT token response."""
access_token: str
token_type: str = "bearer"
expires_in: int
# ============ Completion Models ============
class CompletionRequest(BaseModel):
"""Request for text completion."""
message: str = Field(..., description="User message to complete")
model: ModelName = Field(default=ModelName.MISTRAL_LARGE, description="LLM model to use")
agent: Optional[str] = Field(
default=None,
description="Agent identifier to use (ex: 'V1', 'V2', or 'AGENT'). If omitted, defaults to 'AGENT'."
)
stream: bool = Field(default=False, description="Enable streaming response")
temperature: float = Field(default=0.7, ge=0.0, le=2.0, description="Sampling temperature")
max_tokens: Optional[int] = Field(default=None, description="Maximum tokens to generate")
conversation_history: Optional[List[Dict[str, str]]] = Field(
default=None,
description="Optional conversation history"
)
# Project-scoped retrieval
project_id: Optional[str] = Field(default=None, description="Optional project id to scope retrieval")
sources: Optional[List[str]] = Field(
default=None,
description="Optional list of document UUIDs to restrict project retrieval. Empty list or null means no restriction.",
)
# Server-side memory (LangGraph thread_id). When set, conversation history is managed by the server; conversation_history is ignored.
conversation_id: Optional[str] = Field(
default=None,
description="Conversation id for server-side memory (thread_id). When set, conversation_history is ignored."
)
class CompletionResponse(BaseModel):
"""Response for text completion (non-streaming)."""
response: str
model: str
agent: Optional[str] = None
usage: Optional[Dict[str, Any]] = None
metadata: Optional[Dict[str, Any]] = None
conversation_id: Optional[str] = Field(
default=None,
description="Conversation id used for this request. Reuse it in subsequent requests to maintain server-side memory."
)
class StreamChunk(BaseModel):
"""Single chunk in streaming response."""
content: str
done: bool = False
conversation_id: Optional[str] = Field(
default=None,
description="Conversation id present in every chunk. Reuse it in subsequent requests to maintain server-side memory."
)
metadata: Optional[Dict[str, Any]] = None
# ============ Transcription Models ============
class TranscriptionResponse(BaseModel):
"""Response for audio transcription.
Usage, emissions, latency, etc. are under metadata.usage and metadata.emissions_*.
"""
text: str
language: Optional[str] = None
duration_s: Optional[float] = None
model: str = "whisper-1"
metadata: Optional[Dict[str, Any]] = None
class TranscriptMessage(BaseModel):
"""Single message in a voice conversation transcript."""
role: Literal["user", "assistant"]
text: str
timestamp: datetime
class TranscriptListResponse(BaseModel):
"""Transcript for a given conversation."""
conversation_id: str
messages: List[TranscriptMessage]
# ============ Model Info Models ============
class ModelInfo(BaseModel):
"""Information about an available model."""
name: str
provider: str
description: Optional[str] = None
supports_streaming: bool = True
context_window: Optional[int] = None
class ModelsListResponse(BaseModel):
"""List of available models."""
models: List[ModelInfo]
total: int
class AgentInfo(BaseModel):
"""Information about an available agent."""
type: str
name: str
description: str
available: bool = True
class AgentsListResponse(BaseModel):
"""List of available agents."""
agents: List[AgentInfo]
total: int
# ============ Error Models ============
class ErrorResponse(BaseModel):
"""Error response."""
error: str
detail: Optional[str] = None
timestamp: datetime = Field(default_factory=lambda: datetime.now(timezone.utc))
# ============ Health Check ============
class HealthResponse(BaseModel):
"""Health check response."""
status: str
version: str
timestamp: datetime = Field(default_factory=lambda: datetime.now(timezone.utc))
# ============ Voice / VAD Models ============
class VadConfigDTO(BaseModel):
"""Voice Activity Detection configuration from client or settings.
Domain DTO with validation. Mapping to Pipecat VADParams is done in
services/voice/vad_config_service to keep domain independent of Pipecat.
"""
vad_stop_secs: float = Field(
default=0.2,
ge=0.2,
le=2.0,
description="Seconds of silence before confirming speech has stopped",
)
vad_start_secs: float = Field(
default=0.2,
ge=0.1,
le=0.5,
description="Seconds of speech before confirming voice start",
)
vad_confidence: float = Field(
default=0.7,
ge=0.5,
le=0.95,
description="Minimum confidence threshold for voice detection (0-1)",
)
vad_min_volume: float = Field(
default=0.6,
ge=0.3,
le=0.9,
description="Minimum audio volume threshold for speech detection (0-1)",
)
# ============ Upload / Ingestion Jobs ============
class UploadJobResponse(BaseModel):
"""Response returned when a background upload/ingestion job is created."""
job_id: str
status: str = "queued"
created_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc))
# Optional: server-measured audio duration for transcription jobs (seconds)
duration_s: Optional[float] = None
class JobStatusResponse(BaseModel):
"""Snapshot of ingestion job status for polling."""
job_id: str
status: str
# Logical job type: document_ingestion | transcription_audio | transcription_meeting | ...
job_type: Optional[str] = None
# Progress and stage
progress: Optional[float] = None
progress_percent: Optional[int] = None
stage: Optional[str] = None # upload | ocr | chunk | embed | index
# Counters
pages_total: Optional[int] = None
pages_done: Optional[int] = None
chunks_total: Optional[int] = None
chunks_done: Optional[int] = None
inserted_count: Optional[int] = None
# Transcription-specific fields (for audio transcription jobs)
transcript_text: Optional[str] = None
transcript_language: Optional[str] = None
transcript_duration: Optional[float] = None
transcript_model: Optional[str] = None
transcript_metadata: Optional[Dict[str, Any]] = None # usage, emissions_kgCO2eq, latency_s, etc.
# Error and timestamps
error: Optional[str] = None
created_at: Optional[datetime] = None
started_at: Optional[datetime] = None
updated_at: Optional[datetime] = None
finished_at: Optional[datetime] = None
class DeleteDocumentResponse(BaseModel):
"""Response returned when deleting a document's vector chunks."""
project_id: str
document_id: str
deleted_count: int