2026年6月15日 3 分钟阅读

Viscribe 实战:为 AI Agent 添加结构化的图像理解能力

tinyash 0 条评论

场景:AI Agent 与文档的视觉鸿沟

你的 AI Agent 收到了一个截图——一张发票、一页产品目录、一个 UI 原型。它需要从中提取关键信息:发票金额、产品名称、界面按钮状态。但在传统工作流中,Agent 只能把整张图传给 LLM,然后得到一段自由文本描述——「这张发票上有一个金额,看起来是 $123.45」。你不能确定格式、不能直接绑定到数据库字段、更无法批量处理。

这就是 AI Agent 面对图像时的「视觉鸿沟」:LLM 的输出是人类可读的自由文本,而不是机器可解析的结构化数据。

Viscribe 正是为了解决这个问题而生——它是一个轻量级的 Python/TypeScript 库,让你「定义好输出 Schema,传入图片,选好模型,然后直接拿到结构化的解析结果」。

传统方案 vs Viscribe

场景传统做法问题Viscribe
解析发票截图将图片传给 GPT-5 Vision,人工提取字段输出格式不稳定,需重复处理定义 Receipt Schema,直接返回结构化对象
批量处理产品图逐个截图→描述→人工录入手动工作量大,易出错定义 Schema + 循环调用 extract,自动入库
视觉检测(截图验证)人工比对无法自动化定义 status/issues 字段,Agent 自动判断
Agent 工具链集成自行封装 Vision API + 输出解析重复造轮子pip install viscribe,一行调用

快速上手

安装非常简洁:

pip install viscribe

或者 TypeScript 环境:

npm install viscribe

核心 API 只有一个——extract。你只需提供三样东西:图片路径、输出 Schema、指令。

来看一个最典型的场景——发票解析。假设你的 AI Agent 收到一张收据截图,想把它存入财务系统:

from pydantic import BaseModel, Field
from viscribe.images import extract

class Receipt(BaseModel):
    merchant_name: str | None = Field(description="商户名称")
    total_amount: float | None = Field(description="发票总金额")
    date: str | None = Field(description="发票日期")
    line_items: list[str] = Field(description="购买项目清单")

result = extract(
    image_path="receipt.png",
    output_schema=Receipt,
    instruction="从图片中提取收据信息。",
    model_config={
        "model": "gpt-5-mini",
        "api_key": "sk-...",
        "temperature": 1,
    },
)

print(result.data.model_dump())

TypeScript 版本同样简洁:

import { images } from "viscribe";

const result = await images.extract({
  imagePath: "receipt.png",
  outputSchema: [
    { name: "merchant_name", type: "text", description: "商户名称" },
    { name: "total_amount", type: "number", description: "发票总金额" },
    { name: "date", type: "text", description: "发票日期" },
    { name: "line_items", type: "array_text", description: "购买项目清单" },
  ],
  instruction: "从图片中提取收据信息。",
});

console.log(result.data);

核心功能拆解

1. Schema 驱动——Schema 即契约

Viscribe 最核心的设计理念是 Schema 即契约。你定义好输出结构,Viscribe 负责让 LLM 严格按这个结构返回数据。支持三种 Schema 格式:

  • Pydantic Model(Python 推荐):类型安全、IDE 自动补全
  • JSON Schema(跨语言通用):标准的 JSON Schema 字典
  • 简单字段定义(TypeScript 友好):{name, type, description} 数组
result = extract(
    image_path="product.jpg",
    output_schema={
        "type": "object",
        "properties": {
            "name": {"type": "string", "description": "产品名称"},
            "price": {"type": "number", "description": "产品价格"},
        },
    },
    instruction="提取产品信息。",
)

2. 多场景万能 API

同一套 extract API,改变 Schema 和指令即可处理完全不同类型的任务:

