Chainlit集成Langchain并使用通义千问AI知识库高级检索(多重查询)网页对话应用教程

news2024/11/15 23:52:52

前言

之前写过几篇利用Chainlit集成Langchain和国内通义千问大模型集成的知识库检索增加的网页对话应用的技术文章。文章中关于Langchain的知识库检索只是入门级别的教学,本篇文章针对Langchain的知识库高级检索技术和之前对话应用的代码进行完善。
本次主要改进的点

  • 使用自定义提示词,之前使用的是系统默认提示词,全英文的提示词,回答的时候,经常会出现英文,这次使用中文的提示词加国内的大模型,出现英文的回答大大降低,而且还用了中文设置了系统角色的提示词。
  • 使用多查询检索技术,即将用户问题列变成三个相似的问题,分别对知识库进行检索,并将检索结果合并处理给AI。大大提升了知识检索的准确度。

以前的文章:
《Chainlit集成Langchain并使用通义千问和智谱AI实现AI知识库检索网页对话应用》
《使用Chainlit接入通义千问快速实现一个本地文档知识问答机器人》
《使用Chainlit接入通义千问快速实现一个本地文档知识问答机器人增强版》

快速上手

创建一个文件,例如“chainlit_chat”

mkdir chainlit_chat

进入 chainlit_chat文件夹下,执行命令创建python 虚拟环境空间(需要提前安装好python sdkChainlit 需要python>=3.8。,具体操作,由于文章长度问题就不在叙述,自行百度),命令如下:

python -m venv .venv
  • 这一步是避免python第三方库冲突,省事版可以跳过
  • .venv是创建的虚拟空间文件夹可以自定义

接下来激活你创建虚拟空间,命令如下:

#linux or mac
source .venv/bin/activate
#windows
.venv\Scripts\activate

在项目根目录下创建requirements.txt,内容如下:

langchain
chainlit
openai
chromadb
tiktoken
pymupdf
langchain_community
dashscope~=1.20.3

执行以下命令安装依赖:

pip install -r .\requirements.txt
  • 安装后,项目根目录下会多出.chainlit.files文件夹和chainlit.md文件

只使用通义千问的DashScope模型服务灵积的接口

在项目根目录下创建.env环境变量,配置如下:

DASHSCOPE_API_KEY="sk-api_key"
  • DASHSCOPE_API_KEY 是阿里dashscope的服务的APIkey,代码中使用DashScope的sdk实现,所以不需要配置base_url。默认就是阿里的base_url。
  • 阿里模型接口地址 https://dashscope.console.aliyun.com/model

在项目根目录下创建app.py文件,代码如下:

from pathlib import Path
from typing import List

import chainlit as cl
from langchain.callbacks.base import BaseCallbackHandler
from langchain.prompts import ChatPromptTemplate
from langchain.retrievers import MultiQueryRetriever
from langchain.schema import Document
from langchain.schema import StrOutputParser
from langchain.schema.runnable import RunnablePassthrough, RunnableConfig
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.document_loaders import (
    PyMuPDFLoader, CSVLoader, TextLoader, Docx2txtLoader
)
from langchain_community.embeddings import DashScopeEmbeddings
from langchain_community.llms import Tongyi
from langchain_community.vectorstores import Chroma
from langchain_core.messages import SystemMessage
from langchain_core.prompts import HumanMessagePromptTemplate

chunk_size = 1024
chunk_overlap = 100

FILE_STORAGE_PATH = "data_file"

embeddings_model = DashScopeEmbeddings()


@cl.cache
def process_files(file_storage_path: str):
    file_directory = Path(file_storage_path)
    docs = []  # type: List[Document]
    text_splitter = RecursiveCharacterTextSplitter(chunk_size=chunk_size, chunk_overlap=chunk_overlap)

    for file_path in file_directory.glob("*.pdf"):
        loader = PyMuPDFLoader(str(file_path))
        docs += text_splitter.split_documents(loader.load())

    for file_path in file_directory.glob("*.csv"):
        loader = CSVLoader(str(file_path), encoding="UTF-8")
        docs += text_splitter.split_documents(loader.load())

    for file_path in file_directory.glob("*.txt"):
        loader = TextLoader(str(file_path), encoding="UTF-8")
        docs += text_splitter.split_documents(loader.load())

    for file_path in file_directory.glob("*.doc"):
        loader = Docx2txtLoader(str(file_path))
        docs += text_splitter.split_documents(loader.load())

    vector_store = Chroma.from_documents(docs, embeddings_model)

    return vector_store


llm = Tongyi(model='qwen-plus')
doc_search = process_files(FILE_STORAGE_PATH)
retriever = doc_search.as_retriever(search_kwargs={"k": 9})
multi_retriever = MultiQueryRetriever.from_llm(
    retriever=retriever, llm=llm
)



