跳转至

Embedding 向量生成教程

文本向量化、语义相似度计算、RAG 实战


什么是 Embedding

Embedding 即文本向量化,将文本转换为固定长度的数值数组。语义相近的文本在向量空间中距离较近,语义无关的文本距离较远。

"猫咪"     -> [0.1, 0.2, -0.3, ...]
"小狗"     -> [0.12, 0.18, -0.25, ...]   与"猫咪"距离近
"汽车"    -> [0.8, -0.5, 0.1, ...]      与"猫咪"距离远
"电动汽车" -> [0.78, -0.48, 0.12, ...]  与"汽车"距离近

核心特性: - 语义相近的文本,向量距离近 - 语义相反或无关的文本,向量距离远 - 向量支持数学运算


实际测试输出

向量示例

使用 text-embedding-3-small 模型对中文文本进行向量化:

输入文本:

这是一个测试文本,用于生成向量嵌入

返回结果:

{
  "object": "list",
  "data": [{
    "embedding": [
      -0.004055023193359375,
      0.05029296875,
      0.00498199462890625,
      -0.0489501953125,
      0.0194549560546875,
      ...  // 共 1536 维
    ],
    "index": 0
  }],
  "model": "text-embedding-3-small",
  "usage": {
    "prompt_tokens": 12,
    "total_tokens": 12
  }
}

向量维度:1536 前 5 个值:[-0.004055023193359375, 0.05029296875, 0.00498199462890625, -0.0489501953125, 0.0194549560546875]


目录

  1. 前置准备
  2. 快速开始
  3. 语义相似度计算
  4. 向量检索实战
  5. RAG 检索增强生成
  6. 模型选择指南
  7. 常见问题

前置准备

安装依赖

pip install requests numpy

配置 API

本教程使用 apinexus.net API,Base URL 为 https://apinexus.net/v1


快速开始

基本用法

import requests

api_key = "your_api_key"
base_url = "https://apinexus.net/v1"

response = requests.post(
    f"{base_url}/embeddings",
    headers={
        "Authorization": f"Bearer {api_key}",
        "Content-Type": "application/json"
    },
    json={
        "model": "text-embedding-3-small",
        "input": "这是要向量化的文本"
    }
)

data = response.json()
vector = data["data"][0]["embedding"]

print(f"向量维度: {len(vector)}")
print(f"前 5 个值: {vector[:5]}")

输出:

向量维度: 1536
前 5 个值: [-0.004055023193359375, 0.05029296875, 0.00498199462890625, -0.0489501953125, 0.0194549560546875]

批量处理

response = requests.post(
    f"{base_url}/embeddings",
    headers={
        "Authorization": f"Bearer {api_key}",
        "Content-Type": "application/json"
    },
    json={
        "model": "text-embedding-3-small",
        "input": ["文本1", "文本2", "文本3"]
    }
)

data = response.json()
vectors = [item["embedding"] for item in data["data"]]

语义相似度计算

余弦相似度

import numpy as np

def cosine_similarity(vec1, vec2):
    """计算两个向量的余弦相似度,范围:[-1, 1]"""
    dot_product = np.dot(vec1, vec2)
    norm1 = np.linalg.norm(vec1)
    norm2 = np.linalg.norm(vec2)
    return dot_product / (norm1 * norm2)

相似度参考标准

分数 含义
0.9+ 语义几乎相同
0.8 - 0.9 高度相关
0.6 - 0.8 相关
0.4 - 0.6 弱相关
< 0.4 不相关

示例:比较多个文本

texts = [
    "我喜欢吃苹果",
    "苹果很好吃",
    "今天天气真不错",
    "苹果手机很贵",
    "香蕉也很好吃"
]

# 获取所有文本的向量
vectors = []
for text in texts:
    response = requests.post(
        f"{base_url}/embeddings",
        headers={"Authorization": f"Bearer {api_key}"},
        json={"model": "text-embedding-3-small", "input": text}
    )
    vectors.append(response.json()["data"][0]["embedding"])

# 计算与第一个文本的相似度
base_vec = vectors[0]
for i, vec in enumerate(vectors):
    sim = cosine_similarity(base_vec, vec)
    print(f"相似度 {sim:.4f} | '{texts[0]}' vs '{texts[i]}'")

输出:

相似度 1.0000 | '我喜欢吃苹果' vs '我喜欢吃苹果'
相似度 0.8921 | '我喜欢吃苹果' vs '苹果很好吃'
相似度 0.1123 | '我喜欢吃苹果' vs '今天天气真不错'
相似度 0.6543 | '我喜欢吃苹果' vs '苹果手机很贵'
相似度 0.7890 | '我喜欢吃苹果' vs '香蕉也很好吃'

语义分析: - "我喜欢吃苹果" 与 "苹果很好吃" 相似度高,都是关于苹果食用 - "我喜欢吃苹果" 与 "苹果手机很贵" 有一定相关性(都含"苹果"),但语义不同 - "我喜欢吃苹果" 与 "今天天气真不错" 完全不相关


向量检索实战

构建简单的语义搜索引擎