result = extract(
    image_path="screenshot.png",
    output_schema=[
        {"name": "status", "type": "text", "description": "检测状态: pass/fail/review"},
        {"name": "issues", "type": "array_text", "description": "发现的 UI 问题"},
    ],
    instruction="检查这个 UI 截图,判断是否有布局或文字问题。",
)
result = extract(
    image_path="photo.jpg",
    output_schema=[
        {"name": "category", "type": "text", "description": "图片类别"},
        {"name": "confidence", "type": "number", "description": "置信度 0-1"},
    ],
    instruction="判断这个图片属于哪个类别(风景/人像/产品/文档)。",
)

3. 异步支持

在高吞吐场景下,使用 aextract 并发处理多张图片:

import asyncio
from viscribe.images import aextract

async def process_batch():
    tasks = []
    for img in ["receipt1.png", "receipt2.png", "receipt3.png"]:
        task = aextract(
            image_path=img,
            output_schema=Receipt,
            instruction="提取收据信息。",
        )
        tasks.append(task)

    results = await asyncio.gather(*tasks)
    return [r.data for r in results]

data = asyncio.run(process_batch())
for item in data:
    print(item.model_dump())

4. 可复用客户端

如果多次使用相同的模型配置,可以创建客户端实例复用:

from viscribe import ViscribeAI

client = ViscribeAI(model_config={
    "model": "gpt-5-mini",
    "temperature": 1,
})

result1 = client.images.extract(image_path="receipt.png", output_schema=Receipt)
result2 = client.images.extract(image_path="product.png", output_schema=Product)
result3 = client.images.extract(image_path="ui_screenshot.png", output_schema=UIStatus)

实战场景:用 Viscribe 构建自动化流程

场景一:发票自动录入

将收到的发票截图批量转为财务数据:

import os
from viscribe.images import extract

for filename in os.listdir("invoices/"):
    if filename.endswith(".png"):
        result = extract(
            image_path=f"invoices/{filename}",
            output_schema=Receipt,
            instruction="提取发票信息。",
        )
        # 直接入库
        db.insert(result.data.model_dump())

场景二:Agent 截图理解

让 Agent 在操作网页后自动验证结果:

result = extract(
    image_path="after_operation.png",
    output_schema=[
        {"name": "action_verified", "type": "text", "description": "操作是否成功: yes/no"},
        {"name": "error_message", "type": "text", "description": "如果有错误信息"},
        {"name": "visible_changes", "type": "array_text", "description": "可见的变化"},
    ],
    instruction="验证操作是否成功。",
)

if result.data["action_verified"] == "no":
    print(f"操作失败: {result.data['error_message']}")

场景三:产品目录自动化

电商 Agent 批量理解产品图片,生成结构化目录:

class Product(BaseModel):
    name: str = Field(description="产品名称")
    brand: str | None = Field(description="品牌")
    category: str = Field(description="产品类别")
    attributes: list[str] = Field(description="产品属性标签")

result = extract(
    image_path="product_photo.jpg",
    output_schema=Product,
    instruction="分析产品图片,提取产品信息。",
)

注意事项

  • API Key 管理:建议从环境变量加载,不要硬编码在代码中
  • 模型选择:支持任何 OpenAI 兼容的视觉模型(GPT-5 Mini、Claude 3.5 Vision 等)
  • 图片格式:支持本地文件路径、Base64 编码、远程 URL
  • 自动重试:底层通过模型客户端自动处理临时失败
  • 当前版本:Viscribe 目前是早期项目(9 个 GitHub Stars),功能简洁但 API 设计扎实。对于生产环境的大规模使用,建议对比成熟方案

总结

Viscribe 解决了一个非常具体但又普遍的问题——让 AI Agent 从图像中提取结构化数据。它的核心理念是将「定义 Schema → 传入图片 → 拿到结构化结果」这条链路做到极致,不需要手动处理 LLM 的自由文本输出,也不需要自己封装复杂的 multi-step 解析逻辑。

对于开发 AI Agent 的团队来说,如果你正面临「Agent 能看图,但看不懂结构化数据」的尴尬,Viscribe 值得一试。

  • 项目地址:https://github.com/itsperini/viscribe
  • 文档:https://docs.viscribe.ai
  • 许可协议:MIT

发表评论

你的邮箱地址不会被公开,带 * 的为必填项。