使用langchain与你自己的数据对话(五):聊天机器人

这篇具有很好参考价值的文章主要介绍了使用langchain与你自己的数据对话(五):聊天机器人。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

使用langchain与你自己的数据对话(五):聊天机器人,Langchain,ChatGPT,langchain,chatgpt,语言模型,人工智能,自然语言处理

之前我已经完成了使用langchain与你自己的数据对话的前四篇博客,还没有阅读这四篇博客的朋友可以先阅读一下:

  1. 使用langchain与你自己的数据对话(一):文档加载与切割
  2. 使用langchain与你自己的数据对话(二):向量存储与嵌入
  3. 使用langchain与你自己的数据对话(三):检索(Retrieval)
  4. 使用langchain与你自己的数据对话(四):问答(question answering) 

今天我们来继续讲解deepleaning.AI的在线课程“LangChain: Chat with Your Data”的第六门课:chat。

Langchain在实现与外部数据对话的功能时需要经历下面的5个阶段,它们分别是:Document Loading->Splitting->Storage->Retrieval->Output,如下图所示:

使用langchain与你自己的数据对话(五):聊天机器人,Langchain,ChatGPT,langchain,chatgpt,语言模型,人工智能,自然语言处理

在前面的四篇博客中我们以及完成了这5给阶段所有的内容介绍,并在第四篇博客中我们还创建了RetrievalQA实现了对数据的问答功能,但是这里有一个小小的缺陷,那就是通过RetrievalQA实现的问答功能只能针对当前问题进行回答,它无法参考上下文来来回答问题,也就是说它没有记忆能力,无法实现连贯性聊。今天我们就来解决这个问题,我们会创建一个真正的个性化聊天机器人,它会学习用户提供的数据,并解答任何关于数据内容的问题,并且它具有记忆能力,能够实现真正的连贯性聊天。

在讨论聊天机器人之前之前,先让我们完成一些基础性工作,比如设置一下openai的api key:

import os
import openai
import sys
sys.path.append('../..')

import panel as pn  # GUI
pn.extension()

from dotenv import load_dotenv, find_dotenv
_ = load_dotenv(find_dotenv()) # read local .env file

openai.api_key  = os.environ['OPENAI_API_KEY']

 先前内容回顾

之前我们介绍了Langchain在实现与外部数据对话的功能时需要经历下面的5个阶段,它们分别是:Document Loading->Splitting->Storage->Retrieval->Output。下面我们通过代码来简单实现一下这5个阶段的功能:

from langchain.vectorstores import Chroma
from langchain.embeddings.openai import OpenAIEmbeddings

#加载本地向量数据库
persist_directory = 'docs/chroma/'
embedding = OpenAIEmbeddings()
vectordb = Chroma(persist_directory=persist_directory, 
                  embedding_function=embedding)

#搜索与问题相关的文档
question = "What are major topics for this class?"
docs = vectordb.similarity_search(question,k=3)

#查看搜索结果中的文档数量
len(docs)

使用langchain与你自己的数据对话(五):聊天机器人,Langchain,ChatGPT,langchain,chatgpt,语言模型,人工智能,自然语言处理

 这里我们在向量数据库中搜索到3篇与问题相关的文档,下面我们查看一下这3篇文档:

docs

使用langchain与你自己的数据对话(五):聊天机器人,Langchain,ChatGPT,langchain,chatgpt,语言模型,人工智能,自然语言处理 下面我们来创建RetrievalQA,同时我们加入一个prompt的模板,在该prompt我们要求llm尽量用简洁的语言来回答问题,并且不能编造答案,最后我们还要求llm在答案的结语上加上“thanks for asking!”,通过这个prompt模板llm能给出简洁的格式化的答案:


from langchain.chat_models import ChatOpenAI
from langchain.prompts import PromptTemplate

# Build prompt
template = """Use the following pieces of context to answer the question at the end. \
If you don't know the answer, just say that you don't know, don't try to make up an answer. \
Use three sentences maximum. Keep the answer as concise as possible. \
Always say "thanks for asking!" at the end of the answer. 

{context}
Question: {question}
Helpful Answer:"""
QA_CHAIN_PROMPT = PromptTemplate(input_variables=["context", "question"],template=template,)

