国内团队接入 OCR API,第一反应通常是比较识别率,然后直接调接口。真正上线后才发现,时间大多耗在接入层:图片能不能稳定传上去、晚高峰链路是否可用、账单用美元还是人民币、发票能不能入账,以及批量任务跑到一半失败后怎么续跑。
OCR 和聊天 API 的差别在于输入是图片或 PDF,请求体更大、超时更常见、重试更容易产生重复费用。本文比较官方直连、自建代理和国内 AI 网关三条路线,重点讲图片上传、限流、故障切换与核验清单。具体服务与计费以站内模型价格及服务商文档为准。
说明:OpenAI、Claude、Gemini、百度智能云、腾讯云、阿里云等名称是其各自权利人的商标;本文仅作技术讨论,与相关厂商无隶属或代理关系。跨境网络、数据出境与支付结算需遵守所在地法律法规及平台服务条款。
一、三条路线先摆清楚
官方直连是直接调用 OCR 厂商或模型厂商的接口。若使用国内云厂商的 OCR,链路和付款本来就在境内,通常最省事;若使用海外视觉模型,则要自行处理跨境网络、美元账单和汇率。直连的优点是文档与功能同步快,出了问题能直接对照厂商说明排查。
自建代理是在合规服务器上部署反向代理或网关,把鉴权、日志、重试和限流收口。控制力强,但服务器、证书、升级和值班都由自己承担。OCR 场景还要额外调整请求体上限和超时,否则大图很容易在代理层被截断。
国内 AI 网关提供 OpenAI 兼容入口,人民币结算,通常带控制台、用量统计和发票。接入成本低,也便于统一多个模型;需要确认服务主体、数据条款、限额规则和故障响应方式。
| 维度 | 官方直连 | 自建代理 | 国内 AI 网关 |
|---|---|---|---|
| 网络与接入 | 国内厂商链路短;海外模型需跨境 | 线路可自选,需自行运维 | 国内入口,通常开箱可用 |
| 图片上传 | 受厂商请求体与格式限制 | 需同步调整代理层限制 | 看网关的请求体与超时配置 |
| 付款与发票 | 国内厂商人民币;海外模型美元 | 取决于账号与服务器主体 | 人民币结算,通常可开发票 |
| 批量与限流 | 受厂商 QPS、并发和配额约束 | 可做队列,但仍受上游限制 | 看网关限额、调度与重试能力 |
| 数据边界 | 需自行评估出境与条款 | 数据位置自行负责 | 需审查服务商条款与资质 |
| 运维成本 | 中,主要是网络与账号 | 高,服务器、证书、监控 | 低,控制台集中管理 |
| 模型覆盖 | 以单一厂商为主 | 可自行扩展 | 通常覆盖多家模型 |
没有一条路线适合所有团队。只用国内云 OCR、付款和发票顺畅,直连最省事;需要固定出口与审计,选自建代理;没有运维人力、又要统一多家视觉模型账单,再评估国内网关。
二、网络与图片上传:先解决 413 和超时
OCR 请求体比文本请求大得多。一张 3 MB 的图片转成 Base64 后会增大约三分之一,变成约 4 MB;如果接口只收 Base64,客户端、反向代理和网关都要放开请求体上限。常见故障往往不是“识别不准”,而是 413、连接重置、超时和半截响应。
几个实践建议:
- 接口支持 URL 或对象存储预签名地址时,优先用 URL 传图,减少请求体。确认链接在识别完成前保持有效,且不需要登录态。
- 按业务可接受的分辨率压缩,但不要压过头。小字、印章、手写和表格线对清晰度很敏感,建议按长边和文件大小双阈值压缩,并保留原图以便复核。
- 按 EXIF 方向旋转后再上传,避免整页横置导致识别顺序错乱。
- 代理层同步调整
client_max_body_size、proxy_read_timeout和proxy_send_timeout,不要只改应用侧超时。 - 多页 PDF 优先使用异步任务接口,而不是把整份文件塞进一次同步请求。
如果由服务商拉取图片 URL,还要确认该地址公网可达、没有 IP 白名单限制,且签名有效期足够覆盖排队时间。
三、付款、合同与发票
国内团队常见的卡点是付款主体。个人卡充值、代付和报销凭证不一致,财务往往无法入账。选方案前先问清楚:合同和谁签、结算币种是什么、能开什么类型的发票、预付款是否有有效期、退款规则如何。
按量计费还要确认账单口径:按图片张数、PDF 页数、请求次数还是 Token 计费;失败请求是否计入;重试是否重复计费;用量能否按项目或 Key 拆分。把这些写进采购对比表,再用同一批图片实测,才能估算真实成本。具体费用以模型价格和合同为准。
四、限流、并发与批量任务
OCR 接口通常同时受 QPS、并发数、单图大小、PDF 页数和账号日配额约束。429 不一定代表服务异常,可能只是瞬时并发过高。批量识别建议按下面的顺序设计:
- 为每张图片或每个 PDF 计算 SHA-256,作为幂等键,先查本地结果表再决定是否提交。
- 按接口限制拆分任务:单图大小、单请求页数、并发上限分别设阈值。
- 并发从低开起,例如先 2–4 路,观察 429 比例和 P95 延迟后再逐步增加。
- 对 429 和瞬时 5xx 做指数退避加随机抖动;401、403 和参数错误不要重试,先修配置。
- 异步任务记录 task_id、提交时间、状态和结果地址,结果文件及时落盘,因为结果链接往往有过期时间。
- 每批结束统计成功数、失败数、计费张数和耗时,失败样本单独进入重跑队列。
- 全量结束后抽样人工复核,并核对入库条数与原文件数量。
五、重试、幂等与故障切换
重试之前先做幂等,否则一次网络抖动可能变成两次费用、两条重复记录。下面的示例用图片哈希标记请求,并对可重试错误做退避:
import base64
import hashlib
import os
import time
from openai import OpenAI
client = OpenAI(
api_key=os.environ["ZSQH_API_KEY"],
base_url=os.environ["ZSQH_BASE_URL"],
timeout=90.0,
max_retries=0,
)
def ocr_image(path, model, attempts=4):
raw = open(path, "rb").read()
key = hashlib.sha256(raw).hexdigest()
data_url = "data:image/jpeg;base64," + base64.b64encode(raw).decode()
for i in range(attempts):
try:
resp = client.chat.completions.create(
model=model,
messages=[{
"role": "user",
"content": [
{"type": "text", "text": "识别图中的全部文字,按原顺序输出。"},
{"type": "image_url", "image_url": {"url": data_url}},
],
}],
)
return key, resp.choices[0].message.content
except Exception as exc:
if i == attempts - 1:
raise
wait = min(2 ** i, 30) + 0.5 * (i + 1)
print(key[:8], type(exc).__name__, "retry in", wait)
time.sleep(wait)
key, text = ocr_image("invoice.jpg", os.environ["VISION_MODEL"])
print(key[:12], len(text))
故障切换有一个容易忽略的边界:不同 OCR 引擎的输出不能直接混用。传统 OCR 返回文字和坐标,视觉大模型返回自然语言或 JSON,字段名、坐标体系和置信度口径都可能不同。切换前应固定一组真实样本,比较字符准确率、字段准确率和结构化输出成功率;解析代码、校验规则和人工复核流程要一起调整,而不是只改一个模型名。
六、上线前的核验清单
- 链路:大图、多页 PDF、晚高峰时段分别压测,记录 413、超时和 5xx 比例。
- 准确率:用 50–100 张真实图片覆盖清晰、模糊、倾斜、手写、表格和多栏版式。
- 用量:响应中的 usage 或张数与后台账单能否对上,重试是否被重复计费。
- 限流:并发上限、429 比例、退避后成功率是否可接受。
- 数据:图片是否含个人信息或商业机密,服务方的保留、日志和删除策略是否说得清。
- 退出:Key 能否轮换,余额能否退款,旧服务和回退路线是否保留。
任何一项说不清,都建议先小流量试跑,不要直接把生产流量切过去。
七、按约束选型
先看网络与付款能否长期稳定,再看是否需要固定出口与审计,最后看模型范围和账单能力。使用国内云 OCR 且流程顺畅,直连即可;使用海外视觉模型、又没有跨境运维人力,可以评估国内网关。需要统一入口、人民币结算和多模型对比,可以在中商起航 AI 网关创建测试 Key,先用小批量图片跑通,再逐步放量;可选模型与计费方式见模型价格。
相关阅读:
常见问题
国内直连海外 OCR 接口稳定吗?
取决于本地出口、时段、目标区域和账号限额,不能一概而论。建议用真实图片和真实并发连续观察几天,记录错误率与 P95 延迟,再与网关方案做对照,不要仅凭一次成功请求下结论。
图片用 Base64 还是 URL 上传?
小图用 Base64 简单直接;大图、多页 PDF 或高并发场景优先用 URL 或对象存储预签名地址,能显著减小请求体。无论哪种方式,都要确认接口的大小限制、格式要求和链接有效期。
OCR 批量识别中断了怎么续跑?
用图片内容哈希做幂等键,按批落盘,失败只补缺失部分。重跑前核对已入库条数与原文件数量,避免重复写入,也避免把半批结果当成完整结果。
切换 OCR 服务后结果格式会变吗?
通常会。不同引擎的字段名、坐标体系、置信度和错误结构都可能不同,结构化输出还需要重新做 schema 校验。迁移时应保留旧结果一段时间,并用固定样本对比新旧输出。
发票和用量能按项目拆分吗?
取决于服务方。签约前确认能否按项目、Key 或模型导出用量,账单口径是否包含失败和重试请求,以及发票内容能否匹配采购要求。