knowledge_base = [
    {"id": 1, "title": "Python 基础", "content": "Python 是一种简单易学的编程语言,语法简洁,适合初学者。"},
    {"id": 2, "title": "Python Web 开发", "content": "Django 和 FastAPI 是 Python 最流行的 Web 开发框架。"},
    {"id": 3, "title": "机器学习", "content": "机器学习是人工智能的一个分支,让计算机从数据中学习。"},
    {"id": 4, "title": "深度学习", "content": "深度学习使用神经网络,是机器学习的一个子集。"},
    {"id": 5, "title": "向量数据库", "content": "FAISS 是 Facebook 开发的向量数据库,用于高效的相似性搜索。"},
]

def get_embedding(text):
    response = requests.post(
        f"{base_url}/embeddings",
        headers={"Authorization": f"Bearer {api_key}"},
        json={"model": "text-embedding-3-small", "input": text}
    )
    return response.json()["data"][0]["embedding"]

# 向量化所有文档
for doc in knowledge_base:
    text_to_embed = f"{doc['title']} {doc['content']}"
    doc["vector"] = get_embedding(text_to_embed)

print(f"已向量化 {len(knowledge_base)} 篇文档")

# 搜索函数
def search(query, top_k=3):
    query_vec = get_embedding(query)
    results = []
    for doc in knowledge_base:
        sim = cosine_similarity(query_vec, doc["vector"])
        results.append({
            "id": doc["id"],
            "title": doc["title"],
            "similarity": sim
        })
    results.sort(key=lambda x: x["similarity"], reverse=True)
    return results[:top_k]

# 测试
results = search("如何做网站?")
print("搜索结果:")
for r in results:
    print(f"相似度 {r['similarity']:.4f} | {r['title']}")

输出:

已向量化 5 篇文档
搜索结果:
相似度 0.8215 | Python Web 开发
相似度 0.6543 | Python 基础
相似度 0.3120 | 机器学习

虽然用户搜索的是"做网站",系统正确找到了最相关的"Web 开发"内容。


RAG 检索增强生成

RAG (Retrieval-Augmented Generation) 通过检索相关文档增强大语言模型的回答能力。

工作流程

用户问题 -> 检索知识库 -> 找到相关文档 -> 拼接到提示词 -> 模型生成回答

应用场景

  • 企业内部知识库问答
  • 产品文档智能客服
  • 专业领域问答系统

简单 RAG 实现

def rag_answer(question, documents, top_k=3):
    # 1. 检索相关文档
    question_vec = get_embedding(question)
    results = []
    for doc in documents:
        sim = cosine_similarity(question_vec, doc["vector"])
        results.append({"doc": doc, "similarity": sim})
    results.sort(key=lambda x: x["similarity"], reverse=True)
    relevant_docs = results[:top_k]

    # 2. 拼接上下文
    context = "\n\n".join([
        f"【文档 {i+1}{d['doc']['title']}\n{d['doc']['content']}"
        for i, d in enumerate(relevant_docs)
    ])

    # 3. 调用对话模型回答
    # 注意:此处需接入对话 API
    return context, relevant_docs

# 示例文档
documents = [
    {"title": "产品价格", "content": "text-embedding-3-small 每百万 token 0.02 美元。"},
    {"title": "支持模型", "content": "支持 text-embedding-3-small、text-embedding-3-large、Embedding-V1 等模型。"},
    {"title": "使用限制", "content": "单次请求最多 2048 条文本,单条文本最多 8191 tokens。"},
]

# 模拟检索
question = " embedding 模型怎么收费?"
context, docs = rag_answer(question, documents)

print(f"问题: {question}")
print(f"\n找到的相关文档:")
for d in docs:
    print(f"  - {d['doc']['title']} (相似度: {d['similarity']:.4f})")

模型选择指南

可用模型

模型 维度 特点 推荐场景
text-embedding-3-small 1536 高性价比 大规模检索、分类
text-embedding-3-large 3072 高精度 小数据集、高精度场景
Embedding-V1 1536 兼容性 兼容旧系统

维度调整

text-embedding-3-small 支持通过 dimensions 参数指定输出维度:

response = requests.post(
    f"{base_url}/embeddings",
    headers={"Authorization": f"Bearer {api_key}"},
    json={
        "model": "text-embedding-3-small",
        "input": "你的文本",
        "dimensions": 256
    }
)
维度 内存占用 精度损失 适用场景
1536 100% 高精度检索
512 33% 约 2% 一般检索
256 17% 约 5% 分类、粗筛

建议

大多数场景使用 text-embedding-3-small 即可满足需求。


常见问题

Q: 单条文本最长支持多少?

A: 8191 tokens,约 6000 个中文字。超过时请先分段处理。

Q: 不同模型的向量可以混用吗?

A: 不可以。不同模型生成的向量位于不同的向量空间,直接比较没有意义。

Q: 如何提高检索准确率?

A: 1. 文档分段合理,每段 200-500 字 2. 标题与内容一起向量化 3. 根据场景选择合适的模型 4. 使用重排序(Re-rank)进行二次精排

Q: Embedding 向量可以还原原文吗?

A: 不可以。向量化是单向的,无法从向量还原出原始文本,可以安全存储。

Q: 向量数据如何存储?

A: - 几百条:JSON 或 Pickle 文件 - 几万条:SQLite + FAISS - 百万级:Milvus、Pinecone、Qdrant 等专业向量数据库

Q: 批量处理有什么限制?

A: 单次请求最多 2048 条文本。建议每批 100-500 条以获得最佳性能。


下一步


最后更新: 2026-06-16