准备工作
购买云服务器;
如果需要的话,配置服务器的安全组规则(参考 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

踩坑回顾

  1. 有时候新开通的服务器需要配置安全组白名单,要不然无法进行ssh连接(但有时候又不需要,令人猝不及防)
  2. Dockerfile中需要让python安装streamlit,langchain,oepanai,duckduckgo-search等基础包
  3. Dockerfile中需要配置把test.py放到一个子目录下进行部署,要不然会出现一些中间文件python访问不到(貌似是这个原因,具体我也没搞明白),导致报错
  4. 国内的服务器无法访问ChatGPT的API,所以需要香港或者国外的服务器
  5. 安装docker最好按照教程中给出的那三个命令安装,如果按照命令行提示的snap install docker安装,会发现按照好的docker无法正常部署虚拟环境,并且卸载非常麻烦,最终我被迫重装服务器系统
  6. 重装服务器系统后本地要想再连接服务器需要先执行ssh-keygen -R <服务器公网ip>,删除原先的ssh配置,才能正常连接
  7. 租用服务器内存至少要开到1G,只有512M内存的情况下运行docker build -t streamlit .内存会爆掉,导致系统崩溃
最后修改:2023 年 12 月 06 日
如果觉得我的文章对你有用,请随意赞赏