【橘子大模型】使用streamlit来构建自己的聊天机器人(上)

一、简介

我们之前已经掌握了很多关于和LLM交互的操作了,现在我们需要在这些操作上面构建自己的机器人,进而在客户端操作服务。
我们需要使用的工具是streamlit
你就把他理解为python的uniapp吧。

二、开发环境准备

我们这次是真实的操作代码了,所以就不用jupyter这种交互式的开发了。我们用pycharm这种ide来开发。

1、创建项目,选择虚拟环境

我们创建一个project,继续选择之前的虚拟环境。
操作方式其实我在使用text2vec向量化文本一文中谈到过,这里再复述一遍。
我们之前在vscode中写的时候创建了一个虚拟环境venv3110。我们用pycharm打开项目之后点击seeting->project->project Interpreter
在这里插入图片描述

2、安装streamlit依赖

我们需要安装一下对应的依赖。你可以在终端进入你的虚拟环境

source 你的虚拟环境路径/bin/activate

在虚拟环境下执行
pip3 install streamlit 
或者是
pip install streamlit 

取决于你是不是用的python3

pip list 检查你的安装包

也可以在ide中安装。
在这里插入图片描述
在这里插入图片描述
然后安装好的就可以在列表中看到了。
在这里插入图片描述
此时我们的项目结构就很简单,两个文件。一个python文件,一个.env文件存储环境变量。
在这里插入图片描述
至此我们完成了环境的准备。

三、使用streamlit实现交互

我们依然引入之前的那些依赖包,只不过这次要多一个streamlit,并且记得启动es和ollama。
chatBot.py

from dotenv import load_dotenv
from langchain_ollama import ChatOllama
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables.history import RunnableWithMessageHistory
from langchain_community.chat_message_histories import ElasticsearchChatMessageHistory

from streamlit import streamlit as st

# load env file
load = load_dotenv("./.env")

# init llm
llm = ChatOllama(
    base_url = "http://127.0.0.1:11434",
    model = "deepseek-r1:8b",
    temperature = 0.5,
    num_predict = 10000,
    max_tokens = 250
)
# streamlit的一个标题
st.title("哥哥你好,这里是橘子GPT,我是小橘?")
st.write("哥哥,请把您的问题输入,小橘会认真回答的哦。")

 # 无密码的elasticsearch配置
es_url = "http://localhost:9200"
# 存储的索引,我们不用预先创建索引,因为说实话我也不知道字段,langchain会创建,并且自动映射字段
index_name = "chat_history"
# 构建一个session id,暂时写死
session_id = "levi1122322"

template = ChatPromptTemplate.from_messages([
    ('human',"{prompt}"),
    ('placeholder',"{history}")
])
chain = template | llm | StrOutputParser()

# 构建ElasticsearchChatMessageHistory
def get_session_history(session_id: str) :
    return  ElasticsearchChatMessageHistory(
        index=index_name,
        session_id=session_id,
        es_url=es_url,
        ensure_ascii=False
    )

chain_with_history = RunnableWithMessageHistory(
    chain,
    get_session_history,
    input_messages_key="prompt",
    history_messages_key="history",
)

# 构建st的结构,添加一个数组进去
st.session_state.chat_history = []
# 获取st在页面的输入,也就是用户输入的问题
user_prompt = st.chat_input("我是你的妹妹小橘,请输入你的问题吧哥哥")
# 如果拿到了输入
if user_prompt :
	# 根据输入去调用大模型,并且指定session_id
    response = chain_with_history.invoke(
    {"prompt": user_prompt},
        config={"configurable": {"session_id": session_id}})
    # 在数组中挂一些信息,这个目前还没用    
    st.session_state.chat_history.append({'role':'user','content':user_prompt})
    # 最后执行之后返回结果,如果是用户输入的显示用户的问题
    with st.chat_message('user'):
        st.markdown(user_prompt)
    # 在数组中挂一些信息,这个目前还没用    
    st.session_state.chat_history.append({'role':'assistant','content':response})
    # 最后执行之后返回结果,如果是ai结果的显示ai的答案
    with st.chat_message('assistant'):
        st.markdown(response)

然后使用streamlit启动这个类。

streamlit run 这个py文件的路径地址
比如我是在这个目录下,我直接就streamlit run ./chatbot.py
然后就跳转到浏览器了。

最后的结果如下。
在这里插入图片描述
但是这个还是有问题,因为当前你要问到第二个问题,他会覆盖前面的问题和回答,你的页面永远只有一个问题。不会是那种类似于聊天的一问一答那样的。
所以我们需要修改代码把历史保存的记录也显示出来。

from dotenv import load_dotenv
from langchain_ollama import ChatOllama
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables.history import RunnableWithMessageHistory
from langchain_community.chat_message_histories import ElasticsearchChatMessageHistory

from streamlit import streamlit as st

# load env file
load = load_dotenv("./.env")

# init llm
llm = ChatOllama(
    base_url = "http://127.0.0.1:11434",
    model = "deepseek-r1:8b",
    temperature = 0.5,
    num_predict = 10000,
    max_tokens = 250
)

st.title("你好,这里是橘子GPT,我是小橘")
st.write("请把您的问题输入,小橘会认真回答的哦。")

 # 无密码的elasticsearch配置
es_url = "http://localhost:9200"
# 存储的索引,我们不用预先创建索引,因为说实话我也不知道字段,langchain会创建,并且自动映射字段
index_name = "chat_history"
session_id = "levi23422"


template = ChatPromptTemplate.from_messages([
    ('human',"{prompt}"),
    ('placeholder',"{history}")
])
chain = template | llm | StrOutputParser()

# 构建ElasticsearchChatMessageHistory
def get_session_history(session_id: str) :
    return  ElasticsearchChatMessageHistory(
        index=index_name,
        session_id=session_id,
        es_url=es_url,
        ensure_ascii=False
    )

chain_with_history = RunnableWithMessageHistory(
    chain,
    get_session_history,
    input_messages_key="prompt",
    history_messages_key="history",
)


user_prompt = st.chat_input("我是小橘,请输入你的问题吧")

# 如果没有就创建,不要每次都建立新的
if 'chat_history' not in st.session_state:
    st.session_state.chat_history = []
# 遍历里面的内容,取出来存进去的每一组role 和 content
for message in st.session_state.chat_history :
    # 通过取出来的信息,构建st.chat_message,不同的角色会有不同的ui样式,这里就是做这个的
    with st.chat_message(message['role']):
        # 把内容展示出来
        st.markdown(message['content'])


if user_prompt :
    response = chain_with_history.invoke(
    {"prompt": user_prompt},
        config={"configurable": {"session_id": session_id}})
    # 保存历史,上面用来遍历显示,避免后面覆盖前面的显示
    st.session_state.chat_history.append({'role':'user','content':user_prompt})
    with st.chat_message('user'):
        st.markdown(user_prompt)
    # 保存历史,上面用来遍历显示,避免后面覆盖前面的显示
    st.session_state.chat_history.append({'role':'assistant','content':response})
    with st.chat_message('assistant'):
        st.markdown(response)

我们遍历显示之后就好了。
在这里插入图片描述
你会发现中间那个没回复,现在还不到优化他的时候。目前我们基本完成了单session下面的功能。后面我们继续完善,争取对标各大商用gpt。
至此我们还是遗留了一些问题,session_id是写死的,没有从前端传入。
无法开启新的session,只能改代码重启服务。

四、参考

1、官方文档
2、进阶实战
3、https://zhuanlan.zhihu.com/p/707786990

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值