【Langchain大语言模型开发教程】基于Langchain的私人助手

news2024/9/22 11:42:16

终于学习完了Langchain框架的核心内容,最后基于langchain技术实现一个个人知识库助手的小项目,将这些内容串联起来,在实际中进行应用。

工具清单:

1、langchain框架

2、chroma向量数据库

3、embedding模型(bge-large-zh-v1.5、bge-large-en-v1.5)

4、rerank模型(bge-reranker-v2-m3)

5、gradio前端框架

6、LLM(GLM4系列模型)

1、数据读取与数据库构建

我们使用langchain提供的文本加载器来进行各种类型数据的加载;

def file_loader(file, loaders):
    if isinstance(file, tempfile._TemporaryFileWrapper):
        file = file.name
    if not os.path.isfile(file):
        [file_loader(os.path.join(file, f), loaders) for f in os.listdir(file)]
        return
    file_type = file.split('.')[-1]
    if file_type == 'pdf':
        loaders.append(PyMuPDFLoader(file))
    elif file_type == 'md':
        pattern = r"不存在|风控"
        match = re.search(pattern, file)
        if not match:
            loaders.append(UnstructuredMarkdownLoader(file))
    elif file_type == "txt":
        loaders.append(TextLoader(file))
    elif file_type == "docx":
        loaders.append(Docx2txtLoader(file))
    return

得到数据后,由于Token上下文的限制,LLM不能一次将整个文档全都读入,我们需要将文档进行切分得到chunk;langchain为我们提供了多种文本分割器,每个文本分割器都根据 chunk_size (块大小)和 chunk_overlap (块与块之间的重叠大小)进行分割;

  • chunk_size 指每个块包含的字符或 Token的数量;
  • chunk_overlap 指两个块之间共享的字符数量,用于保持上下文的连贯性,避免分割丢失上下文信息;

 这里我们选择使用RecursiveCharacterTextSplitter,按字符串分割文本,递归地尝试按不同的分隔符进行分割文本;

我们得到分割后的文本后,我们就可以将数据存储到数据库中了,所有我们这里就需要一个embedding模型,embedding可以将文本映射到一个高维的向量空间,实现一个文本到数据的映射,而相似的文本编码后得到的向量就会相近;

最后我们初始化数据库,并将数据可持久化到硬盘,方便我们后续直接加载;

def create_db(files=DEFAULT_DB_PATH, persist_directory=DEFAULT_PERSIST_PATH, embeddings="bge-large-zh-v1.5"):

    if files == None:
        return "can't load empty file"
    if type(files) != list:
        files = [files]
    loaders = []
    [file_loader(file, loaders) for file in files]
    docs = []
    for loader in loaders:
        if loader is not None:
            docs.extend(loader.load())
    # 切分文档
    text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=150)
    split_docs = text_splitter.split_documents(docs)

    print(len(split_docs))
    if type(embeddings) == str:
        embeddings = get_embedding(embedding=embeddings)
    # 加载数据库
    vectordb = Chroma.from_documents(
        documents=split_docs,
        embedding=embeddings,
        persist_directory=persist_directory  # 允许我们将persist_directory目录保存到磁盘上
    )

    vectordb.persist()
    return vectordb

2、 构建RAG问答链

由了刚刚构建的数据库,我们这里直接将其接入到问答流程;

这里我们需要传入一些必要的参数,然后加载一下我们的向量数据库,并根据该向量数据库构建一个检索器,作为我们的基本检索器,我们使用rerank模型将检索到的chunk进行进一步的精排,从而提升查询结果相关性;

    def __init__(self, model: str, temperature: float = 0.0, top_k: int = 4, api_key: str = None, file_path: str = None,
                 persist_path: str = None, embedding=None, template=default_template_rq):

        print(persist_path)

        self.model = model
        self.temperature = temperature
        self.top_k = top_k
        self.file_path = file_path
        self.persist_path = persist_path
        self.api_key = api_key
        self.embedding = embedding
        self.template = template
        self.vectordb = get_vectordb(self.file_path, self.persist_path, self.embedding)

        self.prompt = PromptTemplate(input_variables=["context", "question"], template=self.template)

        self.retriever = self.vectordb.as_retriever(search_type="similarity",
                                                    search_kwargs={'k': 10})

        self.reranker = HuggingFaceCrossEncoder(model_name="../embedding/BAAI/bge-reranker-v2-m3",
                                                model_kwargs={'device': 'cuda'})

        print(f"向量库中存储的数量:{self.vectordb._collection.count()}")

