LLM - 使用 Langchain 实现本地 Naive RAG

本文详细介绍了如何使用Python构建本地Langchain知识库,包括文档收集、切分、内容编码、本地库构建与缓存,以及读取和相似搜索功能。作者通过实例展示了如何添加和检索文档,探讨了营销策略对品牌影响及本地知识库在LLM推理中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

一.引言

二.构建本地 Langchain 库

1.Doc 知识文档

2.Split 文档切分

3.Encode 内容编码

4.Similar 本地库构建

三.缓存本地 Langchain 库

四.读取本地 Langchain 库

1.Load 读取缓存

2.Similar 预测

3.Add 添加文档

五.总结


一.引言

上一篇博客介绍了当下 RAG 的一些发展情况,主要有 Naive RAG、Advanced RAG 以及 Modular RAG,本文通过 Python langchain 库实现一个本地 RAG 的 demo,主要是体会 RAG 搜索增强的流程。本文主要聚焦 Langchain 本地知识库的构建,后续的 LLM 推理因为本机显存的限制,大家可以参考之前推理的博客。

Tips 本文主要从三个方面介绍本地知识库的构建:

- 构建本地 Langchain 知识库

- 缓存本地 Langchain 知识库

- 读取缓存 Langchain 知识库

由于 Langchain 库的更新比较快,有一些 API 的引入方式与用法稍有出入,博主这里的 python 版本为 3.8.6,Langchain 相关 package 版本如下:

二.构建本地 Langchain 库

1.Doc 知识文档

由于是构建本地知识库,所以我们需要获得各个内容的文档,这里我们整理了几篇汽车的新闻作为本地知识库的内容,主要是零跑、理想、小鹏、蔚来汽车的相关新闻。

以 lx.txt 为例,其包含新闻的全部文本:

有消息透露:截至昨晚(3月4日)MEGA大定还没破万,小定转大定的数量有限,不少客户回流到小鹏X9、腾势D9和问界M9。

这样的成绩一定是不符合理想原本的预期的。但自MEGA上市以来经历的网络舆论风向,似乎冥冥之中也指向了这个结果……

经过一年多精心设计的宣传造势,3月1日理想正式推出了它征战纯电市场的首款车型——MEGA。

大约是为了给新车上市增加一波热搜,在发布会之前,李想(理想汽车创始人、董事长)按照惯例再次亲自下场,试图直接蹭一波“苹果放弃造车”的热度。

但李厂长万万没想到,这次的剧情没有按照设计好的发展:热搜还是上了,但话题却非常尴尬——MEGA的设计被不少网友直呼像“棺材”。


汽车的造型设计见仁见智,欣赏不了MEGA的另类造型的确是一些消费者的真实看法。在理想的线下门店,汽车产经记者就遇到多位看车用户直言,对MEGA的配置十分满意,但造型难以接受。

而在这一波黑MEGA的舆论攻势里,“像棺材”虽说是一种更易于理解的具象化表达,但也确实是非常恶劣了。尤其对国人来说,这个“不吉利”的词一旦和一款车深度绑定,必定会对产品的终端销量造成不小的影响。

总之,舆论走向超出了最初的预期,理想彻底怒了,官方直接开始举报、删帖+律师函警告。同时,不少站理想的自媒体KOL纷纷下场,斥责这些行为是“下作、无底线的抹黑”。

其实汽车产品中被送过类似称呼的并非MGEA一个。2015年左右途观事故频发,被消费者调侃为“土棺”。2022年极氪009上市时,也被“赠予”了和MEGA一样的称呼……但这些信息并没有被大肆发酵,尤其是后者,只是新车上市发布时的一个花絮注脚。

这一次理想一心一意想要打造的“公路高铁”MEGA,为什么被黑地愈演愈烈?

很多人认为是,舆论反噬。就像网友说的:理想只是遭遇了“回旋镖”。