# Run chain
from langchain.chains import RetrievalQA
question = "Is probability a class topic?"
qa_chain = RetrievalQA.from_chain_type(llm=ChatOpenAI(temperature=0),
                                       retriever=vectordb.as_retriever(),
                                       return_source_documents=True,
                                       chain_type_kwargs={"prompt": QA_CHAIN_PROMPT})


result = qa_chain({"query": question})
result["result"]

 ​​​​​使用langchain与你自己的数据对话(五):聊天机器人,Langchain,ChatGPT,langchain,chatgpt,语言模型,人工智能,自然语言处理

 这里我们看到RetrievalQA返回了一个很简洁的答案,并在最后附加了“thanks for asking!”,这符合我们对它的要求。

ConversationalRetrievalChain

到目前为止我们已经创建好了RetrievalQA,可以实现对数据内容的问答,不过这里会有一个问题,就是通过RetrievalQA创建的检索问答链,它没有记忆功能,它无法记住之前用户已经提出过问题,所以RetrievalQA不能实现连贯性的聊天问答。为了解决这个功能,我们可以通过创建ConversationalRetrievalChain,它会存储每次聊天的历史记录,当LLM在回答当前问题的时候都会参考历史聊天记录,这样就可以实现连贯性的聊天:

使用langchain与你自己的数据对话(五):聊天机器人,Langchain,ChatGPT,langchain,chatgpt,语言模型,人工智能,自然语言处理

为了保存么此用户和LLM之间的聊天记录,我们需要创建一个ConversationBufferMemory组件,该组件会自动保存每一次用户和LLM之间对话记录。ConversationalRetrievalChain包含3给主要的参数:

  • llm: 语言模型,这里我们使用openai的“gpt-3.5-turbo”模型
  • retriever:检索器,这里我们由向量数据库来创建检索器
  • memory:记忆力组件,这里我们使用ConversationBufferMemory
from langchain.chat_models import ChatOpenAI
from langchain.memory import ConversationBufferMemory
from langchain.chains import ConversationalRetrievalChain


#创建memory
memory = ConversationBufferMemory(
    memory_key="chat_history",
    return_messages=True
)

#创建ConversationalRetrievalChain
qa = ConversationalRetrievalChain.from_llm(
    llm=ChatOpenAI(temperature=0),
    retriever=vectordb.as_retriever(),
    memory=memory
)

这里我们创建了ConversationalRetrievalChain的实例qa,接下来我们来实现连贯性的聊天,我们首先向LLM提出一个问题:概率是这门课的主题吗?

question1="概率是这门课的主题吗?"
result = qa({"question": question1})
print(result['answer'])

使用langchain与你自己的数据对话(五):聊天机器人,Langchain,ChatGPT,langchain,chatgpt,语言模型,人工智能,自然语言处理

 接下来我们第二给问题:为什么需要先修课程呢?,这里需要说明的是该问题其实是衔接第一个问题的答案,如果我们的ConversationalRetrievalChain有记忆功能,那么它一定会知道这里的先修课程是指哪些课程,并且给出正确的回答:

question2 = "为什么需要先修课程呢?"
result = qa({"question": question2})
print(result['answer'])

使用langchain与你自己的数据对话(五):聊天机器人,Langchain,ChatGPT,langchain,chatgpt,语言模型,人工智能,自然语言处理

 这里我们向LLM提出了2个问题,第一个问题是:概率是这门课的主题吗?我们知道,我们的向量数据库中存储的是吴恩达老师著名的机器学习课程cs229的课程讲义,因此课程中涉及到了一些概率的基础知识,那么接下来提出的第二给问题:为什么需要先修课程呢?该问题其实是衔接第一个问题的答案,要回答该问题必须要知道这里的先修课程是指哪些课程,因为LLM在回答第一个问题的时候已经明确告知用户概率是这门课的一个主题,那么概率也就是这门课的先修课程,这里我们看到ConversationalRetrievalChain在回答第二给问题的时候已经参考了之前的历史聊天记录,因此它给出了合理的答案。

创建聊天机器人

