feat(v1): T-R1 采纳 ai-model-router 可解释路由评分——五维加权+硬过滤带拒绝理由+置信度分差推导
- 新增 router_system/explain.py:CandidateProfile(capability/cost/latency/ reliability/difficulty 画像)+ explain_routing(硬过滤先行、逐条人话拒绝理由、 五维归一评分、同分按领域字典序、confidence=0.8+分差推导封顶 0.99) - Router._explain 纯解释层装配(解释层任何异常不影响主链路,D-G4 同款纪律); 路由胜负与既有决策完全等价,/chat 响应新增 route_explanation 字段(缓存命中为 None) - experts:Expert.nominal_latency_ms 标称延迟元数据(mock 1/hf 300/api 800) - stats:upgraded_by_domain 计数 + domain_reliability()(无数据给 0.9 中性先验) - .gitignore 登记 extra/(参考项目目录不入库) - 新增 tests/test_explain.py 8 项;全量 33 passed(基线 25)
This commit is contained in:
+95
-94
@@ -1,94 +1,95 @@
|
||||
"""FastAPI 网关:对外提供 /chat /health /metrics 接口。
|
||||
|
||||
启动:
|
||||
uvicorn gateway.api:app --host 0.0.0.0 --port 8000
|
||||
或:
|
||||
python -m gateway.api
|
||||
|
||||
依赖:fastapi, uvicorn, pydantic(见 requirements.txt)
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import List, Optional
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from router_system.config import load_config
|
||||
from router_system.router import Router, build_router
|
||||
|
||||
# ---- 全局单例 ----
|
||||
_router: Optional[Router] = None
|
||||
|
||||
|
||||
def get_router() -> Router:
|
||||
global _router
|
||||
if _router is None:
|
||||
_router = build_router()
|
||||
return _router
|
||||
|
||||
|
||||
# ---- 请求/响应模型 ----
|
||||
class QueryRequest(BaseModel):
|
||||
query: str = Field(..., min_length=1, max_length=8000, description="用户查询")
|
||||
|
||||
|
||||
class QueryResponse(BaseModel):
|
||||
response: str
|
||||
domain: str
|
||||
difficulty: str
|
||||
confidence: float
|
||||
upgraded: bool
|
||||
quality_score: float
|
||||
model_used: str
|
||||
route: List[str]
|
||||
latency_ms: float
|
||||
cache_hit: bool
|
||||
cache_level: Optional[str]
|
||||
cost_est: float
|
||||
error: Optional[str] = None
|
||||
|
||||
|
||||
class HealthResponse(BaseModel):
|
||||
status: str
|
||||
domains: List[str]
|
||||
classifier: str
|
||||
judge: str
|
||||
fallback: str
|
||||
|
||||
|
||||
# ---- FastAPI 应用 ----
|
||||
try:
|
||||
from fastapi import FastAPI
|
||||
|
||||
app = FastAPI(
|
||||
title="Multi-Expert Router API",
|
||||
description="多专业小模型 + 路由模型系统(MVP)",
|
||||
version="0.1.0",
|
||||
)
|
||||
|
||||
@app.get("/health", response_model=HealthResponse, tags=["system"])
|
||||
async def health():
|
||||
return get_router().health()
|
||||
|
||||
@app.post("/chat", response_model=QueryResponse, tags=["chat"])
|
||||
async def chat(req: QueryRequest):
|
||||
result = await get_router().route(req.query)
|
||||
return QueryResponse(**result.to_dict())
|
||||
|
||||
@app.get("/metrics", tags=["system"])
|
||||
async def metrics():
|
||||
r = get_router()
|
||||
return {
|
||||
"router": r.stats.summary(),
|
||||
"cache": r.cache.stats(),
|
||||
}
|
||||
|
||||
except ImportError:
|
||||
# fastapi 未安装时,提供 CLI 入口提示
|
||||
app = None
|
||||
print("[gateway] 未安装 fastapi,请执行: pip install -r requirements.txt")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import uvicorn
|
||||
uvicorn.run("gateway.api:app", host="0.0.0.0", port=8000, reload=False)␍
|
||||
"""FastAPI 网关:对外提供 /chat /health /metrics 接口。
|
||||
|
||||
启动:
|
||||
uvicorn gateway.api:app --host 0.0.0.0 --port 8000
|
||||
或:
|
||||
python -m gateway.api
|
||||
|
||||
依赖:fastapi, uvicorn, pydantic(见 requirements.txt)
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, Dict, List, Optional
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from router_system.config import load_config
|
||||
from router_system.router import Router, build_router
|
||||
|
||||
# ---- 全局单例 ----
|
||||
_router: Optional[Router] = None
|
||||
|
||||
|
||||
def get_router() -> Router:
|
||||
global _router
|
||||
if _router is None:
|
||||
_router = build_router()
|
||||
return _router
|
||||
|
||||
|
||||
# ---- 请求/响应模型 ----
|
||||
class QueryRequest(BaseModel):
|
||||
query: str = Field(..., min_length=1, max_length=8000, description="用户查询")
|
||||
|
||||
|
||||
class QueryResponse(BaseModel):
|
||||
response: str
|
||||
domain: str
|
||||
difficulty: str
|
||||
confidence: float
|
||||
upgraded: bool
|
||||
quality_score: float
|
||||
model_used: str
|
||||
route: List[str]
|
||||
latency_ms: float
|
||||
cache_hit: bool
|
||||
cache_level: Optional[str]
|
||||
cost_est: float
|
||||
error: Optional[str] = None
|
||||
route_explanation: Optional[Dict[str, Any]] = None # T-R1 可解释评分(缓存命中为 None)
|
||||
|
||||
|
||||
class HealthResponse(BaseModel):
|
||||
status: str
|
||||
domains: List[str]
|
||||
classifier: str
|
||||
judge: str
|
||||
fallback: str
|
||||
|
||||
|
||||
# ---- FastAPI 应用 ----
|
||||
try:
|
||||
from fastapi import FastAPI
|
||||
|
||||
app = FastAPI(
|
||||
title="Multi-Expert Router API",
|
||||
description="多专业小模型 + 路由模型系统(MVP)",
|
||||
version="0.1.0",
|
||||
)
|
||||
|
||||
@app.get("/health", response_model=HealthResponse, tags=["system"])
|
||||
async def health():
|
||||
return get_router().health()
|
||||
|
||||
@app.post("/chat", response_model=QueryResponse, tags=["chat"])
|
||||
async def chat(req: QueryRequest):
|
||||
result = await get_router().route(req.query)
|
||||
return QueryResponse(**result.to_dict())
|
||||
|
||||
@app.get("/metrics", tags=["system"])
|
||||
async def metrics():
|
||||
r = get_router()
|
||||
return {
|
||||
"router": r.stats.summary(),
|
||||
"cache": r.cache.stats(),
|
||||
}
|
||||
|
||||
except ImportError:
|
||||
# fastapi 未安装时,提供 CLI 入口提示
|
||||
app = None
|
||||
print("[gateway] 未安装 fastapi,请执行: pip install -r requirements.txt")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import uvicorn
|
||||
uvicorn.run("gateway.api:app", host="0.0.0.0", port=8000, reload=False)
|
||||
|
||||
Reference in New Issue
Block a user