From 5ba3cc778b1ff234cb139799ff7dbb1aca1a83fa Mon Sep 17 00:00:00 2001 From: tzt <14718231+flying-travel@user.noreply.gitee.com> Date: Sun, 30 Aug 2026 21:26:16 +0800 Subject: [PATCH] =?UTF-8?q?feat(v2):=20Web=20=E7=95=8C=E9=9D=A2=EF=BC=88?= =?UTF-8?q?=E5=AF=B9=E8=AF=9D/=E5=8D=8F=E4=BD=9C=E8=BF=87=E7=A8=8B/?= =?UTF-8?q?=E4=BA=BA=E5=B7=A5=E6=A3=80=E9=AA=8C/=E6=8C=87=E6=A0=87?= =?UTF-8?q?=EF=BC=89+=20worker=20=E4=BC=98=E9=9B=85=E9=99=8D=E7=BA=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 +- gateway/api.py | 10 +++ gateway/static/index.html | 167 ++++++++++++++++++++++++++++++++++++++ router_system/worker.py | 23 ++++-- tests/test_gateway.py | 8 ++ 5 files changed, 202 insertions(+), 10 deletions(-) create mode 100644 gateway/static/index.html diff --git a/README.md b/README.md index 7818e35..43a10b6 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,8 @@ - ✅ **人工检验队列**(`review.py`):sqlite 队列、抽样 + safety 强制入队、verdict/correction 回写 - ✅ **打包分发**(`scripts/setup_runtime.py`):llama-server + GGUF 下载(断点续传/大小校验) - ✅ **E1 token 经济学实验**(`scripts/bench_tokens.py` → `research/v2_experiments/`) -- ✅ **测试**:**228 项全绿**(含 v1 legacy 126 项 + v2 新模块) +- ✅ **Web 界面**(gateway/static/index.html,FastAPI 托管,无构建):对话 / 协作过程(交流文本可视化)/ 人工检验 / 指标 四视图 +- ✅ **测试**:**229 项全绿**(含 v1 legacy 126 项 + v2 新模块) --- @@ -66,6 +67,7 @@ C:\Python314\python.exe -m venv .venv # 4. 启动网关(v2 /chat 默认走 mock worker,无需 API key/模型即可演示) .venv\Scripts\python.exe scripts/serve.py --port 8000 +# 浏览器打开 http://127.0.0.1:8000/ 使用 Web 界面(对话 / 协作过程 / 人工检验 / 指标) # 5. 调用 curl http://127.0.0.1:8000/health diff --git a/gateway/api.py b/gateway/api.py index da12dcf..ee7510b 100644 --- a/gateway/api.py +++ b/gateway/api.py @@ -107,6 +107,9 @@ class HealthResponse(BaseModel): # ---- FastAPI 应用 ---- try: from fastapi import FastAPI, HTTPException + from fastapi.responses import HTMLResponse + + _INDEX_PATH = Path(__file__).resolve().parent / "static" / "index.html" app = FastAPI( title="端云协同 LLM 协作系统", @@ -118,6 +121,13 @@ try: async def health(): return get_router().health() + @app.get("/", response_class=HTMLResponse, tags=["ui"]) + async def index(): + """端云协同 Web 界面(单文件前端,无需构建)。""" + if _INDEX_PATH.exists(): + return HTMLResponse(_INDEX_PATH.read_text(encoding="utf-8")) + return HTMLResponse("

Web 界面未生成

缺少 gateway/static/index.html

") + # ---------------- v2:/chat ---------------- @app.post("/chat", tags=["chat"]) async def chat(req: QueryRequest): diff --git a/gateway/static/index.html b/gateway/static/index.html new file mode 100644 index 0000000..33d8924 --- /dev/null +++ b/gateway/static/index.html @@ -0,0 +1,167 @@ + + + + + +端云协同 LLM 协作系统 + + + +
+

⚙️ 端云协同 LLM 协作系统

+ Architect(大模型 API)+ Worker(本地小模型)+ 交流文本协议 + +
+ +
+ +
+
+
+
+ + +
+
+ + +
+
+
+
+
+
+
+ +
+
+ + +
+
+
+ +
+
+ + +
+
+
+ +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/router_system/worker.py b/router_system/worker.py index 462ecdb..afe8225 100644 --- a/router_system/worker.py +++ b/router_system/worker.py @@ -190,14 +190,19 @@ def _make_llama_generate(cfg: Dict[str, Any]) -> Callable[[str], Awaitable[str]] timeout_s = float(cfg.get("per_step_timeout_s", 300)) async def _gen(prompt: str) -> str: - import httpx - async with httpx.AsyncClient(timeout=timeout_s) as client: - resp = await client.post( - f"{base_url}/chat/completions", - json={"model": model, "messages": [{"role": "user", "content": prompt}], - "temperature": temperature, "max_tokens": 4096}, - ) - resp.raise_for_status() - return resp.json()["choices"][0]["message"]["content"] + try: + import httpx + async with httpx.AsyncClient(timeout=timeout_s) as client: + resp = await client.post( + f"{base_url}/chat/completions", + json={"model": model, "messages": [{"role": "user", "content": prompt}], + "temperature": temperature, "max_tokens": 4096}, + ) + resp.raise_for_status() + return resp.json()["choices"][0]["message"]["content"] + except Exception as e: # noqa: BLE001 + # 连不上本地模型 -> 优雅降级(不抛 500),提示用户准备运行时 + return ("(本地降级)无法连接本地 llama-server,未能生成该步骤内容。" + f"请先运行 scripts/setup_runtime.py 并启动模型。错误:{type(e).__name__}") return _gen diff --git a/tests/test_gateway.py b/tests/test_gateway.py index c6721bc..ebb2cb8 100644 --- a/tests/test_gateway.py +++ b/tests/test_gateway.py @@ -71,6 +71,14 @@ def test_workspace_not_found(client): assert resp.status_code == 404 +def test_web_ui_served(client): + resp = client.get("/") + assert resp.status_code == 200 + assert resp.headers["content-type"].startswith("text/html") + assert "端云协同" in resp.text + assert "发送" in resp.text + + def test_review_flow(client): q = ga.get_review() rid = q.enqueue("req-x", "q", "ans", tags=["safety"], reason="test")