首页 > 其他分享 >Chainlit集成Langchain并使用通义千问和智谱AI实现AI知识库检索网页对话应用

Chainlit集成Langchain并使用通义千问和智谱AI实现AI知识库检索网页对话应用

时间:2024-09-12 13:53:21浏览次数:3  
标签:千问 cl AI self Langchain langchain file path import

LangChain 简介

LangChain 是一个开源框架,设计用于开发和部署与语言模型(如大型语言模型LLM)交互的应用程序。它提供了一种简便的方法来构建基于自然语言处理(NLP)的系统,这些系统可以执行各种任务,例如问答、文本生成、文档检索等。LangChain 的主要目标是简化开发过程,使开发者能够快速地将强大的语言模型功能集成到他们的应用程序中。

LangChain 包含三个关键组件:

  1. 链(Chains):这是执行特定任务的模块化工作流。链条可以简单也可以复杂,取决于任务需求。它们可以是简单的问答机制,也可以是涉及多个步骤的复杂流程。

  2. 语言模型(Language Models):这些是预训练的模型,可以生成或修改文本。LangChain 支持多种语言模型,包括那些可以从外部服务调用的模型。

  3. 代理(Agents):代理是更高级的概念,它们使用链条来自主地执行任务。代理可以根据环境或输入数据的变化来决定使用哪些链条,从而实现一定程度的自动化决策。

LangChain 还支持与文档数据库的交互,这使得从结构化数据中提取信息变得容易,并且可以通过 API 调用来集成其他服务。开发者可以利用 LangChain 来创建聊天机器人、虚拟助手、自动化的写作工具以及其他依赖于语言理解和生成的应用程序。

LangChain 官方地址 https://python.langchain.com/v0.2/docs/introduction/

快速上手

创建一个文件,例如“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文件

方案1

使用通义千问的openai 兼容接口和智谱清言的向量化open ai接口实现知识库问答

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

OPENAI_API_BASE="https://dashscope.aliyuncs.com/compatible-mode/v1"
OPENAI_API_KEY="ypur-api_key"
  • OPENAI_API_BASE 是 openai的api 的base地址,如果你能直接使用openai,这可以不设置,这里我用的是阿里的open ai兼容接口
  • OPENAI_API_KEY 替换成你自己的API 密匙
  • 阿里模型接口地址 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.schema import Document
from langchain.schema import StrOutputParser
from langchain.schema.runnable import Runnable, RunnablePassthrough, RunnableConfig
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.document_loaders import (
    PyMuPDFLoader, CSVLoader, TextLoader, Docx2txtLoader
)
from langchain_community.embeddings import OpenAIEmbeddings
from langchain_community.vectorstores import Chroma
from langchain_openai import ChatOpenAI

chunk_size = 1024
chunk_overlap = 100

FILE_STORAGE_PATH = "data_file"

embeddings_model = OpenAIEmbeddings(base_url='https://open.bigmodel.cn/api/paas/v4', api_key='your-pai-key',
                                    model='embedding-3')


@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


doc_search = process_files(FILE_STORAGE_PATH)
retriever = doc_search.as_retriever(search_kwargs={"k": 4})
model = ChatOpenAI(model_name="qwen-plus", streaming=True)


