当前位置: 首页 > news >正文

大模型开发框架LangChain之构建知识库

1.前言

为了避免 llm正确的废话和幻觉,知识库可以说是现在开发 agent的必备了。同时,作为 rag中的 r,知识库召回的成功率会极大的影响 llm的最终回复效果。一般,会把知识库召回的内容作为背景知识给到 llm,并在 prompt中明确告诉它优先使用知识库召回的内容回答用户问题,甚至要求必须基于知识库回答也是可以的。

环境信息如下:

​ python-3.13、langchain-0.3.26

2.知识库设计

这里设计一个轻量级知识库,基于 csv格式的数据,可用于小型项目,维护成本极低。样例如下:

报错信息,原因分析,修复建议
"java.sql.SQLException: EXECUTION FAILED: Task DDL error HiveException: [Error 20604] Can not create table: create table busi.dwd_cd_eksiq_024323331015027700004_20250720_de083461-142e-4768-38si-bd7046532ca9 failed","Hive相关服务负载过高","排除服务故障后可尝试重做任务"
"The ownership on the staging directory file:/tmp/hadoop/mapred/staging/KS_MACHINE1666781422/.staging is not as expected. It is owned by hctr. The directory must be owned by the submitter KS_MACHINE or KS_MACHINE@LAKEHOUSE.IK","权限信息错误或者kinit没有正确连接","优先联系管理员确认权限问题"
"org.apache.hadoop.hive.ql.metadata.HiveException: Invalid Value ""1"" for decimal(3,3) column when inserting. Column to inserting: name","字段和字段内容不匹配导致无法写入","decimal字段小数点位数不能超过保留位数"

这是一个运维场景,记录了任务报错的日志原因分析修复建议。日常维护可以使用 excel进行管理,然后导出成 csv即可,非常的方便快捷。

对于一线的运维来说只是简单记录日常工作,而且能反过来提高自己的工作效率,故一般都不会排斥。

3.加载知识库

首先,读取和解析 csv需要用到 langchain_community的 CSVLoader。如下:

loader = CSVLoader(file_path="task-records.csv",encoding="utf-8",metadata_columns=["原因分析", "修复建议"],content_columns=["报错信息"],
)
docs = loader.load()

这里的重点是:content_columns,内容列,知识库召回时会基于此列的内容,使用 embedding模型进行向量化的时候也是用这一列。

metadata_columns是元数据列,不会参与召回,可用于丰富召回结果。比如 补充数据来源、原因分析和修复建议。

其次,需要对文本进行分块,如下:

text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=0)
all_splits = text_splitter.split_documents(docs)

chunk_size分块大小为 1000个字符,chunk_overlap设置为0表示片段无重叠,这两个参数会影响召回成功率,需要根据知识库和业务调用实际情况修改。比如 业务调用时多用关键词,则需要把 chunk_size调小;反之,如果用的是句子段落,则需要把chunk_size调大。

4.修改Embedding客户端

这里选取的 embedding模型是 BAAI-bge-small-zh-v1.5离线版,维度是 1024,使用 docker进行部署,适合无法联网的环境,比如 内网、局域网。如果使用的是 langchain支持厂商的 embedding模型,可以跳过本步骤。

为了适配此离线 embedding模型,故基于 langchain-openai embedding客户端进行改造,修改内容如下:

// 修改 _get_len_safe_embeddings函数
// 把下面的内容去掉
for i in _iter:response = self.client.create(input=tokens[i : i + _chunk_size], **client_kwargs)if not isinstance(response, dict):response = response.model_dump()batched_embeddings.extend(r["embedding"] for r in response["data"])

这个函数主要影响的是知识库分段后的向量化过程,很重要。

其他的 离线 embedding模型可以参考此方式进行修改,不一定适用所有的模型。

5.知识库召回

知识库是需要存储的,这里选用极致轻量化的方案:内存存储,对应的代价就是每次程序重启或知识库更新时需要全量初始化,比较耗时。

首先,进行知识库向量化:

embeddings = BAAIEmbeddings(base_url="http://127.0.0.1:9997/v1",  # 远程embedding服务地址api_key="no-key",model="BAAI-bge-small-zh-v1.5",
)vector_store = InMemoryVectorStore(embeddings)
vector_store.add_documents(documents=all_splits)

