
使用 LangGraph、FastAPI 和 Streamlit 构建人工智能聊天机器人--端到端指南
- Rifx.Online
- Programming , Chatbots , Generative AI
- 28 Feb, 2025
聊天机器人的最终用户界面 — 作者提供的图片
聊天机器人是自动化互动的强大工具,但从零开始构建一个聊天机器人涉及连接多个组件。在本指南中,我们将使用 LangGraph 来管理对话流程,使用 FastAPI 来提供聊天机器人服务,并使用 Streamlit 创建一个简单的用户界面。我们不仅仅是使用聊天机器人,而是探索构建和集成这些组件的过程,以构建一个功能齐全的系统。我意识到称其为 AI 聊天机器人可能有些多余,因为所有聊天机器人都是基于 AI 构建的(如果不是,它们的对话能力可能非常有限),但听起来很高大上,那为什么不呢?
为了提供一些背景,在 Codika 中,我们专注于自动化软件开发,使开发人员能够更快、更高效地修改和部署生产就绪的移动应用程序。作为这项工作的一个部分,我们探索了使用聊天机器人来协助代码修改,这引发了我对聊天机器人如何处理和结构化互动的更深兴趣。这段经历激励我将从零开始构建聊天机器人的过程进行拆解,不仅作为一个独立工具,而是作为一个可以集成到更大开发工作流程中的模块化组件。
目录
- 项目设置
- 使用 LangGraph 构建聊天机器人
- 创建 FastAPI 后端
- 使用 Streamlit 构建前端
- 与聊天机器人互动
- 结论与后续步骤
设置项目
在我们开始编码之前,需要设置项目结构并安装必要的依赖项。首先创建一个新的项目目录并进入该目录。
mkdir end-to-end-chatbot && cd end-to-end-chatbot
然后以您选择的方法创建一个虚拟环境。我个人使用 mamba,但 conda 或 venv 也可以正常工作。我使用 Python 3.11 创建了这个项目。我建议您也使用这个版本,因为我无法保证与其他版本的兼容性。
mamba create -n ete-chatbot python=3.11 mamba activate ete-chatbot
现在环境已激活,您可以安装必要的依赖项。以下列表显示了我使用的确切包版本:
langgraph==0.2.71
python-dotenv==1.0.1
langchain-anthropic==0.3.7
langchain-ollama==0.2.3
langchain-openai==0.3.5
langchain==0.3.18
ipython==8.32.0
fastapi==0.115.8
uvicorn==0.34.0
streamlit==1.42.0
您可以将此列表保存在 requirements.txt 文件中,并使用以下命令安装依赖项:
pip install -r requirements.txt
该代码支持 Anthropic 和 OpenAI 模型。为了使用它们,您需要一个 API 密钥。您可以选择您喜欢使用的一个。您的 API 密钥应存储在名为 .env 的文件中,该文件应遵循以下结构:
ANTHROPIC_API_KEY=“<your-anthropic-api-key>“
OPENAI_API_KEY=“<your-openai-api-key>”
从技术上讲,代码也支持 Ollama 模型。这些模型可以免费使用,但设置可能有点复杂,并超出了本文的范围,因此我不会涵盖那部分内容。
项目具有以下结构:
end-to-end-chatbot/
│
│
│
.env
每个文件夹包含一个或多个专用文件。我们将在接下来的部分中进行探讨。
使用 LangGraph 构建聊天机器人
如果您对 LangGraph 不熟悉,建议您阅读其文档以更好地了解该框架。他们还在网站上发布了一门课程,这可以作为一个有价值的资源。
在我们的案例中,我们将通过构建一个只有一个节点的图来保持简单:聊天机器人。最初,我认为我们需要两个节点:一个用于机器人,一个用于处理人类输入。然而,在我们的案例中,我们不需要一个单独的节点来处理人类输入。随着我们逐步查看代码,这一点会变得更加清晰。
图的表示 — 用户提供的图像。
我们需要定义三个主要组件:状态、节点和图。我们将把每个组件的代码存储在三个单独的文件中。
end-to-end-chatbot/ │ │ │ │ │ │ .env
让我们首先看看状态。
from typing import Annotated, Optional
from langgraph.graph.message import add_messages from typing_extensions import TypedDict
class ChatbotState(TypedDict):
messages: Annotated\[list, add\_messages\]
session\_id: Optional\[str\] = None
这是一个非常简单的状态,有两个变量:
- messages:聊天消息的列表,包括最新的一条。
- session_id:聊天会话的唯一标识符。
现在我们已经定义了状态,让我们继续聊天机器人节点。但在此之前,让我们添加一个用于处理模型的工具文件。
from dotenv import load_dotenv import os
def get_model(model_name: str, temperature: float = 0, **kwargs): """ 从环境变量中获取模型。 """
load\_dotenv()
if "claude" in model\_name:
from langchain\_anthropic import ChatAnthropic
if not os.getenv("ANTHROPIC\_API\_KEY"):
raise ValueError("未在环境变量中找到 ANTHROPIC\_API\_KEY。")
os.environ\["ANTHROPIC\_API\_KEY"\] = os.getenv("ANTHROPIC\_API\_KEY")
return ChatAnthropic(model=model\_name, temperature=temperature, \*\*kwargs)
elif "gpt" in model\_name:
from langchain\_openai import ChatOpenAI
if not os.getenv("OPENAI\_API\_KEY"):
raise ValueError("未在环境变量中找到 OPENAI\_API\_KEY。")
os.environ\["OPENAI\_API\_KEY"\] = os.getenv("OPENAI\_API\_KEY")
return ChatOpenAI(model=model\_name, temperature=temperature, \*\*kwargs)
elif 'llama' in model\_name:
from langchain\_ollama import ChatOllama
return ChatOllama(model=model\_name, temperature=temperature, \*\*kwargs)
else:
raise ValueError(f"模型 {model\_name} 不受支持。")
这个函数使用 dotenv 包从 .env 文件加载环境变量,并使用适当的 LangChain 包检索指定的模型。目前,该函数支持 OpenAI、Anthropic 和 Ollama,但可以通过遵循相同的逻辑轻松扩展到其他提供商。项目树结构变为:
end-to-end-chatbot/ │ │ │ │ │ │ │ │ .env
我们现在可以将模型名称作为字符串传递给我们的节点,而我们的工具函数会处理其余的。让我们看看我们的聊天机器人节点。
from typing import Optional, List
from langchain_core.messages import SystemMessage
from chatbot.state import ChatbotState from chatbot.utils.model_provider import get_model
class ChatbotNode: def __init__( self, model_name: str, temperature: float = 0, system_prompt: str = “您是一个乐于助人的助手。” ): self.system_message = SystemMessage(content=system_prompt) self.model = get_model(model_name, temperature)
def run(self, state: ChatbotState):
messages = state\["messages"\]
if not messages or type(messages\[0\]) != SystemMessage:
messages.insert(0, self.system\_message)
response = self.model.invoke(messages)
state\["messages"\].append(response)
return state
我喜欢为节点制作自己的包装类,但如果您不想这样做,只要遵循相同的逻辑即可。构造函数初始化两个变量:模型(使用工具函数检索)和系统提示。我在这里使用了一个通用的系统提示,但您可以根据自己的需要进行修改。run 方法包含将由图执行的逻辑。它将当前状态作为输入(包含消息和会话 ID),并通过在当前消息列表上调用模型并将模型的响应附加到该列表中返回更新后的状态。if 语句确保系统提示始终添加到该列表的开头。我最初使用了 LangChain 的 ChatPromptTemplate.from_messages 方法,但我遇到了一些问题,系统提示被附加到序列的末尾,导致模型过于关注对话的后半部分。尽管这是一种更具体的系统提示,我发现这个解决方案效果很好。
这部分代码只剩下一个组件要编码:图。与节点一样,我更喜欢为此定义自己的类,但如果您不想这样做,也可以。
from IPython.display import Image, display from typing import Optional
from langgraph.checkpoint.memory import MemorySaver from langgraph.graph import StateGraph, START from langchain_core.runnables import RunnableConfig
from chatbot.node import ChatbotNode from chatbot.state import ChatbotState
class ChatbotGraph: def __init__(self, model_name: str, temperature: float = 0): self.model_name = model_name self.temperature = temperature
self.system\_prompt = "您是一个乐于助人的助手。"
self.chatbot\_node = ChatbotNode(self.model\_name, self.temperature, self.system\_prompt)
self.memory\_saver = MemorySaver()
@property
def graph(self):
if hasattr(self, "\_graph"):
return self.\_graph
self.\_graph = self.graph\_builder()
return self.\_graph
def graph\_builder(self):
graph\_builder = StateGraph(ChatbotState)
graph\_builder.add\_node("chatbot\_agent", self.chatbot\_node.run)
graph\_builder.add\_edge(START, "chatbot\_agent")
return graph\_builder.compile(checkpointer=self.memory\_saver)
def display(self):
display(Image(self.graph.get\_graph(xray=True).draw\_mermaid\_png()))
def invoke(self, input: str, config: Optional\[RunnableConfig\] = None):
return self.graph.invoke(input, config)
ChatbotGraph 类是对话流的结构。在初始化时,它创建一个 ChatbotNode 的实例和一个 MemorySaver 以存储对话历史。该类没有立即构建图,而是定义了一个图属性,在首次访问时懒惰地初始化它。再次强调,这不是必需的,但在我看来,这是一个好习惯。实际构建发生在 graph_builder 中,其中使用 ChatbotState 作为状态类型创建 StateGraph。一个名为 chatbot_agent 的单个节点被添加到图中,并且从 START 节点到这个聊天机器人节点建立了一条边,这意味着每个用户消息都直接由聊天机器人处理。然后图被编译,并启用内存保存功能。
为了可视化图结构,display 方法生成一个 Mermaid 图表,如本节开头所示,使理解消息流变得更容易。最后,invoke 方法允许通过图与聊天机器人进行外部交互,传递用户消息并返回更新的状态以及聊天机器人的响应。
如果我们通过命令行界面(CLI)运行这个图,我们通常需要一个单独的节点来处理人类输入。这个节点将捕获用户消息并将其传递给聊天机器人节点。然而,在我们的案例中,API 将通过 HTTP 请求接收用户消息,并直接将其传递给聊天机器人。这简化了图的结构,因为我们只需要一个聊天机器人的节点。
这就是本博客文章的第一部分。接下来,我们将继续进行 API 实现。
创建 FastAPI 后端
现在我们的聊天机器人逻辑已经就位,我们需要一种通过网络与其交互的方法。这就是 FastAPI 的用武之地。FastAPI 是一个用于构建 Python API 的现代网络框架,以其速度和易用性而闻名。在本节中,我们将创建一个简单的后端,暴露一个用于向我们的聊天机器人发送消息的端点。这个后端将处理传入请求,将用户输入传递给我们的 LangGraph 聊天机器人,并以 JSON 格式返回聊天机器人的响应。
我们的 FastAPI 后端将分为两个主要部分。第一部分将专注于定义 数据模型,这些模型将作为我们 API 的输入和输出模式。这些模型确保在客户端和后端之间传递的数据遵循明确定义的结构,使得验证和序列化变得简单明了。第二部分将定义 FastAPI 应用程序 本身,包括处理聊天交互、处理用户输入和返回聊天机器人响应的路由。将这些关注点分开有助于提高可维护性和清晰性。项目结构如下:
end-to-end-chatbot/ │ │ │ │ │ │ │ │ │ │ .env
让我们从最简单的文件开始:models.py。
from pydantic import BaseModel, Field from enum import Enum
class ModelName(str, Enum): CLAUDE_3_5_SONNET_20240620 = “claude-3-5-sonnet-20240620” GPT_4_TURBO_2024_04_09 = “gpt-4-turbo-2024-04-09”
class ChatRequest(BaseModel): user_input: str model_name: ModelName = Field(default=ModelName.CLAUDE_3_5_SONNET_20240620) temperature: float = Field(default=0.0) recursion_limit: int = Field(default=25)
class ChatResponse(BaseModel): response: str session_id: str
这个文件定义了构建我们 FastAPI 端点的数据模型。它首先创建了一个枚举 ModelName,列出了支持的语言模型。我在这里添加了两个,但任何 Anthropic、OpenAI 或 Ollama 模型都可以添加。使用枚举确保只能使用预定义的模型名称,从而防止无效输入。接下来,ChatRequest 类定义了用户与聊天机器人交互时的预期请求有效载荷。它需要一个 user_input 字符串,并允许可选参数,如 model_name、temperature 和 recursion_limit,所有这些都有合理的默认值。最后,ChatResponse 类指定了 API 响应的结构,包括聊天机器人的回复(response)和用于跟踪进行中的对话的 session_id。这些 Pydantic 模型强制执行类型验证并提供自动请求解析,使我们的 API 更加健壮和可预测。
在深入 FastAPI 实现之前,重要的是要注意本节假设您对 RESTful API 有一定的了解。如果您对这个概念不熟悉,我建议查看 FastAPI 文档或其他关于 RESTful 设计原则的资源,因为我不会在这里覆盖基础知识。相反,我将重点介绍我们如何将聊天机器人逻辑集成到 FastAPI 后端,构建路由并将所有内容连接在一起。
from fastapi import FastAPI, HTTPException import logging from typing import Dict, Any import traceback import uuid
from langchain_core.messages import HumanMessage
from chatbot.graph import ChatbotGraph from api.models import ChatRequest, ChatResponse
logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__)
app = FastAPI( title=“聊天机器人 API”, description=“与聊天机器人交互的 API”, version=“1.0.0” )
chat_sessions: Dict[str, Dict[str, Any]] = {}
@app.post(“/chat/start”, response_model=ChatResponse) async def start_chat(request: ChatRequest): """开始与聊天机器人新的聊天会话""" try:
graph = ChatbotGraph(
model\_name=request.model\_name,
temperature=request.temperature,
)
session\_id = str(uuid.uuid4())
inputs = {"messages": \[{"role": "user", "content": request.user\_input}\]}
config = {
"recursion\_limit": request.recursion\_limit,
"configurable": {"thread\_id": session\_id}
}
output = graph.invoke(
input\=inputs,
config=config
)
chat\_sessions\[session\_id\] = {
"graph": graph,
"state": output,
"config": config
}
return ChatResponse(
response=output\["messages"\]\[-1\].content,
session\_id=session\_id
)
except Exception as e:
logger.error(f"启动聊天时出错: {traceback.format\_exc()}")
raise HTTPException(status\_code=500, detail=traceback.format\_exc())
@app.post(“/chat/{session_id}/continue”, response_model=ChatResponse) async def continue_chat(session_id: str, request: ChatRequest): if session_id not in chat_sessions: raise HTTPException(status_code=404, detail=“会话未找到”)
chat\_session = chat\_sessions\[session\_id\]
chat\_session\["state"\]\["messages"\].append(HumanMessage(content=request.user\_input))
new\_state = chat\_session\["graph"\].invoke(chat\_session\["state"\], chat\_session\["config"\])
chat\_sessions\[session\_id\].update({"state": new\_state})
return ChatResponse(
response=new\_state\["messages"\]\[-1\].content,
session\_id=session\_id
)
@app.get(“/chat/sessions”) async def list_sessions(): """列出所有活动的聊天会话""" return {“sessions”: list(chat_sessions.keys())}
@app.delete(“/chat/{session_id}”) async def end_session(session_id: str): """结束聊天会话""" if session_id not in chat_sessions: raise HTTPException(status_code=404, detail=“聊天会话未找到”)
del chat\_sessions\[session\_id\]
return {"message": "会话成功结束"}
这个文件定义了我们 FastAPI 后端的核心,处理聊天会话、处理用户输入以及管理与 ChatbotGraph 的交互。让我们详细分解一下。
在文件的开头,设置了 INFO 级别的日志记录,确保任何问题或重要事件都被记录以便调试。然后创建了 FastAPI 实例,带有标题、描述和版本,明确表示该 API 负责聊天机器人交互。我们还定义了一个字典 chat_sessions,用于存储活动的聊天会话。每个会话(由其 session_id 定义)将保存一个 ChatbotGraph 实例、当前聊天状态和会话配置。这使我们能够跟踪对话并在多次交互中继续进行。
start_chat 端点负责启动一个新的聊天会话。当用户向该端点发送请求时,它遵循以下步骤:
1. 提取用户输入: API 接收一个 ChatRequest 对象,其中包含用户的初始输入消息、所需模型、温度设置和递归限制。
2. 创建聊天机器人图: 根据请求中指定的模型名称和温度创建一个新的 ChatbotGraph 实例。
3. 生成唯一的会话 ID: 使用 uuid.uuid4(),API 生成一个会话标识符,用于跟踪此对话。
4. 准备聊天机器人输入: 将请求的用户输入结构化为 LangGraph 预期的格式。
5. 配置会话: 准备一个配置字典(config),包含递归限制和会话的唯一线程标识符。
6. 调用聊天机器人: 聊天机器人图处理输入消息并返回包含聊天机器人响应的更新状态。
7. 存储会话: 聊天机器人实例、对话状态和配置存储在 chat_sessions 中,使对话得以持久化。
8. 返回响应: 从状态中提取聊天机器人的最后一条消息,并连同会话 ID 一起发送回用户。
如果在此过程中发生任何错误,它们会被捕获并使用 traceback.format_exc() 记录以确保清晰,并引发状态代码为 500 的 HTTPException。
continue_chat 端点允许用户在进行中的会话中发送新消息。当收到请求时:
1. 验证会话: 会话 ID 会与 chat_sessions 进行检查。如果不存在,则返回 404 错误。
2. 检索会话数据: 从 chat_sessions 中提取相应的聊天机器人实例、对话状态和配置。
3. 添加用户消息: 从新输入创建一个 HumanMessage 对象,并将其附加到聊天机器人状态中的消息列表中。
4. 调用聊天机器人: 聊天机器人图处理更新的状态并生成新的响应。
5. 更新会话: 将新状态存回 chat_sessions,确保对话保持最新。
6. 返回聊天机器人响应: 从状态中提取最后一条聊天机器人消息并发送给用户。
list_sessions 端点简单地返回一个 JSON 对象,其中包含所有活动会话的 ID。这对于调试或管理多个并发对话非常有用。end_session 端点允许用户终止聊天会话。我们在此实现中不会使用它们,但将来可能会很方便。
这个 FastAPI 实现创建了一种与我们的聊天机器人交互的结构化方式。API 允许用户启动对话、继续对话、列出活动会话并结束对话。通过将聊天机器人实例存储在 chat_sessions 中,API 确保每个对话都是持久的。使用 FastAPI 的请求验证和响应模型确保了后端与任何与之交互的客户端之间的清晰、可靠的通信。
每次用户启动或继续聊天时,他们通过 API 调用发送输入,这直接更新聊天机器人的状态并调用下一个响应。这意味着 FastAPI 端点本身充当人类输入机制,消除了在 LangGraph 内部显式人类输入节点的需要。相反,用户消息动态注入到会话状态中,使聊天机器人完全响应外部 API 调用,而不是依赖阻塞输入机制。
有了我们的后端准备就绪,我们现在可以开始用户界面了!
使用 Streamlit 构建前端
现在我们已经通过 FastAPI 运行了一个功能齐全的聊天机器人,我们需要一个简单直观的方式让用户与之互动。这就是 Streamlit 的用武之地。Streamlit 是一个轻量级的 Python 框架,使我们能够以最小的努力构建交互式网页应用程序。
Streamlit 不需要像 React 或 Vue 这样的独立前端框架,而是让我们可以使用纯 Python 创建一个功能齐全的用户界面。这使得它成为快速原型设计和部署 AI 驱动应用程序的绝佳选择。在这一部分,我们将构建一个 聊天界面,连接到我们的 FastAPI 后端,使用户能够开始对话、发送消息并接收回复——这一切都在一个简单而优雅的网页应用中完成。这个最后的文件使我们的项目结构完整。
end-to-end-chatbot/ │ │ │ │ │ │ │ │ │ │ │ .env
让我们来看一下文件的内容。
import streamlit as st
import requests
API\_URL = "http://127.0.0.1:8000"
st.title("Chatbot 🤖")
if "session\_id" not in st.session\_state:
st.session\_state.session\_id = None
if "messages" not in st.session\_state:
st.session\_state.messages = \[\]
for message in st.session\_state.messages:
role = "You" if message\["role"\] == "user" else "Bot"
st.chat\_message(role).write(message\["content"\])
user\_input = st.chat\_input("Ask me anything...")
if user\_input:
st.session\_state.messages.append({"role": "user", "content": user\_input})
st.chat\_message("You").write(user\_input)
if st.session\_state.session\_id is None:
response = requests.post(f"{API\_URL}/chat/start", json={"user\_input": user\_input})
if response.status\_code == 200:
data = response.json()
st.session\_state.session\_id = data.get("session\_id")
bot\_response = data.get("response")
st.session\_state.messages.append({"role": "bot", "content": bot\_response})
st.chat\_message("Bot").write(bot\_response)
else:
st.error("Failed to start chat session.")
else:
response = requests.post(
f"{API\_URL}/chat/{st.session\_state.session\_id}/continue",
json={"user\_input": user\_input}
)
if response.status\_code == 200:
data = response.json()
bot\_response = data.get("response")
st.session\_state.messages.append({"role": "bot", "content": bot\_response})
st.chat\_message("Bot").write(bot\_response)
else:
st.error("Failed to continue chat.")
这个 Streamlit 脚本提供了一个简单的网页界面,用于与我们的聊天机器人 API 进行交互。它允许用户无缝地开始新的聊天会话或继续现有的会话。界面设计简约,同时确保了流畅的用户体验。
在脚本的开头,我们导入了必要的库:streamlit 用于 UI 组件,requests 用于与我们的 FastAPI 后端进行通信。API_URL 设置为指向本地 FastAPI 服务器,但如果后端部署在其他地方,可以更改此设置。
为了跟踪进行中的对话,我们使用 Streamlit 的会话状态。session_id 变量确保聊天会话保持不变,而 messages 存储聊天历史,以便之前的交流在新输入后仍然可见。如果这些会话状态变量不存在,则会进行初始化。
该脚本通过循环存储的消息来显示聊天历史。每条消息被分类为用户输入或机器人回复,并相应地在聊天窗口中使用 Streamlit 的 st.chat_message() 显示。这使得交互显得自然且连续。
当用户输入消息时,脚本确定是开始新的聊天会话还是继续现有的会话。如果没有活动会话,它会向 FastAPI 后端的 /chat/start 端点发送请求。响应包含一个唯一的会话 ID 和聊天机器人的回复,这两者都存储在会话状态中以确保连续性。如果会话已经处于活动状态,脚本则会将输入发送到 /chat/{session_id}/continue,接收并显示机器人的回复,同时保持对话的流畅。
如果出现任何错误,例如 API 请求失败,脚本会显示错误消息以通知用户。这确保了任何连接问题或服务器问题都能有效传达。
这种方法确保了顺畅且互动的聊天机器人体验。聊天历史始终可见,会话持久性允许进行更长的对话,而使用 Streamlit 则使实现变得简单而强大。通过这种方式,用户可以像在任何标准聊天应用程序中一样与聊天机器人进行互动。
与聊天机器人互动
我们终于可以测试我们的产品了。首先,我们需要启动我们的 FastAPI 后端。我们可以使用以下命令来实现:
uvicorn api.main:app —reload
此命令启动 API 服务器,默认情况下可以通过 http://127.0.0.1:8000 访问。— reload 标志确保任何代码更改都会自动反映,而无需手动重启服务器。
后端运行后,您现在可以启动 Streamlit UI。通过执行以下命令(仍然在项目的根目录下)来导航到该目录:
streamlit run ui/chatbot_ui.py
这将在您的默认浏览器中启动一个看起来像这样的网页界面:
聊天机器人 UI 的截图 — 作者提供的图片。
在这里,您可以在聊天输入框中输入消息,并从聊天机器人那里接收响应。当您发送第一条消息时,应用程序将自动启动一个新的聊天会话,后续消息将在同一会话中继续对话。
如果一切设置正确,您现在应该能够顺利与聊天机器人互动。如果遇到任何问题,请检查终端日志以查看 FastAPI 服务器或 Streamlit 应用程序的错误消息。
结论与后续步骤
通过这次实现,我们现在拥有一个功能齐全的聊天机器人,利用 LangGraph 进行对话流程,使用 FastAPI 作为后端,以及 Streamlit 作为用户界面。按照本指南中概述的步骤,您应该能够在本地运行聊天机器人,与其互动,并查看不同组件如何无缝协作。
该项目的完整源代码可在 GitHub 上获取:
欢迎您探索代码,进行修改,并尝试不同的配置以更好地满足您的需求。
下一步的合理改进之一是将聊天机器人部署到网络上,而不是在本地运行。这将允许用户从任何地方访问,而无需设置本地环境。部署选项可以包括在 AWS、Google Cloud 或 Vercel 等云平台上托管 FastAPI 后端,并使用 Streamlit Community Cloud 或其他托管服务部署 Streamlit UI。
除了部署之外,其他改进还可以包括集成更高级的 AI 模型、添加持久的聊天记录存储,或为用户特定的交互实现身份验证。如果您希望看到这些改进的实际应用,请在评论中告诉我。
基础已经搭建好——现在由您来扩展和增强它!