接下来就是我们的问答环节,用户发出一个问题,我们根据用户指定的一些参数(temperature、top-k等)来初始化我们的大语言模型和重排器,我们使用langchain框架提供的RetrievalQA链来构建我们的问答链;

    def answer(self, question: str = None, temperature=None, top_k=4):
        """"
        核心方法,调用问答链
        arguments: 
        - question:用户提问
        """

        if len(question) == 0:
            return ""

        if temperature is None:
            temperature = self.temperature

        if top_k is None:
            top_k = self.top_k

        llm = model_to_llm(self.model, temperature, self.api_key)

        compressor = CrossEncoderReranker(model=self.reranker, top_n=top_k)

        compression_retriever = ContextualCompressionRetriever(base_compressor=compressor,
                                                               base_retriever=self.retriever)
        # 自定义 QA 链
        qa_chain = RetrievalQA.from_chain_type(llm=llm,
                                               retriever=compression_retriever,
                                               return_source_documents=True,
                                               chain_type_kwargs={"prompt": self.prompt})

        result = qa_chain({"query": question})
        answer = result["result"]
        source_documents = result["source_documents"]
        answer = re.sub(r"\\n", '<br/>', answer)
        return answer, source_documents

 以上就是我们问答助手的整个流程,接下来我们可以使用gradio框架快速的搭建起我们的交互界面;

我们问一个问题:

如何保持持续行动(刻意学习中的一个内容)

 

这是我们在数据库中检索到的内容: 

