Files
hunjing/backend/app/schemas/preferences.py
T
2026-08-21 16:00:13 +08:00

135 lines
5.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""设置 API schema(模型网关与生成偏好)。
前端只见逻辑模型 / provider 密钥脱敏状态 / 生成参数偏好;
真实 model 名、endpoint URL、API Key 由后端持有,不进入响应(environment-config §3)。
"""
from pydantic import BaseModel, ConfigDict, Field
class ModelEndpointStatus(BaseModel):
"""endpoint 池状态。base_url / api_key 原值不回传(脱敏),仅回覆盖标记 + env 变量名。"""
name: str = Field(description="endpoint 名称(如 primary / fallback)。")
provider: str = Field(description="所属 provider。")
status: str = Field(description="endpoint 状态:active / inactive / unhealthy / cooldown。")
weight: int | None = Field(default=None, description="权重(weighted_random 路由用)。")
priority: int | None = Field(
default=None, description="优先级(priority_failover 用,数值越小越优先)。"
)
is_overridden: bool = Field(default=False, description="是否存在 DB 覆盖。")
has_url_override: bool = Field(
default=False, description="是否用 DB 覆盖了 base_url(优先于 .env)。"
)
has_key_override: bool = Field(
default=False, description="是否用 DB 覆盖了 api_key(优先于 .env)。"
)
base_url_env: str | None = Field(
default=None, description="base_url 的 .env 变量名(只读展示)。"
)
api_key_env: str | None = Field(
default=None, description="api_key 的 .env 变量名(只读展示)。"
)
class ProviderKeyStatus(BaseModel):
"""供应商密钥脱敏状态:configured 表示 .env 是否已配置该 provider 的 API Key。"""
provider: str = Field(description="provider 标识。")
configured: bool = Field(description="是否已配置 API Key(仅 true/false,绝不暴露值)。")
class LogicalModel(BaseModel):
"""逻辑模型(契约字典 §16)。业务层 model_hint 引用 name。"""
name: str = Field(description="逻辑模型名,业务层 model_hint 引用。")
display_name: str = Field(description="展示名。")
provider: str = Field(description="默认 provider。")
capabilities: list[str] = Field(
description="能力清单:chat / tool_use / structured_output / reasoning / long_context / vision。"
)
routing_strategy: str = Field(description="路由策略。")
supports_streaming: bool = Field(description="是否支持流式。")
supports_thinking: bool = Field(description="是否支持思考。")
supports_structured_output: bool = Field(description="是否支持结构化输出。")
context_window: int = Field(description="上下文窗口大小。")
max_output_tokens: int | None = Field(default=None, description="最大输出 token 数。")
endpoints: list[ModelEndpointStatus] | None = Field(
default=None, description="endpoint 池脱敏状态。"
)
is_default: bool | None = Field(default=None, description="是否为默认对话模型槽位。")
class ModelGatewayStatus(BaseModel):
model_config = ConfigDict(
json_schema_extra={
"examples": [
{
"default_model_hint": "default-chat",
"models": [],
"providers": [{"provider": "deepseek", "configured": True}],
}
]
}
)
models: list[LogicalModel] = Field(description="逻辑模型清单。")
providers: list[ProviderKeyStatus] = Field(description="provider 密钥脱敏状态。")
default_model_hint: str = Field(description="默认逻辑模型名。")
class GenerationPreferencesResponse(BaseModel):
"""生成参数偏好(业务层,不含密钥)。"""
model_config = ConfigDict(
json_schema_extra={
"examples": [
{
"default_model_hint": "default-chat",
"temperature": 0.7,
"top_p": 1.0,
"max_output_tokens": 4096,
"streaming": True,
}
]
}
)
default_model_hint: str = Field(description="默认对话逻辑模型名。")
temperature: float = Field(description="采样温度。")
top_p: float = Field(description="核采样概率。")
max_output_tokens: int = Field(description="最大输出 token 数。")
streaming: bool = Field(description="是否启用流式输出。")
class UpdateGenerationPreferencesRequest(BaseModel):
"""更新生成偏好;至少传一个字段。"""
default_model_hint: str | None = Field(
default=None, max_length=120, description="默认对话逻辑模型名。"
)
temperature: float | None = Field(default=None, ge=0.0, le=2.0, description="采样温度。")
top_p: float | None = Field(default=None, ge=0.0, le=1.0, description="核采样概率。")
max_output_tokens: int | None = Field(
default=None, ge=1, le=200000, description="最大输出 token 数。"
)
streaming: bool | None = Field(default=None, description="是否启用流式输出。")
class UpdateEndpointOverrideRequest(BaseModel):
"""更新 endpoint 覆盖(PATCH /settings/models/{model}/endpoints/{endpoint})。
字段全可选;传 None 表示清除该字段覆盖、回退 yaml/env。base_url/api_key 经 DB
覆盖优先于 .env。响应脱敏,不回 base_url/api_key 原值。
"""
base_url: str | None = Field(
default=None, description="覆盖 base_url(DB 优先 env);None 清除。"
)
api_key: str | None = Field(
default=None, description="覆盖 api_key(DB 优先 env);None 清除。"
)
status: str | None = Field(default=None, description="覆盖 endpoint 状态。")
weight: int | None = Field(default=None, ge=0, description="覆盖权重。")
priority: int | None = Field(default=None, ge=0, description="覆盖优先级。")