Embedding API使用指南:文本向量化与语义搜索

传统搜索靠关键词匹配:搜“苹果手机”找不到只写了“iPhone”的文档。而语义搜索能理解“苹果手机”和“iPhone”是同一个意思,因为它们在语义空间里距离很近。实现这种“理解”的核心技术就是 Embedding(向量嵌入)

Embedding 是 RAG、语义搜索、推荐系统、聚类分析的共同地基。本文从原理到代码,讲清楚 Embedding 是什么、怎么调用 API、如何计算相似度、如何搭建一个可用的语义搜索引擎。

一、Embedding 到底是什么

Embedding 就是把一段文本映射成一个固定长度的浮点数向量(比如 1536 维)。这个映射不是随机的,而是经过训练的:语义相近的文本,向量距离也近;语义无关的文本,向量距离远。

可以把它理解成给每段文本在“语义空间”里标了一个坐标。两段文本的语义相似度,就转化为两个向量在空间里的距离。这样,“找语义相近的内容”就变成了“找距离近的向量”——一个可以用数学快速解决的问题。

Embedding 模型经过海量语料训练,能捕捉同义词、上下位关系、甚至跨语言语义。比如“猫”和“cat”的向量会很接近,尽管字面完全不同。

二、调用 Embedding API

调用 Embedding API 和调用聊天接口一样简单,只是端点不同。下面用 OpenAI SDK 通过 EnlyAI 统一接入获取向量。

from openai import OpenAI

client = OpenAI(api_key="sk-your-enlyai-key", base_url="https://enlyai.com/v1")

# 单条文本向量化
resp = client.embeddings.create(
    model="text-embedding-3-small",
    input="大模型让搜索变得更智能"
)
vector = resp.data[0].embedding
print(f"向量维度:{len(vector)}")
print(f"前5维:{vector[:5]}")

提示:通过 EnlyAI 统一接入,一个 key 即可调用 text-embedding-3-small、text-embedding-3-large 等各类 Embedding 模型,无需在多个平台分别注册,调用方式与 OpenAI 完全一致。

批量向量化

实际项目里要处理成千上万条文本,必须批量调用以降低请求次数和成本。Embedding API 原生支持传入列表:

def batch_embed(texts, model="text-embedding-3-small", batch_size=100):
    """分批获取向量,避免单次请求过大"""
    all_vecs = []
    for i in range(0, len(texts), batch_size):
        batch = texts[i:i+batch_size]
        resp = client.embeddings.create(model=model, input=batch)
        all_vecs.extend([d.embedding for d in resp.data])
    return all_vecs

docs = ["iPhone 降价了", "苹果手机促销", "今天天气不错", "如何写 Python"]
vectors = batch_embed(docs)

三、计算相似度:余弦相似度

拿到向量后,怎么衡量“相似”?最常用的是余弦相似度:衡量两个向量方向的夹角,取值 -1 到 1,越接近 1 越相似。它只看方向不看长度,对文本长短不敏感,最适合文本场景。

import numpy as np

def cosine_similarity(a, b):
    a, b = np.array(a), np.array(b)
    return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))

# 对比语义相似度
print(f"iPhone降价 vs 苹果手机促销: {cosine_similarity(vectors[0], vectors[1]):.3f}")
print(f"iPhone降价 vs 今天天气不错: {cosine_similarity(vectors[0], vectors[2]):.3f}")
print(f"iPhone降价 vs 如何写Python: {cosine_similarity(vectors[0], vectors[3]):.3f}")

运行结果会显示前两个(同义)相似度高达 0.8+,后两个(无关)只有 0.3 左右。这就是语义搜索的基础。

四、搭建语义搜索引擎

把上面几步组合起来,就是一个最小可用的语义搜索系统:预先把文档向量化存好,查询时把问题向量化,找最相似的文档。

import numpy as np

