From 7fc9570ffe875111fc2c5d38d9da12cb9bef7843 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Wed, 20 May 2026 10:32:15 +0800 Subject: [PATCH] =?UTF-8?q?model:=20=E5=8A=A0=20GLM=205.1=20=E6=A1=A3?= =?UTF-8?q?=E6=A1=88=20(zai=20provider=20+=20=E5=9B=BD=E5=86=85=E7=AB=99?= =?UTF-8?q?=20bigmodel.cn)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - config/models/glm.yaml: family=glm, variant=pro, model_id=zai/glm-5.1, api_base 覆盖到 https://open.bigmodel.cn/api/paas/v4,env ZHIPUAI_API_KEY - thinking_mode 暂不开:GLM 协议是 body {"type":"enabled"} 而非 reasoning_effort 等级,需 core/llm.py 加 family 分支才能透传,留 TODO - requirements.txt: litellm 下限 1.50→1.83(zai provider PR #17307 merge 后才内置,旧版不识别 zai/ 前缀会炸) - RUN.md: .env 例子加 ZHIPUAI_API_KEY,probe 命令加 glm.pro Co-Authored-By: Claude Opus 4.7 (1M context) --- PROGRESS.md | 4 +++- RUN.md | 5 ++++- config/models/glm.yaml | 27 +++++++++++++++++++++++++++ requirements.txt | 2 +- 4 files changed, 35 insertions(+), 3 deletions(-) create mode 100644 config/models/glm.yaml diff --git a/PROGRESS.md b/PROGRESS.md index bd02528..44c4db2 100644 --- a/PROGRESS.md +++ b/PROGRESS.md @@ -2,7 +2,7 @@ > 配合 `DESIGN.md`。本文件只记 phase 状态、决策偏差、文件量、下一步。每条 2-4 句:做了啥 + 关键判断 + 没动什么;细节查 `git log` / `git diff`。 -最后更新:2026-05-20(files SPA UX 翻面:主区干掉行 checkbox / 黄 bar / 全选,改成"选入到此处"弹框 — 目的地是主区当前路径,源在弹框里跨目录勾;附拖拽上传 + 修一处 `input[type=checkbox]` 被全局 `width:100%` 撑爆的 layout bug) +最后更新:2026-05-20(dev SPA 主页轻量美化:header 加 brand logo / 左 pane filter 行轻分隔 / 顶栏语义按钮改 hover 上色 / 圆角阴影微调) --- @@ -23,6 +23,8 @@ ### 2026-05-20 +- **dev SPA 主页轻量美化(纯 CSS / HTML,不动 JS / 路由)**:用户要"简洁美化主页"。改四处:① header 从裸 "zcbot" 文字 → brand wrapper(24px 红渐变 "Z" logo + 标题字号 14→15 + letter-spacing + 顶栏 1px 极淡阴影),沿用登录页 brand 视觉但缩小;② 左 pane 三行 pane-head(任务标签/搜索/排序)用 `#pane-left .pane-head + .pane-head` 选择器把 filter / sort 子行换白底 + `--border-soft #ececec` 分隔,弱化为子层级,把两条 inline `border-top` 顺手去掉(与新 `border-bottom` 重叠会出双线);③ 顶栏 4 个语义按钮(完成/导出/废弃/删除)+ 选入弹框的复制/移动按钮从"常态彩边 + hover 加底色"改"常态中性 + hover 一次性上语义色(color + border + bg)",给 button 基础类加 transition 让色变平滑(沿用现有 `button.danger` 的同款 hover-only 范式);④ 圆角统一:button / input / textarea / select / floating-menu / .msg 4→6,三个 modal 卡片 6→8 + 阴影 `0 8px 24px → 0 12px 32px` 略深显悬浮感。**没动**:布局 / 交互逻辑 / 任何 JS / 后端 / DESIGN(纯视觉)/ RUN(无对外接口变化);dd-item 菜单的语义色保留(菜单内本来就靠色区分动作类型,不属于"顶栏中性"范畴)。 +- **加 `config/models/glm.yaml`:智谱 GLM 5.1 接入(litellm zai provider + 国内站 bigmodel.cn)**:用户要加 GLM。litellm 1.83.14 内置 `zai` provider(PR #17307 早就 merge,我初次 grep 漏了 — 只搜了 zhipu/glm/doubao),`zai/glm-5.1` 自动路由到 z.ai 国际站(`api.z.ai`,env `ZAI_API_KEY`)。**用户用国内站 bigmodel.cn**(账号 / key 跟 z.ai 国际站不通用),YAML 走 `api_base: https://open.bigmodel.cn/api/paas/v4` 覆盖 litellm 默认(`core/llm.py:71-72` 已有 `if self.api_base: kwargs["api_base"]=...` 透传通道),env 命名 `ZHIPUAI_API_KEY` 跟国际站 `ZAI_API_KEY` 分开。family=`glm`,单 variant `pro`,context 200K / reliable 100K / max_out 8192,tool calling 标 good,run_python 开。**`thinking_mode: false`**:GLM 的 thinking 协议是 body `{"type":"enabled"}` 开关 +(可选)budget,与 OpenAI/DeepSeek 的 `reasoning_effort` int 等级不同;`core/llm.py:77-78` 只透传 `reasoning_effort`,要接 GLM thinking 得加 family 分支(`if family.startswith("glm"): kwargs["extra_body"]={"thinking":{"type":"enabled"}}`),不在加 YAML 范围,留 TODO。smoke:`ModelCapabilities.load('glm.pro', ...)` 正常 + `litellm.get_llm_provider('zai/glm-5.1')` 返 `(model=glm-5.1, provider=zai, default_base=https://api.z.ai/api/paas/v4)`,YAML override 生效后实际打 bigmodel.cn;`/v1/models` 扫描结果含 `glm.pro / 'GLM 5.1' / thinking=False`。**没动**:`core/llm.py`(避免半成品 thinking 分支)、DESIGN.md(只加模型档案,非架构变更)、`default_model`(仍 `deepseek_v4.flash`,GLM 是可选项,前端下拉里出现)。**已知待办**:① 接 GLM thinking 透传;② 豆包图像/视频生成(seedream/seedance,完全不同 API 形态,要单独管线)。 - **files SPA UX 翻面 + 拖拽上传 + 修 checkbox 全局 width bug**:沿用上条新加的两路由,但前端 UX 整套换。**原模型**(select-then-pick-dest):主区行带 checkbox + 顶栏全选三态 + 黄 bar(复制到 / 移动到 / 取消)→ 弹框选目标目录。**新模型**(at-dest-pull-sources):主区只读浏览,顶栏加 `[选入…]` 按钮 → 弹框内浏览任意目录 + 跨目录勾文件 / 子目录(`Set` 跨切换保留)+ 底部 `[复制到此处]` `[移动到此处]` 两按钮直接落到主区当前 `state.filesPath`。**理由**:用户切任务时主区自动跳 task working_dir,绝大多数操作是"把外面素材喂进当前 working_dir",destination-first 比 source-first 少一次心智切换,且主区干净。**附带**:① 主区 `` 被全局 `input{ width:100%; }` 撑成全行宽 → 把 `.name`(`flex: 1; flex-basis: 0`)挤成 0 宽,行里只剩看不见的文字 + 居中的 checkbox(用户报"看不到文字"),根因不修永远埋雷,改 selector 排除 checkbox/radio/file。② 拖拽上传:`#pane-right` 监听 dragenter/over/leave/drop,有 `Files` 才响应(忽略文本拖拽),`#file-droparea` 红色虚线 overlay,落点 = `state.filesPath`,沿用 `/v1/files/upload`。**删了**:`state.selectedFiles` + `syncBulkBar` + `dirPicker` 模块 + 顶栏 selall + 黄 bar 整块 + 行 checkbox 渲染(按 CLAUDE.md 不留旧 UX)。**没动**:后端 `/v1/files/copy` `/v1/files/move`(同样的 `paths` + `dest_dir`)、DESIGN、RUN。 - **`POST /v1/files/copy` + `/v1/files/move` 跨目录批量搬动**(原"+ dev SPA 多选 + 目录选择弹框"已被上一条翻面替换):用户要"在文件夹间复制/移动文件"。后端两路由共用 `_validate_transfer` 预检 helper(批量原子校验:源存在、不能等于/含 dest、不在 dest 直接子级、批内重名、target 已存 409,任一失败整批 abort,无 FS 副作用)。**move 加额外闸**:任一源是顶层目录且为某 task `working_dir` → 409(维持"working_dir = 顶层目录"invariant — 允许沉到子目录后,rename 顶层只更新当前层 task 的 DB-aware 逻辑会失效,代码复杂度翻倍才能扛住嵌套场景;用户想归档项目目录:先 DELETE task)。**copy 无此闸**,新副本无 task 关联。dev SPA:`.file-row` 加 `` 列 + 顶栏 `#files-selall` 三态(全/半/无),选中 ≥1 出黄底 toolbar(`复制到…` / `移动到…` / `取消选中`)。目录选择弹框 `#dir-picker-modal` 复用 `/v1/files` 浏览(只列目录,面包屑可点回上层,源目录灰禁),底部按钮文案随 mode 切。`state.selectedFiles` 切 task / 切 filesPath 时清,refresh 后剔除已不存在的 rel 保 view 一致。**部分失败**:沿用现有 rename / delete 单向语义,FS 中途失败抛 500 + 已成功项保留(`shutil.move/copytree` 失败几乎只在跨卷断连 / 磁盘满,workspace 同盘罕见)。**没动**:DESIGN(API 添加非语义变更)、RUN(无 CLI / env 变化)、DB schema。 - **working_dir 视为可重生 FS 视图**:DB 是 source of truth,FS 目录可独立删 / 用户手动 rmtree / 跨机器迁移丢失,**下次跑就自动 mkdir 重建**。三处改:① `DELETE /v1/tasks/{id}` 删完后若同 user 下再无 task 引用此 working_dir 且 FS 目录为空 → best-effort `rmdir` 清孤儿(非空 / 不存在 / 外部 --working-dir 静默跳过)。② `POST /v1/files/delete` 顶层目录去掉「有 task 引用就 409」闸,允许独立删空目录,task.working_dir 字段不动。③ `core/agent_builder.py::build_agent` 把 `working_dir_path.mkdir(parents=True, exist_ok=True)` 从 `if not resume:` 里挪出,resume 也兜底建目录(用户手删 FS 后再 send message 不会炸)。smoke `scripts/smoke_files_rename.py` 增 case 4 (200 + working_dir 不变) / case 8 (DELETE task 空目录自动清) / case 9 (非空目录保留),全 9 pass。**没动**:DB schema、rename 顶层目录的同步 UPDATE 逻辑(rename 是明确改名,和"删后重生"语义不同)、外部 --working-dir(DB 绝对串)的清理(避免误删用户外部项目)。 diff --git a/RUN.md b/RUN.md index 7a679c8..492d852 100644 --- a/RUN.md +++ b/RUN.md @@ -2,7 +2,7 @@ > 怎么把 zcbot 跑起来。env / 常用命令 / 故障兜底。设计看 `DESIGN.md`,进度看 `PROGRESS.md`。 -最后更新:2026-05-20(working_dir 改为可重生 FS 视图:`DELETE /v1/tasks/{id}` 顺手清空孤儿目录;`POST /v1/files/delete` 顶层目录无 task-ref 闸) +最后更新:2026-05-20(加 GLM 5.1 模型档案:`.env` 加 `ZHIPUAI_API_KEY`,probe 示例加 `glm.pro`) --- @@ -12,6 +12,8 @@ - **配置文件 `.env`**(项目根,git 忽略,litellm 自动加载): ``` DEEPSEEK_API_KEY=sk-... + # 用 GLM 的话再加一条;国际站 z.ai 用 ZAI_API_KEY,国内站 bigmodel.cn 用 ZHIPUAI_API_KEY(对应 config/models/glm.yaml 的 api_key_env 字段) + ZHIPUAI_API_KEY=... ZCBOT_DB_URL=postgresql://user:pass@host:5432/zcbot # main.py web 必填(probe/db/user 不验) PLATFORM_KEY=<≥16 字符随机串,platform 机器对机器入口校验> @@ -61,6 +63,7 @@ python -m venv .venv ```bash # 模型能力对账(费 token) .venv/Scripts/python.exe main.py probe --model deepseek_v4.flash +.venv/Scripts/python.exe main.py probe --model glm.pro # 智谱 GLM-5.1(走 litellm zai provider + 国内站 bigmodel.cn) # DB migration .venv/Scripts/python.exe main.py db upgrade head diff --git a/config/models/glm.yaml b/config/models/glm.yaml new file mode 100644 index 0000000..6745130 --- /dev/null +++ b/config/models/glm.yaml @@ -0,0 +1,27 @@ +# 智谱 GLM 模型档案 +# 走 litellm 原生 zai provider(1.83+ 内置)。litellm 默认 api_base 是国际站 api.z.ai; +# 国内站 bigmodel.cn 通过 yaml 的 api_base 字段覆盖。两站 API key 不通用,env 也分开命名。 +# thinking 暂不接:GLM 的 thinking 协议是 body `{"type":"enabled"}`,与 OpenAI/DeepSeek +# 的 `reasoning_effort` 等级不同,要 core/llm.py 加 family 分支才能透传 — 留 TODO。 +family: glm + +variants: + pro: + display_name: GLM 5.1 + model_id: zai/glm-5.1 + api_base: https://open.bigmodel.cn/api/paas/v4 + api_key_env: ZHIPUAI_API_KEY + max_context: 200000 + reliable_context: 100000 + max_output: 8192 + parallel_tools: false + tool_calling_quality: good + thinking_mode: false + reasoning_effort_levels: [] + default_reasoning_effort: "" + code_quality: good + enable_run_python: true + max_iterations: 50 + optimal_temperature: 0.3 + prompt_caching: false + extended_thinking: false diff --git a/requirements.txt b/requirements.txt index c81740a..6d81f01 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -litellm>=1.50.0 +litellm>=1.83.0 # zai provider(GLM)要 ≥1.83;PR #17307 merge 后才内置 pyyaml>=6.0 click>=8.1.0 rich>=13.7.0