首页
/ Langchain-Chatchat 大模型应用技术原理:RAG 向量库选型、混合检索与 Agent Function Call 实战

Langchain-Chatchat 大模型应用技术原理:RAG 向量库选型、混合检索与 Agent Function Call 实战

2026-09-05 16:45:44作者:裴锟轩Denise

本文围绕 Langchain-Chatchat 内置样例知识库文档《大模型应用技术原理》展开,系统梳理 RAG 应用的技术骨架——向量数据库选型标准、索引算法与量化方法、Embedding 模型、混合检索(向量检索 + BM25 关键字检索)以及 RAG 增强(Self-RAG)与 Agent 的 function call 机制,并逐一对照本仓库源码中的知识库服务与检索器实现。读完本文,你既能掌握大模型应用技术选型的方法论,也能在 Langchain-Chatchat 的代码中找到每项技术的落地点。

一、RAG 应用的总体技术骨架

从样例文档的思维导图结构看,一个完整的 RAG(Retrieval-Augmented Generation,检索增强生成)应用由以下层次组成:

  1. 向量数据库:存储文本切片(chunk)的向量表示,支持相似度检索,是 RAG 的存储底座;
  2. Embedding 模型:把文本编码为向量,分为 bi-encoder(双塔编码器)与 cross-encoder(交叉编码器)两类;
  3. 【可选】文本检索引擎:如 ElasticSearch、OpenSearch,提供关键字/全文检索能力;
  4. 【可选】图数据库:用于结构化知识检索,配合 NL2Cypher 使用;
  5. 检索:向量检索、关键字检索(BM25)、NL2Cypher、NL2SQL 等多种方式组合;
  6. RAG 增强:如 Self-RAG,通过反思机制提升检索与生成质量;
  7. Agent:通过 function call 让大模型调用外部工具,ToolFormer 是这一方向的经典工作。

Langchain-Chatchat 本身就是这条技术链路的一个完整工程实现:其知识库子系统(chatchat/server/knowledge_base/)覆盖文档加载、文本切片、向量化、存储与检索;Agent 子系统(chatchat/server/agent/)则以工具注册表的方式实现 function call。下文逐层展开。

二、向量数据库选型标准

文档给出了四个维度的选型标准,这是向量库选型时的通用方法论。

2.1 开源 vs 闭源 vs 源码可见

  • 开源项目(如 faiss、milvus)可自托管、可修改源码,便于审计与二次开发;
  • 闭源/托管服务(如 pinecone)以完全云原生方式交付,上手成本最低,但依赖厂商与网络环境;
  • 源码可见介于两者之间,商业支持更完善。

2.2 客户端/SDK 语言

选型时需确认服务端是否有目标语言的官方 SDK(Python、Java、Go、Node.js 等)。faiss 支持 C++、Python、Go 客户端;milvus 提供 Python、Java、Go、Node.js SDK,还提供 milvus lite 这种 in-memory 运行形态。

2.3 托管方式

文档将向量库按部署形态划分为四类:

形态 代表方案 特点
self-hosted / on-premise redis、pgvector、milvus 自托管,数据留在本地,运维成本自担
managed / cloud-native zilliz、pinecone 云托管,开箱即用
embeded + cloud-native chroma、LanceDB 嵌入式部署,本地轻量使用
self-hosted + cloud-native vald、drant、weaviate、vespa、elasticsearch 两种形态均支持

Langchain-Chatchat 的 kbs_config 配置恰好体现了这一谱系:同一个应用内同时支持 faiss(本地文件)、milvus(自托管)、zilliz(云托管)、pg/relyt(pgvector 路线)、es(ElasticSearch)、chromadb(嵌入式)等多种后端,详见 settings.py 中的 KBSettings

2.4 索引方法与量化

文档列出了向量索引算法的完整分类树:

  • Flat:暴力精确检索,小数据集下精度最高;
  • Tree-based:Annoy、KD-Tree、Trinary Projection Trees;
  • IVF:Inverted File,含 IVMF(Inverted Multi-index File);
  • Graph-based:HNSW、NSG、Vamana(DiskANN);
  • Hashing-based:LSH、Spherical Hashing、Spectral Hashing。

量化方面,文档给出了两种压缩手段的定义:

  • PQ(Product Quantization,乘积量化):将特征空间分解为多个低维子空间的笛卡尔乘积,然后单独地对每一个子空间进行量化,从而大幅压缩向量存储;
  • SQ(Scalar Quantization,标量量化):将每一个维度量化成指定位数的一个数。

仓库中的实现印证:Langchain-Chatchat 对 Milvus 的默认索引配置就是 Graph-based 中的 HNSW,见 settings.py 的 milvus_kwargs

