ai-robot-core/ai-service/app/models/__init__.py

89 lines
3.2 KiB
Python

"""
Data models for AI Service.
[AC-AISVC-02] Request/Response models aligned with OpenAPI contract.
[AC-AISVC-13] Entity models for database persistence.
"""
from enum import Enum
from typing import Any
from pydantic import BaseModel, Field
class ChannelType(str, Enum):
WECHAT = "wechat"
DOUYIN = "douyin"
JD = "jd"
class Role(str, Enum):
USER = "user"
ASSISTANT = "assistant"
class ChatMessage(BaseModel):
role: Role = Field(..., description="Message role: user or assistant")
content: str = Field(..., description="Message content")
class ChatRequest(BaseModel):
session_id: str = Field(..., alias="sessionId", description="Session ID for conversation tracking")
current_message: str = Field(..., alias="currentMessage", description="Current user message")
channel_type: ChannelType = Field(..., alias="channelType", description="Channel type: wechat, douyin, jd")
history: list[ChatMessage] | None = Field(default=None, description="Optional conversation history")
metadata: dict[str, Any] | None = Field(default=None, description="Optional metadata")
model_config = {"populate_by_name": True}
class ChatResponse(BaseModel):
reply: str = Field(..., description="AI generated reply content")
confidence: float = Field(..., ge=0.0, le=1.0, description="Confidence score between 0.0 and 1.0")
should_transfer: bool = Field(..., alias="shouldTransfer", description="Whether to suggest transfer to human agent")
transfer_reason: str | None = Field(default=None, alias="transferReason", description="Reason for transfer suggestion")
metadata: dict[str, Any] | None = Field(default=None, description="Response metadata")
model_config = {"populate_by_name": True}
class ErrorCode(str, Enum):
INVALID_REQUEST = "INVALID_REQUEST"
MISSING_TENANT_ID = "MISSING_TENANT_ID"
INTERNAL_ERROR = "INTERNAL_ERROR"
SERVICE_UNAVAILABLE = "SERVICE_UNAVAILABLE"
TIMEOUT = "TIMEOUT"
LLM_ERROR = "LLM_ERROR"
RETRIEVAL_ERROR = "RETRIEVAL_ERROR"
class ErrorResponse(BaseModel):
code: str = Field(..., description="Error code")
message: str = Field(..., description="Error message")
details: list[dict[str, Any]] | None = Field(default=None, description="Detailed error information")
class SSEEventType(str, Enum):
MESSAGE = "message"
FINAL = "final"
ERROR = "error"
class SSEMessageEvent(BaseModel):
delta: str = Field(..., description="Incremental text content")
class SSEFinalEvent(BaseModel):
reply: str = Field(..., description="Complete AI reply")
confidence: float = Field(..., ge=0.0, le=1.0, description="Confidence score")
should_transfer: bool = Field(..., alias="shouldTransfer", description="Transfer suggestion")
transfer_reason: str | None = Field(default=None, alias="transferReason", description="Transfer reason")
metadata: dict[str, Any] | None = Field(default=None, description="Response metadata")
model_config = {"populate_by_name": True}
class SSEErrorEvent(BaseModel):
code: str = Field(..., description="Error code")
message: str = Field(..., description="Error message")
details: list[dict[str, Any]] | None = Field(default=None, description="Error details")