Agent 智能体开发实战指南(八):UI 集成与生产部署
系列导读:这是《Agent 智能体开发实战指南》系列的最终篇,将讲解如何将 Agent 集成到用户界面,以及生产环境的部署策略、性能优化和最佳实践。
一、Streamlit 快速入门
1.1 为什么选择 Streamlit?
| 特性 | 说明 |
|---|---|
| 快速开发 | 几十行代码就能搭建交互式 UI |
| Python 原生 | 无需学习前端技术 |
| 自动刷新 | 状态变化自动重新渲染 |
| 内置组件 | 聊天界面、文件上传、图表等 |
| 适合演示 | 快速原型、内部工具、Demo 展示 |
1.2 最小可用示例
python
# app.py
import streamlit as st
st.title("我的第一个 Streamlit 应用")
name = st.text_input("请输入你的名字")
if name:
st.write(f"你好,{name}!")
bash
# 运行
streamlit run app.py
二、完整的 Agent 聊天界面
2.1 核心代码
python
import time
import streamlit as st
from agent.react_agent import ReactAgent
# 页面配置
st.set_page_config(
page_title="智扫通智能客服",
page_icon="🤖",
layout="wide"
)
# 标题
st.title("🤖 智扫通机器人智能客服")
st.divider()
# 初始化 Agent(单例模式)
if "agent" not in st.session_state:
st.session_state["agent"] = ReactAgent()
# 初始化消息历史
if "messages" not in st.session_state:
st.session_state["messages"] = []
# 显示历史消息
for message in st.session_state["messages"]:
with st.chat_message(message["role"]):
st.write(message["content"])
# 用户输入
prompt = st.chat_input("请问有什么可以帮您?")
if prompt:
# 显示用户消息
st.chat_message("user").write(prompt)
st.session_state["messages"].append({
"role": "user",
"content": prompt
})
# 生成回复
response_messages = []
with st.spinner("智能客服思考中..."):
res_stream = st.session_state["agent"].execute_stream(prompt)
# 流式显示(打字机效果)
def capture(generator, cache_list):
for chunk in generator:
cache_list.append(chunk)
# 逐字输出,模拟打字机
for char in chunk:
time.sleep(0.01)
yield char
# 显示助手回复
with st.chat_message("assistant"):
response = st.write_stream(
capture(res_stream, response_messages)
)
# 保存回复到历史
st.session_state["messages"].append({
"role": "assistant",
"content": response_messages[-1] if response_messages else response
})
# 刷新页面
st.rerun()
2.2 关键组件说明
| 组件 | 作用 |
|---|---|
st.set_page_config() |
页面配置(标题、图标、布局) |
st.title() |
页面标题 |
st.divider() |
分割线 |
st.session_state |
会话状态存储 |
st.chat_message() |
聊天消息气泡 |
st.chat_input() |
聊天输入框 |
st.spinner() |
加载动画 |
st.write_stream() |
流式输出 |
st.rerun() |
重新渲染页面 |
2.3 Session State 管理
python
# 为什么需要 session_state?
# Streamlit 每次交互都会重新运行整个脚本
# session_state 用于在多次运行之间保持状态
# 初始化(只运行一次)
if "agent" not in st.session_state:
st.session_state["agent"] = ReactAgent()
# 后续运行会复用已创建的实例
agent = st.session_state["agent"] # 不会重新创建
# 消息历史同理
if "messages" not in st.session_state:
st.session_state["messages"] = []
# 添加消息
st.session_state["messages"].append({"role": "user", "content": prompt})
三、Agent 流式执行封装
3.1 ReactAgent 类实现
python
# agent/react_agent.py
from langchain.agents import create_agent
from model.factory import chat_model
from utils.prompt_loader import load_system_prompts
from agent.tools.agent_tools import (
rag_summarize, get_weather, get_user_location,
get_user_id, get_current_month,
fetch_external_data, fill_context_for_report
)
from agent.tools.middleware import (
monitor_tool, log_before_model, report_prompt_switch
)
class ReactAgent:
def __init__(self):
"""初始化 Agent"""
self.agent = create_agent(
model=chat_model,
system_prompt=load_system_prompts(),
tools=[
rag_summarize, get_weather, get_user_location,
get_user_id, get_current_month,
fetch_external_data, fill_context_for_report
],
middleware=[
monitor_tool, log_before_model, report_prompt_switch
],
)
def execute_stream(self, query: str):
"""
流式执行 Agent
参数:
- query: 用户问题
返回:
- 生成器,逐块输出 Agent 响应
"""
# 组装输入
input_dict = {
"messages": [
{"role": "user", "content": query},
]
}
# 流式执行
# context={"report": False} 初始化为非报告场景
for chunk in self.agent.stream(
input_dict,
stream_mode="values",
context={"report": False}
):
latest_message = chunk["messages"][-1]
if latest_message.content:
yield latest_message.content.strip() + "\n"
3.2 流式处理要点
python
# 1. 使用 stream_mode="values" 获取完整状态
for chunk in agent.stream(input_dict, stream_mode="values"):
# 2. 获取最新消息
latest_message = chunk["messages"][-1]
# 3. 提取内容
if latest_message.content:
yield latest_message.content
# 4. 在 UI 层逐字显示
def capture(generator, cache_list):
for chunk in generator:
cache_list.append(chunk) # 保存完整内容
for char in chunk: # 逐字输出
time.sleep(0.01) # 打字机延迟
yield char
四、生产环境部署
4.1 部署方案对比
| 方案 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| 本地运行 | 开发测试 | 简单快速 | 无法对外服务 |
| Streamlit Cloud | 公开 Demo | 免费、易部署 | 资源有限、国内访问慢 |
| Docker 容器 | 生产环境 | 隔离、可移植 | 需要容器化知识 |
| 云服务器 | 生产环境 | 可控、高性能 | 成本较高 |
| 内网部署 | 企业内网 | 安全、私有 | 需要内网环境 |
4.2 Docker 部署方案
Dockerfile:
dockerfile
FROM python:3.11-slim
WORKDIR /app
# 安装系统依赖
RUN apt-get update && apt-get install -y \
build-essential \
&& rm -rf /var/lib/apt/lists/*
# 复制依赖文件
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# 复制项目文件
COPY . .
# 暴露端口
EXPOSE 8501
# 启动命令
CMD ["streamlit", "run", "app.py", "--server.port=8501", "--server.address=0.0.0.0"]
构建和运行:
bash
# 构建镜像
docker build -t zhisaotong-agent .
# 运行容器
docker run -d -p 8501:8501 \
-v $(pwd)/data:/app/data \
-v $(pwd)/logs:/app/logs \
--name agent-app \
zhisaotong-agent
# 查看日志
docker logs -f agent-app
# 停止容器
docker stop agent-app
4.3 云服务器部署(以 Ubuntu 为例)
1. 环境准备:
bash
# 更新系统
sudo apt update && sudo apt upgrade -y
# 安装 Python
sudo apt install -y python3.11 python3.11-venv python3-pip
# 安装 Git
sudo apt install -y git
# 创建用户
sudo useradd -m agent-user
sudo passwd agent-user
2. 项目部署:
bash
# 切换到用户
sudo su - agent-user
# 克隆项目
git clone https://github.com/your-repo/zhisaotong-agent.git
cd zhisaotong-agent
# 创建虚拟环境
python3.11 -m venv venv
source venv/bin/activate
# 安装依赖
pip install -r requirements.txt
# 配置环境变量
cp .env.example .env
# 编辑 .env 文件,填入 API 密钥等
3. 后台运行:
bash
# 使用 nohup
nohup streamlit run app.py --server.port=8501 --server.address=0.0.0.0 > app.log 2>&1 &
# 或使用 systemd 服务
sudo nano /etc/systemd/system/agent-app.service
systemd 服务配置:
ini
[Unit]
Description=Zhisaotong Agent App
After=network.target
[Service]
Type=simple
User=agent-user
WorkingDirectory=/home/agent-user/zhisaotong-agent
Environment="PATH=/home/agent-user/zhisaotong-agent/venv/bin"
ExecStart=/home/agent-user/zhisaotong-agent/venv/bin/streamlit run app.py --server.port=8501 --server.address=0.0.0.0
Restart=always
[Install]
WantedBy=multi-user.target
bash
# 启动服务
sudo systemctl daemon-reload
sudo systemctl enable agent-app
sudo systemctl start agent-app
# 查看状态
sudo systemctl status agent-app
4. Nginx 反向代理:
nginx
server {
listen 80;
server_name your-domain.com;
location / {
proxy_pass http://localhost:8501;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# WebSocket 支持(Streamlit 需要)
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
五、性能优化建议
5.1 Agent 层面
1. 限制最大迭代次数:
python
agent = create_agent(
model=chat_model,
tools=tools,
max_iterations=10, # 防止无限循环
)
2. 设置超时:
python
for chunk in agent.stream(
input_dict,
stream_mode="values",
config={"timeout": 30} # 30 秒超时
):
yield chunk
3. 缓存工具结果:
python
from functools import lru_cache
@lru_cache(maxsize=100)
def cached_tool_call(tool_name: str, args: str) -> str:
# 缓存工具调用结果
pass
5.2 向量检索层面
1. 限制检索数量:
yaml
# config/chroma.yml
k: 3 # 只检索最相关的 3 条
2. 使用元数据过滤:
python
retriever = vector_store.as_retriever(
search_kwargs={
"k": 3,
"filter": {"category": "故障排除"}
}
)
3. 定期清理向量库:
python
# 删除旧数据
vector_store.delete_collection()
# 重新加载
vector_store.load_document()
5.3 Streamlit 层面
1. 使用缓存装饰器:
python
@st.cache_resource
def get_agent():
"""Agent 实例缓存,避免重复创建"""
return ReactAgent()
agent = get_agent()
2. 优化大文件加载:
python
@st.cache_data
def load_knowledge_base():
"""知识库加载缓存"""
vs = VectorStoreService()
vs.load_document()
return vs
3. 减少不必要的重新渲染:
python
# 使用 session_state 避免重复计算
if "result" not in st.session_state:
st.session_state["result"] = expensive_computation()
result = st.session_state["result"]
六、监控与日志
6.1 应用监控
python
# middleware/monitoring.py
import time
from collections import defaultdict
from utils.logger_handler import logger
# 统计指标
metrics = defaultdict(lambda: {
"count": 0,
"total_time": 0,
"errors": 0
})
@wrap_tool_call
def monitor_performance(request, handler):
"""性能监控中间件"""
tool_name = request.tool_call['name']
start = time.time()
try:
result = handler(request)
return result
except Exception as e:
metrics[tool_name]["errors"] += 1
raise
finally:
duration = time.time() - start
metrics[tool_name]["count"] += 1
metrics[tool_name]["total_time"] += duration
avg_time = (
metrics[tool_name]["total_time"] /
metrics[tool_name]["count"]
)
logger.info(
f"工具{tool_name}: "
f"调用{metrics[tool_name]['count']}次,"
f"平均耗时{avg_time:.2f}s, "
f"错误{metrics[tool_name]['errors']}次"
)
6.2 日志轮转
python
# utils/logger_handler.py
from logging.handlers import RotatingFileHandler
def get_logger_with_rotation(name: str = "agent"):
logger = logging.getLogger(name)
logger.setLevel(logging.DEBUG)
# 轮转文件 Handler
# 每个文件最大 10MB,保留 5 个备份
file_handler = RotatingFileHandler(
f"logs/{name}.log",
maxBytes=10*1024*1024,
backupCount=5
)
file_handler.setFormatter(DEFAULT_LOG_FORMAT)
logger.addHandler(file_handler)
return logger
七、安全最佳实践
7.1 敏感信息管理
错误:硬编码密钥:
python
# 不要这样做!
API_KEY = "sk-abc123xyz"
正确:环境变量:
python
# .env 文件(加入 .gitignore)
DASHSCOPE_API_KEY=sk-abc123xyz
CHROMA_PERSIST_PATH=/secure/path
# 代码中读取
import os
from dotenv import load_dotenv
load_dotenv()
API_KEY = os.getenv("DASHSCOPE_API_KEY")
7.2 输入验证
python
@tool(description="查询天气")
def get_weather(city: str) -> str:
# 输入验证
if not city or len(city) > 50:
return "无效的城市名称"
# 防止注入
city = city.strip()
city = ''.join(c for c in city if c.isalnum() or c in '中国省市自治区')
return query_weather_api(city)
7.3 权限控制
python
@wrap_tool_call
def check_permission(request, handler):
"""权限检查中间件"""
sensitive_tools = ["delete_user", "export_data", "admin_command"]
if request.tool_call['name'] in sensitive_tools:
user_role = request.runtime.context.get("user_role", "guest")
if user_role != "admin":
logger.warning(f"非管理员尝试调用敏感工具")
raise PermissionError("无权执行此操作")
return handler(request)
八、系列总结
8.1 知识回顾
| 篇序 | 主题 | 核心收获 |
|---|---|---|
| 01 | Agent 基础概念 | 理解 Agent 与 Chain 的区别 |
| 02 | 工具调用系统 | 掌握@tool 装饰器和工具设计 |
| 03 | ReAct 框架详解 | 学会思考 - 行动 - 观察循环 |
| 04 | 流式输出与调试 | 理解 stream_mode 各种模式 |
| 05 | 中间件系统 | 掌握 Hooks 和动态提示词 |
| 06 | RAG 与向量存储 | 实现知识库检索增强 |
| 07 | 项目架构设计 | 学习工程化实践 |
| 08 | UI 集成与部署 | 完成从开发到部署 |
8.2 进阶方向
1. 多 Agent 协作:
python
# 多个 Agent 协同完成复杂任务
researcher_agent = create_agent(...)
writer_agent = create_agent(...)
reviewer_agent = create_agent(...)
# 工作流:研究 → 写作 → 审核
2. 记忆系统:
python
# 长期记忆存储
from langchain.memory import ConversationBufferMemory
memory = ConversationBufferMemory(
memory_key="chat_history",
return_messages=True
)
3. 评估与优化:
python
# 使用 LangSmith 等平台进行 Agent 评估
# 追踪每次执行的完整链路
# 分析工具调用准确率
4. 更多工具集成:
- 数据库查询工具
- API 调用工具
- 代码执行工具
- 文件操作工具
九、结语
恭喜你完成了《Agent 智能体开发实战指南》全系列!
从最基础的 Agent 概念,到完整的项目部署,你已经掌握了:
- Agent 的核心架构和工作原理
- 工具调用系统的设计与实现
- ReAct 框架的多步推理能力
- 流式输出与状态管理
- 中间件系统的高级应用
- RAG 与向量存储的集成
- 工程化的项目架构设计
- 生产环境的部署与优化
但这只是开始。Agent 技术正在快速发展,新的框架、工具和最佳实践不断涌现。保持学习,持续实践,你一定能构建出更强大的智能应用。
最后的建议:
- 动手实践:教程看十遍不如动手做一遍
- 从小开始:先做一个简单的 Agent,再逐步扩展
- 记录问题:遇到的每个问题都是学习机会
祝你在 Agent 开发的道路上越走越远!