下面我们把Langchain在实现与外部数据对话的功能的5个阶段所有的内容整合起来,然后建一个真正意义上的聊天机器人,这里我们在jupyter notebook中使用panel组件来创建一个GUI的聊天对话界面:

from langchain.embeddings.openai import OpenAIEmbeddings
from langchain.text_splitter import CharacterTextSplitter, RecursiveCharacterTextSplitter
from langchain.vectorstores import DocArrayInMemorySearch
from langchain.document_loaders import TextLoader
from langchain.chains import RetrievalQA,  ConversationalRetrievalChain
from langchain.memory import ConversationBufferMemory
from langchain.chat_models import ChatOpenAI
from langchain.document_loaders import TextLoader
from langchain.document_loaders import PyPDFLoader
import panel as pn
import param

def load_db(file, chain_type, k):
    # load documents
    loader = PyPDFLoader(file)
    documents = loader.load()
    # split documents
    text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=150)
    docs = text_splitter.split_documents(documents)
    # define embedding
    embeddings = OpenAIEmbeddings()
    # create vector database from data
    db = DocArrayInMemorySearch.from_documents(docs, embeddings)
    # define retriever
    retriever = db.as_retriever(search_type="similarity", search_kwargs={"k": k})
    # create a chatbot chain. Memory is managed externally.
    qa = ConversationalRetrievalChain.from_llm(
        llm=ChatOpenAI(temperature=0), 
        chain_type=chain_type, 
        retriever=retriever, 
        return_source_documents=True,
        return_generated_question=True,
    )
    return qa 


class cbfs(param.Parameterized):
    chat_history = param.List([])
    answer = param.String("")
    db_query  = param.String("")
    db_response = param.List([])
    
    def __init__(self,  **params):
        super(cbfs, self).__init__( **params)
        self.panels = []
        self.loaded_file = "docs/cs229_lectures/MachineLearning-Lecture01.pdf"
        self.qa = load_db(self.loaded_file,"stuff", 4)
    
    def call_load_db(self, count):
        if count == 0 or file_input.value is None:  # init or no file specified :
            return pn.pane.Markdown(f"Loaded File: {self.loaded_file}")
        else:
            file_input.save("temp.pdf")  # local copy
            self.loaded_file = file_input.filename
            button_load.button_style="outline"
            self.qa = load_db("temp.pdf", "stuff", 4)
            button_load.button_style="solid"
        self.clr_history()
        return pn.pane.Markdown(f"Loaded File: {self.loaded_file}")

    def convchain(self, query):
        if not query:
            return pn.WidgetBox(pn.Row('User:', pn.pane.Markdown("", width=600)), scroll=True)
        result = self.qa({"question": query, "chat_history": self.chat_history})
        self.chat_history.extend([(query, result["answer"])])
        self.db_query = result["generated_question"]
        self.db_response = result["source_documents"]
        self.answer = result['answer'] 
        self.panels.extend([
            pn.Row('User:', pn.pane.Markdown(query, width=600)),
            pn.Row('ChatBot:', pn.pane.Markdown(self.answer, width=600, style={'background-color': '#F6F6F6'}))
        ])
        inp.value = ''  #clears loading indicator when cleared
        return pn.WidgetBox(*self.panels,scroll=True)

    @param.depends('db_query ', )
    def get_lquest(self):
        if not self.db_query :
            return pn.Column(
                pn.Row(pn.pane.Markdown(f"Last question to DB:", styles={'background-color': '#F6F6F6'})),
                pn.Row(pn.pane.Str("no DB accesses so far"))
            )
        return pn.Column(
            pn.Row(pn.pane.Markdown(f"DB query:", styles={'background-color': '#F6F6F6'})),
            pn.pane.Str(self.db_query )
        )

    @param.depends('db_response', )
    def get_sources(self):
        if not self.db_response:
            return 
        rlist=[pn.Row(pn.pane.Markdown(f"Result of DB lookup:", styles={'background-color': '#F6F6F6'}))]
        for doc in self.db_response:
            rlist.append(pn.Row(pn.pane.Str(doc)))
        return pn.WidgetBox(*rlist, width=600, scroll=True)

    @param.depends('convchain', 'clr_history') 
    def get_chats(self):
        if not self.chat_history:
            return pn.WidgetBox(pn.Row(pn.pane.Str("No History Yet")), width=600, scroll=True)
        rlist=[pn.Row(pn.pane.Markdown(f"Current Chat History variable", styles={'background-color': '#F6F6F6'}))]
        for exchange in self.chat_history:
            rlist.append(pn.Row(pn.pane.Str(exchange)))
        return pn.WidgetBox(*rlist, width=600, scroll=True)

    def clr_history(self,count=0):
        self.chat_history = []
        return 


