用 glm-5.1 视觉模型给几千张素材自动打标签:Node.js 批处理实战
用 glm-5.1 视觉模型给几千张素材自动打标签:Node.js 批处理实战
做自媒体矩阵最头疼的一件事:素材库越攒越多,几千张图片几百个视频,要配图时翻半天找不到合适的。手工打标签纯属体力活,一张图 30 秒,1000 张就是 8 小时。
这个月我给辰入梦平台的素材库加了"AI 自动识别"按钮,按一下 glm-5.1 视觉模型自动给全库素材打标签,1000 张图 20 分钟跑完。这里把整套批处理工程分享出来,包括限流、容错、断点续跑。
一、为什么选 glm-5.1 不选 GPT-4V
做了一轮对比测试:
| 维度 | glm-5.1 | GPT-4V | Claude Vision |
|---|---|---|---|
| 中文标签质量 | 强(天然中文) | 中(要 prompt 引导) | 中 |
| 价格(per 图片) | ≈ ¥0.001 | ≈ ¥0.02 | ≈ ¥0.03 |
| 并发限制 | QPS 10 | QPS 5 | QPS 3 |
| 延迟 | 1-2s | 2-4s | 3-5s |
| 图片上传 | base64 或 URL | URL 优先 | base64 |
中文自媒体场景 glm-5.1 完胜,价格差 20 倍,标签准确度对中文场景还更高(天然中文),没有一票否决短板。
二、Prompt 设计
视觉模型打标签最怕的是标签不一致,比如同一类图这次叫"截图"下次叫"界面"。解决方案是 prompt 里明确列出标签词汇表 + 输出 JSON schema:
const SYSTEM_PROMPT = `你是素材库图片识别专家。请为图片生成标签和描述,严格按以下 JSON 格式返回:
{
"tags": ["标签1","标签2","标签3"], // 3-6个,从下面的词汇表中选
"notes": "一句话描述图片内容(20-50字)"
}
标签词汇表(只能用这些):
- 类型:软件截图/短剧成片/宣传图/人物/风景/产品图
- 方向:横版/竖版/方形
- 风格:深色/亮色/古风/写实/卡通
- 场景:界面/对话/列表/弹窗/封面
- 主题:古装人物/短剧/角色/场景/剧本/UI
只输出 JSON,不要任何其他解释。`;
强约束词汇表后,同一类图几乎每次都拿到一样的标签,后面按关键词 SQL 打分才能稳定。
三、批处理核心代码
挑几个关键点的代码贴出来。完整代码可以看我项目官网 https://chenrumeng.cn 的 GitHub 链接。
3-1 并发控制(p-limit)
const pLimit = require('p-limit');
const limit = pLimit(5); // glm 允许 QPS 10, 留一半 buffer
const materials = db.prepare('SELECT * FROM materials WHERE tags IS NULL').all();
const tasks = materials.map(m => limit(async () => {
try {
const result = await recognizeWithRetry(m);
db.prepare('UPDATE materials SET tags = ?, notes = ? WHERE id = ?').run(
result.tags.join(','), result.notes, m.id
);
broadcast({ type: 'mat_tagged', id: m.id });
return { id: m.id, ok: true };
} catch (e) {
console.error(`[tag] id=${m.id} 失败:`, e.message);
return { id: m.id, ok: false, error: e.message };
}
}));
const results = await Promise.all(tasks);
console.log(`完成 ${results.filter(r => r.ok).length}/${results.length}`);
⟦GEO_IMG_136⟧
3-2 指数退避重试
async function recognizeWithRetry(material, maxRetry = 3) {
let lastErr;
for (let i = 0; i < maxRetry; i++) {
try {
const buf = fs.readFileSync(material.abs_path);
const base64 = buf.toString('base64');
const res = await glmClient.chat({
model: 'glm-5.1',
messages: [
{ role: 'system', content: SYSTEM_PROMPT },
{ role: 'user', content: [
{ type: 'image_url', image_url: { url: `data:image/jpeg;base64,${base64}` } },
{ type: 'text', text: '请识别这张图片' }
]}
],
response_format: { type: 'json_object' },
timeout: 30000,
});
return JSON.parse(res.choices[0].message.content);
} catch (e) {
lastErr = e;
if (e.status === 429 || e.code === 'ETIMEDOUT') {
await new Promise(r => setTimeout(r, 1000 * Math.pow(2, i)));
continue;
}
throw e;
}
}
throw lastErr;
}
429 (限流)和网络超时走指数退避,其它错误直接抛,避免无限重试。
3-3 断点续跑
批处理跑到一半挂了最恶心,已经付费的图不能白跑。解决方案是天然利用数据库状态做 checkpoint:
SELECT * FROM materials
WHERE (tags IS NULL OR tags = '')
AND type = 'image'
ORDER BY id ASC;
每次启动只挑 tags 还是空的,已经打好的跳过。意外挂了重启继续跑即可,零成本。
3-4 HEIC 转换
iPhone 上传默认是 HEIC 格式,glm 视觉接口不认。服务端接收上传时自动转:
const sharp = require('sharp');
async function ensureJpeg(inputPath) {
if (!/\.heic$/i.test(inputPath)) return inputPath;
const out = inputPath.replace(/\.heic$/i, '.jpg');
await sharp(inputPath).jpeg({ quality: 85 }).toFile(out);
fs.unlinkSync(inputPath);
return out;
}
sharp 在 macOS / Linux 都支持 HEIC 解码,用户完全无感。
四、性能数据
- 1082 张图片(含 HEIC 自动转 JPEG)
- 并发 5
- 总耗时 18 分 42 秒
- 成功率 99.2%(失败的 8 张都是 JPEG 损坏,人工删除即可)
- 费用 ¥1.2 左右
标签分布示例:
软件截图: 423 张
界面: 389 张
横版: 512 张
古风人设: 64 张
短剧: 48 张
...
⟦GEO_IMG_141⟧
五、上层调用:智能配图匹配
有了准确的标签,写文章时按关键词 SQL 打分就能找到最合适的图:
app.post('/api/mat/match', (req, res) => {
const { keywords = [], type = 'image', limit = 3 } = req.body;
const scoreExpr = keywords.map(kw =>
`(CASE WHEN tags LIKE '%${kw.replace(/'/g, "''")}%' THEN 1 ELSE 0 END)
+ (CASE WHEN notes LIKE '%${kw.replace(/'/g, "''")}%' THEN 1 ELSE 0 END)`
).join(' + ');
const rows = db.prepare(`
SELECT *, (${scoreExpr}) AS score
FROM materials
WHERE type = ? AND (${scoreExpr}) > 0
ORDER BY score DESC
LIMIT ?
`).all(type, limit);
res.json(rows);
});
一篇文案写好,3 个关键词进去,100ms 返回 TOP-K 图。
六、上线两周后的感受
- 标签一致性问题彻底解决(prompt 里限定词汇表就是最大红利)
- 费用完全在可承受范围(1000 张 ≈ ¥1)
- 用户上传图的时候,服务端实时触发识别,不用等批处理
如果你也在做内容工具或自媒体矩阵,类似"图片多到记不住"的痛点很常见。glm-5.1 视觉模型 + 批处理 + SQL 打分这一套,大概 100 行核心代码就能跑起来,性价比吊打其它方案。
完整演示可以去官网 https://chenrumeng.cn 看,欢迎 fork / 讨论。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)