5.0 KiB
5.0 KiB
name, description, metadata
| name | description | metadata | |||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| vision | Agent 识图工具 - Gemini 2.5 Flash Lite(首选)或本地 Qwen2.5-VL(降级)分析图像内容 |
|
Vision 识图技能
目标
当 agent 收到图片消息时,自动调用视觉模型识别图片内容,并将描述纳入对话上下文,让 agent 能够"看见"图片。
触发条件(自动)
agent 在以下任一情况必须自动触发本技能,优先于内置 image 工具:
- 用户通过任何渠道(Telegram、微信、QQ 等)发送的图片消息
- 消息中包含图片附件(
<qqmedia>标签、image_url、文件附件等) - 用户直接要求 agent 看图
- agent 需要理解图片内容才能继续对话
自动执行流程:
- 检测到消息中有图片 → 优先使用本技能(走 Gemini curl 流程)
- 不要依赖内置
image工具,除非 Gemini curl 流程失败 - 识图结果作为辅助信息写入对话上下文,让 agent 能基于图片内容回复用户
引擎策略
按优先级顺序:
- Gemini 2.5 Flash Lite(首选)— 快(1-3 秒),准确,可用性高,通过环境变量
GEMINI_API_KEY调用 - Gemini 2.5 Flash(二选)— 更高精度,但免费层有时 503,仅在 Lite 失败时降级尝试
- 本地 Qwen2.5-VL(最终降级)— 纯本地,但 CPU 推理非常慢(10-90 秒),仅在前两者都不可用时回退
调用方式
第一步:定位图片文件
图片文件存放在 /Users/guchen/.openclaw/media/inbound/ 目录下,文件名通过消息中的 UUID 标识获取。
例如消息中的 media 路径或 filename 中包含 UUID,对应的文件路径为 /Users/guchen/.openclaw/media/inbound/{UUID}.jpg。
如果图片以 URL 形式传入,先下载到临时文件:
curl -sL -x http://127.0.0.1:7897 -o /tmp/vision_input.jpg "{图片URL}"
第二步:Gemini API(首选,通过 exec + curl)
# 加载 GEMINI_API_KEY(注意:~/.zshrc 里 export 的值带双引号,
# 用 eval 展开确保去掉外层引号,否则 API 调用会报 key invalid)
eval "$(grep '^export GEMINI_API_KEY=' ~/.zshrc 2>/dev/null)"
export HTTPS_PROXY=http://127.0.0.1:7897
VISION_B64=$(base64 -i /tmp/vision_input.jpg | tr -d '\n')
# 或者从 inbound 目录读取
VISION_B64=$(base64 -i /Users/guchen/.openclaw/media/inbound/{UUID}.jpg | tr -d '\n')
# 用 python3 构建 JSON 避免 shell 转义问题
curl -s --max-time 30 -x http://127.0.0.1:7897 \
"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash-lite:generateContent?key=***" \
-H "Content-Type: application/json" \
-d "$(python3 -c "
import json
b64 = '''$VISION_B64'''
payload = {
'contents': [{
'parts': [
{'text': '请用中文详细描述这张图片的内容'},
{'inline_data': {'mime_type': 'image/jpeg', 'data': b64}}
]
}]
}
print(json.dumps(payload))
")"
从响应中提取:.candidates[0].content.parts[0].text
如果 gemini-2.5-flash-lite 失败(429/503),尝试降级到 gemini-2.5-flash:
- 将 URL 中的
gemini-2.5-flash-lite替换为gemini-2.5-flash
第三步:降级到本地 Qwen API
如果 Gemini 调用失败(超时、API key 未设置、网络不通、额度用完等),降级到本地模型:
VISION_B64=$(base64 -i /tmp/vision_input.jpg | tr -d '\n')
curl -s --max-time 120 http://127.0.0.1:8081/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "guff",
"messages": [
{
"role": "user",
"content": [
{"type": "text", "text": "请用中文详细描述这张图片的内容"},
{"type": "image_url", "image_url": {"url": "data:image/jpeg;base64,"'$VISION_B64'"}}
]
}
],
"max_tokens": 500
}' 2>&1
从响应中提取:.choices[0].message.content
第四步:纳入上下文
将识图得到的文字描述以辅助信息形式写入对话上下文,格式参考:
[Vision: 图片描述内容...]
然后根据图片内容回复用户。
速度参考
| 引擎 | 延迟 | 备注 |
|---|---|---|
| Gemini 2.5 Flash Lite | 1-3 秒 | 首选,可用性高 |
| Gemini 2.5 Flash | 1-3 秒 | 二选,精度更高但有时 503 |
| 本地 Qwen2.5-VL | 10-90 秒 | CPU 推理,无网络依赖 |
注意事项
- 每次识图调用串行处理,不要并发多张图片
- 图片大小建议不超过 5MB,过大的图片应先压缩
- 识别结果不一定 100% 准确,在回复中适当表达不确定性
- 如果 Gemini 和本地模型都不可用,给出友好提示而非报错
- API key 存放于
~/.zshrc中的GEMINI_API_KEY环境变量 - 密钥加载必须用
eval "$(grep '^export GEMINI_API_KEY=' ~/.zshrc)"而不是source ~/.zshrc,因为后者引入的变量值可能因 shell 引号上下文不一致而出错 - 代理地址:
127.0.0.1:7897