@cl.on_chat_start
async def on_chat_start():
    system_prompt = """
    # 角色
    石家庄医专学校智能客服
    ## 能力
    - 利用用户提供的省份、文理科、分数、位次等信息,比较分数和位次,给出关于本校的报考建议。
    - 解答用户提问关于学校相关问题
    """
    human_template = """Answer the question based only on the following context:
    {context}
    回答要求:
    - 如果你不清楚答案,你需要澄清。
    - 避免提及你是从 <Data></Data> 获取的知识。
    - 保持答案与 <Data></Data> 中描述的一致。
    - 使用 Markdown 语法优化回答格式。
    - 使用与问题相同的语言回答。

    问题: {question}
    """
    prompt = ChatPromptTemplate.from_messages([
        SystemMessage(content=system_prompt),
        HumanMessagePromptTemplate.from_template(human_template)
    ])

    runnable = (
            {"context": multi_retriever, "question": RunnablePassthrough()}
            | prompt
            | llm
            | StrOutputParser()
    )
    cl.user_session.set("runnable", runnable)


@cl.on_message
async def on_message(message: cl.Message):
    runnable = cl.user_session.get("runnable")
    msg = cl.Message(content="")

    class PostMessageHandler(BaseCallbackHandler):
        """
        用于处理检索程序和LLM进程的回调处理程序。
        用于将检索到的文档的源作为Chainlit元素发布。
        """

        def __init__(self, msg: cl.Message):
            BaseCallbackHandler.__init__(self)
            self.msg = msg
            self.sources = []  # To store unique pairs

        def on_retriever_end(self, documents, *, run_id, parent_run_id, **kwargs):
            for d in documents:
                source_page_pair = (d.page_content, d.metadata['row'])
                if source_page_pair not in self.sources:
                    self.sources.append(source_page_pair)

        async def on_llm_end(self, response, *, run_id, parent_run_id, **kwargs):
            if len(self.sources):
                source_names = []
                for page_content, row in self.sources:
                    source_name = f"source_{row}"
                    source_names.append(source_name)
                    self.msg.elements.append(
                        cl.Text(content=page_content, name=source_name, display="side")
                    )
                await self.msg.stream_token(f"\n\n **数据来源**: {', '.join(source_names)}")

    async for chunk in runnable.astream(
            message.content,
            config=RunnableConfig(callbacks=[
                cl.LangchainCallbackHandler(),
                PostMessageHandler(msg)
            ]),
    ):
        await msg.stream_token(chunk)

    await msg.send()

代码解读

这段代码是一个基于Chainlit框架的聊天机器人应用,它利用LangChain库来处理文档检索、文本分割、向量存储以及问答系统。下面是对代码的逐部分解释:

导入必要的库和模块

首先导入了各种库和模块,包括路径操作(pathlib.Path)、类型提示(typing.List)、Chainlit库、LangChain回调处理器、提示模板、多查询检索器、文档模型、文本分割器、文档加载器、嵌入模型、语言模型、矢量数据库、消息模板等。

全局变量定义

定义了一些全局变量,如chunk_size用于控制文档切分后的每个片段大小,chunk_overlap用于控制文档切分后片段间的重叠长度。FILE_STORAGE_PATH指定了文件存储路径。

嵌入模型实例化

创建了一个DashScopeEmbeddings实例,用于将文本转换为向量表示。

文件处理函数

process_files函数用于处理存储路径下的多种类型的文件(如PDF、CSV、TXT、DOC),加载它们的内容,并使用递归字符文本分割器将其切分为更小的文档片段。然后,这些文档片段会被添加到一个Chroma向量数据库中,以便后续进行相似度搜索。

语言模型实例化

创建了一个Tongyi语言模型实例,这里使用的是qwen-plus模型。

文档检索初始化

通过调用process_files函数获取到的向量存储来初始化文档搜索器,并进一步配置多查询检索器以提高检索效果。

Chat Start 事件监听

on_chat_start装饰器下定义了一个异步函数,当聊天开始时会执行该函数。在这个函数中,定义了系统的角色和能力,以及如何根据上下文回答问题的提示模板。接着构建了一个可运行的流程,这个流程包含了从多查询检索器获取上下文、应用提示模板、使用语言模型生成响应以及解析输出结果等功能。

Message 事件监听

on_message装饰器下定义了一个异步函数,当有新消息到达时会执行该函数。此函数根据用户发送的消息内容,使用之前设置好的可运行流程来生成响应,并且在回调处理器的帮助下,还可以展示检索到的数据源。

总的来说,这段代码实现了一个能够根据用户输入的问题,自动从预处理过的文档集合中查找相关信息,并利用语言模型生成符合语境的回答的聊天机器人。

