使用记忆聊天机器人与你的 CSV 文件聊天 — 用 Langchain 和 OpenAI 制作
在本文中,我们将了解如何构建一个简单的聊天机器人 ,它具有内存,可以回答你关于自己的 CSV 数据的问题。
我们将使用LangChain 链接gpt-3.5
到我们的数据,并使用 Streamlit 为我们的聊天机器人创建用户界面。
与 ChatGPT 提供有限的数据上下文不同(我们最多只能提供 4096 个令牌),由于使用了嵌入和矢量存储,我们的聊天机器人将能够处理 CSV 数据并管理大型数据库。
流程图
代码
现在让我们开始实践吧!我们将使用很少的 Python 语法开发基于 CSV 数据的聊天机器人。
免责声明 :此代码是我创建的聊天机器人的简化版本,未针对降低 OpenAI API 成本进行优化,如需性能更高且经过优化的聊天机器人,请随时查看我的 GitHub 项目:yvann-hub/ChatBot-CSV或只是在chatbot-csv.com 测试应用程序。
- 首先,我们将安装必要的库
pip install streamlit streamlit_chat langchain openai faiss-cpu tiktoken
- 导入聊天机器人所需的库:
import streamlit as st
from streamlit_chat import message
from langchain.embeddings.openai import OpenAIEmbeddings
from langchain.chat_models import ChatOpenAI
from langchain.chains import ConversationalRetrievalChain
from langchain.document_loaders.csv_loader import CSVLoader
from langchain.vectorstores import FAISS
import tempfile
- 输入 OpenAI API 密钥 并,下载或使用自己的可供聊天机器人使用的 CSV 文件。
- 要以较低的成本测试聊天机器人,你可以使用这个轻量级的 CSV 文件:
fishfry-locations.csv
user_api_key = st.sidebar.text_input(
label="#### Your OpenAI API key ",
placeholder="Paste your openAI API key, sk-",
type="password")
uploaded_file = st.sidebar.file_uploader("upload", type="csv")
- 如果使用自己的 CSV 文件,我们使用LangChain 的CSVLoader类加载它
if uploaded_file :
#use tempfile because CSVLoader only accepts a file_path
with tempfile.NamedTemporaryFile(delete=False) as tmp_file:
tmp_file.write(uploaded_file.getvalue())
tmp_file_path = tmp_file.name
loader = CSVLoader(file_path=tmp_file_path, encoding="utf-8")
data = loader.load()
- LangChain
CSVLoader
类允许我们将 CSV 文件拆分为唯一的行。这可以通过显示数据的内容看出:
st.write(data)
---
0:"Document(page_content='venue_name: McGinnis Sisters\nvenue_type: Market\nvenue_address: 4311 Northern Pike, Monroeville, PA\nwebsite: http://www.mcginnis-sisters.com/\nmenu_url: \nmenu_text: \nphone: 412-858-7000\nemail: \nalcohol: \nlunch: True', metadata={'source': 'C:\\Users\\UTILIS~1\\AppData\\Local\\Temp\\tmp6_24nxby', 'row': 0})"
1:"Document(page_content='venue_name: Holy Cross (Reilly Center)\nvenue_type: Church\nvenue_address: 7100 West Ridge Road, Fairview PA\nwebsite: \nmenu_url: \nmenu_text: Fried pollack, fried shrimp, or combo. Adult $10, Child $5. Includes baked potato, homemade coleslaw, roll, butter, dessert, and beverage. Mac and cheese $5.\nphone: 814-474-2605\nemail: \nalcohol: \nlunch: ', metadata={'source': 'C:\\Users\\UTILIS~1\\AppData\\Local\\Temp\\tmp6_24nxby', 'row': 1})"
- 我们可以使用 OpenAIEmbeddings() 将其提供给我们的
vectorstore
( FAISS ) 剪切 CSV 文件。 - Embeddings 允许将 CSVLoader 切割的部分转换为 vectors,然后基于给定文件提供每一行内容的索引。
- 实际上,当用户进行查询时,将在 vectorstore 中执行搜索,并将最匹配的索引返回给 LLM,LLM 将重新表述找到的索引的内容以提供格式化好的的 response 给用户。
- 我建议加深你可以加深对vectorstore和embeddings概念的理解,以便更好地使用。
embeddings = OpenAIEmbeddings()
vectorstore = FAISS.from_documents(data, embeddings)
- 然后,我们通过为其提供所需的聊天模型 gpt-3.5-turbo(或 gpt-4)和 FAISS vectorstore 来添加 ConversationalRetrievalChain,FAISS vectorstore 存储我们通过 OpenAIEmbeddings() 转换为向量的文件。
- 这个 Chain 允许我们拥有一个有记忆的聊天机器人,同时依靠它
vectorstore
从我们的文档中找到相关信息。
chain = ConversationalRetrievalChain.from_llm(
llm = ChatOpenAI(temperature=0.0,model_name='gpt-3.5-turbo'),
retriever=vectorstore.as_retriever())
- 此功能允许我们向 ConversationalRetrievalChain 提供用户的问题和对话历史记录以生成聊天机器人的响应。
-
st.session_state['history']
存储用户在 Streamlit 网站上的对话历史记录。
如果您想对此聊天机器人进行改进,可以查看我的GitHub
def conversational_chat(query):
result = chain({"question": query,
"chat_history": st.session_state['history']})
st.session_state['history'].append((query, result["answer"]))
return result["answer"]
- 我们通过创建 st.session_state[‘history’] 和聊天中显示的第一条消息来初始化聊天机器人会话。
-
['generated']
对应于聊天机器人的响应。 -
['past']
对应于用户提供的消息。 - 容器不是必需的,但可以通过将用户的问题区域放置在聊天消息下方来帮助改进 UI。
if 'history' not in st.session_state:
st.session_state['history'] = []
if 'generated' not in st.session_state:
st.session_state['generated'] = ["Hello ! Ask me anything about " + uploaded_file.name + " "]
if 'past' not in st.session_state:
st.session_state['past'] = ["Hey ! "]
#container for the chat history
response_container = st.container()
#container for the user's text input
container = st.container()
- 现在
session.state
已经配置了 和 容器。 - 我们可以设置 UI 部分,允许用户输入他们的问题并将其发送到我们的
conversational_chat
函数,并将用户的问题作为参数。
with container:
with st.form(key='my_form', clear_on_submit=True):
user_input = st.text_input("Query:", placeholder="Talk about your csv data here (:", key='input')
submit_button = st.form_submit_button(label='Send')
if submit_button and user_input:
output = conversational_chat(user_input)
st.session_state['past'].append(user_input)
st.session_state['generated'].append(output)
- 最后一部分允许使用该模块在 Streamlit 站点上显示用户和聊天机器人的消息
streamlit_chat
。
if st.session_state['generated']:
with response_container:
for i in range(len(st.session_state['generated'])):
message(st.session_state["past"][i], is_user=True, key=str(i) + '_user', avatar_style="big-smile")
message(st.session_state["generated"][i], key=str(i), avatar_style="thumbs")
- 剩下的就是启动脚本:
streamlit run name_of_your_chatbot.py #run 用你的文件名
到此,我们将拥有一个运行在 LangChain、OpenAI 和 Streamlit 上的 Awesome 聊天机器人,能够根据您的 CSV 文件回答您的问题!