Embedding API 怎么调用?2026 三种方案实测,附 RAG 完整代码

Embedding API 怎么调用?2026 三种方案实测,附 RAG 完整代码 上周接了个私活甲方要做企业知识库问答系统。核心技术栈是 RAG第一步就是把文档切片后做 Embedding 向量化。听起来不复杂但我在调 Embedding API 这一步折腾了快两天——OpenAI 的text-embedding-3-large延迟飘忽不定某些开源模型效果又拉胯中间还踩了个维度对齐的大坑。直接说结论调用 Embedding API 的核心就是选对模型、配好接口、处理好分批请求。2026 年主流方案有三种——OpenAI 官方接口、开源模型本地部署、通过聚合 API 平台一个 Key 切换多家 Embedding 模型。对中小项目来说第三种性价比最高改一行base_url就能跑。先说结论我实测了三种方案按「部署成本 × 效果 × 延迟」综合排序方案模型维度中文效果平均延迟月成本10万次/月推荐场景聚合 APItext-embedding-3-large3072★★★★★~350ms≈¥95生产环境首选OpenAI 官方text-embedding-3-large3072★★★★★200ms~2s$13≈¥95网络稳定时本地部署bge-large-zh-v1.51024★★★★~80ms显卡电费数据敏感/离线场景最终我生产环境选了聚合 API开发调试用本地 bge 模型下面展开讲。环境准备# Python 3.10pipinstallopenai numpy tiktoken# 如果要本地部署 bge 模型pipinstallsentence-transformers torch测试环境MacBook Pro M3 Python 3.12服务器是 2C4G 的轻量云主机。方案一OpenAI text-embedding-3-large效果最好的通用 Embedding 模型2026 年在 RAG 场景依然是标杆。fromopenaiimportOpenAIimportnumpyasnp clientOpenAI(api_keyyour-api-key,base_urlhttps://api.ofox.ai/v1# 聚合接口低延迟直连)defget_embeddings(texts:list[str],modeltext-embedding-3-large)-list[list[float]]:批量获取文本向量单次最多 2048 条responseclient.embeddings.create(inputtexts,modelmodel)return[item.embeddingforiteminresponse.data]defcosine_similarity(a,b):计算余弦相似度a,bnp.array(a),np.array(b)returnnp.dot(a,b)/(np.linalg.norm(a)*np.linalg.norm(b))# 测试中文语义相似度texts[如何部署 Kubernetes 集群,K8s 集群搭建教程,今天天气真不错,]embeddingsget_embeddings(texts)print(f语义相近:{cosine_similarity(embeddings[0],embeddings[1]):.4f})# 预期 0.85print(f语义无关:{cosine_similarity(embeddings[0],embeddings[2]):.4f})# 预期 0.3实测输出语义相近: 0.8917 语义无关: 0.1243效果没话说。这里用的是 ofox.ai 的聚合接口ofox.ai 是一个 AI 模型聚合平台一个 API Key 可以调用 GPT-5、Claude Opus 4.6、Gemini 3 等 50 模型包括各家的 Embedding 模型低延迟直连无需代理支持支付宝付款。对我来说最大的好处是不用分别管理 OpenAI、Google、百度各家的 Key。方案二本地部署 bge-large-zh-v1.5数据敏感不能外传或者调用量大想省钱本地部署是正解。BAAI 的 bge 系列在中文场景下效果很能打。fromsentence_transformersimportSentenceTransformerimportnumpyasnp# 首次运行会自动下载模型约 1.3GBmodelSentenceTransformer(BAAI/bge-large-zh-v1.5)defget_local_embeddings(texts:list[str])-np.ndarray:本地模型生成向量# bge 模型推荐加 instruction prefixprefixed[f为这个句子生成表示以用于检索相关文章{t}fortintexts]returnmodel.encode(prefixed,normalize_embeddingsTrue)texts[如何部署 Kubernetes 集群,K8s 集群搭建教程,今天天气真不错,]embeddingsget_local_embeddings(texts)sim_relatednp.dot(embeddings[0],embeddings[1])sim_unrelatednp.dot(embeddings[0],embeddings[2])print(f语义相近:{sim_related:.4f})# 实测 0.8641print(f语义无关:{sim_unrelated:.4f})# 实测 0.1087比 OpenAI 的差一点点但胜在免费且零延迟。有个坑要注意——bge 输出 1024 维OpenAI 是 3072 维两个模型的向量不能混进同一个向量数据库维度不对齐检索直接报错。方案三完整 RAG Pipeline前两个方案只是调 API实际项目里需要一个完整的流程。我把私活的核心代码精简了一下原始文档文本切片Embedding API向量数据库用户提问Query Embedding相似度检索 Top-K拼接 PromptLLM 生成回答完整代码fromopenaiimportOpenAIimportnumpyasnpimportjson clientOpenAI(api_keyyour-key,base_urlhttps://api.ofox.ai/v1)# Step 1: 文本切片 defchunk_text(text:str,chunk_size500,overlap50)-list[str]:滑动窗口切片overlap 防止语义断裂chunks[]start0whilestartlen(text):endstartchunk_size chunks.append(text[start:end])startend-overlapreturnchunks# Step 2: 批量 Embedding defbatch_embed(texts:list[str],batch_size100)-list[list[float]]:分批请求防止单次请求过大被限流all_embeddings[]foriinrange(0,len(texts),batch_size):batchtexts[i:ibatch_size]respclient.embeddings.create(inputbatch,modeltext-embedding-3-large)all_embeddings.extend([item.embeddingforiteminresp.data])print(f已处理{min(ibatch_size,len(texts))}/{len(texts)})returnall_embeddings# Step 3: 简易向量检索生产用 Milvus/Qdrant classSimpleVectorStore:def__init__(self):self.texts[]self.vectors[]defadd(self,texts:list[str],vectors:list[list[float]]):self.texts.extend(texts)self.vectors.extend(vectors)defsearch(self,query_vector:list[float],top_k3)-list[str]:querynp.array(query_vector)scores[]fori,vecinenumerate(self.vectors):simnp.dot(query,np.array(vec))/(np.linalg.norm(query)*np.linalg.norm(np.array(vec)))scores.append((sim,i))scores.sort(reverseTrue)return[self.texts[idx]for_,idxinscores[:top_k]]# Step 4: RAG 问答 defrag_answer(question:str,store:SimpleVectorStore)-str:# 问题向量化q_respclient.embeddings.create(input[question],modeltext-embedding-3-large)q_vecq_resp.data[0].embedding# 检索相关片段relevant_chunksstore.search(q_vec,top_k3)context\n---\n.join(relevant_chunks)# 让 LLM 基于上下文回答completionclient.chat.completions.create(modelgpt-5,messages[{role:system,content:基于以下参考资料回答用户问题。如果资料中没有相关信息请说明。},{role:user,content:f参考资料:\n{context}\n\n问题:{question}}])returncompletion.choices[0].message.content# 使用示例 if__name____main__:# 模拟文档doc Kubernetes简称 K8s是一个开源的容器编排平台。它可以自动化部署、扩展和管理容器化应用程序。 K8s 的核心组件包括 API Server、etcd、Scheduler、Controller Manager。 Pod 是 K8s 最小的部署单元一个 Pod 可以包含一个或多个容器。 Service 用于暴露 Pod 的网络服务支持 ClusterIP、NodePort、LoadBalancer 三种类型。 Deployment 用于管理 Pod 的副本数量支持滚动更新和回滚。 # 切片 向量化chunkschunk_text(doc,chunk_size200,overlap30)vectorsbatch_embed(chunks)# 存入向量库storeSimpleVectorStore()store.add(chunks,vectors)# 提问answerrag_answer(K8s 的 Service 有哪几种类型,store)print(answer)这段代码可以直接跑。生产环境里SimpleVectorStore要换成 Milvus、Qdrant 或 Weaviate我那个私活最后用的 QdrantDocker 一行命令就起了。踩坑记录坑 1Embedding 维度不一致导致检索炸了开发时用 bge 模型1024维上线换 OpenAI3072维忘了重新跑向量入库检索接口直接报维度不匹配。换模型就得重跑全量数据这个别忘了。坑 2单次请求塞太多文本被 429OpenAI Embedding API 单次最多传 2048 条文本但如果每条文本都很长总 token 数超了也会报错。解决方案就是上面的batch_embed每次 100 条很稳。坑 3中文切片不能按固定字符数硬切一开始chunk_size500按字符切把「容器编排」切成了「容器编」和「排平台」语义断裂检索召回率直接暴跌。后来改成按句号分割再合并到目标长度好多了importredefsmart_chunk(text:str,max_size500)-list[str]:按句子边界切片sentencesre.split(r(?[。\n]),text)chunks,current[],forsinsentences:iflen(current)len(s)max_sizeandcurrent:chunks.append(current.strip())currentselse:currentsifcurrent.strip():chunks.append(current.strip())returnchunks坑 4没做 normalize 导致相似度计算异常bge 模型的encode方法默认不归一化余弦相似度算出来会偏大。加上normalize_embeddingsTrue就正常了。OpenAI 的 API 返回值默认已经归一化不用管。小结Embedding 就三件事选模型、切文本、管向量。2026 年的选法效果优先选text-embedding-3-large中英文通吃数据敏感选bge-large-zh-v1.5本地部署怕折腾直接用聚合 API一个 Key 搞定 Embedding Chat代码都贴完整了复制就能跑。做 RAG 项目的话切片策略对最终效果的影响比模型选择大得多这个坑我替你踩过了。有问题评论区聊。