"milvus_kwargs": {
    "search_params": {
        "metric_type": "L2"
    },
    "index_params": {
        "metric_type": "L2",
        "index_type": "HNSW"
    }
}

这段配置在 MilvusKBService._load_milvus 中被直接传入 Milvus 向量库构造函数的 index_paramssearch_params 参数,说明用户修改 kb_settings.yaml 后,索引算法(如 HNSW 换 IVF)与距离度量(L2、IP 等)可以随配置切换。

三、主流向量库方案解析

3.1 文档中的方案要点

文档将主流方案分为 professional(专业向量库)与 traditional(传统数据库扩展)两类:

专业向量库

  • weaviate:文档丰富容易上手;提供混合索引;支持自托管 + 云原生;支持 Python、JS、TS、Go、Java 等客户端;支持 HNSW、HNSW-PQ、DiskANN 等索引;
  • chromaLanceDB:嵌入式 + 云原生形态,适合本地轻量场景;
  • pinecone:完全云原生,非常容易上手;支持自建复合索引;
  • faiss:来自 Meta AI 的开源项目;同时支持 CPU 和 GPU;支持 C++、Python、Go 客户端;支持 IVF、HNSW 等常见索引方式与 PQ 量化;in-memory 运行;self-hosted;
  • milvus:通过代理、负载均衡器、消息代理、Kafka 和 Kubernetes 的组合实现了高度可扩展性(系统也因此变得复杂和资源密集);截至 2023 年它是唯一一个提供可工作 DiskANN 实现的主要供应商;支持在向量相似度检索过程中进行标量字段过滤,实现混合查询;采用存储与计算分离的架构设计;提供 Python、Java、Go、Node.js 等语言 SDK,也提供 milvus lite 等 in-memory 运行方式;提供图形界面客户端。

传统方案:ES(ElasticSearch)、redis、pgvector。

3.2 Langchain-Chatchat 中的向量库落地

支持的后端清单kb_service/base.py 中的 SupportedVSType 枚举定义了当前仓库实际接入的全部向量后端:

class SupportedVSType:
    FAISS = "faiss"
    MILVUS = "milvus"
    DEFAULT = "default"
    ZILLIZ = "zilliz"
    PG = "pg"
    RELYT = "relyt"
    ES = "es"
    CHROMADB = "chromadb"

工厂分发KBServiceFactory.get_servicevs_type 字符串惰性导入并实例化对应的 KBService 子类:faiss 返回 FaissKBService,milvus/zilliz/default 返回 MilvusKBService,pg/relyt/es/chromadb 各自对应独立服务类。每个知识库在元数据库中记录自己的 vs_typeembed_modelget_service_by_name 可以按名重建服务实例,实现了"一个应用、多种向量后端、互不干扰"的架构。

faiss 的实现要点FaissKBService 印证了文档中 faiss"in-memory 运行 + self-hosted"的定位:

  • 向量库通过 kb_faiss_pool(线程安全的 FAISS 连接池)按 (kb_name, vector_name) 键加载与缓存,对应配置项 CACHED_VS_NUM(缓存向量库数量,见 settings.py);
  • 增删文档后调用 vs.save_local(self.vs_path) 持久化到磁盘,重启后可从磁盘重新加载;
  • 每个知识库的向量目录名由 Embedding 模型决定:self.vector_name = self.embed_model.replace(":", "_")。这意味着同一个知识库换用不同 Embedding 模型时必须重建向量库——因为不同模型对同一段文本产生的向量并不可比。

milvus 的实现要点MilvusKBService 体现了文档所述 milvus"高度可扩展"的一面:连接参数(host/port/user/password/secure)从 kbs_config["milvus"] 读取;删除文档时用主键表达式 pk in {id_list} 批量删除;搜索参数使用 metric_type: "L2"nprobe: 10(见 MilvusKBService.search)。

各后端的连接配置。以 settings.py 的 kbs_config 为准:

"faiss": {},
"milvus": {"host": "127.0.0.1", "port": "19530", "user": "", "password": "", "secure": False},
"zilliz": {"host": "...vectordb.zilliz.com.cn", "port": "19530", "secure": True},
"pg": {"connection_uri": "postgresql://postgres:postgres@127.0.0.1:5432/langchain_chatchat"},
"relyt": {"connection_uri": "postgresql+psycopg2://postgres:postgres@127.0.0.1:7000/langchain_chatchat"},
"es": {"scheme": "http", "host": "127.0.0.1", "port": "9200", "index_name": "test_index", ...},
"chromadb": {}

这与文档中"self-hosted / managed / embedded"的分类一一对应:milvus 走本地自托管,zilliz 走云托管(secure=True),pg/relyt 走 pgvector 路线,es 走传统检索引擎,chromadb 走嵌入式。

