Viscribe 实战:为 AI Agent 添加结构化的图像理解能力
场景: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