@cl.on_chat_start
async def on_chat_start():
    template = """Answer the question based only on the following context:
    {context}
    Question: {question}
    """
    prompt = ChatPromptTemplate.from_template(template)
    runnable = (
            {"context": retriever, "question": RunnablePassthrough()}
            | prompt
            | model
            | StrOutputParser()
    )
    cl.user_session.set("runnable", runnable)


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

    class PostMessageHandler(BaseCallbackHandler):
        """
        Callback handler for handling the retriever and LLM processes.
        Used to post the sources of the retrieved documents as a Chainlit element.
        """

        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:
                print(d)
                source_page_pair = (d.page_content, d.metadata['row'])
                self.sources.append(source_page_pair)  # Add unique pairs to the set

        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**数据来源**: {', '.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()

方案2

只使用通义千问的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.schema import Document
from langchain.schema import StrOutputParser
from langchain.schema.runnable import Runnable, 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

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


doc_search = process_files(FILE_STORAGE_PATH)
retriever = doc_search.as_retriever(search_kwargs={"k": 4})
model = Tongyi(model='qwen-turbo')


@cl.on_chat_start
async def on_chat_start():
    template = """Answer the question based only on the following context:
    {context}
    Question: {question}
    """
    prompt = ChatPromptTemplate.from_template(template)
    runnable = (
            {"context": retriever, "question": RunnablePassthrough()}
            | prompt
            | model
            | StrOutputParser()
    )
    cl.user_session.set("runnable", runnable)


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

    class PostMessageHandler(BaseCallbackHandler):
        """
        Callback handler for handling the retriever and LLM processes.
        Used to post the sources of the retrieved documents as a Chainlit element.
        """

        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:
                print(d)
                source_page_pair = (d.page_content, d.metadata['row'])
                self.sources.append(source_page_pair)  # Add unique pairs to the set

        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()

在项目根目录下创建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 在本地快速部署大型语言模型,可进行定制并创建属于您自己的模型》

标签:千问,cl,AI,self,Langchain,langchain,file,path,import
From: https://blog.csdn.net/weixin_40986713/article/details/142053664

相关文章

  • 测评通义灵码,如何实现微信表情、 AI 语音笔记等小功能?
    内容来源MacTalk公众号,作者池建强墨问西东是一家创业公司,很难一下子配齐像大公司那样的研发团队,这类AI编程辅助工具其实在一定程度上帮助我们的研发同学成长为全栈工程师,一个人就能顶上一个团队。从我们团队的使用体验看,通义灵码有两个优点。第一,精准、快速的问答能力,它可以准......
  • 测评通义灵码,如何实现微信表情、 AI 语音笔记等小功能?
    内容来源MacTalk公众号,作者池建强墨问西东是一家创业公司,很难一下子配齐像大公司那样的研发团队,这类AI编程辅助工具其实在一定程度上帮助我们的研发同学成长为全栈工程师,一个人就能顶上一个团队。从我们团队的使用体验看,通义灵码有两个优点。第一,精准、快速的问答能力,它可以准......
  • 测评通义灵码,如何实现微信表情、 AI 语音笔记等小功能?
    内容来源MacTalk公众号,作者池建强墨问西东是一家创业公司,很难一下子配齐像大公司那样的研发团队,这类AI编程辅助工具其实在一定程度上帮助我们的研发同学成长为全栈工程师,一个人就能顶上一个团队。从我们团队的使用体验看,通义灵码有两个优点。第一,精准、快速的问答能力,它可......
  • 我认为苹果将在AI竞赛中成为黑马的5个原因
    现在,要找到一款没有宣传自己人工智能优势的手机或电脑,比找到一款拥有这些功能的设备更难。AI无处不在,几乎在所有东西里都有应用—常常让人找不到明显的理由—而苹果公司在即将推出的iPhone16中也不例外。尽管苹果在生成式AI领域起步较晚,落后于谷歌、微软及新兴企业,但他们......
  • 测评通义灵码,如何实现微信表情、 AI 语音笔记等小功能?
    内容来源MacTalk公众号,作者池建强墨问西东是一家创业公司,很难一下子配齐像大公司那样的研发团队,这类AI编程辅助工具其实在一定程度上帮助我们的研发同学成长为全栈工程师,一个人就能顶上一个团队。从我们团队的使用体验看,通义灵码有两个优点。第一,精准、快速的问答能力,它可......
  • cross-plateform 跨平台应用程序-10-naitvescript 介绍
    跨平台系列cross-plateform跨平台应用程序-01-概览cross-plateform跨平台应用程序-02-有哪些主流技术栈?cross-plateform跨平台应用程序-03-如果只选择一个框架,应该选择哪一个?cross-plateform跨平台应用程序-04-ReactNative介绍cross-plateform跨平台应用程序-05-Flut......
  • AI实战 | 领克汽车线上营销助手:全面功能展示与效果分析
    助手介绍我就不自我介绍了,在我的智能体探索之旅中,很多人已经通过coze看过我的教程。今天,我专注于分享我所开发的一款助手——《领克汽车线上营销》。他不仅仅是一个销售顾问的替身,更是一位能在线上自动为对领克感兴趣的潜在粉丝介绍领克车系的助手。他还能提供全方位的车辆对比......
  • Stable Diffusion4.9(Ai绘画)安装教程(永久许可)
    前言软件获取软件名称StableDiffusion4.9软件语言简体中文软件大小9.6G推荐平台Win10或更高,64位操作系统本次教程将使用AI绘画工具StableDiffusion进行讲解,如还未安装SD的小伙伴可以扫描免费获取哦~软件介绍StableDiffusion(简称SD)是一种生......
  • AI助理驱动的企业知识库:从数据海洋到知识金矿的转变
    在当今这个信息爆炸的时代,企业面临着前所未有的数据洪流。这些数据,无论是来自市场趋势、客户反馈、内部运营还是外部研究,都蕴含着巨大的价值,但同时也带来了筛选、整合与应用的巨大挑战。如何在这片数据海洋中捞出真金白银,成为企业提升竞争力、实现可持续发展的关键。AI助理......
  • 如何通过LlamaIndex工作流程简化我的研究和演示
    LlamaIndex最近引入了一项新功能:Workflows。这对于那些希望创建兼具可靠性和灵活性的AI解决方案的人来说非常有用。为什么呢?因为它允许你通过控制流程定义定制化步骤。它支持循环、反馈和错误处理。就像一个AI驱动的流水线。但与通常实施为有向无环图(DAG)的典型流水线不同,Workf......