四、Embedding 模型:bi-encoder 与 cross-encoder

文档将 Embedding 模型分为两类:

  • bi-encoder(双塔编码器):查询与文档分别独立编码为向量,再做相似度计算。因为文档向量可以离线预计算并存入向量数据库,所以它是 RAG 在线检索的标准选择;
  • cross-encoder(交叉编码器):查询与文档拼接后共同编码、直接输出相关性分数,精度通常更高,但每次查询都需实时推理,无法预计算,一般用于**重排(rerank)**环节。

在 Langchain-Chatchat 中的体现:知识库服务构造时都会接收 embed_model 参数(见 KBService.init,默认值来自 get_default_embedding()),并向量库的向量目录名直接由该模型字符串派生(第二节已述)。KBService.add_doc 在入库前会先调用 check_embed_model() 校验模型可用性,失败则拒绝写入,防止不可用模型产生的向量污染知识库。

从源码结构看,文档中"bi-encoder/cross-encoder"的分工在本仓库体现为:入库与检索阶段使用可预计算的编码模型;排序阶段可结合 reranker 模块chatchat/server/reranker/),后者即 cross-encoder 思想的应用场景。

五、混合检索:向量检索 + BM25 关键字检索

文档"检索"一节点列出向量检索、关键字检索(BM25)、NL2Cypher、NL2SQL 四类方式。Langchain-Chatchat 前两者的结合实现最为完整,是"混合检索"的典型工程范式。

5.1 检索器工厂

retrievers 提供三种检索服务,由 get_Retriever 统一分发:

Retrivals = {
    "milvusvectorstore": MilvusVectorstoreRetrieverService,
    "vectorstore": VectorstoreRetrieverService,
    "ensemble": EnsembleRetrieverService,
}

5.2 纯向量检索

VectorstoreRetrieverService.from_vectorstore 使用 similarity_score_threshold 搜索类型,传入 score_thresholdk 两个参数构造检索器,并在返回时再截断到 top_k

5.3 混合检索(ensemble)的实现

EnsembleRetrieverService.from_vectorstore 完整实现了文档中"向量检索 + 关键字检索(BM25)"的组合:

faiss_retriever = vectorstore.as_retriever(
    search_type="similarity_score_threshold",
    search_kwargs={"score_threshold": score_threshold, "k": top_k},
)
import jieba
docs = list(vectorstore.docstore._dict.values())
bm25_retriever = BM25Retriever.from_documents(
    docs,
    preprocess_func=jieba.lcut_for_search,   # 中文分词预处理
)
bm25_retriever.k = top_k
ensemble_retriever = EnsembleRetriever(
    retrievers=[bm25_retriever, faiss_retriever], weights=[0.5, 0.5]
)

三个值得注意的工程细节:

  1. 中文分词:BM25 的 preprocess_func 使用 jieba.lcut_for_search 做中文搜索模式分词,避免英文按空格切分对中文语料失效——源码注释中还保留了用 cutword 替换的 TODO,说明分词器是可插拔的;
  2. 加权融合EnsembleRetriever[0.5, 0.5] 的权重对两路检索的归一化分数加权平均,即向量语义匹配与 BM25 词频匹配各占一半;
  3. FAISS 路径默认走 ensembleFaissKBService.do_search 明确调用 get_Retriever("ensemble"),而 Milvus 路径调用 get_Retriever("milvusvectorstore")——因为 Milvus 自身的标量过滤能力已经覆盖了部分关键字需求(与文档中 milvus"支持标量字段过滤实现混合查询"的描述一致)。

5.4 检索参数:top_k 与 score_threshold

两个关键参数在 settings.py 的 KBSettings 中定义:

VECTOR_SEARCH_TOP_K: int = 3   # 知识库匹配向量数量
SCORE_THRESHOLD: float = 2.0   # 知识库匹配相关度阈值,取值范围在0-2之间,
                               # SCORE越小,相关度越高,取到2相当于不筛选,建议设置在0.5左右

对 FAISS 距离度量而言,分数是"距离"而非"相似度":SCORE_THRESHOLD=2.0 意味着默认不筛选任何文档,配置为 0.5 附近可过滤低相关结果。这两个参数沿 search_docs → do_search → as_retriever(search_kwargs=...) 的调用链最终注入向量库检索器,构成可调的召回质量闸门。

六、可选组件:文本检索引擎与图数据库

文档把文本检索引擎(ElasticSearch、OpenSearch)与图数据库列为 RAG 的可选增强:

  • 文本检索引擎:Langchain-Chatchat 将其作为一类向量后端接入(SupportedVSType.ESes_kb_service.py),配置见 settings.py 的 "es" 段(scheme/host/port/index_name 及证书选项),复用统一的 KBService 抽象;
  • 图数据库:配合 NL2Cypher 做结构化知识检索。当前仓库源码中未见图数据库实现,文档将其标记为【可选】,属于技术路线预留而非现有功能。

