使用 LangChain 和 OpenAI 在 CSV 数据上构建聊天机器人

使用记忆聊天机器人与你的 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")
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()
  • LangChainCSVLoader类允许我们将 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 给用户。
  • 我建议加深你可以加深对vectorstoreembeddings概念的理解,以便更好地使用。
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 文件回答您的问题!

原文链接