为什么要自己搭建?
起初,笔者一直使用的工具是Poe。它不但有大量的模型可供选择,而且还可以很方便的创建自己的智能助手。但是它需要VPN才能访问,而且对非付费用户有很多限制,例如不能使用高级模型。为了省钱,笔者不得不逐渐放弃这个工具。
后来,笔者将目光转向了国内,开始尝试阿里云百炼。它的模型也很丰富,虽然还没有ChatGPT那么强大,但对于笔者来说已经够用了。但是,它有一个问题,每个智能助手都是一个单独的应用,没有办法把所有智能助手都集成到一个应用里,用起来不是很方便。
所以,笔者尝试自己搭建智能助手平台,使用百炼模型,且能够把各种自定义的智能助手集成在一起。
考虑过哪些方案?
虽然网上有一些开源库能够满足笔者的需求,但它们的功能太多了,笔者只是想要一个界面调一下API而已,实在没有耐心仔细研究它们的文档,于是就放弃了。
后来,笔者想自己用React实现一个,但是工程搭建和配置太繁琐了。再加上在没有VPN的情况下,npx竟然安装不了依赖,失败几次后就把笔者给劝退了。
事情到了这里,这个想法也就该凉凉了,但在一次不经意的搜索中,笔者发现了Streamlit,就像发现新大陆一样!笔者这时才知道,原来搭建一个Web应用可以这么简单!
如何搭建?
Streamlit搭建一个智能助手有多简单?只要25行代码,不仅可以支持API Key的设置,也可以支持完整的问答功能。
import streamlit as st
from openai import OpenAI
with st.sidebar:
openai_api_key = st.text_input("OpenAI API Key", key="chatbot_api_key", type="password")
st.title("💬 Chatbot")
if "messages" not in st.session_state:
st.session_state["messages"] = [{"role": "assistant", "content": "How can I help you?"}]
for msg in st.session_state.messages:
st.chat_message(msg["role"]).write(msg["content"])
if prompt := st.chat_input():
if not openai_api_key:
st.info("Please add your OpenAI API key to continue.")
st.stop()
client = OpenAI(api_key=openai_api_key)
st.session_state.messages.append({"role": "user", "content": prompt})
st.chat_message("user").write(prompt)
response = client.chat.completions.create(model="gpt-3.5-turbo", messages=st.session_state.messages)
msg = response.choices[0].message.content
st.session_state.messages.append({"role": "assistant", "content": msg})
st.chat_message("assistant").write(msg)
不想突然跳出一大段回答,想要流式输出?简单,发送请求时指定流式输出,然后把流写入消息就好啦。
with st.chat_message("assistant"):
stream = client.chat.completions.create(
model=bot["gpt-3.5-turbo"],
messages=st.session_state.messages,
stream=True,
)
response = st.write_stream(stream)
st.session_state.messages.append({"role": "assistant", "content": response})
想要安全一点,增加登录功能?多加一个依赖Streamlit-Authenticator,把用户名和密码写入config.yml,搞定。
pip install streamlit-authenticator
import yaml
from yaml.loader import SafeLoader
with open('../config.yaml') as file:
config = yaml.load(file, Loader=SafeLoader)
authenticator = stauth.Authenticate(
config['credentials'],
config['cookie']['name'],
config['cookie']['key'],
config['cookie']['expiry_days']
)
authenticator.login()
if st.session_state["authentication_status"]:
authenticator.logout()
# 业务代码
elif st.session_state["authentication_status"] is False:
st.error("Username/password is incorrect")
elif st.session_state["authentication_status"] is None:
st.warning("Please enter your username and password")
想要一个智能助手平台,侧边栏显示智能助手列表和会话记录?也简单,借用上文的config.yml,把智能助手的定义添加进去,直接两个for循环就完成了,不需要复杂的布局和样式调整。
with st.sidebar:
st.subheader("新建对话")
for bot in st.session_state.bots:
st.button(
bot["name"],
on_click=set_current_session,
args=(
{
"name": None,
"bot_id": bot["id"],
"messages": [],
},
),
use_container_width=True,
)
st.subheader("会话记录")
for session in st.session_state.bot_sessions:
st.button(
session["name"],
on_click=set_current_session,
args=(session,),
disabled=session["name"] == st.session_state.current_session["name"],
use_container_width=True,
)
最后,笔者已经将完整的代码放在了ai-bots,想要了解更多的同学可以去代码库查看。
总结
Streamlit的功能远远不止笔者提到的这些,它非常适合对各种想法进行快速实现和验证,没使用过的小伙伴可以尝试一下,绝对值得!