RAG 系统 Embedding 流程分析与自托管 API 适配

1. 问题背景

在构建一个轻量化 RAG(检索增强生成)系统时,使用了 LangChain 框架结合自托管的 FreeLLMApi(兼容 OpenAI 格式)进行文本向量化。在开发过程中,遇到了运行时类型错误,并对 Embedding 模型如何处理文本以及自托管服务与 OpenAI 原生服务的差异产生了疑问。


2. 运行时问题分析

2.1 错误现象

错误日志:

TypeError: Document.__init__() got an unexpected keyword argument 'page_content'

2.2 根本原因

该错误发生在 load_chunks_from_file 函数中。代码尝试通过 Document(page_content=..., metadata=...) 实例化对象。

  • 原因 :实例化时传递的参数名 page_content 与当前环境中安装的 Document 类定义不匹配。这通常是因为导入了错误的 Document 类,或者使用了版本不兼容的 LangChain 核心库。
  • 解决方案 :确保从 langchain_core.documents 正确导入 Document 类,并核对该版本类构造函数的参数名。

3. 深度技术探讨:Embedding 工作机制

3.1 文本是如何转换为向量的?

调用 embeddings.embed_documents(batch_texts) 时,内部执行流程如下:

原始文本 →\rightarrow→ Tokenizer分词 →\rightarrow→ Token IDs (整数序列) →\rightarrow→ 神经网络 →\rightarrow→ Embedding向量

核心结论:神经网络无法直接处理字符串,必须经过 Token 化转换为数字 ID 才能进行矩阵运算。

3.2 _tokenize 方法的作用

在 LangChain 的 OpenAIEmbeddings 实现中,_tokenize 方法的作用不是预处理文本 ,而是计数(量长度)

  • 目的:计算当前文本包含多少个 token,以判断是否超过模型最大长度限制(例如 8191 tokens)。
  • 逻辑 :如果超限 →\rightarrow→ 执行截断或切分 →\rightarrow→ 再次检查;如果不超限 →\rightarrow→ 进入 _get_len_safe_embeddings 阶段。

3.3 _get_len_safe_embeddings 解析

该方法名为 "Length Safe",意味着它假设输入文本已经通过了长度校验,因此它会跳过所有校验步骤 ,直接将原始字符串(batch_texts)发送给 API 接口。


4. 自托管服务 vs OpenAI 原生 API

4.1 推理逻辑对比

特性 OpenAI 原生 API 自托管推理服务 (如 FreeLLMApi)
传输内容 原始字符串 (str) 可能是字符串,也可能是 Token IDs
Tokenize 位置 服务端完成 可能在客户端 完成 →\rightarrow→ 传输 IDs
API 接口 https://api.openai.com/v1 私有 IP (如 172.21.6.101) + 自定义端口
模型定义 明确的模型名 (如 text-embedding-3) 可能使用 auto 等路由别名

4.2 如何判断是否为自建推理服务?

  1. IP 地址 :使用私有 IP 段(10.x, 172.16-31.x, 192.168.x)。
  2. 端口号 :使用非标准 HTTPS 端口(如 3001)。
  3. 客户端类型self.client 的类型不是标准 openai.OpenAI 类。
  4. 输入参数 :API 调用时传递的是 batch_tokens (Listint) 而非 batch_texts (Liststr)。

5. 适配方案:让自托管服务走 OpenAI 逻辑

若自托管服务兼容 OpenAI 格式,但其 SDK 强制要求传递 batch_tokens,而你希望传输原始文本,可采取以下方案:

方案 A:重写 Embedding 类 (推荐)

继承 OpenAIEmbeddings 并重写 embed_documents,绕过内部的 Token 转换逻辑,强制发送原始字符串。

方案 B:直接使用 HTTP 请求

不使用 LangChain 的封装,直接通过 requestshttpx 调用 /v1/embeddings 端点,确保 input 字段传递的是字符串列表。

python 复制代码
# 伪代码示例
response = requests.post(
    url="http://172.21.6.101:3001/v1/embeddings",
    json={"model": "auto", "input": ["原始文本1", "原始文本2"]},
    headers={"Authorization": f"Bearer {API_KEY}"}
)

6. 总结

  • 运行时错误 →\rightarrow→ 检查类导入与参数匹配。
  • Embedding 流程 →\rightarrow→ 本地 Tokenize 仅用于长度校验 →\rightarrow→ 传输原始文本 →\rightarrow→ 服务端 Tokenize →\rightarrow→ 生成向量。
  • 自托管识别 →\rightarrow→ 通过私有 IP、非标端口及 self.client 类型判断。
  • 适配关键 →\rightarrow→ 确认 API 接收的是 string 还是 token_ids,通过重写方法或直接调用 REST API 解决不兼容问题。
相关推荐
书源丶27 分钟前
Qwen3-Embedding-0.6B 纯 CPU
网络·语言模型·embedding·llama
wang_shu_mo_ran2 天前
Spring MVC的常用注解和用法(一)
java·spring·mvc
牛油果子哥q5 天前
多模态大模型工程入门:图文Embedding、图文RAG、图片解析、C++多模态接口封装实战
开发语言·c++·embedding
Huanzhi_Lin6 天前
UI业务模块化随笔
ui·mvc·mvp·ecs·ui框架·模块化开发
好菇娘の当自强6 天前
安装 Embedding 模型所需环境(完整指南)
embedding
ZYJCSZKJ6 天前
基于向量检索重排序与查询扩展的GEO优化:从Embedding空间视角提升区域实体引用率
embedding
richard_first7 天前
Transformer与大语言模型:第18章 向量数据库
数据库·人工智能·自然语言处理·transformer·embedding
杨运交7 天前
[070][Web模块]Spring MVC TOTP 二次认证拦截器:设计与源码深度解析
前端·spring·mvc
今天AI了吗7 天前
去中心化 AI 反馈系统:数据不上链,凭证与激励分开管
人工智能·windows·python·数据分析·去中心化·区块链·embedding
CIO_Alliance7 天前
AI微调系列(1)| 全量微调、LoRA、QLoRA 三种方案怎么选
前端·人工智能·神经网络·机器学习·embedding·企业ai转型