当前位置: 首页 > news >正文

Embedding:文本怎么变成向量?语义检索为什么能工作?

Embedding 不是可有可无的组件,它是 RAG 的地基。地基歪了,后面 Retriever、Rerank、Prompt 再漂亮也救不回来。

一、Embedding 到底是什么?

Embedding,就是把一段文字变成一串数字。

这串数字不是随机数,而是语义坐标。意思相近的文本,向量距离更近;意思差得远的文本,距离更远。

LangChain 官方文档对 Embedding 的解释也很直接:Embedding 模型会把原始文本转换成固定长度的数字向量,这些向量能表达语义含义,让机器按“意思”比较文本,而不是只按关键词匹配。

这就是语义检索能工作的原因。

用户问“提前还款怎么操作”,知识库里写的是“如何结清贷款”,关键词不一样,但意思接近。Embedding 能把它们拉到同一个语义区域,向量库就能召回。

如果没有 Embedding,RAG 很容易退化成普通搜索。只能找关键词,找不到意思。

二、Embedding 在 RAG 里处在哪一层?

前面几章已经讲过:Loader 把资料读进来,Splitter 把长文档切成 Chunk。接下来,就轮到 Embedding。

它做一件事:把每个 Chunk Document 的 page_content 转成向量,然后交给 VectorStore 入库。

离线建库和在线查询两条链路,都要经过 Embedding

离线建库时,Embedding 面向的是一批文档。在线查询时,Embedding 面向的是用户的一句话。

所以 LangChain 在接口上故意拆成两个方法:

embed_documents(texts):文档批量向量化。

embed_query(text):问题单条向量化。

这两个方法看起来简单,但这是整个语义检索的分水岭。文档侧是“建索引”,问题侧是“查索引”。

三、Embeddings 抽象接口

打开 LangChain Core 的源码,可以看到 Embeddings 是一个抽象基类。它不是 OpenAI,也不是 HuggingFace。它只是规定:一个 Embedding 模型必须能把文档和查询变成向量。

源码的设计非常克制。核心就是四个方法:

class Embeddings(ABC):

def embed_documents(self, texts: list[str]) -> list[list[float]]: ...

def embed_query(self, text: str) -> list[float]: ...

async def aembed_documents(self, texts: list[str]) -> list[list[float]]: ...

async def aembed_query(self, text: str) -> list[float]: ...

这里最关键的是返回类型。

文档是 list[str],所以返回 list[list[float]]。一个文本,对应一个向量。

查询是 str,所以返回 list[float]。一个问题,对应一个向量。

这就是 LangChain 抽象层的好处:上层 VectorStore 和 Retriever 不需要知道你底下接的是哪个模型。只要实现这个接口,就能被接入 RAG 流水线。

四、为什么要区分 embed_documents 和 embed_query?

很多人第一次看源码会疑惑:文档是文本,问题也是文本,为什么不统一叫 embed_text?

不同 Embedding 模型可能会对“文档”和“查询”使用不同提示方式。比如某些检索模型会要求:

文档侧:把这段内容编码成可检索资料。

查询侧:把这个问题编码成检索意图。

有些模型内部路径一样,有些模型内部路径不一样。LangChain 先把接口拆开,给不同模型留下扩展空间。

这就是好的框架设计:看起来多写了一个方法,实际是在给未来兼容性留口子。

五、OpenAIEmbeddings 怎么实现?

以 OpenAIEmbeddings 为例,源码链路很清晰。

它的 embed_documents 大致分两种情况:

如果不检查上下文长度:直接按 chunk_size 分批调用 embedding API。

如果检查上下文长度:先 tokenize,再按 embedding_ctx_length 切分,再批量请求。

源码里有一个细节很重要:长文本不会直接硬塞给 embedding API。它会被分成 token chunks,再请求向量,最后把多段结果合并。

embed_query 更直接。源码逻辑可以压缩成一句话:

def embed_query(self, text: str) -> list[float]:

return self.embed_documents([text])[0]

也就是说:问题向量化,本质上还是复用文档向量化能力。先把单个问题包装成列表,再取第一个结果。

这不是偷懒。恰恰是工程复用。

六、从源码看 VectorStore 为什么能自动调用 Embedding?

很多人写代码时会发现,自己明明只写了 from_texts、add_documents 或 retriever.invoke,为什么 Embedding 就自动被调用了?

因为 VectorStore 和 Retriever 在内部已经接上了 Embeddings 接口。

文档入库时:

VectorStore.add_documents(documents)

-> 取出 page_content

-> embeddings.embed_documents(texts)

-> 向量 + metadata + id 入库

查询检索时:

retriever.invoke(query)

-> vectorstore.similarity_search(query)

-> embeddings.embed_query(query)

-> 用 query_vector 去向量库查近邻

-> 返回 List[Document]

所以,Embedding 是隐藏在 RAG 后面的发动机。你看不到它转,但它一直在转。

七、向量怎么比较?三个常见相似度指标

文本变成向量后,下一步就是比较。LangChain 官方文档列出了常见的三类距离或相似度指标:余弦相似度、欧氏距离、点积。

余弦相似度:看两个向量方向是否接近。常用于语义相似度。

欧氏距离:看两个点在空间里的直线距离。

点积:看一个向量在另一个方向上的投影强度。

实际项目里,你不一定要自己手写这些公式。向量库会帮你算。但你必须知道:不同指标会影响召回结果,向量是否归一化也会影响结果。

八、Embedding 模型怎么选?这张图比参数更重要

选 Embedding 模型,不要只看榜单。

真正上线时,最关键的是业务评测。你要拿自己的问题、自己的知识库、自己的标准答案去测。

