这篇文章是在 smolagents 官方教程结束后的番外篇二,实现了如何使用 smolagents 库 + Ollama 调用本地模型对图像与文件进行分析。
【注意】:这篇文章需要你在本地部署Ollama的视觉语言模型,如果你的架构方案是纯线上模式,则可以跳过这篇文章。
前情提要
理论上说可以直接加载本地图像转换成 base64
格式的 byte
类型数据或者通过 PIL
库加载,然后通过 run
函数中的参数 images
传给模型,示例图像如下:
【注意】:下面的代码我用了 "meta-llama/Llama-3.2-11B-Vision-Instruct"
模型,如果你没有在HuggingFace上购买 Pro 账户的话是不能使用的,你可以尝试和以前一样不指定模型名,执行后的报错内容是不一样的。
import os
from io import BytesIO
from PIL import Image
from smolagents import CodeAgent, HfApiModelimage_file = "./image.jpg"os.environ["HF_TOKEN"] = "你的Huggingface Token"# 读取并编码图像
with open(image_file, "rb") as img_file:img_data = img_file.read()# 解码为 PIL Image
image = Image.open(BytesIO(img_data))# 初始化模型和代理
model_id = "meta-llama/Llama-3.2-11B-Vision-Instruct"
model = HfApiModel(model_id=model_id)
agent = CodeAgent(tools=[], model=model
)
agent.max_steps = 2
agent.run(task=f"describe local image file {image_file}",images=[image]
)
上面的代码会存在以下几个问题:
- 图像转换成
byte
数据后很容易超出模型的 Token 限制范围; - 原始图像会包含很多无用的内容,你可能只关心图像中的人是否穿了红色衣服,但图像中可能有60%以上的面积是背景,这会直接增加模型的分析压力,文本毅然;
- 图像数据处理起来比纯文本数据耗时,容易触发 Agent 超时错误;
- 不同视觉模型返回的格式与内容不同,容易让Agent误以为模型报错;
其中第一个问题是核心问题,无论你是使用免费的还是付费的API,token都是非常宝贵的,并且如果频繁触发 Agent 超时,那么会快速消耗你的token,所以这里我的方案是将视觉语言模型部署在本地以避免token超限;
运行后会这样:
可以看到尽管模型在 Step4
时已经给出了对这张照片的描述,但Agent因为格式问题仍然认为模型抛出了异常;同时你还需要关注到一点是每个Step的 token 消耗:
[Step 0: Duration 11.32 seconds| Input tokens: 1,993 | Output tokens: 41]
[Step 1: Duration 8.21 seconds| Input tokens: 4,198 | Output tokens: 141]
[Step 2: Duration 6.59 seconds| Input tokens: 6,736 | Output tokens: 203]
[Step 3: Duration 8.56 seconds| Input tokens: 9,528 | Output tokens: 303]
[Step 4: Duration 36.38 seconds| Input tokens: 12,653 | Output tokens: 371]
[Step 5: Duration 0.94 seconds| Input tokens: 15,778 | Output tokens: 439]
[Step 6: Duration 0.94 seconds| Input tokens: 18,903 | Output tokens: 507]
可以看见虽然Agent没能给你有效的结果,但它却实实在在消耗了你总计超过 65,000
个输入token,这样做实在肉疼,因为Agent每次向模型询问都会带上之前的问答记录,对于图像模态的输入而言是无法接受的,土豪的话就不用理会了。
Agent调用本地Ollama模型分析图像
为了能让Agent调用本地Ollama模型保护我们的钱包,我们希望的是Agent在处理图像数据时使用本地模型,将数据处理结果传递给在线模型,以节省token并加强Agent的鲁棒性。
这里我以本地 llama3.2-vision:11b
模型为例,首先安装该模型(需要联网):
$ ollama run llama3.2-vision:11b
然后查看下载后模型的实际名:
$ ollama list
NAME ID SIZE MODIFIED
llama3.2-vision:latest 085a1fdae525 7.9 GB 2 months ago
【注意】:有时候你下载的模型可能不叫 llama3.2-vision:11b
,而是以 latest
为后缀,那么在使用的时候也要用 latest
为后缀的模型。
完成的流程应该如下:
- 定义Agent调用的tool,该工具内部调用本地Ollama模型处理图像;
- 定义Agent与模型并绑定该工具;
- Agent执行命令;
上面步骤的核心就是如何定义这个tool,特别是需要明确函数参数与返回值:
@tool
def ollama_vision_language_model(image_path:str, model_name:str="llama3.2-vision:latest") -> str:""" This tool is use ollama local vision language model to describe local image file.Args:image_path: Local image file path.model_name: Ollama local vision language model name.Returns:str: Model describtion about this image file."""response = ollama.chat(model=model_name,messages=[{'role': 'user','content': 'Describe this image file.','images': [image_path]}])return response.message["content"]
完整代码如下:
import ollama, os
from smolagents import CodeAgent, HfApiModel, tool#---------------------------------------------------------------#
# Step1. 使用os库配置环境变量
os.environ["HF_TOKEN"] = "你的Huggingface Token"#---------------------------------------------------------------#
# Step2. 定义调用本地ollama模型的工具
@tool
def ollama_vision_language_model(image_path:str, model_name:str="llama3.2-vision:latest") -> str:""" This tool is use ollama local vision language model to describe local image file.Args:image_path: Local image file path.model_name: Ollama local vision language model name.Returns:str: Model describtion about this image file."""response = ollama.chat(model=model_name,messages=[{'role': 'user','content': 'Describe this image file.','images': [image_path]}])return response.message["content"]#---------------------------------------------------------------#
# Step3. 定义使用工具的agent
image_file = "./image.jpg"model = HfApiModel()
agent = CodeAgent(tools=[ollama_vision_language_model], model=model
)#---------------------------------------------------------------#
# Step4. Agent调用
agent.run(f"describe local image file {image_file}")
运行结果如下:
$ python Agent.py
从上面的运行结果可以看到,将图像处理部分封装成一个工具后Agent接受到的处理结果就非常简单明了,其消耗的token也仅有 2104
个,这对于资源有限的在线模型而言比较友好。