在项目根目录下创建data_file文件夹

在这里插入图片描述
将你的文件放到这里,代码中设置的支持,pdf、doc、csv 、txt格式的文件,后续可以根据自己的需求增加更多,langchain带有很多格式文件的加载器,可以自行修改代码。

运行应用程序

要启动 Chainlit 应用程序,请打开终端并导航到包含的目录app.py。然后运行以下命令:

 chainlit run app.py -w   
  • -w标志告知 Chainlit 启用自动重新加载,因此您无需在每次更改应用程序时重新启动服务器。您的聊天机器人 UI 现在应该可以通过http://localhost:8000访问。
  • 自定义端口可以追加--port 80

启动后界面如下:

在这里插入图片描述

相关文章推荐

《Chainlit快速实现AI对话应用的界面定制化教程》
《Chainlit接入FastGpt接口快速实现自定义用户聊天界面》
《使用 Xinference 部署本地模型》
《Fastgpt接入Whisper本地模型实现语音输入》
《Fastgpt部署和接入使用重排模型bge-reranker》
《Fastgpt部署接入 M3E和chatglm2-m3e文本向量模型》
《Fastgpt 无法启动或启动后无法正常使用的讨论(启动失败、用户未注册等问题这里)》
《vllm推理服务兼容openai服务API》
《vLLM模型推理引擎参数大全》
《解决vllm推理框架内在开启多显卡时报错问题》
《Ollama 在本地快速部署大型语言模型,可进行定制并创建属于您自己的模型》

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

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

相关文章

月薪14K的网安公司,来做一下笔试题呀~

《网安面试指南》http://mp.weixin.qq.com/s?__bizMzkwNjY1Mzc0Nw&mid2247484339&idx1&sn356300f169de74e7a778b04bfbbbd0ab&chksmc0e47aeff793f3f9a5f7abcfa57695e8944e52bca2de2c7a3eb1aecb3c1e6b9cb6abe509d51f&scene21#wechat_redirect 网络安全简介…

leetcode-枚举算法

1.两数之和 题目一&#xff1a;两数之和 给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标值 target 的那 两个 整数&#xff0c;并返回它们的数组下标。 你可以假设每种输入只会对应一个答案&#xff0c;并且你不能使用两次相同的元素…

JVM JMM 专题篇 ( 12000 字详解 )

一&#xff1a;JVM 简介 JVM 是 Java Virtual Machine 的简称&#xff0c;意为 Java 虚拟机&#xff0c;虚拟机是指通过软件模拟的具有完整硬件功能的、运行在一个完全隔离的环境中的完整计算机系统。 常见的虚拟机&#xff1a;JVM、VMwave、Virtual Box&#xff0c;JVM 和其…

微调大模型不再难:LoRA方法带你轻松节省99%的训练成本!

我们之前说大模型有四种玩家&#xff0c;其中前三种都是要做模型训练的。而大部分公司或个人&#xff0c;都是在第二种开源大模型的基础上来做训练。 而这种训练方式又分为两种。一种要么就是从头训练&#xff0c;要么就Fine-tuning接着开源模型来训练&#xff0c;在基座模型已…

IP 协议分析《实验报告》

目录 一、 实验目的 二、实验设备和环境 三、实验记录 1、实验环境搭建 2、IP 协议分析 1.设置抓包接口 2.IP 报文分析 3.报文长度计算 4.生存时间 TTL 5.分析总结 3、IP分片 1.IP 分片简介 2.捕获分组 3.结果分析 一、 实验目的 1、掌握 IP 协议数据报格式&…

知识图谱与异构图神经网络(7)--1

知识图谱是由实体(节点)和关系( 不同类型的边) 组成的多关系图。作为一种非常重要又特殊的图结构数据&#xff0c;知识图谱被广泛应用在人工智能和自然语言处理领域&#xff0c;从语义解析、命名实体消歧到问答系统、推荐系统中都可以看到来自知识图谱的技术推动。本质上&#…

树和二叉树基本术语、性质

目录 树的相关知识 常见考点1&#xff1a;结点数总度数&#xff0b;1 常见考点2&#xff1a; 度为m的树和m叉树 常见考点3&#xff1a;度为m的树第i层至多有结点数 常见考点4&#xff1a;高度为h的m叉树至多有结点 ​编辑 常见考点5&#xff1a;高度为h的m叉树&#xff0c;高…

可靠性:MSTP 和 VRRP 配置实验

一、拓扑&#xff1a; 说明&#xff1a; 1、交换机 SW1、2、3 分别起 vlan 10、20&#xff0c;都以 trunk 方式连接 2、 PC1、2 分别属于 vlan 10、20 3、SW1、2 起 vlan 100 做为管理段&#xff0c;网关地址分别以 100.1.1.1/24 和 200.1.1.2/24 和 AR1相连 …

