适用场景

底层模型为纯文本模型(如 DeepSeek deepseek-v4-flash),不支持图片输入。通过外接一个视觉模型 API,让 AI 具备识图能力。

原理

Shell
图片 → vision.js 转 base64 → 视觉模型 API → 返回文字描述 → 主模型

视觉模型走 OpenAI 兼容格式,换厂商只需改 BASE_URLAPI_KEYMODEL 三个值。

前置要求

  • Node.js 18+
  • 一个视觉模型 API Key(推荐阿里云百炼,新用户送 100 万 token;智谱 glm-4.6v-flash 免费但高峰期 429 限流严重)

一、获取 API Key

阿里云百炼:https://bailian.console.aliyun.com/ → 开通百炼 → API-KEY 管理 → 创建 Key(sk- 开头)

智谱:https://open.bigmodel.cn/ → 注册实名认证 → 创建 Key(xxxxx.xxxxx 格式)

二、创建 vision.js

新建 vision.js,内容如下:

JavaScript
#!/usr/bin/env node
const fs = require("fs");
const path = require("path");
const https = require("https");

// ==== 需要修改的三个配置 ====
const BASE_URL = process.env.DASHSCOPE_BASE_URL || "https://dashscope.aliyuncs.com/compatible-mode/v1";
const API_KEY  = process.env.DASHSCOPE_API_KEY  || "sk-你的Key";        // ← API Key
const MODEL    = process.env.VISION_MODEL       || "qwen3.5-omni-plus"; // ← 模型名
// ============================

function resolveImageUrl(source) {
  const resolved = path.resolve(source);
  if (!fs.existsSync(resolved)) throw new Error(`文件不存在: ${resolved}`);
  const ext = path.extname(resolved).toLowerCase().replace(".", "");
  const mimeMap = { jpg: "jpeg", jpeg: "jpeg", png: "png", gif: "gif", webp: "webp", bmp: "bmp" };
  const data = fs.readFileSync(resolved);
  return `data:image/${mimeMap[ext] || "jpeg"};base64,${data.toString("base64")}`;
}

function request(payload) {
  const url = new URL(BASE_URL.replace(/\/?$/, "/") + "chat/completions");
  const body = JSON.stringify(payload);
  return new Promise((resolve, reject) => {
    const req = https.request(url, {
      method: "POST",
      headers: {
        Authorization: `Bearer ${API_KEY}`,
        "Content-Type": "application/json",
        "Content-Length": Buffer.byteLength(body),
      },
    }, (res) => {
      let data = "";
      res.on("data", (c) => data += c);
      res.on("end", () => {
        if (res.statusCode >= 400) return reject(new Error(`API ${res.statusCode}: ${data.slice(0, 300)}`));
        try { resolve(JSON.parse(data)?.choices?.[0]?.message?.content || data); }
        catch { resolve(data); }
      });
    });
    req.on("error", reject);
    req.write(body);
    req.end();
  });
}

async function main() {
  const args = process.argv.slice(2);
  const imagePath = args[0];
  const prompt = args[1] || "请详细描述这张图片的内容。";
  if (!imagePath) {
    console.error("用法: node vision.js <图片路径> [问题]");
    process.exit(1);
  }
  const imageUrl = resolveImageUrl(imagePath);
  const result = await request({
    model: MODEL,
    messages: [{ role: "user", content: [
      { type: "image_url", image_url: { url: imageUrl } },
      { type: "text", text: prompt },
    ]}],
    stream: false,
    max_tokens: 1024,
  });
  console.log(result);
}

main().catch(e => { console.error("识图失败:", e.message); process.exit(1); });

三、配置 Agent

Claude Code:项目根目录的 CLAUDE.md 中添加:

Markdown
# 识图能力

你的底层模型不具备原生识图能力。遇到图片时,不要用 Read 工具,改用 vision.js:

    node vision.js "<图片路径>" "用中文描述这张图片"

## 触发场景

- 用户分享图片路径(本地或网络 URL)
- 消息中出现 "Saved attachments:" 并列出图片
- 用户要求分析、描述、识别图片内容

Codex:同样的内容加到项目根目录的 AGENTS.md

四、视觉模型对照

厂商 BASE_URL MODEL
阿里云百炼 https://dashscope.aliyuncs.com/compatible-mode/v1 qwen3.5-omni-plus / qwen-vl-max
智谱 https://open.bigmodel.cn/api/paas/v4 glm-4.6v-flash
OpenAI https://api.openai.com/v1 gpt-4o-mini

五、验证

Shell
node vision.js "/path/to/image.png" "请用中文描述这张图片的内容"

能正确返回图片内容即配置成功。

注意事项

  • 429 限流:免费模型高峰期频繁返回 429,建议用千问或加 30 秒以上间隔的重试。
  • Key 安全:Key 不要明文提交到 git,放 .env 并在 .gitignore 忽略,或用环境变量 DASHSCOPE_API_KEY
  • 图片限制:≤10MB,支持 jpg/png/webp/gif/bmp;过大先压缩。
  • 只提文字用 OCR:仅需提取文字可本地用 tesseract;需要理解图片语义必须用视觉模型。
阅读进度 0%