基于本地知识构建简易的chatPDF

news2024/9/22 9:52:42

Langchain + chatglm-6b


文章目录

  • Langchain + chatglm-6b
  • 前言
  • 一、实验记录
    • 1.1 环境配置
    • 1.2 代码理解
    • 1.3 补充内容
  • 二、总结


前言

介绍:一种利用 ChatGLM-6B + langchain 实现的基于本地知识的 ChatGLM 应用
Github: https://github.com/imClumsyPanda/langchain-ChatGLM


一、实验记录

1.1 环境配置

conda create -n lang python=3.8
conda activate lang

pip install -r requirement.txt

1.2 代码理解

1-将文章使用句号进行分句
2-将句子使用text2vec进行向量化存储
3-将query进行向量化后,和FAISS库里的正文文档进行topk相似度的召回
4-召回到的正文和query构造成prompt,输入到chatglm中

prompt模板的设置:  
prefix_prompt = \
"""基于以下已知信息,简洁和专业的来回答用户的问题。
    如果无法从中得到答案,请说 "根据已知信息无法回答该问题" 或 "没有提供足够的相关信息",不允许在答案中添加编造成分,答案请使用中文。
    
    已知内容:
    {context}
    
    问题:
    {question}"""

核心代码

    def _call(self, inputs: Dict[str, str]) -> Dict[str, Any]:
        """
        question = inputs[self.input_key]   获取query

        docs = self._get_docs(question)     根据query获取上下文中最相似的正文
        answer = self.combine_documents_chain.run(
            input_documents=docs, question=question
        )

        if self.return_source_documents:
            return {self.output_key: answer, "source_documents": docs}
        else:
            return {self.output_key: answer}

    @abstractmethod
    async def acombine_docs(
        self, docs: List[Document], **kwargs: Any
    ) -> Tuple[str, dict]:
        """Combine documents into a single string asynchronously."""

    def _call(self, inputs: Dict[str, Any]) -> Dict[str, str]:
        docs = inputs[self.input_key]
        # Other keys are assumed to be needed for LLM prediction
        other_keys = {k: v for k, v in inputs.items() if k != self.input_key}
        output, extra_return_dict = self.combine_docs(docs, **other_keys)
        extra_return_dict[self.output_key] = output
        return extra_return_dict

然后将找回来的正文和query进行concate之后,统一输入到llm中,对历史信息还是没有处理

    def _get_inputs(self, docs: List[Document], **kwargs: Any) -> dict:
        # Format each document according to the prompt
        doc_strings = [format_document(doc, self.document_prompt) for doc in docs]
        # Join the documents together to put them in the prompt.
        inputs = {
            k: v
            for k, v in kwargs.items()
            if k in self.llm_chain.prompt.input_variables
        }
        inputs[self.document_variable_name] = "\n\n".join(doc_strings)
        return inputs

处理后的数据

data = \
{
	'question': '大气污染预警分为多少级', 
	'context': '建立健全空气质量预报预警应急  体系,加强大气污染防治工作,不断促进大气环境质量改善。\n\n  各责任部门和街道办应根据本预案的相关规定,在大气  污染预警与应急响应期间落实具体的污染防控措施。\n\n  1.5 大气污染预警与应急响应分级  1.5.1 预警分级  大气污染预警分为三级,依次用黄色、橙色和红色表示。\n\n同时,确保大气污染预警应急信息有  效传达,提醒市民采取适当的健康防护措施。\n\n  负责向区政府、市生态环境局报告污染信息;负责判断大  气污染级别,提出发布预警信息的建议;负责空气质量监  市生态环境局龙华  测、预测和信息发布;负责组织专家会商;倡导社会各界  管理局  自觉参与污染减排;确定重点减排企业名单,督促检查工  业企业落实污染减排措施。\n\n获取气象监测预报信息,与市  生态环境局共同会商空气污染预报。'
}

调用

self.llm_chain.predict(**inputs), {}

生成答案的过程:

    def generate(self, input_list: List[Dict[str, Any]]) -> LLMResult:
        """Generate LLM result from inputs."""
        prompts, stop = self.prep_prompts(input_list) input_list上文的data
        return self.llm.generate_prompt(prompts, stop)

    def prep_prompts(
        self, input_list: List[Dict[str, Any]]
    ) -> Tuple[List[PromptValue], Optional[List[str]]]:
        """Prepare prompts from inputs."""
        stop = None
        if "stop" in input_list[0]:
            stop = input_list[0]["stop"]
        prompts = []
        for inputs in input_list:
            selected_inputs = {k: inputs[k] for k in self.prompt.input_variables}
            prompt = self.prompt.format_prompt(**selected_inputs) 
            _colored_text = get_colored_text(prompt.to_string(), "green")
            _text = "Prompt after formatting:\n" + _colored_text
            self.callback_manager.on_text(_text, end="\n", verbose=self.verbose)
            if "stop" in inputs and inputs["stop"] != stop:
                raise ValueError(
                    "If `stop` is present in any inputs, should be present in all."
                )
            prompts.append(prompt)
        return prompts, stop

self.prompt.format_prompt 即是之前设置的 prefix_prompt
构造完毕之后是:

基于以下已知信息,简洁和专业的来回答用户的问题。
    如果无法从中得到答案,请说 "根据已知信息无法回答该问题""没有提供足够的相关信息",不允许在答案中添加编造成分,答案请使用中文。
    
    已知内容:
      2 组织机构和职责  2.1 领导机构  龙华区大气质量提升工作领导小组是龙华区突发事件  应急委员会下设的专项应急指挥部。

深圳市龙华区大气质量提升工作  领导小组(以下简称“区大气领导小组”)负责组织、协调、  指挥大气污染的预警与应急响应工作。

区大气领导小组成员单位包括:区委  宣传部、市生态环境局龙华管理局、区财政局、区城市管理  和综合执法局、区住房和建设局、区水务局、区教育局、区  4  卫生健康局、区建筑工务署、市交通运输局龙华管理局、龙  华交警大队和各街道办。

  深圳市龙华区大气质量提升工作领导小组办公室  年 月 日  25

  2.2 工作机构  区大气领导小组办公室为工作机构,设在市生态环境局  龙华管理局,负责区大气领导小组的日常工作,包括确定预  警与响应等级,督查区有关部门落实预警与应急响应措施。

  经请示深圳市龙华区大气质量提升工作领导小组同意,现决定启  动《深圳市龙华区大气污染应急预案》,请你单位依据大气污染应急  预案的相关规定,立即组织力量参与应急处置工作。
    
    问题:
    龙华区大气质量提升工作领导小组是什么

1.3 补充内容

langchain的基于运行原理

    def run(self) -> None:
        with claim_worker_thread("asyncio"):
            threadlocals.loop = self.loop
            while True:
                item = self.queue.get()
                if item is None:
                    # Shutdown command received
                    return

                context, func, args, future = item
                if not future.cancelled():
                    result = None
                    exception: Optional[BaseException] = None
                    try:
                        result = context.run(func, *args)
                    except BaseException as exc:
                        exception = exc

                    if not self.loop.is_closed():
                        self.loop.call_soon_threadsafe(
                            self._report_result, future, result, exception
                        )

                self.queue.task_done()

构造一个队列等待用户的信号,一旦页面中监测到信号,依次去判断哪个按钮触发的信号,再根据信号的钩函数处理对应的逻辑


二、总结

在这里插入图片描述

这里的整体逻辑还是相对比较简单的,每个环节都还可以继续优化,作者在群里说了,项目代码已经在持续优化中了。

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

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

相关文章

阳光开朗孔乙己,会否奔向大泽乡

前言 🔥学历对职业关系到底有什么影响呢?🔥学历给我们带来了优势吗?🔥到底是什么造成了"孔乙己的长衫"? 孔乙己是中国清代作家鲁迅创作的一篇短篇小说,发表于1919年。这部作品被认为是…

Blender 建模案例一(2)

目录 1. 烛台基座1.1 导入图片1.2 从立方体取一个顶点1.3 用点描边1.4 旋转1.5 实体化修改器1.6 删除内部正面1.7 封盖1.8 平滑着色1.9 表面细分修改器1.10 环切线(卡线) 1. 烛台基座 1.1 导入图片 1.2 从立方体取一个顶点 中间顶点尽量也X轴平行 1.…

FPGA入门系列5--运算符号

文章简介 本系列文章主要针对FPGA初学者编写,包括FPGA的模块书写、基础语法、状态机、RAM、UART、SPI、VGA、以及功能验证等。将每一个知识点作为一个章节进行讲解,旨在更快速的提升初学者在FPGA开发方面的能力,每一个章节中都有针对性的代码…

( 栈和队列) 739. 每日温度 ——【Leetcode每日一题】

❓739. 每日温度 难度:中等 给定一个整数数组 temperatures ,表示每天的温度,返回一个数组 answer ,其中 answer[i] 是指对于第 i 天,下一个更高温度出现在几天后。如果气温在这之后都不会升高,请在该位置…

32k*16 薪,3年自动化测试历经3轮面试成功拿下华为Offer....

前言 转眼过去,距离读书的时候已经这么久了吗?,从18年5月本科毕业入职了一家小公司,到现在快4年了,前段时间社招想着找一个新的工作,前前后后花了一个多月的时间复习以及面试,前几天拿到了华为…

Java并发编程 —— ThreadPoolExecutor线程池详解

一、什么是线程池 线程池是一种池化技术,是管理一系列线程的资源池。当有任务要处理时,直接从线程池中获取线程来处理,处理完之后线程并不会立即被销毁,而是等待下一个任务。这样实现线程的复用,避免重复创建与销毁线…

司美格鲁肽进入临床竞速期,减肥“神药”生于偶然、火于乱象?

减肥作为一门市场需求旺盛的生意,在很多行业都有所渗透,如今其高潮逐渐来到了医药领域。 CDE(国家食品药品监督管理局药品审评中心)网站显示,4月17日,联邦制药全资附属公司联邦生物科技(珠海横…

Figma导出源文件的方法,用这个方法快速转换其它格式

市场上设计工具层出不穷,Sketch、AdobeXD、Axure、InVision、Figma、Pixso等都是优秀的设计工具,设计师经常面临如何从设计工具中导出文件的问题。 Figma软件的导出功能非常强大,因为轻量化体验受到很多设计师的喜爱。如何保存导出Figma源文…

【Leetcode -19.删除链表的倒数第N个结点 -24.两两交换链表中的节点】

Leetcode Leetcode -19.删除链表的倒数第N个结点Leetcode - 24.两两交换链表中的节点 Leetcode -19.删除链表的倒数第N个结点 题目:给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。 示例 1: 输入:he…

软件测试人员在工作中如何运用Linux

从事过软件测试的小伙们就会明白会使用Linux是多么重要的一件事,工作时需要用到,面试时会被问到,简历中需要写到。 对于软件测试人员来说,不需要你多么熟练使用Linux所有命令,也不需要你对Linux系统完全了解&#xff…

vue总线bus的使用和移除注意事项

vue总线bus的使用和移除注意事项 本文目录 vue总线bus的使用和移除注意事项初始化并封装发送事件接收事件移除事件监听实际使用正确测试效果错误测试效果 初始化并封装 在main.js中对bus进行初始化, Bus是一个不具备 DOM 的组件,它具有的仅仅只是它实例…

算法 | 最长回文子串

思路:遍历字符串,对于字符串的每个字符,维持两个游标(left,right),找到游标对应字符相等时就同速度向两边扩散。 对于 奇数长度子串,left right 对于偶数成都子串,lef…

RocketMq消息

消息发送 发送同步消息 public class SyncProducer {public static void main(String[] args) throws Exception{DefaultMQProducer producernew DefaultMQProducer(/*please_rename_unique_group_name*/"group1");producer.setNamesrvAddr("localhost:9876&q…

复现Nginx 解析漏洞

目录 漏洞原理 漏洞复现 编译环境 制作图片马 一:随便弄一张图片 二:准备写一个.php文件,写上木马 三:合成图片马 上传图片马 修复漏洞 漏洞原理 1、 由于nginx.conf的如下配置导致nginx把以’.php’结尾的文件交给fast…

一篇文章告诉你金融行业如何高效管理文件

由于金融行业的行业属性,信息安全万分重要。因此在文件管理工具时,要注意数据安全问题,那么金融行业如何高效管理文件呢? 首先金融行业在文件管理时可能面临以下问题: 1,资料繁杂,整理困难&…

Unity Camera -- (3)控制相机能看到的东西

使用剪裁平面(Clipping Planes)定义相机可视范围 Clipping Planes定义了相机所能看到的场景范围。在有些时候,限制相机所能看到的范围是出于风格上的考量,但编辑Clipping Planes的主要目的是为了优化性能。相机所需要渲染的东西越…

什么是低码平台?低代码平台能解决什么问题?

低代码平台是近年来日益流行的一种新型软件开发工具。它们提供了一种更简单、更快速、更具成本效益的方式来构建和部署定制软件应用程序。在本文中,我们将探讨什么是低码平台,它们可以解决什么问题,以及它们为什么变得如此流行。 一、什么是低…

第十六章 命令模式

文章目录 前言一、命令模式解决智能生活项目设计思想完整代码Command 所有命令的父接口(绑定命令都需要实现)LightReceiver 命令接受者LightOnCommand / LightOffCommand 将具体的命令进行绑定空命令命令调用者Clint 测试 添加新的命令,非常简…

【信息安全案例】——身份与访问安全(学习笔记)

📖 前言:一位用户对计算机信息资源的访问活动中,首先必须拥有身份标识,通过该标识鉴别该用户的身份,进一步地,用户还应当具有执行所请求动作的必要权限,系统会验证并控制其能否执行对资源试图完…

Human Pose Regression with Residual Log-likelihood Estimation

Abstract 通过似然热图对输出分布进行建模的基于热图的方法在人体姿态估计领域占据主导地位。相比之下,基于回归的方法更有效,但效果较差。 在这项工作中,我们探索了最大似然估计(MLE),以开发一种高效有…