Day 17RAG 概念引入 —— Embedding、向量与相似度欢迎来到第十七天从今天起我们正式进入RAGRetrieval-Augmented Generation检索增强生成的世界。RAG 是构建知识密集型 Agent 的核心技术它让模型能够“查阅”外部知识库而不是仅仅依赖训练时记住的内容。理解 RAG 的第一步就是理解Embedding嵌入和向量相似度。今天我们将动手调用 Embedding API计算文本之间的语义相似度为后续构建完整的 RAG 管道打下基础。一、今日学习目标理解什么是 Embedding将文本转化为稠密向量的过程语义相近的文本在向量空间中距离更近。掌握如何调用 DeepSeek 或其他兼容 API 的 Embedding 接口将文本转换为向量。学会使用余弦相似度Cosine Similarity衡量两个向量之间的相似程度。通过实验观察语义相近的句子相似度高语义无关的句子相似度低。了解 Embedding 在 RAG 中的位置用于检索与用户问题最相关的知识片段。二、详细实现步骤步骤 1理解 Embedding 与向量大语言模型处理的文本被表示成 Token但 Token 本身是离散的符号模型无法直接理解它们之间的语义关系。Embedding 技术通过神经网络将每个 Token 或整段文本映射为一个固定维度的实数向量例如 1024 维。这个向量被称为“嵌入向量”它捕捉了文本的语义特征。关键性质语义相近的文本其嵌入向量在向量空间中彼此靠近距离小、相似度高。语义无关的文本其向量距离远相似度低。向量可以进行数学运算例如king - man woman ≈ queen。在 RAG 中我们会将知识库中的每个文档片段预先计算成 Embedding 并存入向量数据库。当用户提问时我们将问题也转换为 Embedding然后在向量数据库中检索与问题向量最相似的片段将这些片段作为上下文提供给 LLM让 LLM 基于这些资料生成回答。步骤 2准备环境与调用 Embedding APIDeepSeek 提供 Embedding 接口吗根据 DeepSeek 官方文档目前 DeepSeek 的 API 主要提供对话模型deepseek-chat和代码模型deepseek-coder暂不提供独立的 Embedding 接口。不过我们可以使用其他兼容 OpenAI 格式的 Embedding 服务例如智谱 AI (GLM) 的 Embedding 模型embedding-2。百度千帆、阿里云通义等也提供 Embedding API。为了教学方便我们也可以使用一个简单的本地 Embedding 模型如sentence-transformers但需要安装较大的依赖。为了保持与之前相同的环境使用 OpenAI SDK我们选择使用智谱 AI 的 Embedding API因为它兼容 OpenAI 格式注册和获取 Key 相对简单。如果你有其他 Embedding 服务也可以替换。步骤 2.1获取智谱 AI 的 API Key访问 智谱AI开放平台 注册账号。在“API Keys”页面创建 API Key复制保存。智谱的 Embedding 模型名为embedding-2接口 Base URL 为https://open.bigmodel.cn/api/paas/v4兼容 OpenAI 格式。步骤 2.2更新环境变量在.env文件中添加ZHIPU_API_KEY你的智谱AI_Key步骤 3调用 Embedding API 将文本转为向量我们使用openaiSDK 调用智谱的 Embedding 接口。注意Embedding 接口的路径是/embeddings但我们需要设置正确的base_url。新建embedding_demo.pyimportosfromdotenvimportload_dotenvfromopenaiimportOpenAI load_dotenv()# 初始化智谱客户端clientOpenAI(api_keyos.getenv(ZHIPU_API_KEY),base_urlhttps://open.bigmodel.cn/api/paas/v4)defget_embedding(text:str)-list:调用 Embedding API返回向量列表responseclient.embeddings.create(modelembedding-2,inputtext)# 提取向量returnresponse.data[0].embedding# 测试text人工智能正在改变世界vectorget_embedding(text)print(f向量维度{len(vector)})print(f向量前10个值{vector[:10]})运行脚本你会看到输出了一个高维向量智谱embedding-2的维度是 1024。步骤 4计算余弦相似度余弦相似度衡量两个向量之间的夹角余弦值范围在 -1 到 1 之间。对于 Embedding 向量通常使用余弦相似度来衡量语义相似性值越接近 1 表示越相似。我们手动实现余弦相似度计算不依赖额外库使用纯 Python 或 numpyimportnumpyasnpdefcosine_similarity(vec1:list,vec2:list)-float:计算两个向量的余弦相似度v1np.array(vec1)v2np.array(vec2)returnfloat(np.dot(v1,v2)/(np.linalg.norm(v1)*np.linalg.norm(v2)))测试几组句子sentences[我喜欢吃苹果,我喜欢吃水果,今天天气很好,人工智能是计算机科学的一个分支]# 计算第一句与其他句子的相似度base_vectorget_embedding(sentences[0])forsinsentences[1:]:vecget_embedding(s)simcosine_similarity(base_vector,vec)print(f“{sentences[0]}” 与 “{s}” 的相似度{sim:.4f})观察与思考“我喜欢吃苹果” 与 “我喜欢吃水果” 的相似度应该较高0.7。“我喜欢吃苹果” 与 “今天天气很好” 的相似度较低0.3。这表明 Embedding 确实捕捉了语义关系。步骤 5批量处理与效率考虑在实际项目中知识库可能包含成千上万个片段逐个调用 API 会非常慢。智谱的 Embedding API 支持批量输入input参数可以是一个字符串数组。我们可以一次发送多个文本获得多个向量defget_embeddings_batch(texts:list)-list:responseclient.embeddings.create(modelembedding-2,inputtexts# 列表)# 返回按顺序排列的向量列表return[item.embeddingforiteminresponse.data]# 示例texts[苹果,香蕉,汽车]vectorsget_embeddings_batch(texts)fort,vinzip(texts,vectors):print(f{t}: 维度{len(v)})批量调用可以大幅减少网络请求次数提高效率。步骤 6简易的向量检索演示我们已经有了计算相似度的工具现在模拟一个极简的“检索”过程从一个文档列表中找出与用户问题最相似的文档片段。# 模拟知识库documents[苹果公司发布了新款 iPhone。,香蕉富含钾元素对心脏有益。,人工智能模型可以生成文本。,汽车轮胎需要定期检查气压。,今天气温 25 摄氏度适合户外活动。]# 预先计算所有文档的 Embedding实际项目中会存入向量数据库doc_vectors[get_embedding(doc)fordocindocuments]defretrieve(query:str,top_k:int2):query_vecget_embedding(query)similarities[]fori,doc_vecinenumerate(doc_vectors):simcosine_similarity(query_vec,doc_vec)similarities.append((i,sim))# 排序取相似度最高的 top_k 个similarities.sort(keylambdax:x[1],reverseTrue)results[]foridx,siminsimilarities[:top_k]:results.append((documents[idx],sim))returnresults# 测试检索query哪种食物对心脏好resultsretrieve(query,top_k2)print(f查询{query})fordoc,siminresults:print(f 相似度{sim:.4f}-{doc})运行后你会看到“香蕉富含钾元素对心脏有益。”被检索出来尽管查询中并没有直接出现“香蕉”这个词。这就是语义检索的魅力——即使没有关键词重叠也能找到相关文档。三、常见问题与调试Q1为什么 DeepSeek 不提供 Embedding API→ DeepSeek 目前专注于对话和代码模型Embedding 服务尚未公开。你可以使用其他提供 Embedding 的厂商如智谱、OpenAI、Cohere 等。也可以本地运行开源 Embedding 模型如bge-small-zh但需要安装sentence-transformers等库对硬件有一定要求。Q2向量维度越高越好吗→ 不一定。更高的维度可能捕捉更细微的语义但也会增加存储和计算成本。目前常用的 Embedding 维度有 768、1024、1536 等选择时需权衡性能与效果。Q3余弦相似度和欧氏距离有什么区别→ 余弦相似度关注方向忽略向量长度欧氏距离关注绝对距离。在 Embedding 比较中余弦相似度更常用因为它对向量长度不敏感不同 Embedding 模型可能产生不同模长的向量。Q4如何提高 Embedding 的检索准确率→ 使用专门针对中文优化的 Embedding 模型如智谱的embedding-2、BAAI 的bge-large-zh等。此外对文档进行合理的切分、添加标题或元数据也可以提升检索效果。Q5我没有智谱 API能用 OpenAI 的 Embedding 吗→ 可以OpenAI 提供text-embedding-3-small等模型但需要能访问 OpenAI 的 API 并付费。替换base_url和model即可。四、今日总结与作业今天你完成了✅ 理解了 Embedding 的概念及其在 RAG 中的核心作用。✅ 学会了调用 Embedding API 将文本转换为向量。✅ 实现了余弦相似度计算并通过实验验证了语义相似性。✅ 模拟了一个简易的语义检索过程体会了“语义搜索”相比关键词搜索的优势。今日作业必做使用智谱或其他的 Embedding API计算以下句子两两之间的相似度并绘制一个相似度矩阵可以用print输出表格“我喜欢打篮球”“我喜欢踢足球”“篮球是一项运动”“今天下雨了”扩展简易检索示例将文档列表增加到 10 条内容自拟测试多个查询观察检索结果是否合理。思考如何改进检索效果例如对文档进行预处理。思考题在 RAG 系统中为什么需要对文档进行切分chunking切分大小对检索和生成有什么影响请用 100 字以内回答。明日预告我们将继续 RAG 的下一步——使用 LangChain 实现文档加载、切分和向量存储构建一个完整的“本地文档问答机器人”。请确保今天的 Embedding 调用成功明天我们会直接使用。有任何问题欢迎随时提问