今日的车圈营销战不断升级,动辄CEO对线、KOLKOC互踩,李想本人确是“功不可没”的。

创始人亲自下场蹭热度、宣传话术避重就轻,乃至操纵媒体、内涵友商、攻击自家车主……在理想的发展壮大过程中,这些传播手段被用得炉火纯青。客观讲理想L系列是好产品,但销量也大有营销的“功劳”。

理想L9上市后,面对“50万的豪车不用铝缺乏诚意”(使用的铁悬架)的质疑,李想选择了人身攻击:“建议觉得铝比钢和铁好的网友们,把自己家的房子钢筋柱结构都拆掉,全换成铝”。

上周五上市的MEGA被质疑“没有后轮转向”时,理想又在对外宣发中统一口径:后轮转向会让“第三排乘客会感受到更快的横向摆动,会不太舒服”,“后轮转向也不是很厉害的技术,我们的转弯半径也就比L9多一个手掌。”

类似事例不再赘述,看下网友的精辟总结:

社交媒体截图社交媒体截图
对一些有关新车的问题避重就轻,其实不算什么大“黑料”。这原本也是一个车企领袖的基本修养(除了骂人),毕竟人无完人、车无完车。

而除了怼网友怼友商,理想对媒体的控制和拿捏也达到了“极致”。

2月份MEGA上市前在三亚组织了一场媒体试驾,所有参与者都签了保密协议。通过这份协议,理想细致拿捏了媒体宣传节奏——仅一次活动安排,让每家媒体按照理想预定的时间和内容方向陆续推送三四次信息,而消费者每天能刷到什么内容,也完全都在掌控之中。

必须夸一句,当友商们还在思考如何打磨技术,如何做出一场出色的发布会时,理想已经凭借对人性的研究,站在了另一个竞争维度。但那些被操控到如此程度的媒体,恐怕心里总有些不得劲吧。

不得不提的还有,至今无论对网友还是消费者来说都不可原谅的一件事:去年12月底发生在广东的一起理想L7事故中,有人质疑理想的车辆安全时,李想选择在微博曝光驾驶者的行车记录信息和视频,并且误导舆论指向事故车主超速驾驶!

这样的理想,被扣上“鸡贼”厂的名号由来已久,甚至理想自家车主对理想和李想的态度是:车是好车,人不认同。

此次MEGA宣发翻车,一方面因为理想流量太盛,枪打出头鸟,不排除真是竞争对手有意为之玩了一手“以彼之道还施彼身”;但也一定煽动了早就看不惯理想做事风格的网友和媒体,跟风行动。

不管是谁策动,都不由得让人想把李厂长diss友商的经典名句返送给他自己:“这点作战都受不了,难道是巨婴?”

而为了MEGA,这个回旋镖,理想是必须要承受的。

周末,北京最大新势力门店聚集地“蓝色港湾”,理想的门店在中午时段甚至需要排队。大家多为MEGA而来,有的感兴趣,有的出于好奇。

不可否认MEGA是一款足够吸引眼球的产品,但这样的关注度有多少转化为最终销量?还很难说。从增程转战纯电的理想,要重新接受考验。

很多人也都注意到,这次MEGA上市后李想并没有像往常一样回怼各种质疑,也没有迫不及待分享传说中的订单数据。甚至在发布会后理想还经历了股价的下滑。

MEGA的舆论和销量会如何相互裹挟着前行?这一波难堪的舆论风波后,李想又会不会对此有所反思?静观其变。

2.Split 文档切分

对于通用文本,这里建议使用 RecursiveCharacterTextSplitter 分割器进行文本切分。

