【AI】九.RAG系统必备之嵌入大模型Embedding 小滴课堂讲师 2025年09月18日 flask python, ai大模型, python 预计阅读 22 分钟 #### 嵌入大模型Embedding和LLM大模型对比 ##### 什么是文本嵌入Text Embedding * 文本嵌入(Text Embedding)是将文本(单词、短语、句子或文档)映射到高维向量空间的技术。 * 类比 * 假设你是一个Java工程师,现在需要将一段文字(比如用户评论)存入数据库。 * 传统方式可能是存字符串,但计算机无法直接“理解”语义。 * Embedding的作用 * 把文字转换成一个固定长度的数字数组(向量),比如 `[0.2, -0.5, 0.8, ...]`,这个数组能“编码”文字的含义。 * 想象每个词或句子是一个点,而Embedding就是给这些点在地图上标坐标。 * 语义相近的词(如“猫”和“狗”)坐标距离近,无关的词(如“猫”和“汽车”)坐标距离远。 * **通俗来说** * 将不可计算、非结构化 的词 转化为 可计算,结构化的 向量,把文字变成一串有含义的数字密码 * 就像给每个句子/词语颁发"数字身份证"。这个身份证号码能表达文字的**核心含义** * 例:"猫" → [0.2, -0.5, 0.8,...](300个数字组成的向量) * 核心特点 * **语义感知**:相似的文字数字也相似 ```python # "狗"和"犬"的嵌入向量距离近 # "苹果"(水果)和"苹果"(手机)的嵌入距离远 ``` * 降维表示:将离散的文本转化为连续的向量 * 维度固定:无论输入多长,同个嵌入大模型 输出数字个数相同(如384/768维) * 案例【采用二维方式,正常的向量化后都是上千个维度】 * 句子 * 句子1:老王喜欢吃香蕉 * 句子2:冰冰喜欢吃苹果 * 句子3:老帆在打篮球 * 向量化后续图形表示【二维】 * 句子1和2相近,因为维度大体相同 ##### 应用场景 * 语义搜索: 找含义相近的内容,不依赖关键词匹配 ``` # 搜索"如何养小猫咪" → 匹配到"幼猫护理指南" ``` * 智能分类:自动识别用户评论的情绪/类型 * 问答系统:快速找到与问题最相关的答案段落 ##### 什么是嵌入Embedding大模型 * Embedding 模型的主要任务是将文本转换为数值向量表示 * 这些向量可以用于计算文本之间的相似度、进行信息检索和聚类分析 * 文本嵌入的整体链路 `原始文本 → Embedding模型 → 数值向量 → 存储/比较`  ##### LLM 大模型 vs Embedding 大模型 | 维度 | LLM (如GPT-4、Claude) | Embedding 模型 (如BERT、text-embedding-3) | | :----------: | :------------------------: | :---------------------------------------: | | **核心能力** | 理解并生成人类语言 | 将文本转化为数学向量 | | **输出形式** | 自然文本(对话/文章/代码) | 数值向量(如1536维浮点数) | | **典型交互** | 多轮对话、持续创作 | 单次转换、批量处理 | * 关键联系 * 数据基础相同: * 都通过海量文本训练,理解语言规律 * 就像作家和图书管理员都读过很多书 * 协作关系 * 常组合使用,Embedding快速筛选相关信息,LLM精细加工生成最终结果 * 就像先让图书管理员找到资料,再让作家整理成报告 * 常见误区 * ❌ 误区1:"Embedding是简化版LLM"→ 其实它们是不同工种,就像厨师和营养师的关系 * ❌ 误区2:"LLM可以直接做Embedding的事"→ 虽然理论上可以,但就像用跑车送外卖——又贵又慢 * ❌ 误区3:"Embedding模型不需要训练"→ 好的Embedding也需要大量训练,就像图书管理员需要学习分类方法 ##### 一句话总结 * LLM是内容生产者,Embedding是内容组织者 * 它们就像餐厅里的厨师和配菜员,一个负责烹饪(生成内容),一个负责准备食材(组织信息) ##### 组合应用场景 * 场景1:智能客服系统 * Embedding:把用户问题"我的订单怎么还没到?"转换成向量,快速匹配知识库中相似问题 * LLM:根据匹配到的问题模板,生成具体回答:"您的订单已发货,预计明天送达" * 场景2:论文查重 * Embedding:把论文段落转为向量,计算与数据库的相似度 * LLM:若发现高相似度,自动改写重复段落并给出修改建议 #### LangChain框架文本嵌入Embedding实战 ##### LangChain框架中的Embedding * 通过标准化接口集成了多种嵌入模型,支持开发者灵活调用 * **功能**:对接各类文本嵌入模型的标准化接口 * **作用**:将文本转换为向量,供后续检索/比较使用 * **类比**:不同品牌手机充电器 → LangChain是万能充电头 * 源码查看 ```python from langchain.embeddings import OpenAIEmbeddings from abc import ABC, abstractmethod from langchain_core.runnables.config import run_in_executor class Embeddings(ABC): @abstractmethod def embed_documents(self, texts: list[str]) -> list[list[float]]: """Embed search docs. Args: texts: List of text to embed. Returns: List of embeddings. """ @abstractmethod def embed_query(self, text: str) -> list[float]: """Embed query text. Args: text: Text to embed. Returns: Embedding. """ ``` * 支持的嵌入模型类型【不同嵌入模型维度和精度不一样】 | 类型 | 代表模型 | 特点 | | :------------: | :-----------------------------: | :--------------------: | | 云端API | OpenAI, Cohere, HuggingFace Hub | 无需本地资源,按量付费 | | 本地开源模型 | Sentence-Transformers, FastText | 数据隐私高,可离线运行 | | 自定义微调模型 | 用户自行训练的模型 | 领域适配性强 | * 核心API与属性 | 方法 | 作用 | 示例场景 | | :----------------------: | :----------------------------: | :----------------: | | `embed_query(text)` | 对单个文本生成向量 | 用户提问的实时嵌入 | | `embed_documents(texts)` | 批量处理多个文本,返回向量列表 | 处理数据库文档 | | `max_retries` | 失败请求重试次数 | 应对API不稳定 | | `request_timeout` | 单次请求超时时间(秒) | 控制长文本处理时间 | ##### 案例实战 * 在线嵌入模型使用,也可以使用其他的厂商 * 地址:https://bailian.console.aliyun.com/ * 访问:https://bailian.console.aliyun.com/?tab=model#/model-market - 向量模型 ```python from langchain_community.embeddings import DashScopeEmbeddings import secret # 初始化模型 ali_embeddings = DashScopeEmbeddings( model="text-embedding-v4", # 第四代通用模型 max_retries=3, dashscope_api_key=secret.api_key, ) # 分析商品评论情感倾向 comments = [ "衣服质量很好,但是物流太慢了", "性价比超高,会回购!", "尺寸偏小,建议买大一号" ] # 生成嵌入向量 embeddings = ali_embeddings.embed_documents(comments) print(embeddings) print(len(embeddings)) # 5 print(len(embeddings[0])) # 1536 ``` #### 本地私有化部署嵌入大模型Embedding实战 ##### 为什么要本地部署嵌入大模型 * **对比云端风险**:第三方API可能造成数据泄露(如某云服务商API密钥泄露事件) | 需求类型 | 典型场景 | 案例说明 | | :------------: | :----------------: | :------------------------------: | | **数据安全** | 政府/金融/医疗行业 | 医院病历分析需符合《数据安全法》 | | **定制化需求** | 垂直领域术语适配 | 法律文书嵌入需理解专业法条词汇 | | **成本控制** | 长期高频使用场景 | 电商评论分析每日百万次调用 | | **网络限制** | 内网隔离环境 | 军工企业研发内部知识库 | * 本地部署嵌入大模型数据闭环 ``` 用户数据 → 企业内网服务器 → 本地模型处理 → 结果存于本地数据库 ```  ##### 部署实战 * 使用ollama下载嵌入大模型 * 地址:https://ollama.com/search?c=embed ```python #下载嵌入模型 ollama run mofanke/acge_text_embedding # 后台启动服务(默认端口11434) ollama serve & #查看运行的模型 ollama ps ``` * 嵌入模型请求测试 ``` curl http://localhost:11434/api/embeddings -d '{"model": "mofanke/acge_text_embedding", "prompt": "小滴课堂AI大模型课程"}' ``` * 编码实战 * 由于 LangChain 0.3.x 尚未原生支持 Ollama 嵌入模型,需自定义接口类 * `pip install requests` ```python from typing import List, Optional from langchain.embeddings.base import Embeddings import requests class OllamaEmbeddings(Embeddings): def __init__(self, model: str = "llama2", base_url: str = "http://localhost:11434"): self.model = model self.base_url = base_url def _embed(self, text: str) -> List[float]: try: response = requests.post( f"{self.base_url}/api/embeddings", json={ "model": self.model, "prompt": text # 注意:某些模型可能需要调整参数名(如"prompt"或"text") } ) response.raise_for_status() return response.json().get("embedding", []) except Exception as e: raise ValueError(f"Ollama embedding error: {str(e)}") def embed_query(self, text: str) -> List[float]: return self._embed(text) def embed_documents(self, texts: List[str]) -> List[List[float]]: return [self._embed(text) for text in texts] ``` * 使用自定义嵌入模型处理文档 ```python embeddings = OllamaEmbeddings( model="mofanke/acge_text_embedding", base_url="http://localhost:11434" ) # 分析商品评论情感倾向 comments = [ "衣服质量很好,但是物流太慢了", "性价比超高,会回购!", "尺寸偏小,建议买大一号" ] # 生成嵌入向量 embeddings = embeddings.embed_documents(comments) print(embeddings) print(len(embeddings)) # 3 print(len(embeddings[0])) # 1024 ``` #### 【面试题】RAG系统构建之嵌入模型性能优化 ##### 需求背景(面试高频题目) * 嵌入计算的痛点 * 嵌入生成成本高:每次调用模型API都需要计算资源 * 重复计算浪费:相同文本多次生成嵌入浪费资源 * API调用限制:商业API有调用次数限制和成本 * 响应速度瓶颈:实时场景需要快速响应 * 解决方案:缓存 * 降低计算成本:相同文本只需计算一次 * 提升响应速度:缓存读取比模型计算快10-100倍 * 突破API限制:本地缓存不受远程API配额限制 * 支持离线场景:网络不可用时仍能获取历史嵌入 ##### CacheBackedEmbeddings介绍 * 技术架构图 ```python [应用程序] → 检查缓存 → 命中 → 返回缓存嵌入 ↓ 未命中 → 调用模型 → 存储结果 → 返回新嵌入 ``` * 是LangChain提供的缓存装饰器,支持 本地文件系统、Redis、数据库等存储方式,自动哈希文本生成唯一缓存键 ``` from langchain.embeddings import CacheBackedEmbeddings ``` * 核心语法与参数 ```python from langchain.storage import LocalFileStore from langchain.embeddings import CacheBackedEmbeddings # 初始化 cache = CacheBackedEmbeddings( underlying_embeddings=embedding_model, # 原始嵌入模型 document_embedding_store=storage, # 缓存存储对象 namespace="custom_namespace" # 可选命名空间(隔离不同项目) ) ``` | 参数 | 类型 | 作用 | | :------------------------: | :--------: | :--------------------------------: | | `underlying_embeddings` | Embeddings | 原始嵌入模型(如OpenAIEmbeddings) | | `document_embedding_store` | BaseStore | 缓存存储实现类(如LocalFileStore) | | `namespace` | str | 缓存命名空间(避免键冲突) | * 存储支持多类型 ```python #这个包里面 from langchain.storage __all__ = [ "create_kv_docstore", "create_lc_store", "EncoderBackedStore", "InMemoryByteStore", "InMemoryStore", "InvalidKeyException", "LocalFileStore", "RedisStore", "UpstashRedisByteStore", "UpstashRedisStore", ] ``` ##### 应用案例:智能客服知识库加速 * 场景需求 * 知识库包含10万条QA对 * 每次用户提问需要检索最相关答案 * 传统方式每次请求都要计算所有问题嵌入 * 缓存方案 * 首次加载时全量预计算并缓存 * 后续请求直接读取缓存 * 新增问题时动态更新缓存 * 代码案例 * 基础版本(无缓存) ```python from langchain.embeddings import OpenAIEmbeddings # 初始化模型 embedder = OpenAIEmbeddings(openai_api_key="sk-xxx") # 生成嵌入 vector = embedder.embed_documents("如何重置密码?") print(f"向量维度:{len(vector)}") ``` * 带缓存版本 ```python from langchain.storage import LocalFileStore from langchain.embeddings import CacheBackedEmbeddings # 创建文件缓存 fs = LocalFileStore("./embedding_cache/") # 组合缓存与模型(Java的装饰器模式模式类似) cached_embedder = CacheBackedEmbeddings.from_bytes_store( underlying_embeddings=embedder, document_embedding_store=fs, namespace="openai-embeddings" # 区分不同模型版本 ) # 首次调用(写入缓存) vector1 = cached_embedder.embed_documents("如何重置密码?") # 二次调用(读取缓存) vector2 = cached_embedder.embed_documents("如何重置密码?") print(f"结果一致性:{vector1 == vector2}") # 输出True ``` * 高级配置示例(分布式案例-存储Redis) ```python # 带TTL的Redis缓存 from redis import Redis from langchain.storage import RedisStore redis_client = Redis(host="localhost", port=6379) redis_store = RedisStore(redis_client, ttl=86400) # 24小时过期 cached_embedder = CacheBackedEmbeddings.from_bytes_store( underlying_embeddings=embedder, document_embedding_store=redis_store, namespace="openai-v3" ) ``` #### 嵌入大模型CacheBackedEmbeddings案例实战 * **案例实战:对比嵌入大模型使用缓存前后性能区别** * 注意:API设计区别 * `embed_documents`:面向批量文档预处理(适合缓存) * `embed_query`:面向实时查询处理(默认不缓存) * 设计考量因素 | 维度 | `embed_documents` | `embed_query` | | :------: | :--------------------------------: | :------------------------------: | | 使用场景 | 预处理大量重复文档(如知识库构建) | 实时响应用户查询 | | 数据特征 | 高重复率(法律条款、产品描述) | 低重复率(用户提问多样化) | | 性能损耗 | 批量处理可分摊缓存读写开销 | 单次查询增加延迟(缓存命中率低) | | 存储效率 | 缓存大量重复文本收益显著 | 缓存大量唯一查询浪费资源 | ##### 编码实战 ```python from langchain.embeddings import CacheBackedEmbeddings # 已被弃用,需改为从 langchain_community.embeddings 导入 # from langchain.embeddings import DashScopeEmbeddings from langchain_community.embeddings import DashScopeEmbeddings import time # 初始化模型和缓存 from langchain.storage import LocalFileStore # 初始化模型 embedding_model = DashScopeEmbeddings( model="text-embedding-v2", # 第二代通用模型 max_retries=3, dashscope_api_key="sk-005c3c25f6d042848b29d75f2f020f08" ) storage = LocalFileStore("./embedding_cache/") # 本地缓存目录 cached_embeddings = CacheBackedEmbeddings.from_bytes_store( embedding_model, storage, namespace="openai_emb" # 命名空间隔离不同模型 ) texts = ["小滴课堂AI大模型开发实战", "小滴课堂AI大模型开发实战"] # 故意重复 start_time = time.time() # 第一次调用(写入缓存) emb1 = cached_embeddings.embed_documents(texts) print(f"首次调用嵌入维度: {len(emb1[0])}") embedded1_end_time = time.time() print(f"首次调用耗时: {embedded1_end_time - start_time}") # 第二次调用(读取缓存) emb2 = cached_embeddings.embed_documents(texts) print(f"二次调用结果相等: {emb1 == emb2}") embedded2_end_time = time.time() print(f"二次调用耗时: {embedded2_end_time - embedded1_end_time}") ``` ##### 最佳实践建议 * **适用场景** - 处理大量重复文本(如商品描述、法律条款) - 需要控制API调用成本的商业应用 - 本地模型加速重复计算 * **存储选择策略** | 存储类型 | 优点 | 缺点 | 适用场景 | | :------------: | :----------------: | :-----------: | :-----------: | | LocalFileStore | 零配置、易调试 | 不适合分布式 | 本地开发/测试 | | RedisStore | 高性能、支持分布式 | 需要运维Redis | 生产环境集群 | | InMemoryStore | 最快速度 | 重启丢失数据 | 临时测试 | ###
评论区