feat: add DeepSeek extreme reasoning tier

This commit is contained in:
wuyang
2026-07-26 17:40:51 +08:00
parent ade5ea1210
commit 2e8e81c790
25 changed files with 567 additions and 30 deletions
+1 -1
View File
@@ -158,7 +158,7 @@ async def bootstrap() -> None:
)
model_response.raise_for_status()
print("Open WebUI bootstrap complete: auth policy, workspace tools, and six fixed Agent entries are ready.")
print("Open WebUI bootstrap complete: auth policy, workspace tools, and eight fixed Agent entries are ready.")
def run() -> None:
+5
View File
@@ -26,6 +26,8 @@ def _float(name: str, default: float) -> float:
class Settings:
model_api_base_url: str
model_api_key: str
deepseek_api_base_url: str
deepseek_api_key: str
openwebui_forward_jwt_secret: str
internal_provider_key: str
internal_gateway_key: str
@@ -49,6 +51,8 @@ class Settings:
return cls(
model_api_base_url=os.getenv("MODEL_API_BASE_URL", "https://api.k1412.top").rstrip("/"),
model_api_key=os.getenv("MODEL_API_KEY", ""),
deepseek_api_base_url=os.getenv("DEEPSEEK_API_BASE_URL", "https://api.deepseek.com").rstrip("/"),
deepseek_api_key=os.getenv("DEEPSEEK_API_KEY", ""),
openwebui_forward_jwt_secret=os.getenv("OPENWEBUI_FORWARD_JWT_SECRET", ""),
internal_provider_key=os.getenv("INTERNAL_PROVIDER_KEY", ""),
internal_gateway_key=os.getenv("INTERNAL_GATEWAY_KEY", ""),
@@ -73,6 +77,7 @@ class Settings:
name
for name, value in (
("MODEL_API_KEY", self.model_api_key),
("DEEPSEEK_API_KEY", self.deepseek_api_key),
("OPENWEBUI_FORWARD_JWT_SECRET", self.openwebui_forward_jwt_secret),
("INTERNAL_PROVIDER_KEY", self.internal_provider_key),
("INTERNAL_GATEWAY_KEY", self.internal_gateway_key),
+25 -6
View File
@@ -4,7 +4,8 @@ from dataclasses import dataclass
from typing import Literal
Mode = Literal["chat", "work"]
Strength = Literal["light", "medium", "high"]
Strength = Literal["light", "medium", "high", "extreme"]
Provider = Literal["k1412", "deepseek"]
@dataclass(frozen=True, slots=True)
@@ -13,15 +14,20 @@ class ModelSpec:
display_name: str
mode: Mode
strength: Strength
provider: Provider
provider_model: str
thinking_enabled: bool
reasoning_effort: str | None
max_output_tokens: int
max_iterations: int
context_char_budget: int
_TIERS = {
"light": ("轻度", "ChatGPT-5.6:Luna", 8, 120_000),
"medium": ("", "ChatGPT-5.6:Terra", 16, 240_000),
"high": ("", "ChatGPT-5.6:Sol", 24, 400_000),
"light": ("轻度", "k1412", "ChatGPT-5.6:Luna", False, None, 4_096, 8, 120_000),
"medium": ("", "k1412", "ChatGPT-5.6:Terra", False, None, 4_096, 16, 240_000),
"high": ("", "k1412", "ChatGPT-5.6:Sol", False, None, 4_096, 24, 400_000),
"extreme": ("极高", "deepseek", "deepseek-v4-pro", True, "max", 16_384, 32, 800_000),
}
MODEL_SPECS: dict[str, ModelSpec] = {
@@ -30,12 +36,25 @@ MODEL_SPECS: dict[str, ModelSpec] = {
display_name=f"{'Chat' if mode == 'chat' else 'Work'} · {label}",
mode=mode,
strength=strength,
provider_model=provider,
provider=provider,
provider_model=provider_model,
thinking_enabled=thinking_enabled,
reasoning_effort=reasoning_effort,
max_output_tokens=max_output_tokens,
max_iterations=max_iterations,
context_char_budget=context_budget,
)
for mode in ("chat", "work")
for strength, (label, provider, max_iterations, context_budget) in _TIERS.items()
for strength, (
label,
provider,
provider_model,
thinking_enabled,
reasoning_effort,
max_output_tokens,
max_iterations,
context_budget,
) in _TIERS.items()
}
+7 -1
View File
@@ -160,7 +160,13 @@ def create_app(
async def forward_direct():
payload = body.model_dump(exclude_none=True)
payload["model"] = spec.provider_model
response = await app.state.provider.forward(payload)
response = await app.state.provider.forward(
payload,
provider=spec.provider,
thinking_enabled=spec.thinking_enabled,
reasoning_effort=spec.reasoning_effort,
max_output_tokens=spec.max_output_tokens,
)
if body.stream:
passthrough_headers = {
key: value
+19 -2
View File
@@ -599,6 +599,10 @@ class AgentLoop:
model=spec.provider_model,
messages=messages,
tools=available_specs,
provider=spec.provider,
thinking_enabled=spec.thinking_enabled,
reasoning_effort=spec.reasoning_effort,
max_output_tokens=spec.max_output_tokens,
)
choice = response["choices"][0]
message = choice.get("message") or {}
@@ -648,9 +652,12 @@ class AgentLoop:
"completion.rejected",
{"reason": failure, "iteration": iteration + 1, "depth": depth},
)
assistant_checkpoint = {"role": "assistant", "content": candidate}
if isinstance(message.get("reasoning_content"), str):
assistant_checkpoint["reasoning_content"] = message["reasoning_content"]
messages.extend(
[
{"role": "assistant", "content": candidate},
assistant_checkpoint,
{"role": "user", "content": recovery_message(failure)},
]
)
@@ -683,6 +690,8 @@ class AgentLoop:
"content": message.get("content"),
"tool_calls": tool_calls,
}
if isinstance(message.get("reasoning_content"), str):
assistant_message["reasoning_content"] = message["reasoning_content"]
messages.append(assistant_message)
blocked_call_reasons: dict[str, str] = {}
batch_mutation_epoch = 0
@@ -801,7 +810,15 @@ class AgentLoop:
),
}
)
response = await self.provider.complete(model=spec.provider_model, messages=messages, tools=None)
response = await self.provider.complete(
model=spec.provider_model,
messages=messages,
tools=None,
provider=spec.provider,
thinking_enabled=spec.thinking_enabled,
reasoning_effort=spec.reasoning_effort,
max_output_tokens=spec.max_output_tokens,
)
answer = str(response["choices"][0].get("message", {}).get("content") or "").strip()
if completion_failure(
artifact_required,
+63 -12
View File
@@ -6,6 +6,7 @@ from typing import Any
import httpx
from agent_platform.config import Settings
from agent_platform.models import Provider
TRANSIENT_COMPLETE_STATUS_CODES = frozenset({408, 425, 429, 500, 502, 503, 504, 524})
COMPLETE_MAX_ATTEMPTS = 2
@@ -132,11 +133,37 @@ class ModelProvider:
@property
def headers(self) -> dict[str, str]:
return self._headers("k1412")
def _headers(self, provider: Provider) -> dict[str, str]:
key = self.settings.deepseek_api_key if provider == "deepseek" else self.settings.model_api_key
return {
"Authorization": f"Bearer {self.settings.model_api_key}",
"Authorization": f"Bearer {key}",
"Content-Type": "application/json",
}
def _base_url(self, provider: Provider) -> str:
return self.settings.deepseek_api_base_url if provider == "deepseek" else self.settings.model_api_base_url
@staticmethod
def _provider_payload(
payload: dict[str, Any],
*,
provider: Provider,
thinking_enabled: bool,
reasoning_effort: str | None,
max_output_tokens: int,
) -> dict[str, Any]:
value = dict(payload)
value.pop("thinking", None)
value.pop("reasoning_effort", None)
value["max_tokens"] = max_output_tokens
if provider == "deepseek" and thinking_enabled:
value["thinking"] = {"type": "enabled"}
if reasoning_effort:
value["reasoning_effort"] = reasoning_effort
return value
async def close(self) -> None:
if self._owns_client:
await self.client.aclose()
@@ -148,13 +175,22 @@ class ModelProvider:
messages: list[dict[str, Any]],
tools: list[dict[str, Any]] | None = None,
temperature: float | None = None,
provider: Provider = "k1412",
thinking_enabled: bool = False,
reasoning_effort: str | None = None,
max_output_tokens: int = COMPLETE_MAX_TOKENS,
) -> dict[str, Any]:
payload: dict[str, Any] = {
"model": model,
"messages": messages,
"stream": True,
"max_tokens": COMPLETE_MAX_TOKENS,
}
payload = self._provider_payload(
{
"model": model,
"messages": messages,
"stream": True,
},
provider=provider,
thinking_enabled=thinking_enabled,
reasoning_effort=reasoning_effort,
max_output_tokens=max_output_tokens,
)
if tools:
payload["tools"] = tools
payload["tool_choice"] = "auto"
@@ -165,8 +201,8 @@ class ModelProvider:
try:
async with self.client.stream(
"POST",
completions_url(self.settings.model_api_base_url),
headers=self.headers,
completions_url(self._base_url(provider)),
headers=self._headers(provider),
json=payload,
) as response:
if response.status_code in TRANSIENT_COMPLETE_STATUS_CODES and attempt < COMPLETE_MAX_ATTEMPTS:
@@ -184,11 +220,26 @@ class ModelProvider:
raise RuntimeError("Model provider retry loop exited unexpectedly")
async def forward(self, payload: dict[str, Any]) -> httpx.Response:
async def forward(
self,
payload: dict[str, Any],
*,
provider: Provider = "k1412",
thinking_enabled: bool = False,
reasoning_effort: str | None = None,
max_output_tokens: int = COMPLETE_MAX_TOKENS,
) -> httpx.Response:
payload = self._provider_payload(
payload,
provider=provider,
thinking_enabled=thinking_enabled,
reasoning_effort=reasoning_effort,
max_output_tokens=max_output_tokens,
)
request = self.client.build_request(
"POST",
completions_url(self.settings.model_api_base_url),
headers=self.headers,
completions_url(self._base_url(provider)),
headers=self._headers(provider),
json=payload,
)
response = await self.client.send(request, stream=bool(payload.get("stream")))