from langchain_community.document_loaders import TextLoader
from langchain_community.embeddings import HuggingFaceEmbeddings
from langchain_community.vectorstores.chroma import Chroma
from langchain_text_splitters import RecursiveCharacterTextSplitter    


    # 读取原始文档
    raw_documents_lp = TextLoader('/Users/xxx/langchain/LocalDB/lp.txt', encoding='utf-8').load()
    raw_documents_lx = TextLoader('/Users/xxx/langchain/LocalDB/lx.txt', encoding='utf-8').load()

    # 分割文档
    text_splitter = RecursiveCharacterTextSplitter(chunk_size=100, chunk_overlap=0)
    documents_lp = text_splitter.split_documents(raw_documents_lp)
    documents_lx = text_splitter.split_documents(raw_documents_lx)
    documents = documents_lp + documents_lx
    print("documents nums:", documents.__len__())

这里加载零跑与理想的文档,如果文档多的同学直接 os.path 遍历 for 循环添加即可,我们最终得到的是多个通过 text_splitter 分割的 document 文档。其主要包含 page_content 和 metadata 两个属性,前者包含分割后的文本块 Chunk,后者包含一些元信息,主要是文档内容来源。

运行上述代码后会得到分割后文档数量,其中 chunk_size 代表每个块的保留大小,chunk_overlap 代表前后 content 是否有重叠,类似滑动窗口一样。

documents nums: 75

3.Encode 内容编码

由于需要通过向量存储与检索 Top-K,所以需要对应的编码器生成对应 content 的 Embedding,这里我们选择通过 HuggingFaceEmbeddings 方法来生成文本的 Embedding。

    # 生成向量(embedding)
    embedding_model_dict = {
        "mini-lm": "/Users/xxx/model/All-MiniLM-L6-V2"
    }
    EMBEDDING_MODEL = "mini-lm"
    embeddings = HuggingFaceEmbeddings(model_name=embedding_model_dict[EMBEDDING_MODEL])

由于网络连接的问题,这里博主建议把模型下载到本地文件夹中直接加载,登录 HuggignFace 官网 https://huggingface.co/sentence-transformers/ 可以检索到多个文本编码的模型:

这里我们选择轻量级的 all-MiniLM-L6-v2 作为 Embedding 编码的模型,手动一个一个下载或者挂着镜像用 API 下载都可以:

执行完毕后我们获得一个可以编码的 Embedding 模型: 

4.Similar 本地库构建

    db = Chroma.from_documents(documents, embedding=embeddings)

    # 检索
    query = "理想汽车怎么样?"
    docs = db.similarity_search(query, k=5)

    # 打印结果
    for doc in docs:
        print("===")
        print("metadata:", doc.metadata)
        print("page_content:", doc.page_content)

通过本地分割好的文档 documents 与指定的 embedding 模型我们构建本地 Langchain DB,通过 query 与 sim_search API 进行 Top-k 文本的获取,得到的 doc 我们可以获取其 metadata 即来源以及其对应的文本:

可以看到 5 条中有 4 条来自 lx.txt 即理想的文档,而一条来自 lp.txt 即零跑汽车,基于这些 page_content,我们还需要做清洗、合并等处理才能得到最终的增强信息,对用户的原始 Query 进行扩展得到最终的 Prompt 再输入 LLM 得到回复。

三.缓存本地 Langchain 库

如果不想每次都处理加载文档再构建 DB 可以预先处理并把 DB 做本地的 cache,用的时候直接读取 cache 加载即可。

def persist():
    raw_documents_news = TextLoader('/Users/xxx/langchain/lx.txt', encoding='utf-8').load()
    text_splitter = RecursiveCharacterTextSplitter(chunk_size=100, chunk_overlap=0)
    documents_news = text_splitter.split_documents(raw_documents_news)
    embedding_model_dict = {
        "mini-lm": "/Users/xxx/model/All-MiniLM-L6-V2"
    }
    EMBEDDING_MODEL = "mini-lm"
    # 初始化 huggingFace 的 embeddings 对象
    embeddings = HuggingFaceEmbeddings(model_name=embedding_model_dict[EMBEDDING_MODEL])
    db = Chroma.from_documents(documents_news, embeddings, persist_directory="./local_cache")
    db.persist()
    print("Save Success ...")

