feat: add DeepSeek extreme reasoning tier
This commit is contained in:
Executable
+257
@@ -0,0 +1,257 @@
|
||||
#!/usr/bin/env python3
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import asyncio
|
||||
import json
|
||||
import os
|
||||
import tempfile
|
||||
import time
|
||||
import uuid
|
||||
from dataclasses import replace
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
from docker.errors import NotFound
|
||||
|
||||
from agent_platform.auth import UserIdentity
|
||||
from agent_platform.config import Settings
|
||||
from agent_platform.gateway.provider import DockerExecutionProvider, workspace_ref
|
||||
from agent_platform.models import get_model_spec
|
||||
from agent_platform.runtime.loop import AgentLoop
|
||||
from agent_platform.runtime.provider import ModelProvider
|
||||
from agent_platform.runtime.schemas import PlanItem
|
||||
from agent_platform.runtime.tools import TOOL_METADATA, ToolContext
|
||||
from agent_platform.store import RuntimeStore
|
||||
|
||||
EVAL_TOOL_NAMES = (
|
||||
"workspace_status",
|
||||
"list_files",
|
||||
"read_file",
|
||||
"search_files",
|
||||
"write_file",
|
||||
"apply_patch",
|
||||
"exec",
|
||||
"update_plan",
|
||||
)
|
||||
|
||||
|
||||
class DirectDockerRegistry:
|
||||
def __init__(
|
||||
self,
|
||||
execution: DockerExecutionProvider,
|
||||
store: RuntimeStore,
|
||||
tool_timeout_seconds: int,
|
||||
) -> None:
|
||||
self.execution = execution
|
||||
self.store = store
|
||||
self.tool_timeout_seconds = tool_timeout_seconds
|
||||
|
||||
def specs(self, *, read_only: bool = False, allow_delegate: bool = True) -> list[dict[str, Any]]:
|
||||
names = [name for name in EVAL_TOOL_NAMES if not read_only or TOOL_METADATA[name].read_only]
|
||||
return [TOOL_METADATA[name].openai_spec() for name in names]
|
||||
|
||||
async def execute(
|
||||
self,
|
||||
name: str,
|
||||
arguments: dict[str, Any],
|
||||
context: ToolContext,
|
||||
) -> dict[str, Any]:
|
||||
user_id = context.identity.user_id
|
||||
if name == "workspace_status":
|
||||
result = await self.execution.status(user_id)
|
||||
elif name == "list_files":
|
||||
result = await self.execution.list_files(
|
||||
user_id,
|
||||
str(arguments.get("path", ".")),
|
||||
int(arguments.get("max_depth", 4)),
|
||||
int(arguments.get("limit", 500)),
|
||||
)
|
||||
elif name == "read_file":
|
||||
result = await self.execution.read_file(
|
||||
user_id,
|
||||
str(arguments["path"]),
|
||||
int(arguments.get("start_line", 1)),
|
||||
int(arguments.get("max_lines", 1000)),
|
||||
)
|
||||
elif name == "search_files":
|
||||
result = await self.execution.search_files(
|
||||
user_id,
|
||||
str(arguments["query"]),
|
||||
str(arguments.get("path", ".")),
|
||||
arguments.get("glob"),
|
||||
int(arguments.get("limit", 200)),
|
||||
)
|
||||
elif name == "write_file":
|
||||
result = await self.execution.write_file(
|
||||
user_id,
|
||||
str(arguments["path"]),
|
||||
str(arguments["content"]),
|
||||
)
|
||||
elif name == "apply_patch":
|
||||
result = await self.execution.apply_patch(
|
||||
user_id,
|
||||
str(arguments["patch"]),
|
||||
str(arguments.get("cwd", ".")),
|
||||
)
|
||||
elif name == "exec":
|
||||
result = await self.execution.exec(
|
||||
user_id,
|
||||
str(arguments["command"]),
|
||||
str(arguments.get("cwd", ".")),
|
||||
min(
|
||||
int(arguments.get("timeout_seconds", 120)),
|
||||
self.tool_timeout_seconds,
|
||||
),
|
||||
)
|
||||
elif name == "update_plan":
|
||||
items = [PlanItem.model_validate(item).model_dump() for item in arguments.get("items", [])]
|
||||
await self.store.update_plan(user_id, context.chat_id, items)
|
||||
return {
|
||||
"ok": True,
|
||||
"explanation": arguments.get("explanation"),
|
||||
"items": items,
|
||||
}
|
||||
else:
|
||||
raise ValueError(f"Unsupported evaluation tool: {name}")
|
||||
return result.model_dump()
|
||||
|
||||
|
||||
def parse_args() -> argparse.Namespace:
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Run the real Work loop against a live provider in a disposable Docker workspace."
|
||||
)
|
||||
parser.add_argument("--model", default="work-extreme")
|
||||
parser.add_argument(
|
||||
"--prompt",
|
||||
default="写脚本对比一下几个常见排序算法,给一个报告",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--workspace-image",
|
||||
default=os.getenv("WORKSPACE_IMAGE", "k1412-agent-workspace:test"),
|
||||
)
|
||||
parser.add_argument("--keep-workspace", action="store_true")
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
async def cleanup_workspace(execution: DockerExecutionProvider, user_id: str) -> None:
|
||||
ref = workspace_ref(user_id)
|
||||
try:
|
||||
execution.client.containers.get(ref.container_name).remove(force=True)
|
||||
except NotFound:
|
||||
pass
|
||||
try:
|
||||
execution.client.volumes.get(ref.volume_name).remove(force=True)
|
||||
except NotFound:
|
||||
pass
|
||||
try:
|
||||
execution.client.networks.get(ref.network_name).remove()
|
||||
except NotFound:
|
||||
pass
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
args = parse_args()
|
||||
spec = get_model_spec(args.model)
|
||||
if spec.mode != "work":
|
||||
raise SystemExit("--model must select a Work tier")
|
||||
if spec.provider == "deepseek" and not os.getenv("DEEPSEEK_API_KEY", "").strip():
|
||||
raise SystemExit("DEEPSEEK_API_KEY is required")
|
||||
|
||||
user_id = f"live-eval-{uuid.uuid4().hex}"
|
||||
chat_id = f"live-eval-{uuid.uuid4().hex}"
|
||||
started = time.monotonic()
|
||||
event_counts: dict[str, int] = {}
|
||||
usage_totals = {
|
||||
"prompt_tokens": 0,
|
||||
"completion_tokens": 0,
|
||||
"reasoning_tokens": 0,
|
||||
"cached_tokens": 0,
|
||||
"total_tokens": 0,
|
||||
}
|
||||
|
||||
with tempfile.TemporaryDirectory(prefix="k1412-live-eval-") as temp_dir:
|
||||
settings = replace(
|
||||
Settings.from_env(),
|
||||
database_url=f"sqlite+aiosqlite:///{Path(temp_dir) / 'runtime.sqlite3'}",
|
||||
workspace_image=args.workspace_image,
|
||||
workspace_network_enabled=False,
|
||||
workspace_memory_limit="1g",
|
||||
workspace_cpu_limit=1.0,
|
||||
workspace_pids_limit=128,
|
||||
tool_timeout_seconds=180,
|
||||
)
|
||||
store = RuntimeStore(settings.database_url)
|
||||
await store.initialize()
|
||||
provider = ModelProvider(settings)
|
||||
execution = DockerExecutionProvider(settings)
|
||||
registry = DirectDockerRegistry(execution, store, settings.tool_timeout_seconds)
|
||||
|
||||
async def record(event_type: str, payload: dict[str, Any]) -> None:
|
||||
event_counts[event_type] = event_counts.get(event_type, 0) + 1
|
||||
if event_type == "model.responded":
|
||||
usage = payload.get("usage") or {}
|
||||
prompt_details = usage.get("prompt_tokens_details") or {}
|
||||
completion_details = usage.get("completion_tokens_details") or {}
|
||||
usage_totals["prompt_tokens"] += int(usage.get("prompt_tokens", 0))
|
||||
usage_totals["completion_tokens"] += int(usage.get("completion_tokens", 0))
|
||||
usage_totals["reasoning_tokens"] += int(completion_details.get("reasoning_tokens", 0))
|
||||
usage_totals["cached_tokens"] += int(
|
||||
prompt_details.get("cached_tokens", 0) or usage.get("prompt_cache_hit_tokens", 0)
|
||||
)
|
||||
usage_totals["total_tokens"] += int(usage.get("total_tokens", 0))
|
||||
if event_type == "tool.completed":
|
||||
print(
|
||||
json.dumps(
|
||||
{
|
||||
"event": event_type,
|
||||
"name": payload.get("name"),
|
||||
"ok": payload.get("ok"),
|
||||
"summary": str(payload.get("summary", ""))[:500],
|
||||
},
|
||||
ensure_ascii=False,
|
||||
),
|
||||
flush=True,
|
||||
)
|
||||
|
||||
try:
|
||||
answer = await AgentLoop(
|
||||
provider,
|
||||
registry,
|
||||
store,
|
||||
max_tool_output_chars=settings.max_tool_output_chars,
|
||||
).run(
|
||||
spec=spec,
|
||||
messages=[{"role": "user", "content": args.prompt}],
|
||||
identity=UserIdentity(user_id, "", "Live Eval", "user"),
|
||||
raw_user_jwt="local-evaluation",
|
||||
chat_id=chat_id,
|
||||
callback=record,
|
||||
)
|
||||
listing = await execution.list_files(user_id, ".", 4, 500)
|
||||
print(
|
||||
json.dumps(
|
||||
{
|
||||
"model": spec.public_id,
|
||||
"provider_model": spec.provider_model,
|
||||
"elapsed_seconds": round(time.monotonic() - started, 3),
|
||||
"events": event_counts,
|
||||
"usage": usage_totals,
|
||||
"answer": answer,
|
||||
"workspace": listing.model_dump(),
|
||||
"workspace_id": workspace_ref(user_id).workspace_id if args.keep_workspace else None,
|
||||
},
|
||||
ensure_ascii=False,
|
||||
indent=2,
|
||||
)
|
||||
)
|
||||
finally:
|
||||
await provider.close()
|
||||
await store.close()
|
||||
if not args.keep_workspace:
|
||||
await cleanup_workspace(execution, user_id)
|
||||
execution.client.close()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
@@ -18,6 +18,7 @@ export OPENWEBUI_FORWARD_JWT_SECRET="e2e-forward-jwt-secret-at-least-32-bytes"
|
||||
export INTERNAL_PROVIDER_KEY="e2e-provider-secret-at-least-32-bytes"
|
||||
export INTERNAL_GATEWAY_KEY="e2e-gateway-secret-at-least-32-bytes"
|
||||
export MODEL_API_KEY="e2e-model-key"
|
||||
export DEEPSEEK_API_KEY="e2e-deepseek-key"
|
||||
export POSTGRES_PASSWORD="e2e-postgres-password"
|
||||
export WEB_IMAGE="k1412-agent-web:e2e"
|
||||
export RUNTIME_IMAGE="k1412-agent-runtime:e2e"
|
||||
|
||||
@@ -24,6 +24,7 @@ export OPENWEBUI_FORWARD_JWT_SECRET=verify-forward-jwt-secret-at-least-32-bytes
|
||||
export INTERNAL_PROVIDER_KEY=verify-provider-secret-at-least-32-bytes
|
||||
export INTERNAL_GATEWAY_KEY=verify-gateway-secret-at-least-32-bytes
|
||||
export MODEL_API_KEY=verify-model-key
|
||||
export DEEPSEEK_API_KEY=verify-deepseek-key
|
||||
export POSTGRES_PASSWORD=verify-postgres-password
|
||||
export WEB_IMAGE=docker.k1412.top/wuyang/k1412-agent-web:verify
|
||||
export RUNTIME_IMAGE=docker.k1412.top/wuyang/k1412-agent-runtime:verify
|
||||
|
||||
Reference in New Issue
Block a user