[Document(page_content='些工作量。平时要更加严格地要求自己了。我有时候时间充裕,一天会多\n写两篇文章,即使某天真的安排不出时间,也全然不会有“完蛋,我中断\n了”的感觉。树挪死,人挪活,持续行动的核心在于持续稳定。\n成长会里有位朋友在某知名通信企业任职,有一次谈到加班,她\n说:“很多公司的加班是今天做昨天的事情,或者今天做今天还没完成的事\n情,反正加班是因为做不完事情,而我们的加班是因为今天要把明天的事\n情做完,这个月把下个月的事情做完,所以能够永远赶在竞争对手前面。”\n另外一个例子是,在成长会的一些练习小组里每天都会有任务。往往\n出现这样一种情况:有一些成员从周一到周五,没有按时完成对应的任\n务,于是拖到周六,用一天的时间把所有作业都补完。很多人会觉得这好\n像挺正常,平常都做不完,周末再补,其实这是大部分人碌碌无为的原\n因。\n换一个场景你可能就会觉得这很荒谬,我们平常吃饭,每天每餐都要\n吃,到了点要吃,饿了就要吃。你会不会说我从周一到周五不吃饭,我周\n六一天把前面五天的饭全吃了?你没法五天不吃饭,你也无法一天补吃原\n来五天的饭。做事情就像吃饭一样,每天都要吃饭,于是这会变成一个常\n规项目。持续行动也应该如此。', metadata={'author': 'Scalers', 'creationDate': "D:20201006233519+00'00'", 'creator': 'calibre 3.39.1 [https://calibre-ebook.com]', 'file_path': '../knowledge_db/刻意学习.pdf', 'format': 'PDF 1.4', 'keywords': '', 'modDate': '', 'page': 91, 'producer': 'calibre 3.39.1 [https://calibre-ebook.com]', 'source': '../knowledge_db/刻意学习.pdf', 'subject': '', 'title': '刻意学习', 'total_pages': 235, 'trapped': ''}), Document(page_content='持续的事情,或者你也就走出了两三步,就迫不及待地想分享一些“牛×的\n方法”“秘籍成果”。\n这就像传销一样。一个人做了一点点事情,先把自己感动了,然后开\n始把这种感动转换成文字,营造了一个“感动场”,营造因为自己感动而产\n生的幻象。然后这个文字传播出去,立即引发一群人的感动和对牛×的憧\n憬,于是这群人在什么都没有做的情况下,便开始了新一轮的情绪高潮,\n高潮过后继续传播……于是这种氛围从公众号蔓延到社群……但是一轮一\n轮下来,你还是什么都没有做,那只是一群人产生了一些精神垃圾,然后\n找到另一群人接盘而已。这就跟开着印钞机印钞票,增发货币,是一个道\n理。\n当然,在持续行动中,我们需要正向反馈。每到一个关键节点,我们\n停下来整理整理思绪,甚至给自己一个小小的庆贺,这的确是有必要的。\n因为本质上这是一种正向反馈,有利于形成正循环。所以你看我过去每逢\n一百天都会有那么一篇总结文章,但是你也能看出越到后面的文章,我的\n心态越平和。\n如果我们在持续行动和持续进步,如果我们是在持续成长,那我们现\n在所取得的成绩,在未来都不值一提。如果我们每天都是在怀念自己以前', metadata={'author': 'Scalers', 'creationDate': "D:20201006233519+00'00'", 'creator': 'calibre 3.39.1 [https://calibre-ebook.com]', 'file_path': '../knowledge_db/刻意学习.pdf', 'format': 'PDF 1.4', 'keywords': '', 'modDate': '', 'page': 53, 'producer': 'calibre 3.39.1 [https://calibre-ebook.com]', 'source': '../knowledge_db/刻意学习.pdf', 'subject': '', 'title': '刻意学习', 'total_pages': 235, 'trapped': ''}), Document(page_content='因。\n换一个场景你可能就会觉得这很荒谬,我们平常吃饭,每天每餐都要\n吃,到了点要吃,饿了就要吃。你会不会说我从周一到周五不吃饭,我周\n六一天把前面五天的饭全吃了?你没法五天不吃饭,你也无法一天补吃原\n来五天的饭。做事情就像吃饭一样,每天都要吃饭,于是这会变成一个常\n规项目。持续行动也应该如此。\n在我刚开始写作的时候,总会担心万一有什么不可抗拒的事情,让我\n中断了写作,于是纠结不已。后面我发现这只是无谓的担心。生活中有很\n多人总是在为没有发生的事情担心,但也仅仅是担心却不做预案。以前我\n也是如此,后来才发现,不管发生什么,总是可以想办法在一天的繁忙中\n找出时间来做事情。\n白天再忙,总要起床,起床后的一段时间不会有人打扰你,于是你可\n以再起早一些,就有了属于自己的时间了;睡觉之前也有不被打扰的时\n间,这个时间也可以用来做事,只是你需要有足够的体力让自己不会感到\n困乏,于是体育锻炼的重要性就显现出来了。\n这么一来,我总能找到一些时间干自己的事情,于是就更加安心地持\n续行动了。在我持续写作的时间里,有人和我说自己想多做一些事情,却', metadata={'author': 'Scalers', 'creationDate': "D:20201006233519+00'00'", 'creator': 'calibre 3.39.1 [https://calibre-ebook.com]', 'file_path': '../knowledge_db/刻意学习.pdf', 'format': 'PDF 1.4', 'keywords': '', 'modDate': '', 'page': 91, 'producer': 'calibre 3.39.1 [https://calibre-ebook.com]', 'source': '../knowledge_db/刻意学习.pdf', 'subject': '', 'title': '刻意学习', 'total_pages': 235, 'trapped': ''})]

这是我们调用大语言模型后的答案:

保持持续行动需要:1. 严格自我要求,确保每天稳定完成任务,避免堆积工作。2. 提前规划,像吃饭一样将行动变成日常习惯,不断前行。3. 正向反馈,适时庆祝关键节点,形成正循环。谢谢你的提问! 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1982572.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