cb = cbfs()

file_input = pn.widgets.FileInput(accept='.pdf')
button_load = pn.widgets.Button(name="Load DB", button_type='primary')
button_clearhistory = pn.widgets.Button(name="Clear History", button_type='warning')
button_clearhistory.on_click(cb.clr_history)
inp = pn.widgets.TextInput( placeholder='Enter text here…')

bound_button_load = pn.bind(cb.call_load_db, button_load.param.clicks)
conversation = pn.bind(cb.convchain, inp) 

jpg_pane = pn.pane.Image( './img/convchain.jpg')

tab1 = pn.Column(
    pn.Row(inp),
    pn.layout.Divider(),
    pn.panel(conversation,  loading_indicator=True, height=300),
    pn.layout.Divider(),
)
tab2= pn.Column(
    pn.panel(cb.get_lquest),
    pn.layout.Divider(),
    pn.panel(cb.get_sources ),
)
tab3= pn.Column(
    pn.panel(cb.get_chats),
    pn.layout.Divider(),
)
tab4=pn.Column(
    pn.Row( file_input, button_load, bound_button_load),
    pn.Row( button_clearhistory, pn.pane.Markdown("Clears chat history. Can use to start a new topic" )),
    pn.layout.Divider(),
    pn.Row(jpg_pane.clone(width=400))
)
dashboard = pn.Column(
    pn.Row(pn.pane.Markdown('# ChatWithYourData_Bot')),
    pn.Tabs(('Conversation', tab1), ('Database', tab2), ('Chat History', tab3),('Configure', tab4))
)

#启动聊天应用程序
dashboard

使用langchain与你自己的数据对话(五):聊天机器人,Langchain,ChatGPT,langchain,chatgpt,语言模型,人工智能,自然语言处理

使用langchain与你自己的数据对话(五):聊天机器人,Langchain,ChatGPT,langchain,chatgpt,语言模型,人工智能,自然语言处理

使用langchain与你自己的数据对话(五):聊天机器人,Langchain,ChatGPT,langchain,chatgpt,语言模型,人工智能,自然语言处理

 总结

 今天我们学习了如何开发一个具有记忆能力的个性化问答机器人,所谓个性化是指该机器人可以针对用户数据的内容进行问答,我们在实现该机器人时使用了ConversationalRetrievalChain组件,它是一个具有记忆能力的检索链,也是机器人的核心组件。希望今天的内容对大家有所帮助!

参考资料

Overview — Panel v1.2.1

Welcome to Param! — param v1.13.0

https://github.com/sophiamyang/tutorials-LangChain文章来源地址https://www.toymoban.com/news/detail-635121.html

