Skip to content

Latest commit

 

History

History
 
 

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 

README.md

自定义 Langchain RAG 组件示例

本示例演示如何基于 LangchainKnowledge 自定义 RAG 管线中的核心组件(Document Loader、Text Splitter、Retriever),并验证自定义组件在文档加载、文本分割、语义检索三条链路上的正确性。

关键特性

  • 自定义 Document Loader:继承 BaseLoader,按行加载文件内容,支持同步与异步两种模式
  • 自定义 Text Splitter:继承 BaseDocumentTransformer,按指定分隔符分割文本,保留原始元数据
  • 自定义 Retriever:继承 BaseRetriever,基于关键词匹配返回 Top-K 文档,并支持 from_documents 工厂方法
  • 向量检索集成:使用 HuggingFaceEmbeddingsBAAI/bge-small-en-v1.5)+ InMemoryVectorStore 完成 Embedding 索引与相似度检索
  • 三组独立 Demo 覆盖:同一程序内依次运行 Custom Loader / Custom Splitter / Custom Retriever 三个场景

组件层级结构说明

本例是纯 Knowledge 组件示例,不涉及 LlmAgent 或多 Agent 路由,核心结构如下:

LangchainKnowledge (x3 实例)
├── Demo 1: Custom Document Loader
│   ├── document_loader: CustomDocumentLoader (按行读取文件)
│   ├── document_transformer: RecursiveCharacterTextSplitter
│   ├── embedder: HuggingFaceEmbeddings (BAAI/bge-small-en-v1.5)
│   └── vectorstore: InMemoryVectorStore
├── Demo 2: Custom Text Splitter
│   ├── document_loader: TextLoader
│   ├── document_transformer: CustomTextSplitter (按 \n 分割)
│   ├── embedder: HuggingFaceEmbeddings (BAAI/bge-small-en-v1.5)
│   └── vectorstore: InMemoryVectorStore
└── Demo 3: Custom Retriever
    ├── retriever: ToyRetriever (关键词匹配, Top-K)
    └── prompt_template: PromptTemplate("{query}")

关键文件:

关键代码解释

这一节用于快速定位"自定义 Loader、自定义 Splitter、自定义 Retriever"三条核心链路。

1) 自定义 Document Loader(agent/tools.pyCustomDocumentLoader

  • 继承 BaseLoader,在 lazy_load 中逐行读取文件,每行生成一个 Document(携带 line_numbersource 元数据)
  • 可选实现 alazy_load,使用 aiofiles 提供原生异步支持;未安装时自动回退到父类默认实现
  • agent.pycreate_document_loader_knowledge() 中,将该 Loader 与 RecursiveCharacterTextSplitter + InMemoryVectorStore 组装成完整 RAG 管线

2) 自定义 Text Splitter(agent/tools.pyCustomTextSplitter

  • 继承 BaseDocumentTransformer,在 transform_documents 中按指定 separator 分割文档内容
  • 分割后为每个 chunk 保留原始元数据,并附加 chunk_indexoriginal_doc_id
  • agent.pycreate_text_splitter_knowledge() 中,搭配标准 TextLoader 使用

3) 自定义 Retriever(agent/tools.pyToyRetriever

  • 继承 BaseRetriever,在 _get_relevant_documents 中通过关键词包含匹配返回 Top-K 文档
  • 实现 from_documents 类方法,支持与 VectorStore 配合使用时的工厂创建模式
  • agent.pycreate_retriever_knowledge() 中,直接传入预构造的 Document 列表,不依赖 Embedding 模型

环境与运行

环境要求

  • Python 3.12

安装步骤

git clone https://github.com/trpc-group/trpc-agent-python.git
cd trpc-agent-python
python3 -m venv .venv
source .venv/bin/activate
pip3 install -e ".[knowledge]"

注意:本示例依赖 langchain-text-splitterslangchain-communitylangchain-huggingface 等包, 必须使用 pip3 install -e ".[knowledge]" 安装 knowledge 可选依赖,否则会报 ModuleNotFoundError

环境变量要求

examples/knowledge_with_custom_components/.env 中配置(或通过 export):

  • TRPC_AGENT_API_KEY
  • TRPC_AGENT_BASE_URL
  • TRPC_AGENT_MODEL_NAME

运行命令

cd examples/knowledge_with_custom_components
python3 run_agent.py

运行结果(实测)

==================================================
Demo 1: Custom Document Loader
==================================================
Warning: You are sending unauthenticated requests to the HF Hub. Please set a HF_TOKEN to enable higher rate limits and faster downloads.
Loading weights: 100%|██████████████████████████████████████████████████████████████| 199/199 [00:00<00:00, 6858.73it/s]
BertModel LOAD REPORT from: BAAI/bge-small-en-v1.5
Key                     | Status     |  |
------------------------+------------+--+-
embeddings.position_ids | UNEXPECTED |  |

Notes:
- UNEXPECTED:   can be ignored when loading from different task/architecture; not ok if you expect identical arch.
📝 Query: beijing
🤖 Result: {'status': 'success', 'report': 'content: beijing: cloudy'}
----------------------------------------
==================================================
Demo 2: Custom Text Splitter
==================================================
Loading weights: 100%|██████████████████████████████████████████████████████████████| 199/199 [00:00<00:00, 14694.83it/s]
BertModel LOAD REPORT from: BAAI/bge-small-en-v1.5
Key                     | Status     |  |
------------------------+------------+--+-
embeddings.position_ids | UNEXPECTED |  |

Notes:
- UNEXPECTED:   can be ignored when loading from different task/architecture; not ok if you expect identical arch.
📝 Query: beijing
🤖 Result: {'status': 'success', 'report': 'content: beijing: cloudy'}
----------------------------------------
==================================================
Demo 3: Custom Retriever
==================================================
📝 Query: Shenzhen
🤖 Result: {'status': 'success', 'report': 'content: Shenzhen: sunny'}
----------------------------------------

结果分析(是否符合要求)

结论:符合本示例测试要求

  • Loader 链路正确CustomDocumentLoader 逐行加载测试文件后,经 RecursiveCharacterTextSplitter 分割并入库,查询 beijing 成功返回 beijing: cloudy
  • Splitter 链路正确CustomTextSplitter\n 分割文档后入库,同样查询 beijing 返回 beijing: cloudy,说明自定义分割逻辑生效
  • Retriever 链路正确ToyRetriever 基于关键词匹配,查询 Shenzhen 正确返回 Shenzhen: sunny,无需 Embedding 模型参与
  • 组件替换透明:三组 Demo 均通过 LangchainKnowledge 统一接口调用 search,验证了自定义组件可无缝替换默认实现

适用场景建议

  • 需要自定义文档加载逻辑(如从数据库、API 加载):参考 Demo 1 的 CustomDocumentLoader
  • 需要自定义文本分割策略(如按段落、按标记分割):参考 Demo 2 的 CustomTextSplitter
  • 需要自定义检索逻辑(如关键词匹配、混合检索):参考 Demo 3 的 ToyRetriever
  • 快速验证 LangchainKnowledge 组件替换是否正常工作:适合使用本示例

参考文档