← 返回列表
未验证
一个在 llm-pi-ai 设置命名空间上分为两半的插件。Models…
尚未跑自动兼容性验证,可查看页面内的依赖与入口分析。 · 最近上游提交 2026/9/10 · 已提供中文文档
修补自定义提供程序视觉模型
综合分
29.2
GitHub 分
29.2
用户评分
—
★ Stars
0
周下载量
—
兼容 / 相关生态插件(非 dsh 原生,请按其对应运行时安装)
git clone https://github.com/ryasrk/dsh-vision-patch.git数据截至 2026/9/18(元数据每日更新 · 实装验证按队列轮转,单条结论的验证时间见上方)
依赖的 DSH / Cordis 模块
@deepseek-ai/cordis用户评分
还没有人投票,来当第一个
订阅周报,不错过优质插件更新
每周一封 · 高评分插件 + 新用户活动
README
dsh-vision-patch
一个在 llm-pi-ai 设置命名空间上分为两半的插件。Models 页面上的客户端卡片按模型和按路由声明哪些模型接受图像输入,并为每条路由挑选一个视觉回退模型。宿主端使用该回退模型来描述图像,这样一轮对话就不会因为主模型无法读取的图像而中断。
该卡片渲染在 Models 页面为 llm-pi-ai 路由绘制的每个提供商卡片内部(已保存的行、首次运行设置行、添加提供商草稿),并通过设置 Remote 写入。宿主端不添加自己的 HTTP 路由;它注册一个 agent/pre-step 拦截器。
它的作用
- 按模型复选框 —— 模型存储条目上的 input: ['text', 'image']。取消勾选会完全移除 input 键,因此该模型继承已安装目录的能力(它绝不会写入 ['text'],因为那会直接禁止图像)。
- 路由级复选框 —— defaultInput: ['text', 'image'](通过路径操作设置/取消设置),作用于该路由上所有未声明自己列表的模型。
- 视觉回退模型 —— 一个按路由的下拉菜单,列出该路由中具备视觉能力的模型(那些自己声明图像或从路由继承图像的模型)。所选模型存储为 visionFallbackModel。
- 模型筛选 —— 一旦某条路由列出超过 8 个模型,就会出现一个搜索框;计数行显示当前有多少模型声明了图像。
- 实时刷新 —— 卡片在每次写入后重新读取,并跟随 settings/document-updated,因此页面其他位置的编辑会收敛一致。
没有存储配置文件的提供商(从未从 Models 页面保存过)会显示引导文本而不是复选框。
视觉回退(宿主)
llm-pi-ai 设置命名空间中的提供商路由可以携带一个 visionFallbackModel 字段:{ provider?: string; model: string }。provider 默认为该路由本身;model 指定其上具备视觉能力的模型。字段缺失即为该路由关闭此功能。Models 卡片的下拉菜单写入此字段;宿主读取同一存储配置文件,因此两端始终一致。
当宿主的 agent/pre-step 拦截器看到某一步的用户消息包含 image 内容块,且该步的路由(来自 agent.options.provider)配置了 visionFallbackModel 时,它会:
1. 通过 llm 服务的 stream({ provider, model, messages, signal }) 将该轮对话流式发送到回退视觉模型,以描述图像;
2. 将用户消息中的每个 image 块替换为包含该描述的 text 块;以及
3. 返回重写后的消息,使主模型基于描述继续。
它不检查当前主模型的模态:只要配置了回退且存在图像,它就会进行描述。如果描述失败、超时、未配置回退,或 llm 服务不可用,拦截器会原样委托(next()),因此图像会落到
harness 的默认处理,且该轮次永远不会被阻塞。
宿主服务访问(为什么用 ctx.get,而不是 ctx.)
宿主侧作为 Cordis 插件运行,因此它的 ctx 是一个 Cordis Proxy。读取插件未在 inject 中声明的服务属性会抛出异常(cannot get property "" without inject)——而且它是在属性读取本身抛出异常,所以可选链(ctx?.settings?.describe)也不是安全的探测方式。严格的 ctx.get(name) 是唯一对不存在的服务返回 undefined 的读取方式,因此 lib/host.js 中每一处可选服务读取都通过它进行。
在编辑此插件之前,有两个值得了解的后果:
- settings 是宿主服务,而不是客户端 Remote。 宿主读取 ctx.get('settings') 并调用 describe(),它返回一个同步数组,包含命名空间描述符。ctx.remote.settings 是仅限客户端的 Remote,其调用返回 { ok, value } 信封;该形状在宿主上并不存在。此插件的客户端部分才是使用 Remote 的地方。
- 绝不要添加裸的 ctx. 读取。 它会在加载时使整个 profile 启动失败,而不是在运行时降级。
持久性与日志记录
当拦截器描述一张图像时,它会重写用户自己的消息,将每个 image 内容块替换为持有该描述的 text 块。该重写后的文本没有打上插件 source 类型的标记。整个宿主接缝仅针对 mock 进行了验证——没有实时宿主来确认新的、非目录的 source 类型会被接受——而且重写一条已存在的用户消息(而不是追加一条新消息)有覆盖该消息上 harness 自身 source 标记的风险。因此,注入措辞的持久性由 harness 决定;此插件改为通过宿主日志器使注入可观测:
- 当尝试进行描述时(存在图像、配置了回退模型,且 ctx.llm.stream 可用)记录 info;
- 当描述未产生可用文本且拦截器原样委托(next())时记录 debug;
- 当描述实际被注入且该轮次进入重写状态时记录 debug;
- 当描述被跳过,因为同一 agent 已有一个描述正在进行中时(按 agent 的并发保护)记录 debug。
所有日志记录都经过防护(ctx?.logger?.info?.(...) / debug / warn?.(...)),因此日志器缺失也无害。静默的描述在日志中从不静默:如果用户认为某张图像已被描述,但没有文本被组装出来(例如真实的 ctx.llm.stream 块形状与 mock 不同),debug 行会指出回退到原样 next() 的 agent。
安装
dsh plugin --profile web add github:ryasrk/dsh-vision-patch
该 profile 的 dsh.profile.bundles 列表会自动拾取该包(其 package.json 声明了 dsh.bundle.patch)。重启 web 宿主,以便新的 bundle 层组合生效,然后重新加载 Models 页面。
布局
| 路径 | 角色 |
| --- | --- |
| cordis.patch.yml | 插入 dsh-vision-patch 加载器行 |
| lib/index.js | 宿主入口 — apply(ctx) 通过 lib/host.js 注册 agent/pre-step 拦截器 |
| lib/host.js | 宿主辅助函数:描述图像并重写轮次的 agent/pre-step 处理器,以及设置回退读取器 |
| client/client.js | 浏览器打包文件:卡片(图像输入复选框 + 视觉回退下拉菜单),注册在 settings.models.provider-card 槽位上,键为 llm-pi-ai |
| package.json | dsh.bundle.patch + dsh.client(web 平台,注入边) |
客户端打包文件仅需要 react(一个平台种子词);它无需
构建步骤,也没有运行时依赖。
写入方式
所有写入都通过 ctx.remote.settings 针对 llm-pi-ai 命名空间进行,
并携带上次读取所观察到的修订版本(在竞争失败时返回 settings-conflict):
- 路由级开关 → 对 ['providers', , 'defaultInput'] 执行 mutate 路径操作
- 视觉回退 → 对 ['providers', , 'visionFallbackModel'] 执行 mutate 路径操作(set 设置 { model } 选择,unset 清除)
- 按模型 → update 合并,重述整个已存储的 models 列表(路径
操作无法寻址数组元素),每个未触及的字段都通过合并保留。
成功落地的写入会返回该命名空间的写入后视图,该视图会直接
折回卡片中。
卸载
dsh plugin --profile web remove dsh-vision-patch
(然后重启 web 宿主,以便打包层离开组合。)同作者(ryasrk)的其他插件
扫码进群