# 模型能力配置指南 DSH 里"某个模型能不能读图""子代理能用哪些模型",**取决于配置声明,而不是模型自动识别**。配置里缺一行声明,就会出现"明明支持的模型却用不了"。本文记录如何查看、如何声明、以及常见报错的对照处理。 --- ## 一、怎么查看当前模型能力 ### 方法:用 `llm` 服务探测 挂载一个临时 Cordis 插件(或让 agent 用 `cordis_define` 定义一个),注入 `llm` 服务后查询: ```js // 列出所有 provider 的模型 for (const p of ctx.llm.listProviders()) { const models = await ctx.llm.listModels(p.id || p.name) for (const m of models) { const info = await ctx.llm.resolveModelInfo(p.id || p.name, m.id || m.name) console.log(p.id, m.id, info.inputModalities) // ['text'] 或 ['text','image'] } } ``` `info.inputModalities` 含 `image` 才**能**读图。 --- ## 二、图像能力声明(重点,最容易踩的坑) ### 关键事实 DSH 的模型能力字段 **默认值是 `["text"]`**: ```js inputModalities: model.inputModalities ?? ["text"] ``` 也就是说——**即使模型实际支持图像,只要配置里没声明 `image`,`read_image` 就会被拒绝**: ``` Error: cannot read "xxx.png" as an image: model "xxx" does not declare image input; switch to an image-capable model to read images ``` ### 怎么声明 在 `~/.dsh/settings.yaml` 对应 provider 的模型条目下补 `inputModalities`: ```yaml llm-deepseek: models: - id: deepseek-flash name: DeepSeek-V4.1-Flash inputModalities: - text - image # ← 补上这行,就能读图了 ``` > 配置是**热加载**的,通常不需要重启 DSH。 ### 可选图像参数 声明 `image` 后,还可以细调图像处理预算(都以适配器默认值为准,可不填): ```yaml inputModalities: - text - image imagePixelBudget: low # 像素预算:数字,或 "low"(低精度) imageMaxBytes: 1048576 # 单图编码字节上限 ``` ### schema 约束(配错会报错) - `inputModalities` 只能含 `"text"` / `"image"`,**不能为空、不能重复**; - **text-only 模型不能声明 `imagePixelBudget` / `imageMaxBytes`**(会报错提示)。 --- ## 三、子代理模型白名单 DSH 可以限制"子代理能用哪些模型",配置在 `settings.yaml`: ```yaml subagent-model-selection: enabled: true allowedModels: - provider: deepseek-official model: deepseek-flash - provider: kimi-coding model: k3-256k - provider: kimi-coding model: kimi-for-coding ``` **要点**: - `workflow` / `subagent` 派生子代理时,**指定白名单外的模型会失败**(子代理返回 `null`); - 规划"识图 / 审查"用哪个模型前,先确认它在白名单里,或把目标模型加进白名单。 --- ## 四、常见报错对照表 | 报错 / 现象 | 原因 | 处理 | |---|---|---| | `model "X" does not declare image input` | 配置缺 `image` 声明(默认 `["text"]`) | 在该模型配置里加 `inputModalities: [text, image]` | | `The DeepSeek chat-completions adapter does not support image content` | 请求走了 text-only 路径 | 同上:补图像声明 | | 子代理返回 `null` / 无输出 | 指定了**白名单外**的模型 | 换成 `allowedModels` 里的模型,或把目标模型加进白名单 | | 预设挂载失败:`$.prefix missing required value (at prefix)` | DSH 升级后 `dsh-persona` 字段由 `text` 改为 `prefix` | 把预设声明(0.2.0 起为 bundle 的 `cordis.patch.yml`)里 persona 的 `text:` 改成 `prefix:` | | `row(s) published process-global service(s) [...]` | 预设里有行发布了服务但没放在 `isolate` realm 里 | 用 `cordis:group` + `isolate` 包住该行 | --- ## 五、实测案例(2026-09-10) **现象**:用 DeepSeek V4.1 Flash(`deepseek-official/deepseek-flash`)读图,`read_image` 报 `does not declare image input`。 **排查**: 1. `llm.resolveModelInfo` 显示 `inputModalities = ["text"]`; 2. 查 `dsh-llm-deepseek` 源码,发现适配器**本身支持图像**(`prepareRequestImages`、`resolveRequestImagePolicy`、v4 vision token 计费、PNG/JPEG/WebP/GIF 支持),且内置模型目录里 `deepseek-v4-flash` 声明的是 `["text", "image"]`; 3. 根因:`settings.yaml` 里自定义的那条 `deepseek-flash` 条目**漏了图像声明**。 **修复**:补上 `inputModalities: [text, image]`。 **验证**:修复后实测 V4.1 Flash 成功读图,并输出完整的逐项审查(标题 / 坐标轴 / 图例 / 遮挡 / 几何自洽 / PASS 判定)。 --- ## 六、文件读取能力对照(2026-09-10 实测) | 类型 | 主模型能否直接读 | 说明 | |---|---|---| | **图片**(PNG / JPG / WebP / GIF) | ✅ **能**(前提:配置声明了 `image`) | 用 `read_image` 工具直接读,主模型即可看到图内容并做图表审查 | | **PDF** | ❌ **不能** | `read` 工具只支持 UTF-8 文本,读 PDF 报 `binary file`;PDF 需用脚本提取(如 pypdf / pdfplumber),或在 Web UI 上传后经文件工具读取 | **对工作流的影响**: - **图表质检可以直接用主模型做**(若它支持图像)——不必再派识图子代理,少一层派发; - **仍在两种情况下用识图子代理**:① 主模型不支持图像;② 想要独立/隔离的看图结论,或想用更便宜的视觉模型; - **PDF 题目/模板仍需脚本提取文本**(当前 agent 侧没有原生 PDF 工具)。 ### PDF 文本提取方法(实测可用) 本机 `python` 是 msys64 自带、**没有 pip**;推荐用 `uv` 临时装依赖跑脚本(不污染系统环境)。 **第 1 步:写提取脚本 `extract_pdf.py`** ```python from pypdf import PdfReader import sys src, dst = sys.argv[1], sys.argv[2] reader = PdfReader(src) parts = [] for i, page in enumerate(reader.pages, 1): parts.append(f"===== 第 {i} 页 =====") parts.append(page.extract_text() or "(无文本)") with open(dst, "w", encoding="utf-8") as fh: fh.write("\n".join(parts)) print(f"提取完成:{len(reader.pages)} 页 -> {dst}") ``` **第 2 步:用 `uv` 运行**(自动临时安装 `pypdf`,不污染系统环境) ```powershell uv run --with pypdf python extract_pdf.py "题目.pdf" "题目提取.txt" ``` **第 3 步**:用 `read` 工具读取生成的 `题目提取.txt`。 **备选方案**: - 系统 python 有 pip 时,可直接 `pip install pypdf` 后运行同一脚本; - 需要连表格/版式一起提取时,改用 `pdfplumber`(同样 `uv run --with pdfplumber`); - 题目 PDF 若已通过 Web UI 上传,可尝试用文件工具直接读取(取决于部署是否暴露该工具)。 ## 七、经验小结 1. **"能不能读图"看配置声明,不看模型名气**——先 `resolveModelInfo` 确认,别凭印象判断; 2. **实际支持图像却被拒**,第一反应应该是"配置里有没有声明 `image`"; 3. **派子代理前先看白名单**,避免白跑一轮; 4. **DSH 升级后留意 schema 变化**(如 `text` → `prefix`),升级后跑一次预设挂载校验(`agentPresets.standingKeyFor(id)`)能及早发现。