跳转至

多模态识图教程

使用视觉模型理解图片内容、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 可选,图片质量级别:lowhighauto(默认)

detail 参数说明

  • low:低分辨率,响应更快,适合简单图片
  • high:高分辨率,更详细的分析,消耗更多 token
  • auto:自动选择,由模型决定
# 指定高分辨率以获得更详细的分析
{
    "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 错误表示请求频率超过限制。处理方法:

  1. 等待后重试:使用指数退避策略,等待时间逐渐增加
  2. 减少请求频率:在循环中调用时添加延时
  3. 切换模型:不同模型的限制独立,可以尝试其他视觉模型
  4. 错峰使用:避开高峰期请求
# 指数退避示例
wait_time = 1 * (2 ** attempt)  # 1秒, 2秒, 4秒...
time.sleep(wait_time)

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 使用指南,基于实际测试编写。