news 2026/9/10 16:49:33

Langchain-Chatchat 知识库模型解析:DocumentWithVSId 向量化文档对象的字段、调用链与实战用法

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Langchain-Chatchat 知识库模型解析:DocumentWithVSId 向量化文档对象的字段、调用链与实战用法

Langchain-Chatchat 知识库模型解析:DocumentWithVSId 向量化文档对象的字段、调用链与实战用法

【免费下载链接】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

DocumentWithVSId是 Langchain-Chatchat 知识库(RAG)体系中最核心的数据载体之一,它定义了"经过向量化检索后返回给上层链路的文档"的标准结构:在 Langchain 原生Document的基础上扩展出idscore两个字段。本篇文章以 kb_document_model.md 文档为骨架,结合 模型定义源码、知识库服务层、文档 API、文档摘要与 Agent 工具注册等真实实现,系统讲解它的类结构、字段语义、三条典型调用链(搜索、列举、摘要),以及在参数调优与二次开发时的注意事项。读完本文,你将能准确理解"向量检索结果中的idscore从哪来、代表什么、如何被消费",并能据此正确使用search_docs/list_docs相关接口或在自定义知识库后端中复用它。

一、类定位:RAG 链路中"检索结果"的统一封装

在 Langchain-Chatchat 的知识库问答(RAG)流程中,一条完整的数据流大致是:用户提问 → 文本向量化 → 在向量库(Faiss / Milvus / Chroma / ES / PG 等)中做相似度检索 →得到若干"向量化后的文档"→ 拼装进 Prompt 交给大模型回答,或用于知识库文件管理、文档摘要等功能模块。

这一环节的返回结果对象正是DocumentWithVSId。正如文档中描述的那样,它"继承自Document类,用于表示一个经过向量化处理的文档",在知识库系统中承担"检索结果 / 处理结果"的统一表示职责。

模型定义文件位于 kb_document_model.py,完整实现十分精简:

from langchain.docstore.document import Document class DocumentWithVSId(Document): """ 矢量化后的文档 """ id: str = None score: float = 3.0

可以看到它利用 Pydantic 模型继承机制,在 Langchain 的Document基础上只新增了两个字段:id(字符串,默认None)与score(浮点数,默认3.0)。底层Document本身自带的page_content(文档正文)与metadata(元数据字典)两个字段会被原样继承,因此一个完整的DocumentWithVSId实例实际承载的信息包括:正文内容、元数据、向量库中的唯一标识id、与查询的相关性评分score四部分。

二、字段语义:id 与 score 分别表示什么

结合 原文档 与源码实现,两个扩展字段的语义如下:

字段类型默认值语义说明
idstrNone文档在知识库 / 向量库中的唯一标识符。文档指出"需保证其唯一性,确保每个实例能够准确对应知识库中的一个具体文档";实践中它常与向量索引中的 doc_id(如 Faiss 缓存中的文档 ID、metadata中的id)保持一致
scorefloat3.0文档与检索查询的匹配度 / 相关性度量,会在搜索、排序等操作中被更新。文档特别提醒"取值可能随操作或上下文环境变化,使用时应注意其含义与计算方式"

关于score的"方向",需要结合 Langchain-Chatchat 的检索实现来理解。在 kb_chat.py 的接口参数注释中明确写道:

知识库匹配相关度阈值,取值范围在 0-1 之间,SCORE越小,相关度越高,取到 1 相当于不筛选,建议设置在 0.5 左右

因此在本项目中,score本质是一种距离 / 不相似度度量而非百分制相似度:数值越小表示与查询越相关,默认值3.0处于"不设限"的量级——即当一个文档实例未经检索打分、只做结构化包装时(例如在按file_name/metadata列举文档的场景下),它不会被误判为"高度相关"。

默认值3.0还有一个直接意义:任何通过DocumentWithVSId(id=..., score=3.0)形式构造的对象,在未进入打分流程前都带有这个"中性"评分,避免后续逻辑对未打分文档做无效的阈值截断。

三、构造方式:两种核心初始化模式

从源码看,DocumentWithVSId的实例化在整个代码库中遵循两种模式,它们都出现在知识库 API 与摘要链路中:

模式一:由底层Document展开后补齐id

在 kb_doc_api.py 中,搜索结果的包装逻辑为:

data = [DocumentWithVSId(**{"id": x.metadata.get("id"), **x.dict()}) for x in docs]

即在保留page_contentmetadata等字段的同时,从文档元数据的id键中提取唯一标识注入id字段(该文件同位置还保留了一行注释掉的旧写法DocumentWithVSId(**x[0].dict(), score=x[1], ...),从侧面印证了score在部分向量库检索实现中作为二元组第二项返回的历史形态)。

