多模态识图教程¶
使用视觉模型理解图片内容、OCR 文字识别、图表解读
视觉能力概述¶
多模态视觉模型可以同时理解文本和图片内容,支持多种应用场景:
支持的功能: - 图片描述和问答 - OCR 文字提取(截图、照片、扫描件) - 图表和表格解读(自动数据分析) - 图片内物体识别 - 代码截图识别和提取
可用的视觉模型:
| 模型 | 说明 |
|---|---|
| gpt-4o-2024-08-06 | OpenAI 最新视觉模型,支持高质量图片理解 |
| gpt-4-vision-preview | OpenAI GPT-4 视觉预览版 |
| claude-3-5-sonnet-20240620 | Anthropic Claude 视觉模型,OCR 能力强 |
快速开始¶
基本调用示例¶
from openai import OpenAI
client = OpenAI(
api_key="your_api_key",
base_url="https://apinexus.net/v1"
)
response = client.chat.completions.create(
model="gpt-4o-2024-08-06",
messages=[
{
"role": "user",
"content": [
{"type": "text", "text": "请描述这张图片的内容"},
{
"type": "image_url",
"image_url": {"url": "https://example.com/your-image.png"}
}
]
}
]
)
print(response.choices[0].message.content)
请求参数详解¶
消息内容结构 (content)¶
content 数组包含多个内容块,支持混合文本和图片:
"content": [
{"type": "text", "text": "你的问题或指令"},
{"type": "image_url", "image_url": {"url": "图片URL"}}
]
image_url 对象¶
| 参数 | 类型 | 说明 |
|---|---|---|
| url | string | 图片 URL 地址,支持 http/https 链接或 base64 编码的数据 URI |
| detail | string | 可选,图片质量级别:low、high、auto(默认) |
detail 参数说明¶
low:低分辨率,响应更快,适合简单图片high:高分辨率,更详细的分析,消耗更多 tokenauto:自动选择,由模型决定
# 指定高分辨率以获得更详细的分析
{
"type": "image_url",
"image_url": {
"url": "https://example.com/image.png",
"detail": "high"
}
}
错误处理与重试机制¶
在实际使用中,可能会遇到各种错误,其中最常见的是 429 速率限制错误。以下是完整的错误处理和重试逻辑实现。
429 速率限制错误¶
当请求频率超过限制时,API 会返回 429 错误:
import time
import base64
from openai import OpenAI
from openai.error import RateLimitError
client = OpenAI(
api_key="your_api_key",
base_url="https://apinexus.net/v1"
)
def encode_image(image_path):
"""将本地图片转换为 base64 编码"""
with open(image_path, "rb") as f:
return base64.b64encode(f.read()).decode("utf-8")
def describe_image_with_retry(image_source, max_retries=3, initial_delay=1):
"""
带重试机制的图片描述函数
参数:
image_source: 图片路径或 URL
max_retries: 最大重试次数
initial_delay: 初始延迟秒数
"""
for attempt in range(max_retries):
try:
# 判断是本地文件还是 URL
if image_source.startswith("http://") or image_source.startswith("https://"):
image_url = image_source
else:
# 本地文件转换为 base64
base64_image = encode_image(image_source)
image_url = f"data:image/jpeg;base64,{base64_image}"
response = client.chat.completions.create(
model="gpt-4o-2024-08-06",
messages=[
{
"role": "user",
"content": [
{"type": "text", "text": "请详细描述这张图片的内容"},
{"type": "image_url", "image_url": {"url": image_url}}
]
}
]
)
return response.choices[0].message.content
except RateLimitError as e:
# 429 错误:速率限制
if attempt < max_retries - 1:
wait_time = initial_delay * (2 ** attempt) # 指数退避
print(f"速率限制,将在 {wait_time} 秒后重试... (尝试 {attempt + 1}/{max_retries})")
time.sleep(wait_time)
else:
print(f"达到最大重试次数 ({max_retries}),请求失败")
raise Exception(f"图片描述失败: 速率限制") from e
except Exception as e:
print(f"发生错误: {e}")
raise
# 使用示例
try:
result = describe_image_with_retry(
"https://raw.githubusercontent.com/openai/pngs/main/mini-overworld.png"
)
print(result)
except Exception as e:
print(f"最终失败: {e}")
完整的错误处理模板¶
from openai import OpenAI
from openai.error import RateLimitError, APIError, Timeout
client = OpenAI(
api_key="your_api_key",
base_url="https://apinexus.net/v1"
)
def call_vision_with_fallback(image_url, prompt="请描述这张图片"):
"""
使用视觉模型,带完整错误处理
参数:
image_url: 图片 URL
prompt: 要询问的问题
"""
models = [
"gpt-4o-2024-08-06",
"gpt-4-vision-preview",
"claude-3-5-sonnet-20240620"
]
last_error = None
for model in models:
try:
response = client.chat.completions.create(
model=model,
messages=[
{
"role": "user",
"content": [
{"type": "text", "text": prompt},
{"type": "image_url", "image_url": {"url": image_url, "detail": "auto"}}
]
}
],
timeout=30 # 30 秒超时
)
return response.choices[0].message.content
except RateLimitError:
print(f"模型 {model} 速率限制,跳过尝试下一个模型")
last_error = "429 Rate Limit"
continue
except Timeout:
print(f"模型 {model} 请求超时,跳过尝试下一个模型")
last_error = "Timeout"
continue
except APIError as e:
print(f"模型 {model} API 错误: {e}")
last_error = str(e)
continue
raise Exception(f"所有模型均失败,最后错误: {last_error}")
# 调用示例
result = call_vision_with_fallback(
image_url="https://raw.githubusercontent.com/openai/pngs/main/mini-overworld.png",
prompt="这张图片展示了什么?请详细描述"
)
print(result)
使用场景¶
场景一:OCR 文字识别¶
从截图中提取文字内容:
response = client.chat.completions.create(
model="gpt-4o-2024-08-06",
messages=[
{
"role": "user",
"content": [
{
"type": "text",
"text": "请提取图片中所有的文字内容,保持原有格式"
},
{"type": "image_url", "image_url": {"url": "你的截图URL"}}
]
}
]
)
print(response.choices[0].message.content)
场景二:表格识别与转换¶
将图片中的表格转换为 Markdown 格式:
response = client.chat.completions.create(
model="gpt-4o-2024-08-06",
messages=[
{
"role": "user",
"content": [
{
"type": "text",
"text": "提取图片中的表格数据,转换为 Markdown 表格格式输出"
},
{"type": "image_url", "image_url": {"url": "表格图片URL"}}
]
}
]
)
场景三:图表数据分析¶
分析柱状图、折线图等图表并提取数据:
response = client.chat.completions.create(
model="gpt-4o-2024-08-06",
messages=[
{
"role": "user",
"content": [
{
"type": "text",
"text": """请分析这张图表:
1. 识别图表类型和主题
2. 提取所有数据点,整理成表格
3. 计算关键指标(最大值、最小值、增长率等)
4. 给出业务洞察"""
},
{"type": "image_url", "image_url": {"url": "图表URL"}}
]
}
]
)
场景四:代码截图识别¶
从截图中提取代码并保持格式:
response = client.chat.completions.create(
model="gpt-4o-2024-08-06",
messages=[
{
"role": "user",
"content": [
{
"type": "text",
"text": "这是一张代码截图,请提取其中的代码,用 ``` 包裹保持格式"
},
{"type": "image_url", "image_url": {"url": "代码截图URL"}}
]
}
]
)
场景五:多图对比分析¶
一次请求分析多张图片:
response = client.chat.completions.create(
model="gpt-4o-2024-08-06",
messages=[
{
"role": "user",
"content": [
{
"type": "text",
"text": "对比这两张图片的异同"
},
{"type": "image_url", "image_url": {"url": "图片1URL"}},
{"type": "image_url", "image_url": {"url": "图片2URL"}}
]
}
]
)
最佳实践¶
1. 图片格式和大小¶
| 格式 | 推荐程度 | 说明 |
|---|---|---|
| JPEG | 高 | 体积小,加载快 |
| PNG | 高 | 无损压缩,适合截图 |
| WEBP | 中 | 体积最小,部分模型支持有限 |
建议:单张图片控制在 5MB 以内,分辨率 1024x1024 左右性价比最高。
2. 提高识别准确率¶
推荐的做法: - 图片清晰,文字可辨读 - 保持图片水平,避免严重倾斜 - 光线充足,无明显反光或阴影 - 表格图片确保边框完整
避免的做法: - 模糊、失焦的图片 - 严重水印遮挡文字 - 旋转 90 度或倒置的图片
3. 使用 detail 参数优化¶
# 简单图片,使用 low 加快响应
{"type": "image_url", "image_url": {"url": url, "detail": "low"}}
# 复杂图表或小文字,使用 high 获得更多细节
{"type": "image_url", "image_url": {"url": url, "detail": "high"}}
常见问题 FAQ¶
Q: 遇到 429 速率限制错误怎么办?¶
A: 429 错误表示请求频率超过限制。处理方法:
- 等待后重试:使用指数退避策略,等待时间逐渐增加
- 减少请求频率:在循环中调用时添加延时
- 切换模型:不同模型的限制独立,可以尝试其他视觉模型
- 错峰使用:避开高峰期请求
Q: 图片上传有限制吗?¶
A: 单张图片建议不超过 5MB,视频帧或高分辨率图片建议提前压缩。
Q: 支持本地文件上传吗?¶
A: 支持。将本地图片转换为 base64 编码后,以 data URI 格式传递:
import base64
with open("image.jpg", "rb") as f:
image_data = base64.b64encode(f.read()).decode("utf-8")
image_url = f"data:image/jpeg;base64,{image_data}"
Q: 可以同时分析多张图片吗?¶
A: 可以。在 content 数组中添加多个 image_url 对象即可,模型会对比分析多张图片的异同。
Q: OCR 识别准确率如何?¶
A: 对于清晰的印刷文字,准确率很高。对于手写体,工整的识别率高,潦草的准确率会下降。建议使用清晰的图片以获得最佳效果。
Q: 如何提高 OCR 准确率?¶
A: 1. 确保图片清晰、光线充足 2. 尽量使用印刷体而非手写体 3. 图片保持正向,不要旋转 4. 表格图片确保边框完整清晰
测试记录¶
测试图片: https://raw.githubusercontent.com/openai/pngs/main/mini-overworld.png
测试说明:在测试过程中,该图片 URL 曾返回 429 速率限制错误。这说明即使是公开的图片 URL,在高并发情况下也可能触发限制。实际使用中建议: - 实现重试机制应对临时限制 - 对于重要请求,考虑将图片下载到本地或使用自己的存储
本文档为 API Nexus 使用指南,基于实际测试编写。