Embedding API 调用成本:主流厂商定价与省钱策略
你大概率是在算完对话 API 的账单之后,才第一次正眼看 Embedding 的账单——毕竟一次问答几毛钱,肉眼可见;但把十万篇文档喂进向量库、每次用户提问都要再向量化一遍查询语句,这笔钱是悄悄堆起来的,月底一看总额度才发现 Embedding 调用次数比对话调用高一个数量级。这篇就是把这笔”隐形账”摊开来算清楚,顺便把踩过的坑标出来。
声明:以下价格描述均为截至 2026-06 的定性比较,仅供参考,以各厂商官方定价页面为准。
Embedding API 的计费逻辑
Embedding 调用的计费与对话 API 有一个重要区别:只有输入 token,没有输出 token(输出是一个固定维度的向量,不按 token 计费)。
| 计费项 | 说明 |
|---|---|
| 输入 token | 待向量化的文本内容 |
| 输出(向量) | 固定维度,不额外计费 |
| 请求次数 | 少数厂商按请求数收费,多数不单独计 |
因此,Embedding 的成本计算相对简单:文本总 token 数 × 单价。
但这句话里藏着一个很多人第一次接手 RAG 项目都会踩的坑:中文文本的 token 数不能拍脑袋估。英文按空格分词,一个单词大致对应 1 个 token,估算误差不大;中文分词器(不管是 OpenAI 的 tiktoken 还是国产厂商自己的分词器)对汉字的切分粒度不统一,同一段 500 字的中文,不同厂商算出来的 token 数可能相差 20%~30%。如果你是按”字数 × 经验系数”去预估预算,建议先用目标厂商的官方 tokenizer(大多数厂商控制台或 SDK 里都带)跑一遍真实语料,再定系数,不要直接照抄别人文章里的中文系数——那个系数是针对他的语料分布算出来的,未必适配你的文档结构(比如你的知识库里代码块、表格、标点符号占比高,token 密度会明显不同)。
主流厂商 Embedding 定价对比
以下为定性分层,具体数字以各官方文档为准。
| 厂商 | 代表模型 | 价格定性 | 向量维度 |
|---|---|---|---|
| OpenAI | text-embedding-3-small | 低(海外中最低) | 1536(可压缩) |
| OpenAI | text-embedding-3-large | 中 | 3072 |
| Cohere | embed-v3 | 中 | 1024 |
| 阿里云 | text-embedding-v3 | 低(国内主流) | 1024/1536 |
| 百度 | Embedding-V1 | 低到中 | 384 |
| 智谱 | Embedding-3 | 低 | 2048 |
| DeepSeek | (暂无独立 Embedding) | — | — |
关键结论:Embedding 在所有 AI API 调用中单价最低,但体量大时总成本不可忽视。
这张对比表背后还有个值得说清楚的原因:为什么 Embedding 单价能压得这么低?对话模型每次推理要生成不定长的输出,中间要维护完整的注意力上下文,算力开销随生成长度线性增长;而 Embedding 是一次前向传播就出结果,模型规模通常也比对话大模型小得多(几百 M 到几 B 参数级别,远小于旗舰对话模型),单次推理的算力成本天然就低。国产厂商价格更低,一部分是模型本身更精简,另一部分是把 Embedding 当作获客钩子——先用低价甚至免费额度把你的向量库和索引沉淀在自己的生态里,后续检索、重排、Agent 编排的调用才是真正的利润点。理解这一层逻辑,你在选型时就不会只盯着单价,还要看这家厂商的 Embedding 生态是否配套(比如向量库、重排模型是否在同一个体系里,联调成本能不能省下来)。
OpenAI text-embedding-3 系列能做维度压缩,底层用的是 Matryoshka Representation Learning(套娃式表征学习):训练时就让向量的前 N 维尽量保留主要语义信息,截断后半部分维度也能用,只是精度略降。这也是为什么”降维”不是简单的 PCA 降维或者随手截断——如果你用的是不支持这种训练方式的旧模型(比如 text-embedding-ada-002)或者国产某些模型,直接截断维度会导致语义信息被破坏,检索效果断崖式下跌。降维前一定确认模型文档里明确写了支持 dimensions 参数,而不是自己去截。
Embedding 成本的量级感知
以一个典型的 RAG 知识库构建场景为例:
| 参数 | 假设值 |
|---|---|
| 知识库文档 | 10,000 篇 |
| 平均每篇 token | 500 |
| 总输入 token | 5,000,000(500 万) |
按海外最低档(text-embedding-3-small)的定价量级,500 万 token 的成本大约在几美元到十几美元之间。国内厂商则通常更低。
结论:初次构建知识库成本可控,但实时更新场景(频繁增删文档)或高并发查询时实时重算才是成本黑洞。
自己动手估一遍比看任何文章里的数字都靠谱,花不了五分钟:
import tiktoken
enc = tiktoken.get_encoding("cl100k_base") # 部分厂商可替换为对应分词器
docs = load_your_documents() # 你自己的文档加载逻辑
total_tokens = sum(len(enc.encode(doc)) for doc in docs)
price_per_1k = 0.00002 # 换成目标厂商官网当前单价,别抄文章里的旧数字
print(f"总 token 数: {total_tokens}")
print(f"预估成本: ${total_tokens / 1000 * price_per_1k:.4f}")
跑完你应该能看到一个具体的美元或人民币数字——如果这个数字比你想象中高一个数量级,大概率是文档里混了大段代码、日志或重复模板内容,先做去重和清洗再入库,能省下的钱往往比你后续做任何”选便宜模型”的优化都多。
真实踩过的一个坑:批量调用时如果单次传入的文本条数超过厂商限制(比如 OpenAI 的 2048 条上限),接口会直接返回 400 错误,报错信息类似 Invalid input: array too long。第一次遇到很容易误以为是 token 超限,去折腾单条文本长度,结果排查半天发现是数组条数超了。解决办法很简单:批量提交前先按厂商的条数上限做分片(chunk),每片单独发请求,用 for i in range(0, len(texts), 2048) 这种滑窗分片即可,不要指望 SDK 会自动帮你切。
节省 Embedding 成本的核心策略
1. 向量缓存(最重要)
相同文本不要重复调用 Embedding API,本地缓存结果:
- 使用 SQLite / Redis / 向量数据库存储 <文本哈希, 向量> 映射
- 命中缓存直接返回,不调用 API
- 对于固定知识库,构建一次后只在更新时重新调用
缓存的关键是用文本内容的哈希做 key,而不是文档 ID。很多人第一版实现图省事,直接拿文档 ID 当缓存 key,结果文档内容改了一个标点,缓存没失效,检索出来的还是旧向量——这个 bug 排查起来很折磨人,因为向量本身看不出”新旧”,只有检索结果隐约不对劲。正确做法是对文本内容做 hashlib.sha256(text.encode()).hexdigest(),内容变了哈希自然变,缓存自动失效,不用你手动管理版本号:
import hashlib
def get_cache_key(text: str) -> str:
return hashlib.sha256(text.encode("utf-8")).hexdigest()
def get_or_embed(text: str, cache, embed_fn):
key = get_cache_key(text)
if key in cache:
return cache[key]
vector = embed_fn(text)
cache[key] = vector
return vector
命中率是这套机制的核心指标,值得单独打点记录:如果你的知识库是”高频重复问答”场景(比如客服 FAQ),缓存命中率做到 60% 以上很常见,等于直接省掉六成 Embedding 调用;如果是”每次内容都不一样”的场景(比如实时抓取的新闻摘要),命中率天然就低,这时候优化重点应该转向下面的批量提交和本地部署,而不是死磕缓存策略。
2. 批量提交
大多数 Embedding API 支持一次请求传入多段文本(batch input):
- 减少请求次数,降低网络延迟
- 部分厂商对批量请求有额外优化
- OpenAI text-embedding 支持一次最多 2048 个文本段
批量提交还有一个绕不开的问题:请求量上来之后大概率会撞到限速(rate limit),报错通常是 HTTP 429,Rate limit reached for requests。裸调用遇到 429 直接抛异常会让整个入库脚本中途崩掉,正确做法是加指数退避重试:
import time
def embed_with_retry(text, embed_fn, max_retries=5):
for attempt in range(max_retries):
try:
return embed_fn(text)
except RateLimitError:
wait = 2 ** attempt # 1s, 2s, 4s, 8s, 16s
time.sleep(wait)
raise RuntimeError("重试次数耗尽,检查是否需要申请更高并发额度")
如果你的知识库构建是一次性批量任务(比如夜间跑批),比起同步一条条发请求,用 asyncio + 信号量控制并发数会快很多,同时又不会因为并发过高触发限速:
import asyncio
sem = asyncio.Semaphore(10) # 按厂商实际并发上限调整
async def embed_one(text, embed_fn):
async with sem:
return await embed_fn(text)
async def embed_all(texts, embed_fn):
return await asyncio.gather(*[embed_one(t, embed_fn) for t in texts])
并发数不是越大越好——超过厂商单账号的并发上限,一样会被限速甚至触发风控,具体数值以你账号控制台里显示的配额为准,不同套餐、不同实名等级的并发上限差异很大。
3. 选对维度(OpenAI 特有)
OpenAI text-embedding-3 系列支持维度压缩(dimensions 参数),可以在牺牲少量精度的前提下降低存储成本和计算成本。对于对精度要求不极致的场景,1024 维往往足够。
4. 选本地 Embedding 模型
对于对延迟、成本敏感的场景,开源 Embedding 模型(如 bge-m3、nomic-embed-text)可本地部署,API 调用费用为零,只需算力成本:
| 方案 | 优点 | 缺点 |
|---|---|---|
| API Embedding | 零维护、开箱即用 | 有调用成本、延迟依赖网络 |
| 本地 Embedding | 零 API 成本、低延迟 | 需要 GPU/CPU 资源,维护成本 |
小规模项目 API 更省心;大规模生产环境值得评估本地部署。
RAG 场景的 Embedding 成本规划
RAG 系统的 Embedding 成本分两部分:
| 阶段 | 触发时机 | 优化方向 |
|---|---|---|
| 索引构建 | 文档入库时 | 批量处理,缓存已有向量 |
| 查询向量化 | 每次用户查询时 | 低维模型,本地小模型 |
查询向量化是高频操作,建议选小维度、低价格的 Embedding 模型,或者本地部署轻量 Embedding 模型处理查询,只用 API 处理文档入库。
更多成本优化技巧见:大模型 API 成本优化 10 招
常见问题
Embedding API 和对话 API 共用同一个 token 配额吗?
通常分开计费,使用不同的价格区间和配额池。具体以各厂商控制台显示为准。
Embedding 的质量怎么评估?
通常用检索召回率(Recall@K)衡量。对于中文场景,建议实测对比 OpenAI 和国产 Embedding 模型,不要只看参数维度。中文 Embedding 模型(如 bge-m3)在中文检索任务上往往优于 OpenAI 模型。
换 Embedding 模型需要重建向量库吗?
是的。不同模型的向量空间不兼容,切换模型必须对所有文档重新 Embedding 并重建索引。这是一次性成本,提前选好模型可以避免重建。
延伸阅读:
- 计费原理全解:大模型 token 计费完全指南
- 成本优化技巧:大模型 API 成本优化 10 招
- 国产价格对比:国产大模型价格横向对比
- 实时价格查询:价格对比表工具
- 成本话题 Hub:token 成本专题