BAAIEmbeddings这个类是基于 openai进行改造后的,add_documents时会调用 embedding模型进行知识库分片的向量化,并将结果存储在内存中。

至此,知识库已经完全准备好了,可以进行召回测试了,如下:

retrieved_docs = vector_store.similarity_search_with_score(query="/tmp/hadoop/mapred/staging/KS_MACHINE1666781422/.staging is not as expected",k=1,
)
print(retrieved_docs)

这里 k能够控制最终召回的数据条数,在召回成功率低的情况下可以调大。

知识库召回效果如下

[(Document(id=‘d06c773b-fd98-4de9-b939-ce2d3e513a11’, metadata={‘source’: ‘task-records.csv’, ‘row’: 2, ‘原因分析’: ‘权限信息错误或者kinit没有正确连接’, ‘修复建议’: ‘优先联系管理员确认权限问题’}, page_content=‘报错信息: The ownership on the staging directory file:/tmp/hadoop/mapred/staging/KS_MACHINE1666781422/.staging is not as expected. It is owned by hctr. The directory must be owned by the submitter KS_MACHINE or KS_MACHINE@LAKEHOUSE.IK’), 0.8914968315763799)]

可以看到 langchain准确的找出了知识库中与问题最匹配的数据,并且可以在元数据中看到是来自task-records.csv、原因分析和修复方式,以及文本相似度。这些信息在实际项目中都是需要进行展示的,增加可信度和便于溯源。

6.总结

本文描述了如何使用 langchain构建一个轻量级的知识库,步骤如下:

  1. 设计csv格式的知识库
  2. 加载csv文件
  3. 文本分片
  4. 文本向量化与存储
  5. 文本召回

其实基于其他的存储,比如 pg、es,步骤类似,其次知识库的工程化不能忽视,否则会极大的影响召回成功率。

在实际项目中,召回数据通常会有很多条,一般生产环境会默认允许召回 20条、30条甚至更多,故还可以增加 rerank模型进行重排,进一步增加知识库检索准确率。

http://www.dtcms.com/a/309572.html

相关文章:

  • 高速公路桥梁安全监测系统解决方案
  • 技术栈:基于Java语言的搭子_搭子社交_圈子_圈子社交_搭子小程序_搭子APP平台
  • 安全专家发现利用多层跳转技术窃取Microsoft 365登录凭证的新型钓鱼攻击
  • 【C#学习Day14笔记】泛型、集合(数组列表Arraylist、列表list)与字典
  • Python 中的可迭代、迭代器与生成器——从协议到实现再到最佳实践
  • 最新docker国内镜像源地址大全
  • AttributeError: ChatGLMTokenizer has no attribute vocab_size
  • 强反光干扰下识别率↑89%!陌讯多模态融合算法在烟草SKU识别的实战解析
  • MySQL分析步
  • U-Net vs. 传统CNN:为什么医学图像分割需要跳过连接?
  • C语言的复合类型、内存管理、综合案例
  • 【AI 加持下的 Python 编程实战 2_12】第九章:繁琐任务的自动化(上)——自动清理电子邮件文本
  • PendingIntent相关流程解析
  • MySQL——事务详解
  • React Refs:直接操作DOM的终极指南
  • RAGFlow Agent 知识检索节点源码解析:从粗排到精排的完整流程
  • Java学习第九十六部分——Eureka
  • Elasticsearch IK 中文分词器指南:从安装、配置到自定义词典
  • IPAM如何帮助企业解决IP冲突、识别未经授权设备并管理子网混乱
  • MAC 升级 Ruby 到 3.2.0 或更高版本
  • ARM Cortex-M 处理器的应用
  • Smart Launcher:安卓设备上的智能启动器
  • ElasticSearch Linux 下安装及 Head 插件 | 详情
  • 设计Mock CUDA库的流程与实现
  • 【秋招笔试】07.27文远知行-第一题
  • Git 实现原理剖析
  • Boost.Asio学习(5):c++的协程
  • Python Flask框架Web应用开发完全教程
  • 后台管理系统权限管理:前端实现详解
  • 关于WIKI的一些使用技巧