""" NVIDIA Nemotron API Models - ADR-036 ==================================== 2026-03-29 ogt: Nemotron Tool Calling 整合 (83.3% 精準度) OpenAI 相容格式 - 用於 Tool Calling 任務 """ from typing import Any from pydantic import BaseModel, Field class ToolFunction(BaseModel): """Tool Function 定義""" name: str = Field(..., description="Tool 函數名稱") arguments: str = Field(..., description="Tool 參數 (JSON 字串)") class ToolCall(BaseModel): """Tool Call 結構""" id: str = Field(..., description="Tool Call ID") type: str = Field(default="function", description="Tool 類型") function: ToolFunction = Field(..., description="Tool 函數") class NvidiaMessage(BaseModel): """NVIDIA API Message 結構""" role: str = Field(..., description="訊息角色 (assistant/user/system)") content: str | None = Field(default=None, description="訊息內容") tool_calls: list[ToolCall] | None = Field( default=None, description="Tool Calls (僅 assistant)" ) class NvidiaChoice(BaseModel): """NVIDIA API Choice 結構""" index: int = Field(default=0, description="選項索引") message: NvidiaMessage = Field(..., description="回應訊息") finish_reason: str | None = Field( default=None, description="結束原因 (stop/tool_calls)" ) class NvidiaUsage(BaseModel): """NVIDIA API Token 使用統計""" prompt_tokens: int = Field(default=0, description="輸入 Token 數") completion_tokens: int = Field(default=0, description="輸出 Token 數") total_tokens: int = Field(default=0, description="總 Token 數") class NvidiaResponse(BaseModel): """NVIDIA Nemotron API 完整回應""" id: str = Field(..., description="回應 ID") object: str = Field(default="chat.completion", description="物件類型") created: int = Field(..., description="建立時間戳") model: str = Field(..., description="模型名稱") choices: list[NvidiaChoice] = Field(..., description="回應選項") usage: NvidiaUsage | None = Field(default=None, description="Token 使用統計") # === Tool Calling 請求結構 === class ToolDefinition(BaseModel): """Tool 定義 (發送給 API)""" type: str = Field(default="function", description="Tool 類型") function: dict[str, Any] = Field(..., description="函數定義 (JSON Schema)") class NvidiaToolCallRequest(BaseModel): """NVIDIA Tool Calling 請求""" model: str = Field( default="nvidia/nemotron-mini-4b-instruct", description="模型名稱 (2026-03-29 ogt: 修正為可用的 mini 模型)", ) messages: list[dict[str, Any]] = Field(..., description="對話訊息") tools: list[ToolDefinition] = Field(..., description="可用 Tools") tool_choice: str | dict[str, Any] = Field( default="auto", description="Tool 選擇策略" ) temperature: float = Field(default=0.0, description="溫度 (0.0 最確定性)") max_tokens: int = Field(default=1024, description="最大輸出 Token") # === 驗證結果結構 === class ToolCallValidationResult(BaseModel): """Tool Call 驗證結果""" valid: bool = Field(..., description="是否有效") tool_name: str | None = Field(default=None, description="Tool 名稱") arguments: dict[str, Any] | None = Field(default=None, description="解析後參數") error: str | None = Field(default=None, description="錯誤訊息") raw_response: str | None = Field(default=None, description="原始回應 (debug)") class NvidiaProviderResult(BaseModel): """NvidiaProvider 回傳結果""" success: bool = Field(..., description="是否成功") tool_calls: list[ToolCallValidationResult] = Field( default_factory=list, description="驗證後的 Tool Calls" ) usage: NvidiaUsage | None = Field(default=None, description="Token 使用統計") latency_ms: float = Field(default=0.0, description="延遲 (毫秒)") error: str | None = Field(default=None, description="錯誤訊息") fallback_triggered: bool = Field( default=False, description="是否觸發 Fallback" )