qt下载安装

1.在目录栏输入CMD&#xff0c;然后按回车 2. 输入以下内容回车启动在线安装程序 镜像源&#xff1a; 清华大学&#xff1a;https://mirrors.tuna.tsinghua.edu.cn/qt/ 北京理工大学&#xff1a;http://mirror.bit.edu.cn/qtproject/ 中国互联网络信息中心&#xff1a;http…

Android之复制文本(TextView)剪贴板

效果图&#xff1a; 功能简单就是点击“复制”&#xff0c;将邀请码复制到 剪贴板中 布局 <androidx.constraintlayout.widget.ConstraintLayoutandroid:id"id/clCode"android:layout_width"dimen/dp_0"android:layout_height"dimen/dp_49"…

贝壳找房:基于OceanBase构建实时字典服务的实践 | OceanBase案例

贝壳找房作为领先的居住服务综合平台&#xff0c;一直在推进居住产业的数字化与智能化升级。该平台通过汇聚并赋能优质的服务者&#xff0c;旨在为中国广大家庭带来涵盖二手房买卖、新房交易、房屋租赁、家装、家居以及家庭服务等全方位、高质量且高效的居住服务体验。 在贝壳…

Linux学习记录(二)-------文件IO

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言文件IO1.函数open2.函数close3.函数lseek4.函数read5.函数write 前言 文件IO Linux 自带的工具&#xff1a;man手册 man 1 是普通的shell命令&#xff0c;比如…

最新CSS3横向菜单的实现

横向菜单 原始代码&#xff1a; <nav class"list1"><ul><li><a href"#">Shirts</a></li><li><a href"#">Pants</a></li><li><a href"#">Dresses</a>…

零基础STM32单片机编程入门(二十五) 内部FLASH模拟EEPROM实战含源码

文章目录 一.概要二.FLASH模拟EEPROM的优势三.FLASH模拟EEPROM的原理四.数据读写步骤五.数据转移流程图六.FLASH模拟EEPROM读写例程七.CubeMX工程源代码下载八.小结 一.概要 STM32F103C8T6是一款强大而灵活的微控制器&#xff0c;它的片内Flash存储器可以用来存储有关数据&…

sqli-labs-php7-master第5-10关

第五关&#xff1a; 根据提示输入ID,随便来个一 输入100&#xff0c;因为数据库没有&#xff0c;所以这里没输出内容 还是先找注入点&#xff1a;输入单引号试试 注入点找到了‘ 查询数据库列数&#xff1b;&#xff1f;id1 order by 4 -- 测试发现order by 3时页面正常&…

C++笔试练习笔记【5】:最小花费爬楼梯(有题目链接) 初识动态规划

文章目录 题目思路代码 动态规划简介**一、什么是动态规划****二、动态规划的应用场景****三、动态规划的基本步骤****四、动态规划的优缺点** 题目 题目链接&#xff1a;https://www.nowcoder.com/practice/9b969a3ec20149e3b870b256ad40844e?tpld230&tpld39751&ru/…

探索人工智能技术的发展导致知识崩溃危险的可能性

概述 本文分析了人工智能&#xff08;AI&#xff09;技术的发展在缩小人类知识库方面的潜力。 作者认为&#xff0c;如果大语言模型&#xff08;LLMs&#xff09;等人工智能技术迅速发展&#xff0c;人工智能生成的内容成为人类接触的大部分信息&#xff0c;那么长尾知识&…

python图表没有正确显示中文,这通常是因为matplotlib的默认设置不支持中文字符,或者相应的字体没有正确加载。

如果图表没有正确显示中文&#xff0c;这通常是因为matplotlib的默认设置不支持中文字符&#xff0c;或者相应的字体没有正确加载。你可以通过指定支持中文的字体来解决这个问题。下面是如何设置matplotlib以确保能够在图表中显示中文的步骤&#xff1a; 方法1&#xff1a;全局…

