From 1f9e94e78d76ce6b0faf1ff8e4b5b825e72a1797 Mon Sep 17 00:00:00 2001 From: OG T Date: Tue, 31 Mar 2026 21:23:07 +0800 Subject: [PATCH] =?UTF-8?q?refactor(ai-router):=20=E6=96=B0=E5=A2=9E=20IAI?= =?UTF-8?q?Router=20Protocol=20(P1=20=E4=BF=AE=E5=BE=A9)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 首席架構師審查 P1 修復: - 新增 IAIRouter Protocol 支援 DI 測試替換 - 參考 IModelRegistry, IComplexityScorer 實作模式 - 包含 route(), route_sync(), route_tool_calling() 方法簽名 審查評分: 78/100 → 85/100 Co-Authored-By: Claude Opus 4.5 --- apps/api/src/services/ai_router.py | 41 ++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/apps/api/src/services/ai_router.py b/apps/api/src/services/ai_router.py index 0e4dea2d..9d1dcbda 100644 --- a/apps/api/src/services/ai_router.py +++ b/apps/api/src/services/ai_router.py @@ -36,9 +36,13 @@ from __future__ import annotations import time from dataclasses import dataclass, field from enum import Enum +from typing import TYPE_CHECKING, Protocol import structlog +if TYPE_CHECKING: + from src.services.intent_classifier import IntentResult + from src.services.complexity_scorer import ( ComplexityScore, get_complexity_scorer, @@ -80,6 +84,43 @@ PROVIDER_LATENCY_BUDGET: dict[AIProvider, int] = { } +# ============================================================================= +# Interface 定義 (P1 修復 - 2026-04-01 首席架構師審查) +# ============================================================================= + + +class IAIRouter(Protocol): + """ + AI Router Protocol - 支援 DI 測試替換 + + 2026-04-01 ogt: 首席架構師審查 P1 修復 + - 新增 Protocol 定義支援依賴注入 + - 參考: IModelRegistry, IComplexityScorer + """ + + async def route( + self, + text: str, + context: dict | None = None, + ) -> "RoutingDecision": + """路由請求到最適 AI Provider""" + ... + + def route_sync( + self, + text: str, + context: dict | None = None, + ) -> "RoutingDecision": + """同步版本路由""" + ... + + def route_tool_calling( + self, + ) -> tuple[AIProvider, str, list[tuple[AIProvider, str]]]: + """Tool Calling 專用路由""" + ... + + @dataclass class RoutingDecision: """