七、RAG 增强:Self-RAG

文档用较大篇幅介绍了 Self-RAG(Self-Reflective Retrieval-Augmented Generation,自反思检索增强生成),其核心设计分三个层面:

7.1 框架

Self-RAG 不仅可以根据需要自适应地检索段落(模型可以判断是否有必要进行检索增强),还引入了名为**反思令牌(reflection tokens)**的特殊令牌,使 LM 在推理阶段可控。

7.2 训练

训练分两步:首先训练评论家(critic),使用检索器检索到的段落以及反思令牌增强指令-输出数据;然后使用标准的下一个 token 预测目标来训练生成器 LM,使其学会生成自然延续(continuations)以及特殊 tokens(用来检索或批评其自己的生成内容)。

7.3 推理

推理时模型可以适应性地使用检索令牌进行检索,自发判断是否有必要检索;它引入多种细粒度的批评令牌,用于评估生成内容各个方面的质量。生成过程中使用期望的批评令牌概率的线性插值进行 segment 级 beam search,以在每一个时间步骤中确定最佳的 K 个续写方案。

在 Langchain-Chatchat 中的对照:当前仓库的 RAG 链路属于经典 RAG(检索-拼接-生成),未内置 Self-RAG 的反思令牌机制。从源码结构看,chatchat/server/chat/chatchat/server/agent/ 的模块划分(检索工具与对话生成解耦)为未来在 Agent 层引入"是否需要检索"的自适应判断提供了挂载点,但这属于从代码结构出发的推断,并非现有实现。

八、Agent 与 Function Call

文档的 Agent 部分从 function call(以 ToolFormer 为代表:让模型通过预测特殊标记来自主决定何时、调用哪个工具)展开。Langchain-Chatchat 的 Agent 子系统正是这一思路的工程化实现。

8.1 工具注册机制

tools_registry.py 提供 regist_tool 装饰器,作为 Langchain @tool 装饰器的封装,支持自定义 titledescriptionreturn_directargs_schemainfer_schema 等参数,并维护全局 _TOOLS_REGISTRY 注册表。同目录下的 tools_factory/ 内置了 weather、search_internet、search_youtube、arxiv、text2sql、text2promql、search_local_knowledgebase 等一系列工具实现。

8.2 知识库检索作为 Agent 工具

值得注意的是,Agent 与 RAG 在仓库中并非割裂:tools_factory/search_local_knowledgebase.py 把知识库检索封装为一个可被 LLM 调用的 function call 工具,配合 settings.py 的 KB_INFO 配置("每个知识库的初始化介绍……用于在初始化知识库时显示和 Agent 调用,没写则没有介绍,不会被 Agent 调用"),由大模型自主决定何时向哪个知识库发起检索——这正是文档中 Self-RAG"模型自发判断是否有必要检索"思想在工程上的轻量近似。

8.3 输出解析链路

langchain_chatchat/agents/output_parsers/ 目录下按模型族(glm3、qwen、structured_chat、platform_tools)提供了不同的输出解析器,负责把模型输出的工具调用文本解析为结构化动作,是 function call 循环中"解析-执行-回填"环节的关键组件。

九、小结

回到样例文档《大模型应用技术原理.md》的脉络,本文完成了两条线的工作:

  1. 方法论线:向量库选型四标准(开源形态/SDK 语言/托管方式/索引方法)、Flat-Tree-IVF-Graph-Hashing 五类索引算法、PQ/SQ 两种量化、bi-encoder 与 cross-encoder 两类 Embedding 模型、向量+BM25 混合检索、Self-RAG 自适应检索增强、Agent function call;
  2. 实现线:Langchain-Chatchat 用 SupportedVSType + KBServiceFactory 覆盖了 faiss/milvus/zilliz/pg/relyt/es/chromadb 七类后端,用 EnsembleRetrieverService 实现了 jieba 分词 BM25 与向量检索的 0.5/0.5 加权融合,用 milvus_kwargs 暴露了 HNSW 索引与 L2 度量配置,并用 tools_registry + 输出解析器实现了 function call 的注册与解析。

对于需要在自有知识库上做本地化问答与 Agent 应用的开发者,建议的深入阅读顺序是:先读 settings.py 的 KBSettings 理解全部可调参数,再对照 kb_service/base.py 的抽象接口理解各后端的统一契约,最后进入 retrievers 理解检索融合细节。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
528
588
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
906
1.83 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
docsdocs
暂无描述
Markdown
891
5.79 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.53 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.34 K
1.45 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
988
506
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384