python的多线程

python的threading模块&#xff0c;它提供了丰富的接口来创建和管理线程。 定义一个函数print_numbers&#xff0c;这个函数将由线程执行。在这个函数中&#xff0c;我们使用一个循环来打印数字&#xff0c;并使用time.sleep(1)来模拟每个数字打印之间有1秒的延迟。 在 if __…

Windows应急响应-排查方式

目录 Windows应急响应排查流程一、账户排查排查方法&#xff08;1&#xff09;查看用户信息&#xff08;2&#xff09;lusrmgr.msc手动查&#xff08;比较麻烦&#xff09;&#xff08;3&#xff09;检测克隆账户 ---可使用安全工具D盾进行检测&#xff0c;同时可以直接查看端口…

群辉NAS利用AList搭建混合云盘⑥挂接腾讯微云

目录 ……接前文 5、挂接腾讯微云 未完待续…… ……接前文 5、挂接腾讯微云 登录AList后台→管理→存储→驱动供选择“腾讯微云”→填写挂接路径 打开“配置文档”(详见前文) 打开配置文档→简体中文→开始→找到腾讯微云部分,可以看到关于Cookie的设置方法。 手工用…

第十二章 元数据管理10分

12.1 引言 如果没有元数据&#xff0c;组织可能根本无法管理其数据。 ISO/IEC11179 元数据注册标准。 元数据管理原则&#xff1a;应归尽归&#xff0c;应收尽收。衡量标准&#xff1a;目录是否完整。&#xff08;去第十二章 元数据管理&#xff09;。 主数据管理&#xff1a;主…

(Javaweb)Ajax,Axios,Vue

目录 一.Ajax 二.Axios 三.前端工程化 四.接口文档的管理平台YAPI 五.Vue项目 六.Vue项目开发流程 一.Ajax 1.通过Ajax从服务器端获取数据 Ajax---JavaScript&#xff08;网页行为&#xff09;XML&#xff08;标记语言--用来存储数据&#xff09; 客户端--浏览器 服务…

【C++】深入理解类和对象(1)

自己打败自己是最可悲的失败&#xff0c;自己战胜自己是最可贵的胜利。&#x1f493;&#x1f493;&#x1f493; 目录 ✨说在前面 &#x1f34b;知识点一&#xff1a;类的定义 • &#x1f330;1.类定义格式 • &#x1f330;2.访问限定符 • &#x1f330;3.类域 &…

人工智能时代,程序员当如何保持核心竞争力?

目录 前言 一.AI辅助编程对程序员工作的影响 二.程序员应重点发展的核心能力 三.人机协作模式下的职业发展规划 结束语 前言 随着AIGC&#xff08;如chatgpt、midjourney、claude等&#xff09;大语言模型接二连三的涌现&#xff0c;AI辅助编程工具日益普及&#xff0c;程序…

C++第三十一弹---C++继承机制深度剖析(下)

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】【C详解】 1.菱形继承及菱形虚拟继承 1.1 单继承 单继承&#xff1a;一个子类只有一个直接父类时称这个继承关系为单继承。 Student的直接父类是Person&#xff…

双向循环链表和内核链表

目录 双向循环链表 结构设计 初始化 插入 删除 遍历&#xff08;顺序/逆序&#xff0c;打印输出&#xff09; 查找 主函数 内核链表 内核链表初始化定义 内核链表的插入定义 内核链表的遍历定义 内核链表剔除节点定义 内核链表如何移动节点定义 内核链表的应用 临时补充…

身在职场,不得不提防的几个问题,能让少走许多弯路

职场路本就崎岖&#xff0c;如果再走了弯路&#xff0c;脚下的路将会更漫长且难走。 谁不想一帆风顺&#xff0c;可谁又能一帆风顺&#xff1f;不是人心险恶&#xff0c;而是立场本就不同&#xff0c;为了各自的利益考虑无可厚非。 你可以说凭借能力获取利益&#xff0c;为什…