class SemanticSearch:
    def __init__(self):
        self.docs = []
        self.vectors = []

    def add(self, texts):
        self.docs.extend(texts)
        self.vectors.extend(batch_embed(texts))
        self.matrix = np.array(self.vectors)
        # 归一化后内积 = 余弦相似度,加速计算
        self.norm = self.matrix / np.linalg.norm(self.matrix, axis=1, keepdims=True)

    def search(self, query, top_k=3):
        q = np.array(batch_embed([query])[0])
        q = q / np.linalg.norm(q)
        scores = self.norm @ q  # 批量余弦相似度
        idx = np.argsort(scores)[::-1][:top_k]
        return [(self.docs[i], float(scores[i])) for i in idx]

engine = SemanticSearch()
engine.add([
    "GPT-5.5 是 OpenAI 最新旗舰模型,推理能力强",
    "Claude Opus 4.8 擅长长文本与代码",
    "Gemini 3.5 Pro 多模态能力突出",
    "DeepSeek V4-Pro 性价比高,中文好",
])

for doc, score in engine.search("哪个模型最便宜"):
    print(f"[{score:.3f}] {doc}")

即使文档里没有“便宜”这个词,搜索引擎也能通过语义匹配到“性价比高”的 DeepSeek。这就是语义搜索超越关键词匹配的地方。

五、Embedding 的其他应用

1. 文本聚类

把向量做 K-means 聚类,能自动把语义相近的文本分组,用于用户反馈分类、新闻话题发现。

2. 去重与近似去重

计算两两相似度,高于阈值(如 0.95)的视为重复。比纯文本哈希更鲁棒,能识别“换种说法的重复”。

3. 推荐系统

把用户历史行为文本和候选内容都向量化,推荐相似度高的内容。冷启动阶段尤其有效。

4. RAG 检索

这是 Embedding 最热门的应用,配合向量数据库实现知识库问答,详见我们的 RAG 教程。

六、模型选择与最佳实践

模型维度适用场景
text-embedding-3-small1536通用、性价比高,大多数场景首选
text-embedding-3-large3072精度要求高、预算充足

几个关键实践要点:

  1. 索引与查询必须用同一模型:换模型要全量重新向量化,否则维度和语义空间不一致。
  2. 向量要归一化:用余弦相似度时,归一化后能用更快的内积计算。
  3. 缓存向量:向量化是有成本的,已计算的向量存盘复用,别重复算。
  4. 控制输入长度:超长文本先切分再嵌入,单条别超过模型最大 token。
  5. 批量请求:单条调用既慢又贵,务必批量。

七、用 EnlyAI 统一接入 Embedding

Embedding 模型选型需要反复对比,通过 EnlyAI 统一接入,一个 key 调用所有 Embedding 模型,方便横向对比效果与成本:

client = OpenAI(api_key="sk-your-enlyai-key", base_url="https://enlyai.com/v1")

# 对比不同 Embedding 模型在同一查询上的相似度区分度
query = "如何降低 API 成本"
candidates = ["省钱技巧", "模型微调教程"]

for model in ["text-embedding-3-small", "text-embedding-3-large"]:
    q = client.embeddings.create(model=model, input=[query]+candidates)
    vecs = [d.embedding for d in q.data]
    sim0 = cosine_similarity(vecs[0], vecs[1])
    sim1 = cosine_similarity(vecs[0], vecs[2])
    print(f"{model}: 相关={sim0:.3f} 无关={sim1:.3f} 区分度={sim0-sim1:.3f}")

统一接入还能让 Embedding 与对话模型(GPT-5.5、Claude Opus 4.8)共用一套密钥和账单,RAG 系统的模型层管理大大简化。

总结

Embedding 是把“语义”变成“可计算”的桥梁。掌握它,你就掌握了语义搜索、RAG、推荐、聚类的共同地基。本文从 API 调用到相似度计算、再到完整搜索引擎,给出了可直接复用的代码。下一步可以把它接入向量数据库处理百万级数据,或结合 LLM 搭建 RAG 问答系统。

而把 Embedding 调用统一交给 EnlyAI,你就能在多个嵌入模型间灵活切换、与对话模型共用一套接入,把精力放在检索效果而非基础设施上。

想快速搭建语义搜索与 RAG 系统?

EnlyAI 提供 OpenAI 兼容的统一接口,一个 key 调用各类 Embedding 模型与 GPT-5.5、Claude Opus 4.8 等大模型,注册即送免费额度,向量化代码只需改一个 base_url 即可接入。

立即注册 EnlyAI →