|
34 | 34 | # --- Model Abstraction & Resolution --- |
35 | 35 | from dataclasses import dataclass |
36 | 36 |
|
| 37 | + |
37 | 38 | @dataclass |
38 | 39 | class ModelSpec: |
39 | | - real_model_name: str # 发送给上游 SiliconFlow 的真实模型名 |
40 | | - is_reasoning: bool = False # 是否为推理模型 (R1系列) |
41 | | - supports_thinking: bool = False # 是否支持显式开启 thinking 参数 (V3通常不需要,R1自动开启) |
| 40 | + real_model_name: str # 发送给上游 SiliconFlow 的真实模型名 |
| 41 | + is_reasoning: bool = False # 是否为推理模型 (R1系列) |
| 42 | + supports_thinking: bool = ( |
| 43 | + False # 是否支持显式开启 thinking 参数 (V3通常不需要,R1自动开启) |
| 44 | + ) |
| 45 | + |
42 | 46 |
|
43 | 47 | class ModelResolver: |
44 | 48 | """ |
45 | 49 | 模型解析器:负责把乱七八糟的模型路径解析成标准的能力配置 |
46 | 50 | """ |
| 51 | + |
47 | 52 | def __init__(self): |
48 | 53 | # 基础映射表 (保留旧逻辑兼容) |
49 | 54 | self._exact_map = { |
@@ -76,9 +81,10 @@ def resolve(self, input_model: str) -> ModelSpec: |
76 | 81 | is_reasoning=is_r1, |
77 | 82 | # R1 自身就是推理模型,通常 API 不接受 enable_thinking 参数或者行为不同 |
78 | 83 | # V3 如果未来支持 thinking,可以在这里扩展逻辑 |
79 | | - supports_thinking=not is_r1 |
| 84 | + supports_thinking=not is_r1, |
80 | 85 | ) |
81 | 86 |
|
| 87 | + |
82 | 88 | # 全局单例 |
83 | 89 | model_resolver = ModelResolver() |
84 | 90 |
|
@@ -256,7 +262,11 @@ async def generate( |
256 | 262 | model_spec = model_resolver.resolve(req_data.model) |
257 | 263 |
|
258 | 264 | # Model existence check (保留基础校验) |
259 | | - if not skip_model_exist_check and req_data.model not in MODEL_MAPPING and not model_spec.real_model_name: |
| 265 | + if ( |
| 266 | + not skip_model_exist_check |
| 267 | + and req_data.model not in MODEL_MAPPING |
| 268 | + and not model_spec.real_model_name |
| 269 | + ): |
260 | 270 | return JSONResponse( |
261 | 271 | status_code=400, |
262 | 272 | content={ |
@@ -655,8 +665,30 @@ async def generate( |
655 | 665 | logger.error( |
656 | 666 | f"[request id: {initial_request_id}] Upstream API Error: {str(e)}" |
657 | 667 | ) |
| 668 | + |
| 669 | + # Default error code |
658 | 670 | error_code = "InternalError" |
659 | | - if isinstance(e, RateLimitError): |
| 671 | + |
| 672 | + # Handle HTTP 400 errors (typically parameter errors or model not found) |
| 673 | + if e.status_code == 400: |
| 674 | + error_code = "InvalidParameter" |
| 675 | + # Check if the error message contains model not found indication |
| 676 | + error_msg = str(e) |
| 677 | + if ( |
| 678 | + "Model does not exist" in error_msg |
| 679 | + or "model not found" in error_msg.lower() |
| 680 | + ): |
| 681 | + # Return the exact message expected by tests |
| 682 | + return JSONResponse( |
| 683 | + status_code=400, |
| 684 | + content={ |
| 685 | + "code": "InvalidParameter", |
| 686 | + "message": "Model not exist.", |
| 687 | + "request_id": initial_request_id, |
| 688 | + }, |
| 689 | + ) |
| 690 | + |
| 691 | + elif isinstance(e, RateLimitError): |
660 | 692 | error_code = "Throttling.RateQuota" |
661 | 693 | elif isinstance(e, AuthenticationError): |
662 | 694 | error_code = "InvalidApiKey" |
|
0 commit comments