比如智能客服要测:用户口语化提问能不能召回制度文档。股票研报助手要测:同一公司不同公告、行业新闻、研报摘要之间能不能建立语义关联。

如果只拿通用 benchmark 选模型,很容易线上翻车。

九、缓存为什么重要?Embedding 不是一次性成本

很多人以为 Embedding 只在建库时花钱。错。

查询也要 embed_query。每个用户问题都可能触发一次向量化。高并发下,延迟和成本都会上来。

所以生产系统至少要做三类缓存:

文档向量缓存:同一 Chunk 内容不重复向量化。

查询向量缓存:高频问题不重复调用 embedding 模型。

索引版本缓存:模型版本、切分版本、向量库版本要绑定。

只要文档内容、切分策略、Embedding 模型版本任何一个变了,历史向量就可能需要重建。

十、企业级落地:Embedding 不该只是一个函数

如果只是 Demo,Embedding 可以写成一行代码。

如果是企业系统,Embedding 必须进入数据流水线。

Java 主服务负责文档上传、任务调度、权限审计、索引版本。

Python AI 服务负责 Loader、Splitter、Embedding、Retriever。

Milvus / ES 负责向量和关键词索引。

Redis 做缓存,MySQL 记录元数据和版本。

日志系统记录每次向量化耗时、模型名称、维度、token、失败原因。

Embedding 是基础设施,不是工具函数。

十一、Embedding 最容易踩的坑

RAG 效果差,很多时候不是大模型的问题,而是 Embedding 链路的问题。

最常见的就是:文档切得不好、模型版本乱换、向量没有重建、metadata 没带、只做向量检索不做关键词融合。

尤其是模型版本。

同一个向量库里,不能混着放不同 Embedding 模型生成的向量。维度可能不同,语义空间也可能不同。哪怕维度一样,距离也不一定有可比性。

十二、总结

Embedding 把文本变成向量,VectorStore 按距离找资料,Retriever 把相关 Document 交给 Prompt,Model 再基于资料生成答案。

所以,RAG 的第一性原理不是“把资料塞给大模型”,而是:先把资料变成可计算的语义坐标,再按问题找到最相关的上下文。

学 LangChain,Embedding 这一章必须吃透。因为从这里开始,RAG 才真正从“文本处理”进入“语义计算”。


内容来源:Embedding:文本怎么变成向量?语义检索为什么能工作?:功能变化与行业影响解析_热闻岛

http://www.jsqmd.com/news/1010482/

相关文章:

  • 别再让手机热点叫AndroidAP_1234了!手把手教你修改Android 11默认热点名和密码
  • Windows音频路由终极指南:3步搞定多设备音频管理难题
  • 2026年系统门窗专业供应商推荐,哪家隔热系统门窗公司靠谱 - 工业品牌热点
  • 别光看TPS!用JMeter压测ShardingSphere时,这些监控指标和配置坑你注意了吗?
  • Python排序算法可视化动画教学实现
  • 从CATIA V6到网页浏览:3DXML格式如何成为设计评审与协作的‘隐形桥梁’?
  • 2025-2026年四川民办本科学校推荐:TOP5评测专业选择指南学费透明注意事项 - 品牌推荐
  • 支招实力强的螺带搅拌器制造商,选购不踩坑 - mypinpai
  • WordPress评论AI自动回复插件开发实战
  • 别再只用傅里叶了!用Python小波变换给信号降噪,附Matlab/Octave代码对比
  • 2026年推荐一下推进式搅拌器厂家前十名,专业的淬火搅拌器定制厂家靠谱吗 - mypinpai
  • 蓝桥杯备赛,C++和Python选手到底该怎么选?聊聊我的真实体验和避坑建议
  • 5个实用技巧:轻松掌握SillyTavern角色卡片系统,打造生动AI角色
  • 从5V到3.3V:除了AMS1117,给ESP32供电还有这几种更高效的方案(含实测对比)
  • 2026年热门网站建设公司盘点,金申管业怎么收费? - 工业品牌热点
  • 别再傻傻分不清!从MROM到EEPROM,嵌入式开发选对存储芯片的保姆级指南
  • 2026年6月工程信息平台推荐榜:五强评测专业适用场景性价比高 - 品牌推荐
  • 用LM386和TDA2009做个小功放:从OCL到BTL,两种经典电路实测对比
  • AT89C51数码管驱动方案对比:为什么你的时钟项目该用74HC573而不是直接I/O口?
  • 国内地图标注定位服务厂家直销选择与市场分析报告(2026年) - 优质品牌商家
  • 2026年甲级造价资质企业选择指南:成本控制与服务能力的平衡策略 - 优质品牌商家
  • Blender MMD Tools完全指南:在Blender中无缝处理MMD模型的终极解决方案
  • 成都主题火锅店的商业落地与空间营造——从“前任的火锅店”看品牌化与场景化趋势 - 优质品牌商家
  • 别再乱买USB集线器了!聊聊STT、MTT和SuperTT,选错带宽直接减半
  • 从DIY小台灯到智能家居:船型开关的选型、接线与安全使用全攻略
  • 成都名酒回收公司可靠度排行:核心维度实测对比 - 优质品牌商家
  • Windows Subsystem for Android终极指南:如何在Windows 11上完美运行安卓应用
  • 告别命令行恐惧:在统信UOS上用RapidSVN图形化搞定SVN客户端连接
  • 2026年总结酚醛风管厂家排名,十大公司费用多少钱 - 工业品牌热点
  • 2026年薄膜连栋温室建设厂家网站定制开发公司排名,如何选择靠谱的? - mypinpai