监控易监测对象及指标之:全面监控InterSystems Cache数据库

随着企业数字化转型的深入&#xff0c;数据库作为核心的信息资产&#xff0c;其性能和稳定性对于保障业务连续性至关重要。InterSystems Cache作为一款高性能、可扩展的数据库管理系统&#xff0c;广泛应用于医疗、金融、制造等行业。为了确保Cache数据库的高效运行和稳定性能&…

Oracle 启动动态采样 自适应执行计划

为了解决因为统计信息缺失或者统计不够准确而引起的问题&#xff0c;从9iR2的版本开始Oracle推出了动态采样&#xff08;Dynamic Sampling&#xff09;功能&#xff0c;使SQL文在硬解析过程中动态地收集统计信息。 该功能在以后的版本上得到更进一步的增强&#xff0c;从11.2.0…

创建一个Java项目并在项目中新建文件,最后实现程序简单的输出

目录 前言 一、建立项目及新建Java类 二、输入简单代码实现输出 前言 1.本文所讲的是java程序设计语言&#xff0c;其内容是如何在id中新建一个项目&#xff0c;并新建一个Java文件&#xff0c;在其内输入相关代码并对其输出&#xff1b; 2.Java文件的编写以收入到我的专栏…

Docker torchserve 部署模型流程

1.拉取官方镜像 地址: https://hub.docker.com/r/pytorch/torchserve/tags docker pull pytorch/torchserve:0.7.1-gpu2. docker启动指令 CPU docker run --rm -it -d -p 8380:8080 -p 8381:8081 --name torch-server -v /path/model-server/extra-files:/home/model-serve…

计算机毕业设计选题推荐-4S店试驾平台-小程序/App

✨作者主页&#xff1a;IT研究室✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Python…

js 如何代码识别Selenium+Webdriver

Python 的 Selenium 可以模拟用户操作打开浏览器&#xff0c;前端如何去识别是人机还是真人&#xff1a; window.navigator.webdriver Selenium 人机下是这样的&#xff1a; 正常使用&#xff1a;

Makefile语法详解

目录 1 Makefile基本常识1.1 基本格式1.2 makefile规则1.3 伪目标1.4 变量的使用1.5 赋值方式1.6 常用函数 2 Makefile整体编译2.1 编译选项2.2三个.c整体编译2.3 静态库编译2.4 动态库编译 1 Makefile基本常识 1.1 基本格式 如下所示为Makefile的基本格式&#xff0c;特别需…

高等数学 2.5 函数的微分

文章目录 一、微分的定义二、微分的几何意义三、微分运算1、函数和、差、积、商的微分法则2、复合函数的微分法则 四、微分在近似计算中的应用 一、微分的定义 定义 设函数 y f ( x ) y f(x) yf(x) 在某区间内有定义&#xff0c; x 0 x_0 x0​ 及 x 0 Δ x x_0 \Delta x …

大模型时代:普通人如何获利

随着人工智能技术的飞速发展&#xff0c;我们正步入一个以大模型为驱动力的新时代。这些大型语言模型&#xff0c;如GPT-3和BERT&#xff0c;已经在各个领域展现出惊人的能力&#xff0c;包括文本生成、翻译、问答等。这些技术的进步不仅改变了我们的生活&#xff0c;也为普通人…

【数据结构初阶】顺序结构二叉树(堆)接口实现超详解

文章目录 1.树1. 1 树的概念与结构1. 2 树的相关术语1. 3 树的表示1. 4 树形结构实际运用场景 2.二叉树2. 1 概念与结构2. 2 特殊的二叉树2. 2. 1 满二叉树2. 2. 2 完全二叉树 2. 3 二叉树存储结构2. 3. 1 顺序结构2. 3. 2 链式结构 3. 实现顺序结构二叉树&#xff08;小堆&…

【OJ刷题】双指针问题6

这里是阿川的博客&#xff0c;祝您变得更强 ✨ 个人主页&#xff1a;在线OJ的阿川 &#x1f496;文章专栏&#xff1a;OJ刷题入门到进阶 &#x1f30f;代码仓库&#xff1a; 写在开头 现在您看到的是我的结论或想法&#xff0c;但在这背后凝结了大量的思考、经验和讨论 目录 1…

ThreadX源码:Cortex-A7的tx_thread_irq_nesting_start(嵌套中断开始动作).s汇编代码分析

0 参考资料 Cortex M3权威指南(中文).pdf&#xff08;可以参考ARM指令集用法&#xff09; 1 前言 tx_thread_irq_nesting_start.s是用来实现Cortex-A7 IRQ嵌套中断的开始函数实现的汇编文件。 2 源码分析 源码如下&#xff1a; &#xff11;  IRQ_DISABLE 0x80…