尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Langchain-Chatchat 单次知识库检索工具解析:search_knowledgebase_once 与 LLMKnowledgeChain 的实现原理

Langchain-Chatchat 单次知识库检索工具解析:search_knowledgebase_once 与 LLMKnowledgeChain 的实现原理 Langchain-Chatchat 单次知识库检索工具解析search_knowledgebase_once 与 LLMKnowledgeChain 的实现原理【免费下载链接】Langchain-ChatchatLangchain-Chatchat原Langchain-ChatGLM基于 Langchain 与 ChatGLM, Qwen 与 Llama 等语言模型的 RAG 与 Agent 应用 | Langchain-Chatchat (formerly langchain-ChatGLM), local knowledge based LLM (like ChatGLM, Qwen and Llama) RAG and Agent app with langchain项目地址: https://gitcode.com/GitHub_Trending/la/Langchain-Chatchat本指南围绕 Langchain-Chatchat 仓库工具文档 search_knowledgebase_once.md 所描述的技术主体展开这是一条面向 Agent 场景的**「LLM 裁决 单次知识库检索」**调用链核心由底层异步检索函数search_knowledge_base_iter与编排类LLMKnowledgeChain构成。读者读完可掌握知识库检索链路中各参数top_k、score_threshold、temperature、max_tokens、prompt_name 等的真实语义与默认值来源、LLM 输出如何被解析并裁决为“检索动作”或“错误提示”、以及该旧版工具设计与当前仓库 tools_factory 注册式实现的演进关系。文中涉及源码均以仓库实际文件为准并给出相对路径便于继续深入研读。1. 这个工具要解决什么问题在 RAG 应用中“检索知识库”往往不是无条件执行的。更常见的形态是由大语言模型先判断用户问题是否需要查本地知识库、要去哪个库查、以及查完该如何把结果组织成答案。search_knowledgebase_once描述的就是这类场景中最轻量的一种——仅在单轮推理中执行一次知识库检索首先LLM 依据 prompt 判断当前 query 是否“值得检索”并在输出中给出候选查询串然后代码从 LLM 输出中解析出该查询串封装成对指定知识库的检索请求最后把检索得到的回答作为最终输出返回链路即告结束不再进行二次或多库检索。从仓库的文档体系可以看出一条清晰的设计脉络。与它同级的还有两个姊妹工具文档search_knowledgebase_simple.md不经过 LLM 裁决给定 query 直接检索并返回最后一次迭代的回答search_knowledgebase_complex.md通过search_knowledge_multiple以asyncio.gather对多个知识库并行发起检索属于复杂版。三者共用同一个底层异步检索函数search_knowledge_base_iter差异仅在于「是否多轮、是否多库、是否带 LLM 裁决」。once恰好夹在两者之间有 LLM 判断但只检索一次。从这种分层可以推断设计者希望 Agent 根据任务复杂度选择合适粒度的知识库工具。需要特别说明的是本指南所述实现来自仓库 markdown_docs 目录中对该工具的 AutoDoc 描述对应的旧版实现代码文档中提及的server/agent/tools/__init__.py、server/agent/tools_select.py等模块在当前仓库分支中已逐步被 tools_factory 目录下的注册式工具框架取代当前仓库中真正面向 Agent 的本地知识库工具为 search_local_knowledgebase.py。因此本文在忠实还原该工具文档所描述设计的同时也会对照当前源码给出可验证的参数语义与迁移参考。2. 底层异步检索函数search_knowledge_base_iter2.1 函数签名与职责search_knowledge_base_iter(database, query)参数类型含义databasestr要检索的知识库名称querystr用户查询语句该函数是一个async函数职责是调用知识库对话接口、以流式方式迭代返回的每个数据块、把分块 JSON 中的回答内容解析并拼接为最终字符串。它屏蔽了 HTTP/流式响应细节为上层simple/once/complex 三种工具提供一个统一的await search_knowledge_base_iter(...)即可拿到完整回答的异步原语。2.2 转发到知识库对话时使用的关键参数文档明确指出函数在发起请求时设置了一组“精确控制知识库搜索和回答生成行为”的参数model使用的 LLM 模型名称temperatureLLM 采样温度history历史对话记录top_k向量检索返回的候选文档条数max_tokens生成的最大 token 数prompt_name使用的 prompt 模板名称score_threshold知识库匹配相关度阈值stream是否流式输出。这些参数与仓库当前 API 实现 kb_chat.py 中knowledge_base_chat接口从 L30 起的参数一一对应其默认值并非写死而是取自全局设置对象Settings。这一点可从 settings.py 得到验证KBSettings.VECTOR_SEARCH_TOP_K 默认3即默认取回 3 条最相关向量文档源码注释也提示该值与 tool 配置存在重复属于已知演进点KBSettings.SCORE_THRESHOLD 默认2.0KBSettings.KB_INFO 以{samples: 关于本项目issue的解答}这类键值对维护「知识库名 → 用途说明」映射它是 LLM 判断该去哪个库检索的上下文来源model_settings.TEMPERATURE 默认0.7MAX_TOKENS 默认None代表不限制、取模型上限。关于score_threshold的方向性kb_doc_api.py 中search_docs的接口注释给出了权威解释“SCORE 越小相关度越高取到 2 相当于不筛选建议设置在 0.5 左右”。也就是说本工具文档所述的 score_threshold 阈值越小检索越严格默认值 2.0 表示默认不做过滤——若 Agent 需要高精度检索应当显式收紧该值。在底层文档检索层面search_docs 还会接收file_name支持 SQL 通配符与metadata仅支持一级键过滤两个参数用来在知识库内部进一步圈定检索范围。2.3 流式响应如何被逐块消费search_knowledge_base_iter内部通过异步迭代response.body_iterator消费响应体每一次迭代取得的data是一个 JSON 字符串代表回答生成过程中的一个数据分片使用json.loads将其解析为字典从字典中提取「回答」字段并累加/拼接文档信息docs字段在本实现中被解析出来但并未参与后续处理。这种“先解析、后拼接、忽略文档明细”的策略与当前仓库中流式对话的底层语义一致在 kb_chat.py 中流式模式下服务端会把文档引用docs作为第一个分片先行下发随后callback.aiter()逐个产出 token而在非流式模式下则把 token 累加成完整answer后一次性返回。从源码结构看search_knowledge_base_iter更接近后一种「取最终累加回答」的消费模式。需要提醒由于docs被解析后即被丢弃search_knowledge_base_iter返回的只是纯文本回答若上层 Agent 需要携带引用出处就必须像 kb_chat.py 的 OpenAIChatOutput 那样自行扩展数据块处理逻辑。3. 编排核心LLMKnowledgeChainLLMKnowledgeChain是本工具文档中最核心的类它把「LLM 输出 → 是否检索 → 检索 → 给出答案」编排成 LangChain 意义上的一个 Chain。从方法构成可以推断它的整体执行模型是经典的BaseChain模式以_call/_acall为同步/异步执行入口通过_chain_type暴露类型标识通过from_llm提供最常用的构造方式。3.1 内部配置类Config严格模式类内嵌的Config使用 Pydantic 定义模型级配置extra Extra.forbid禁止传入未声明的额外字段。一旦实例化参数中出现模型未定义字段即抛错保证数据对象纯净、一致性高防止意外数据被静默吞掉arbitrary_types_allowed True允许任意类型作为字段类型。默认 Pydantic 只允许标准 Python 类型或 Pydantic 类型开启后可承载自定义类等复杂结构。这两项配置在本场景中是配套出现的Chain 内部需要容纳LLMChain、BasePromptTemplate等 LangChain 自定义类型因此必须开arbitrary_types_allowed同时又要对构造参数做严格白名单校验因此必须forbid额外字段从源头上拦截拼写错误的参数名。3.2raise_deprecation旧式实例化的平滑兼容该函数被设计为 Pydantic v1 的 validatorroot_validator风格挂在类构造入口上处理已弃用的实例化方式检查传入values字典是否含llm键若含则发出警告直接使用llm参数实例化LLMKnowledgeChain已弃用建议改用llm_chain参数或from_llm类方法若values中既没有llm_chain且llm非None则取values[prompt]缺省用模块级默认提示模板PROMPT构造一个LLMChain(llm..., prompt...)写入values[llm_chain]返回更新后的values。该逻辑的收益在于即便旧调用方仍以LLMKnowledgeChain(llmmodel, promptprompt)的方式创建对象也能在收到弃用警告的同时被自动转换为新结构保证存量调用不中断。3.3 输入/输出键与链类型标识input_keys(self)返回[self.input_key]即该 Chain 期望的输入键列表通常为单个查询键output_keys(self)返回[self.output_key]代表输出的结果键也是最终返回字典的键名_chain_type(self)返回固定字符串llm_knowledge_chain用于日志、序列化与框架对链类型的识别。三者都带有:meta private:语义属于类内部约定接口。尤其output_key直接决定了_process_llm_result返回字典的键名使用前必须确保已正确设置。3.4from_llm推荐的构造入口LLMKnowledgeChain.from_llm(llm, promptPROMPT, **kwargs)llmBaseLanguageModel实例即要使用的语言模型promptBasePromptTemplate缺省为PROMPT**kwargs透传给构造函数例如本工具文档明确记录的verboseTrue开启详细日志输出。方法内部先用llmprompt构造LLMChain再以该LLMChain组装出LLMKnowledgeChain返回。文档中给出的典型用法为llm_knowledge_chain LLMKnowledgeChain.from_llm(model, promptPROMPT, verboseTrue) answer llm_knowledge_chain.run(这是一个查询示例) print(answer)4. “是否真的需要检索”的裁决逻辑4.1_process_llm_result把模型输出变成动作_process_llm_result(self, llm_output, llm_input, run_manager)负责把 LLM 的原始文本输出翻译为“可执行的检索动作”处理流程如下通过run_manager.on_text(...)以绿色文本把 LLM 原始输出推给回调系统输出详细程度由verbose决定——这也是from_llm(..., verboseTrue)的意义所在用正则表达式在输出中匹配文本块Final Answer/Answer:等约定格式若匹配成功将提取出的内容连同原始输入交给_evaluate_expression执行真正的知识库检索并生成答案若原始输出本身以Answer:开头或包含Answer:则直接把该段作为答案若前两者都不满足说明模型输出不符合约定格式返回错误信息输入的格式不对: {原始语言模型输出内容}。可推断出的返回形态键名由output_key决定# 正常路径 {output_key: Answer: 这是根据您的查询生成的回答。} # 格式异常路径 {output_key: 输入的格式不对: 原始语言模型输出内容}与其对应的异步版本_aprocess_llm_result(self, llm_output, run_manager)在文档中标记为待补充从命名与 LangChain 惯例可以推断它与同步版本职责等价服务于_acall异步执行路径。4.2_evaluate_expression真正发起一次检索_evaluate_expression(self, dataset, query)是把裁决落到实处的执行者它接收dataset知识库名与query待检索语句内部通过asyncio.run(search_knowledge_base_iter(dataset, query))运行第 2 节的异步检索函数。注意这里asyncio.run的存在意味着_evaluate_expression自身是同步函数它只是临时创建事件循环去驱动异步检索——这是旧式工具代码中常见的“桥接”写法检索成功则返回拼接后的回答字符串一旦抛出任何异常如知识库不存在、查询语句非法捕获后统一返回兜底文案输入的信息有误或不存在知识库。由此整条裁决链可以归纳为LLM 原始输出 → 正则解析 (Final Answer / Answer: 文本块) → _evaluate_expression(dataset, query) → asyncio.run(search_knowledge_base_iter(...)) → knowledge_base_chat(知识库对话接口) → body_iterator 逐块解析 拼接 → 返回回答 / 输入的信息有误或不存在知识库 → 解析失败则返回 输入的格式不对: ...4.3KnowledgeSearchInput检索入参模型工具尾部定义了KnowledgeSearchInput(BaseModel)内含唯一字段locationField(..., descriptionThe query to be searched)即要在知识库中检索的查询串。这是一个典型的工具参数 Schema。它可以被用来声明 Agent 调用该工具时的入参校验规则结合 Pydantic 的BaseModel能力将字符串非法赋值等问题在入口处拦截。文档也提示若知识库结构或检索需求更复杂可在此模型上扩展更多字段与验证逻辑。5. 对外入口与文档留白search_knowledgebase_once(query)在文档中标注为 “Doc is waiting to be generated”正文留白。不过从文档对from_llm被调用场景的说明可以还原其真实行为“from_llm被search_knowledgebase_once调用model语言模型实例与PROMPT提示模板被传入同时附带verboseTrue。随后search_knowledgebase_once用返回的LLMKnowledgeChain实例执行对给定查询的搜索。”因此可以推断入口实现遵循以下模板def search_knowledgebase_once(query: str): model ... # 从模型容器中取出当前 LLM chain LLMKnowledgeChain.from_llm(model, promptPROMPT, verboseTrue) return chain.run(query)PROMPT在文档中被反复引用为模块级默认提示模板raise_deprecation构造默认LLMChain时也回退到它它的作用是引导模型“面对该 query先判断是否需要检索知识库若需要以指定格式输出待检索的查询串”。这也再次印证 once 变体的定位——检索动作本身要经 LLM 认可后才发生一次。6. 在知识库工具家族中的取舍对照三个文档可以给出实用的选型建议变体LLM 裁决检索次数检索范围适用场景search_knowledgebase_simple无一次单库库名预设已明确必须查库的短任务追求低延迟search_knowledgebase_once本文有一次单库需判断是否值得查库、但一次命中即可的问答search_knowledgebase_complex有多次并行多库需要跨库对照、聚合多个知识源的问题其中simple直接同步包装异步检索asyncio.run(search_knowledge_base_iter(...))once在其外层加上LLMKnowledgeChain裁决complex则把单次检索封装成任务并用asyncio.gather并行。三种变体的延迟与召回覆盖面随复杂度递增可根据 Agent 的模型能力与任务类型权衡。7. 与当前仓库实现的对照与迁移参考尽管 once 变体的旧版实现已不在当前工具目录但它表达的「知识库检索工具」能力在现仓库中由 search_local_knowledgebase.py 承担对照阅读可发现如下演进参数外置旧版把top_k、score_threshold等参数直接设置进转发调用新版则通过get_tool_config(search_local_knowledgebase)见 utils.py 中get_tool_config从Settings.tool_settings动态读取同名配置参数与代码解耦输入 Schema 显式化新版工具函数的两个参数database、query直接用 PydanticField声明其中database的choices来自list_kbs()运行时真实存在的知识库列表description成为 LLM 选择参数时的依据注册机制取代手写 Chainsearch_local_knowledgebase通过regist_tool(...)装饰器见 tools_registry.py自动完成工具注册、description 规整与人类可读 title 生成工具集从“写死”走向“可插拔”检索能力下放新工具内部直接调用search_docs(query, knowledge_base_name, top_k, score_threshold, ...)返回带出处format_context的文档列表把「是否送 LLM 总结」的决策交给上层 Agent 框架而不是像旧版 Chain 那样把检索与问答强绑定。这也解释了旧版docs被解析却未使用、新版却刻意保留文档上下文的原因新架构把「引用来源」作为一等公民交给 Agent 呈现。8. 关键注意事项search_knowledge_base_iter是异步函数调用必须await如果从同步代码驱动只能像_evaluate_expression那样借助asyncio.run临时建事件循环注意不要在已有事件循环的线程中直接调用确保database指定的知识库真实存在可通过list_kbs动态确认否则检索阶段会落入输入的信息有误或不存在知识库的兜底分支score_threshold语义为“分数越小相关度越高”默认 2.0 等于不筛选追求准确率请显式收紧到 0.5 左右追求召回请保持宽松top_k默认 3表示进入上下文的最相关候选数它与 tool 配置项在源码中已被标记为重复项配置时应留意两个位置的生效关系_process_llm_result依赖特定模型的输出结构换用不同模型/提示词时需同步核对正则与文本块约定否则会高频触发输入的格式不对: ...直接传llm构造LLMKnowledgeChain的方式已被raise_deprecation标记弃用请优先使用from_llm(llm, prompt..., verbose...)或显式传入llm_chain。9. 延伸阅读同类工具的横向对比 search_knowledgebase_simple.md、search_knowledgebase_complex.md知识库对话 API 的完整参数与流式语义kb_chat.py向量检索函数与阈值语义kb_doc_api.py全局配置默认值 settings.py新式知识库工具的注册式实现search_local_knowledgebase.py 与 tools_registry.py。【免费下载链接】Langchain-ChatchatLangchain-Chatchat原Langchain-ChatGLM基于 Langchain 与 ChatGLM, Qwen 与 Llama 等语言模型的 RAG 与 Agent 应用 | Langchain-Chatchat (formerly langchain-ChatGLM), local knowledge based LLM (like ChatGLM, Qwen and Llama) RAG and Agent app with langchain项目地址: https://gitcode.com/GitHub_Trending/la/Langchain-Chatchat创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表