执行后在 cache 对应文件下生成如下文件即为成功: 

缓存大小为 2mb:

四.读取本地 Langchain 库

1.Load 读取缓存

    embedding_model_dict = {
        "mini-lm": "/Users/xxx/model/All-MiniLM-L6-V2"
    }
    EMBEDDING_MODEL = "mini-lm"
    # 初始化 huggingFace 的 embeddings 对象
    embeddings = HuggingFaceEmbeddings(model_name=embedding_model_dict[EMBEDDING_MODEL])
    db = Chroma(persist_directory="/Users/xxx/langchain/local_cache", embedding_function=embeddings)

同样需要加载 embedding 模型,但是 doc 内容直接从 cache 中获取,通过 persist_directory 方法获取 Chroma Database。

2.Similar 预测

    # 检索
    query = "理想汽车"
    docs = db.similarity_search(query, k=5)

    # 打印结果
    for doc in docs:
        print("===")
        print("metadata:", doc.metadata)
        print("page_content:", doc.page_content)

    exit(0)

3.Add 添加文档

本地库存在更新慢的情况,读取缓存后如果有新的 doc 可以调用 db.add 方法添加,随后再执行查询,下面我们在 cache 的基础上引入小鹏汽车 xp.txt 的信息,并预测新的 query。

    # 添加文档
    text_splitter = RecursiveCharacterTextSplitter(chunk_size=100, chunk_overlap=0)
    raw_documents_xp = TextLoader('/Users/xxx/langchain/LocalDB/xp.txt', encoding='utf-8').load()
    documents_news = text_splitter.split_documents(raw_documents_xp)
    db.add_documents(documents_news)

加载本地 Langchain 库后,我们可以继续将新增的本地 doc 添加至 DB 中,下面我们再测试下,这次寻找与新增小鹏汽车相关的信息:

    # 检索
    query = "小鹏汽车"
    docs = db.similarity_search(query, k=5)

    # 打印结果
    for doc in docs:
        print("===")
        print("metadata:", doc.metadata)
        print("page_content:", doc.page_content)

    exit(0)

xp.txt 里小鹏汽车的关键字比较多,所以匹配下来 metadata 都指向 xp.txt,不存在之前 lx 检索到 lp 的情况: 

五.总结

上面简单测试了基于 Doc 构建本地 Langchain 库的一些方法,关于更细粒度的 Langchain 和 RAG,还涉及到很多细节的点,包括对 query 的清洗与处理,对文档的清理与筛选,对 Langchain 结果的取舍与合并以及 LLM Prompt 的构建,这些细致的点大家可以一一扩散提高搜索的效果。

Tips:

Langchain 中文 API 介绍: LangChain中文网 Concepts | 🦜️🔗 Langchain