模式二:dict()展开后叠加外部id

在文档摘要接口 kb_summary_api.py 中:

doc_info_with_ids = [ DocumentWithVSId(**{**doc.dict(), "id": with_id}) for with_id, doc in zip(doc_ids, doc_infos) ]

将"待摘要的文档 ID 列表"与"按 ID 取回的文档内容列表"一一配对,生成带 ID 的摘要输入。这里的with_id来自知识库服务层的kb.get_doc_by_ids(ids=doc_ids),是各向量库后端实现中真正存储的文档 ID。

此外在知识库服务基类 kb_service/base.py 的list_docs中,同样采用DocumentWithVSId(**{**doc_info.dict(), "id": x["id"]})的形式完成包装。

四、三种核心使用场景与底层调用链

原文档归纳了DocumentWithVSId的三个主要应用场景,下面逐一对应到仓库源码中的真实调用链。

场景一:知识库文档搜索(search_docs)

当调用"知识库文档搜索"接口时,入口位于 kb_doc_api.py 的search_docs

  1. 通过KBServiceFactory.get_service_by_name(knowledge_base_name)取得当前知识库的服务实例(Faiss / Milvus / Chroma / ES / PG 等具体实现);
  2. 有查询词query时调用kb.search_docs(query, top_k, score_threshold)
  3. 服务基类的 search_docs 实现 会先校验 Embedding 模型可用性,再委托给各后端实现的do_search(query, top_k, score_threshold)完成真正的相似度检索;
  4. 返回的每个文档经DocumentWithVSId包装后,通过 HTTP JSON 序列化([x.dict() for x in data])返回给调用方。

此处top_kscore_threshold的默认值分别来自配置项Settings.kb_settings.VECTOR_SEARCH_TOP_KSettings.kb_settings.SCORE_THRESHOLD。这两个参数会直接影响返回的DocumentWithVSId数量与评分分布——在服务层检索时,低于score_threshold(即相似度过低 / 距离过大)的结果会被过滤掉。

该接口也被知识库对话直接复用:在 kb_chat.py 的知识库问答流程中,同样会以querytop_kscore_threshold等参数触发上面的搜索链路,随后将检索出的文档交给format_reference格式化,作为"引用出处"一并呈现在回答中。

场景二:按文件名 / 元数据列举与过滤文档(list_docs)

当知识库文件管理界面需要"按文件名或元数据列出文档内容"时,会走 kb_service/base.py 的 list_docs:

  1. 先从数据库仓库层list_docs_from_db(kb_name, file_name, metadata)查出符合条件(支持文件名与一级键元数据过滤)的文档信息列表doc_infos
  2. 对每个x通过get_doc_by_ids([x["id"]])[0]从向量库按 ID 取回真实文档内容;
  3. 非空时包装为DocumentWithVSId(**{**doc_info.dict(), "id": x["id"]})加入结果列表,为空时跳过该条(源码中的pass分支)。

对应的 HTTP 入口同样是 kb_doc_api.py,当请求只携带file_namemetadata而不携带query时触发。值得注意的一个实现细节是:为降低响应体积,该路径返回前会执行del d.metadata["vector"],从元数据中剔除向量字段后再序列化输出。

在该场景下返回的文档实例score保持默认的3.0,因为并未发生真正的相似度计算,这也再次验证了原文档"score 会随操作环境变化"的说明。

场景三:文档摘要(KBSummary)中的输入载体

DocumentWithVSId也是知识库文档摘要功能的输入格式。调用链位于 kb_summary_api.py 的recreate_summary_vector_store/summary_doc_ids_to_vector_store系列接口:

  1. 通过kb.get_doc_by_ids(ids=doc_ids)按 ID 批量取回待摘要文档;
  2. 如前述"模式二"构造出doc_info_with_ids(即一串DocumentWithVSId);
  3. 交给 summary_chunk.py 中的SummaryAdapter(内部使用MapReduceDocumentsChain做分块-合并式摘要)的summarize(file_description=..., docs=doc_info_with_ids)生成摘要;
  4. 摘要结果随后按原文档 ID 回写知识库摘要存储,从而支持后续的"摘要级"检索与引用。

在这里,id承担的是"把摘要结果与原始文档关联回写"的关键职责,缺失或错乱的id将直接导致摘要与原文无法对应。

五、在 Agent 工具与 WebUI 中的进一步消费