到了这里,关于使用langchain与你自己的数据对话(五):聊天机器人的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 使用Langchain+GPT+向量数据库chromadb 来创建文档对话机器人

    使用Langchain+GPT+向量数据库chromadb 来创建文档对话机器人 文件存放地址 参考: https://python.langchain.com/docs/use_cases/chatbots https://python.langchain.com/docs/integrations/vectorstores/chroma https://blog.csdn.net/v_JULY_v/article/details/131552592?ops_request_misc=%257B%2522request%255Fid%2522%253A%252216945020581680022659096

    2024年02月03日
    浏览(45)
  • 使用LangChain构建问答聊天机器人案例实战(一)

    使用LangChain构建问答聊天机器人案例实战 现场演示GPT-4代码生成 本节我们会通过一个综合案例,跟大家讲解LangChain,这个案例产生的代码会直接在浏览器中运行,并且会输出结果,如图14-1所示,用户问:“What was the highest close price of IBM?”(“IBM的最高收盘价是多少?”)

    2024年02月15日
    浏览(72)
  • 使用LangChain构建问答聊天机器人案例实战(三)

    使用LangChain构建问答聊天机器人案例实战 LangChain开发全流程剖析 接下来,我们再回到“get_prompt()”方法。在这个方法中,有系统提示词(system prompts)和用户提示词(user prompts),这是从相应的文件中读取的,从“system.prompt”文件中读取系统提示词(system_template),从“u

    2024年02月14日
    浏览(53)
  • LangChain入门(九)-使用Memory实现一个带记忆的对话机器人

    目录 一、说明 二、案例 一、说明 在第五章中我们使用的是通过自定义一个列表来存储对话的方式来保存历史的。 当然,你也可以使用自带的 memory 对象来实现这一点。 二、案例 结尾、扫一扫下方微信名片即可+博主徽信哦  ↓↓ ↓↓ ↓↓ ↓↓ ↓↓ ↓↓ ↓↓ ↓↓  ↓↓

    2024年02月16日
    浏览(39)
  • 对话机器人:使用 Python TensorFlow 训练 Chatbot 聊天机器人

    作者:禅与计算机程序设计艺术 为了能够在Facebook Messenger上与用户进行实时的沟通,开发者需要自行构建聊天机器人。然而,构建聊天机器人的过程却很复杂,需要掌握众多的技术、技能和知识。本文通过详细地阐述了如何用Python语言构建一个Facebook Messenger聊天机器人,并分

    2024年02月08日
    浏览(61)
  • 用通俗易懂的方式讲解:使用 MongoDB 和 Langchain 构建生成型AI聊天机器人

    想象一下:你收到了你梦寐以求的礼物:一台非凡的时光机,可以将你带到任何地方、任何时候。 你只有10分钟让它运行,否则它将消失。你拥有一份2000页的PDF,详细介绍了关于这台时光机的一切:它的历史、创造者、构造细节、操作指南、过去的用户,甚至还有一种回到过

    2024年01月23日
    浏览(48)
  • 用通俗易懂的方式讲解:使用 LangChain 和 LlamaIndex 从零构建PDF聊天机器人

    随着大型语言模型(LLM)(如ChatGPT和GPT-4)的兴起,现在比以往任何时候都更容易搭建智能聊天机器人,并且可以堆积如山的文档,为你的输入提供更准确的响应。 无论你是想构建个人助理、定制聊天机器人还是自动文档分析系统,本系列都将为你提供构建自己的LLM聊天机器

    2024年01月18日
    浏览(56)
  • 用通俗易懂的方式讲解:使用 Mistral-7B 和 Langchain 搭建基于PDF文件的聊天机器人

    在本文中,使用LangChain、HuggingFaceEmbeddings和HuggingFace的Mistral-7B LLM创建一个简单的Python程序,可以从任何pdf文件中回答问题。 LangChain是一个在语言模型之上开发上下文感知应用程序的框架。LangChain使用带prompt和few-shot示例的LLM来提供相关响应和推理。LangChain擅长文档问答、聊天

    2024年01月24日
    浏览(59)
  • LLM本地知识库问答系统(一):使用LangChain和LlamaIndex从零构建PDF聊天机器人指南

           随着大型语言模型(LLM)(如ChatGPT和GPT-4)的兴起,现在比以往任何时候都更容易构建比普通熊更智能的智能聊天机器人,并且可以浏览堆积如山的文档,为您的输入提供准确的响应。        在本系列中,我们将探索如何使用pre-trained的LLM创建一个聊天机器人,该聊

    2024年02月11日
    浏览(65)
  • langchain系列:langchain入门(一分钟搞定对话机器人)

       随着aigc的火热,各大厂商开始提供他们自己的api服务,诸如openai、google、等,还有的直接开源出自己的模型,放到Huggingface提供使用,而LangChain就是一个基于语言模型开发应用程序的框架,它可以很方便的去调用不同公司的api,以及huggingface的资源,为人们提供统一的开

    2024年02月10日
    浏览(53)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包