准备工作
购买云服务器;
如果需要的话,配置服务器的安全组规则(参考 https://jackiexiao.github.io/blog/%E6%8A%80%E6%9C%AF/%E4%BD%BF%E7%94%A8docker%E5%92%8Cstreamlit%E9%98%BF%E9%87%8C%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E9%83%A8%E7%BD%B2%E7%AE%80%E5%8D%95%E7%9A%84%E6%BC%94%E7%A4%BA%E7%BD%91%E9%A1%B5/);
如果连接过该服务器然后该服务器被重装系统,远程连接之前需要先执行:
ssh-keygen -R <服务器公网ip>
连接远程服务器
> ssh root@<公网ip>
安装Docker
> apt update # 必须先update,才能安装软件
> curl -fsSL get.docker.com -o get-docker.sh
> sudo sh get-docker.sh --mirror Aliyun # mirror是镜像,为了加速
配置Dockerfile
> vim Dockerfile
# 从python3.6镜像基础上创建
FROM python:3.11
# 设置镜像源,提高pip install 速度
RUN pip config set global.index-url https://mirrors.aliyun.com/pypi/simple/ \
&& pip install streamlit openai langchain
RUN pip install -U duckduckgo-search
COPY . /app
WORKDIR /app
# streamlit hello创建一个演示页面,映射80端口以便网页访问
CMD ["streamlit","run", "test.py", "--server.port","80"]
#ENTRYPOINT ["streamlit", "run"]
#CMD ["test.py"]
准备好示例代码
> vim test.py
from langchain.agents import ConversationalChatAgent, AgentExecutor
from langchain.callbacks import StreamlitCallbackHandler
from langchain.chat_models import ChatOpenAI
from langchain.memory import ConversationBufferMemory
from langchain.memory.chat_message_histories import StreamlitChatMessageHistory
from langchain.tools import DuckDuckGoSearchRun
import streamlit as st
st.set_page_config(page_title="LangChain: Chat with search", page_icon="🦜")
st.title("🦜 LangChain: Chat with search")
openai_api_key = st.sidebar.text_input("OpenAI API Key", type="password")
msgs = StreamlitChatMessageHistory()
memory = ConversationBufferMemory(
chat_memory=msgs, return_messages=True, memory_key="chat_history", output_key="output"
)
if len(msgs.messages) == 0 or st.sidebar.button("Reset chat history"):
msgs.clear()
msgs.add_ai_message("How can I help you?")
st.session_state.steps = {}
avatars = {"human": "user", "ai": "assistant"}
for idx, msg in enumerate(msgs.messages):
with st.chat_message(avatars[msg.type]):
# Render intermediate steps if any were saved
for step in st.session_state.steps.get(str(idx), []):
if step[0].tool == "_Exception":
continue
with st.status(f"**{step[0].tool}**: {step[0].tool_input}", state="complete"):
st.write(step[0].log)
st.write(step[1])
st.write(msg.content)
if prompt := st.chat_input(placeholder="Who won the Women's U.S. Open in 2018?"):
st.chat_message("user").write(prompt)
if not openai_api_key:
st.info("Please add your OpenAI API key to continue.")
st.stop()
llm = ChatOpenAI(model_name="gpt-3.5-turbo", openai_api_key=openai_api_key, streaming=True)
tools = [DuckDuckGoSearchRun(name="Search")]
chat_agent = ConversationalChatAgent.from_llm_and_tools(llm=llm, tools=tools)
executor = AgentExecutor.from_agent_and_tools(
agent=chat_agent,
tools=tools,
memory=memory,
return_intermediate_steps=True,
handle_parsing_errors=True,
)
with st.chat_message("assistant"):
st_cb = StreamlitCallbackHandler(st.container(), expand_new_thoughts=False)
response = executor(prompt, callbacks=[st_cb])
st.write(response["output"])
st.session_state.steps[str(len(msgs.messages) - 1)] = response["intermediate_steps"]
构建docker环境
> docker build -t streamlit .
部署streamlit应用
> docker run -p 80:80 streamlit
踩坑回顾
- 有时候新开通的服务器需要配置安全组白名单,要不然无法进行ssh连接(但有时候又不需要,令人猝不及防)
- Dockerfile中需要让python安装streamlit,langchain,oepanai,duckduckgo-search等基础包
- Dockerfile中需要配置把test.py放到一个子目录下进行部署,要不然会出现一些中间文件python访问不到(貌似是这个原因,具体我也没搞明白),导致报错
- 国内的服务器无法访问ChatGPT的API,所以需要香港或者国外的服务器
- 安装docker最好按照教程中给出的那三个命令安装,如果按照命令行提示的
snap install docker
安装,会发现按照好的docker无法正常部署虚拟环境,并且卸载非常麻烦,最终我被迫重装服务器系统 - 重装服务器系统后本地要想再连接服务器需要先执行
ssh-keygen -R <服务器公网ip>
,删除原先的ssh配置,才能正常连接 - 租用服务器内存至少要开到1G,只有512M内存的情况下运行
docker build -t streamlit .
内存会爆掉,导致系统崩溃