除了知识库服务层,DocumentWithVSId还被更高层的 Agent 与前端界面所消费:

  • Agent 工具上下文组装:在 tools_registry.py 的format_context中,Agent 搜索知识库得到的结果集docs会逐条执行DocumentWithVSId.parse_obj(doc)反序列化,再抽取doc.page_content拼装为给大模型的上下文文本;若结果为空,则生成"没有找到相关文档,请更换关键词重试"的提示语。这说明DocumentWithVSId不仅存活在服务端内部,还会以 JSON 形态跨进程传输后被再次解析。
  • WebUI 对话页:在 dialogue.py 中,该模型类被导入用于对知识库引用文档做类型化处理(与format_reference配合渲染答案下方的引用出处)。从导入关系看,WebUI 直接引用的是chatchat.server.knowledge_base.model.kb_document_model,即本模型文件中的类,而 Agent 侧则经由kb_doc_api间接导入。

由此可见,从"向量库检索结果"到"对话引用展示",再到"Agent 工具返回",DocumentWithVSId是整个知识库召回结果的标准数据契约。

六、源码结构上的设计说明与注意事项

最后,结合源码与文档的"注意"提示,归纳几条对二次开发最有价值的设计要点:

  1. 极轻量的继承扩展:模型文件本身只有 3 个有效代码行,设计上刻意不复制 LangchainDocument的字段,而是依靠 Pydantic 继承自动获得page_contentmetadata等能力。任何知识库后端只要返回"标准Document+ 额外 ID",即可无损转换为DocumentWithVSId
  2. id的唯一性约定id默认None,但按文档要求它应当与知识库 / 向量库中的某个具体文档一一对应。在 Faiss 等本地缓存实现与数据库记录之间,正是靠这个id完成"文件—分块—向量—摘要"的多层关联,因此不要随意置空或复用
  3. score的语义随场景漂移:检索场景下它是"越小越相关"的距离型度量,并受SCORE_THRESHOLD(默认由 kb_settings 配置)影响;列举场景下它保持默认值3.0,不参与任何过滤。消费端切勿假设"score 高即相关"。
  4. 直接可用的序列化能力:由于继承自 Pydantic 模型,DocumentWithVSId天然支持dict()(源码中多次使用)、parse_obj()(Agent 工具侧使用)与 JSON 序列化,跨进程、跨模块传递非常方便,这解释了为何它能在 API 返回体与 WebUI 中自由流动。
  5. 扩展自定义字段的落点:如需要给检索结果附加更多信息(如来源文件、页码、块序号等),惯例是写入继承自Documentmetadata字典,而不是修改模型类的字段集——项目各 API 均已按此约定从metadata读取或剔除(如idmetadata["id"]提取、vectormetadata中删除)。

七、小结

DocumentWithVSId虽然是一个仅含两个新增字段的轻量数据类,却是 Langchain-Chatchat 知识库 RAG 链路承上启下的关键"协议":Document负责承载内容与元数据,id负责打通"数据库记录 ↔ 向量库索引 ↔ 摘要结果"的映射关系,score则承载检索相关性信息并贯穿VECTOR_SEARCH_TOP_KSCORE_THRESHOLD等调优参数。无论是阅读 搜索文档 API、编写自定义知识库后端,还是二次开发 Agent 知识库工具,理解这一模型类的字段语义与三条构造 / 消费路径都是绕不开的第一步。

【免费下载链接】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),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/10 16:49:31

Excel文件解析:DOM与SAX原理及性能对比

1. Excel文件解析的两种核心方式 在数据处理领域,Excel文件解析是每个开发者都会遇到的基础需求。当我们需要处理大型Excel文件时,选择正确的解析方式会直接影响程序性能和内存消耗。SAX(Simple API for XML)和DOM(Doc…

作者头像 李华
网站建设 2026/9/10 16:48:53

电商直播巡检系统:实时数据处理与多线程编程实战

1. 直播巡检系统概述2026年拼多多春招笔试中的直播巡检题目,主要考察应聘者对实时数据处理、多线程编程和算法优化的综合能力。这类系统在电商直播场景中至关重要,需要实时监控成千上万的直播流,确保内容合规、画质稳定、互动流畅。直播巡检系…

作者头像 李华
网站建设 2026/9/10 16:47:18

Altium许可证优化:电子制造企业降本增效实践

1. 项目背景:Altium在电子产品制造业的痛点与机遇在深圳一家中型电子产品制造企业的研发部,我第一次意识到Altium Designer许可证成本对企业的影响有多大。那是一家年营收约3亿元的智能硬件公司,研发团队35人,每月Altium许可证支出…

作者头像 李华
网站建设 2026/9/10 16:44:51

【谨慎学习】手把手教你破解网站管理后台帐号密码

【导读】 对于网站运行的个人站长而言,最担心的是应如何有效且安全的去管理自己的网站,否则自己辛辛苦苦经营的网站就会被不请自来的不速之客给攻破,轻则站点数据被窃取,重则整个网站都被攻陷,导致无法恢复。 本文主…

作者头像 李华