<think>好的,用户想了解RAG在毕业设计中的应用,特别是实现方案和示例代码。首先,我需要回忆一下RAG的基本概念和它在实际中的用途。RAG结合了检索和生成,通过检索外部知识库来增强生成效果,这对于解决大模型的幻觉问题和数据更新问题很有帮助。根据提供的引用,尤其是引用[1]和[3],RAG分为Naive、Advanced和Modular三种,用户可能需要一个基础的实现示例。 接下来,用户可能需要一个具体的实现方案,包括系统架构、技术选型、步骤和代码示例。考虑到毕业设计的规模,选择Naive RAG可能更合适,因为它结构简单,容易实现。技术选型方面,LangChain是常用的框架,HuggingFace的模型和FAISS作为向量数据库比较合适。 然后,我需要规划实现步骤:数据准备、检索系统、生成系统整合。数据预处理部分需要加载、分块和向量化存储。检索部分使用FAISS进行相似度搜索,生成部分用预训练的LLM模型。代码示例需要简洁明了,展示整个流程,同时注意注释和可读性。 在应用场景部分,用户可能需要了解毕业设计中的具体应用,比如智能问答系统、论文辅助写作等。结合引用[3]提到的知识密集型任务,这些应用场景是合适的。同时,优化方向如引用[1]提到的Advanced RAG技术可以作为未来工作的建议,比如查询扩展或优化检索策略。 最后,生成相关问题时要围绕RAG实现细节、优化和应用扩展,确保问题能够帮助用户深入理解。需要检查所有LaTeX格式是否正确,尤其是数学表达式是否用$...$包裹,独立公式用$$...$$。确保引用标识正确添加,例如在提到RAG分类时引用[^1],在解决大模型问题时引用[^2]和[^3]。 现在需要将这些思考整理成一个结构化的回答,包含方案设计、代码示例、应用场景和优化建议,并附上相关问题。同时,确保代码部分用正确的语法高亮,引用正确放置,避免任何格式错误。</think>### RAG(检索增强生成)毕业设计实现方案 #### 一、方案设计 1. **系统架构** - 采用Naive RAG架构(适合毕业设计复杂度) - 流程:数据预处理 → 检索 → 生成 → 评估 $$ \text{RAG}(q) = \text{LLM}(q \oplus \text{Retrieve}(q)) $$ 其中$q$为用户输入,$\oplus$表示信息拼接 2. **技术选型** | 模块 | 工具 | 说明 | |------------|---------------------|--------------------------| | 文本处理 | LangChain | 流程控制与组件集成 | | 向量模型 | HuggingFace SentenceTransformer | 文本向量化 | | 向量数据库 | FAISS | 高效相似度检索 | | 生成模型 | GPT-3.5/LLAMA2-7B | 根据硬件条件选择 | 3. **实现步骤** - **数据准备**:领域知识库构建(如论文/专利/企业文档) - **检索系统**:实现上下文关联的语义搜索 - **生成系统**:控制模型输出与知识库对齐 #### 二、代码示例(基于LangChain) ```python from langchain_community.document_loaders import TextLoader from langchain_text_splitters import CharacterTextSplitter from langchain_community.vectorstores import FAISS from langchain_core.prompts import ChatPromptTemplate from langchain_core.output_parsers import StrOutputParser from langchain_core.runnables import RunnablePassthrough from langchain_huggingface import HuggingFaceEmbeddings # 1. 数据预处理 loader = TextLoader("knowledge_base.txt") documents = loader.load() text_splitter = CharacterTextSplitter(chunk_size=500, chunk_overlap=50) texts = text_splitter.split_documents(documents) # 2. 构建检索系统 embedding = HuggingFaceEmbeddings(model_name="sentence-transformers/all-mpnet-base-v2") vectorstore = FAISS.from_documents(texts, embedding) retriever = vectorstore.as_retriever(search_kwargs={"k": 3}) # 3. 构建生成系统 template = """基于以下上下文回答问题: {context} 问题:{question} 答案:""" prompt = ChatPromptTemplate.from_template(template) model = ChatOpenAI() # 或HuggingFaceHub(repo_id="meta-llama/Llama-2-7b") # 4. 整合流程 rag_chain = ( {"context": retriever, "question": RunnablePassthrough()} | prompt | model | StrOutputParser() ) # 5. 执行示例 print(rag_chain.invoke("RAG技术如何解决大模型幻觉问题?")) ``` #### 三、应用场景(毕业设计方向) 1. **智能问答系统** 构建专业领域的智能助手(如法律/医疗/金融QA系统),通过检索增强保证回答准确性[^2] 2. **论文辅助写作** 实现文献自动检索与内容生成系统,帮助快速生成论文初稿 3. **企业知识管理** 开发内部文档智能检索系统,支持自然语言查询(需数据加密处理) #### 四、优化建议 1. 使用HyDE技术提升检索效果:让模型先生成假设答案,再基于此进行检索 2. 添加引用溯源功能:在生成答案时标注知识来源段落 3. 实现检索结果重排序:通过交叉编码器优化结果排序
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BIT_666

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值