前端界面(极简灰阶设计):
Grafana 监控面板(可用性 SLA 可视化):
基于 LangGraph (ReAct) + Tavily API + FastAPI + Next.js 16 构建的自主决策搜索 Agent。支持 OpenAI 兼容的 LLM(OpenAI / 阿里云百炼 DashScope / DeepSeek 等多平台)。
- ReAct 自主决策: LLM 根据工具描述按需加载工具、自主决定「是否搜索 / 搜索几次 / 何时停止」,不再硬编码流水线
- 多平台适配:
LLM_PROVIDER=openai|qwen|deepseek一键切换,自动处理response_format/ embedding 等平台差异 - 实时搜索: Tavily API 联网搜索,突破 LLM 知识时效限制
- RAG 知识库: 本地知识库检索(分块 + 混合检索 + 时效治理),纯 Python 持久化零冲突,可选 ChromaDB / 本地 embedding
- 护栏与安全: 提示注入检测、敏感信息脱敏、工具权限白名单、日志脱敏
- 上下文压缩: 分层历史压缩 + 前缀稳定化(利于 prompt cache / KV cache),降低延迟与 token 开销
- 辅助工具: 安全计算器(AST 白名单)、当前时间、知识库检索等按需加载
- SSE 流式输出: LLM 答案逐 Token 推送到前端
- 多层容错: 指数退避重试 + LLM 降级回答,异常期可用性 95%+
- 多轮对话: 基于会话 ID 的上下文缓存 + 分层压缩
- 可观测性栈: Prometheus 指标采集 + Grafana 可视化仪表盘 + 告警规则
- 企业级 UI: 极简灰阶设计,去 AI 味,专业排版
┌──────────────────┐ SSE Stream ┌──────────────┐ HTTP ┌────────────────┐
│ Next.js 16 前端 │ ◄─────────────────── │ FastAPI 后端 │ ──────────────────► │ LLM API │
│ (port 3001) │ event: progress │ (port 8000) │ streaming POST │ (OpenAI 兼容) │
│ │ event: token │ │ │ │
│ React 19 + TS │ event: sources │ LangGraph │ ──────────────────► │ Tavily Search │
│ Tailwind CSS 4 │ event: done │ ReAct Agent │ Search API │ API │
│ App Router │ event: error │ │ │ │
├──────────────────┤ ├───────────────┤ └────────────────┘
│ Streamlit 面板 │ │ 全局 httpx │
│ (port 8501) │ │ 连接池复用 │
│ 开发调试用 │ │ │
└──────────────────┘ ├───────────────┤
│ /api/metrics │ ◄── Prometheus 抓取 (每 15s)
│ Prometheus 指标 │
┌──────────────────┐ └───────────────┘
│ Grafana 仪表盘 │ ◄─── PromQL ──── ┌──────────────────┐
│ (port 3002) │ │ Prometheus │
│ 可用性 SLA 监控 │ │ (port 9090) │
└──────────────────┘ │ 抓取 + 告警 │
└──────────────────┘
┌─────────────────────────────────────────────┐
│ LangGraph ReAct 循环 │
│ │
用户输入 ────► │ 模型思考 ──► 需要工具? ──是──► 调用工具 │
│ ▲ │ │ │
│ │ 否 观察结果 │
│ │ │ │ │
│ └──────── 直接作答 ◄───────────┘ │
│ │
│ 可用工具: search / knowledge_search / │
│ calculator / current_time │
└─────────────────────────────────────────────┘
│
▼
最终答案 + 来源
模型根据工具 JSON Schema 描述自主决策调用时机与次数,tools_condition 自动路由驱动循环,信息充分即停止。
qa/
├── agent/ # Agent 核心模块
│ ├── __init__.py # 模块入口
│ ├── graph.py # SearchAgent 薄封装(委托 ReactAgent,会话管理)
│ ├── react.py # ReactAgent:create_react_agent + 系统提示 + 结果提取
│ ├── tools.py # ReAct 工具集:search / knowledge_search / calculator / current_time
│ ├── models.py # Pydantic 数据模型 + AgentState TypedDict
│ └── streaming.py # SSE 流式桥接(astream_events v2 → SSE 事件)
├── tools/ # 工具注册中心(底层实现)
│ ├── __init__.py # 工具模块
│ └── registry.py # tavily_search / rewrite_query / score_relevance / fallback_answer + 组合流水线
├── rag/ # RAG 知识库
│ └── __init__.py # 分块 + 混合检索 + 时效治理(纯 Python 持久化,可选 ChromaDB)
├── memory/ # 会话缓存
│ ├── __init__.py # 内存模块
│ └── session_store.py # 会话缓存 (TTL 过期)
├── utils/ # 工具函数
│ ├── __init__.py # 工具函数模块
│ ├── helpers.py # URL 去重, Token 计数, 限流, 上下文裁剪
│ ├── http_client.py # 全局共享 HTTP 客户端 (连接池复用)
│ ├── metrics.py # Prometheus 指标 + 滑动窗口可用性统计 (95% SLA)
│ ├── guardrails.py # 护栏:提示注入检测 / 敏感脱敏 / 工具白名单
│ └── context.py # 上下文压缩:分层历史 + 前缀稳定化
├── monitoring/ # 可观测性栈
│ ├── prometheus/
│ │ ├── prometheus.yml # Prometheus 配置 (15s 抓取间隔)
│ │ └── alerts.yml # 告警规则 (高错误率/高延迟/服务宕机)
│ └── grafana/
│ ├── dashboards/
│ │ ├── availability.json # 可用性监控 Dashboard (4 区域 11 面板)
│ │ └── dashboard.yml # Dashboard 自动加载配置
│ └── datasources/
│ └── prometheus.yml # Prometheus 数据源
├── tests/ # 测试 (131 条)
│ ├── __init__.py # 测试包
│ ├── test_core.py # 单元测试 (去重/Token/限流/会话/模型)
│ ├── test_registry.py # 工具注册中心测试 (搜索/改写/打分/降级/流水线)
│ ├── test_graph.py # ReactAgent + SearchAgent 类测试
│ ├── test_config.py # 配置加载 + 单例 + 多平台 provider
│ ├── test_production.py # 护栏 / 上下文压缩 / provider 生产级测试
│ └── test_e2e.py # 端到端 ReAct 流水线 + 会话测试
├── evals/ # 行为评估
│ ├── __init__.py # 评估包
│ ├── golden_dataset.json # 黄金行为数据集 (30 用例, 80 断言)
│ ├── evaluate.py # 自动化评估框架 (9 类别, HTML/JSON 报告)
│ ├── benchmark.py # 延迟 & Token 基准测试
│ ├── report.html # HTML 评估报告 (自动生成)
│ └── benchmark.html # HTML 基准测试报告 (自动生成)
├── frontend/ # Next.js 16 前端
│ ├── app/
│ │ ├── layout.tsx # 根布局 (Geist 字体)
│ │ ├── page.tsx # 应用入口页
│ │ ├── globals.css # 全局样式 (Tailwind CSS 4)
│ │ └── api/chat/stream/
│ │ └── route.ts # API 代理 (Next.js → FastAPI rewrite)
│ ├── src/
│ │ ├── components/
│ │ │ ├── ChatArea.tsx # 聊天区域 (消息列表 + 输入框)
│ │ │ ├── ChatInput.tsx # 消息输入框
│ │ │ ├── MessageBubble.tsx # 消息气泡 (Markdown 渲染)
│ │ │ ├── MarkdownContent.tsx # Markdown 渲染 + 流式光标
│ │ │ ├── Sidebar.tsx # 侧边栏 (会话管理)
│ │ │ ├── SourcesPanel.tsx # 来源面板
│ │ │ ├── MetaBar.tsx # 元信息栏 (延迟/Token/置信度)
│ │ │ └── StreamingToken.tsx # 流式 Token 光标
│ │ ├── hooks/
│ │ │ └── useSSE.ts # SSE 流式连接 Hook
│ │ ├── lib/
│ │ │ ├── types.ts # TypeScript 类型定义
│ │ │ └── api.ts # API 调用封装
│ │ └── providers/
│ │ └── ChatProvider.tsx # 聊天状态管理 (React Context)
│ ├── next.config.ts # Next.js 配置 (rewrites 代理 + standalone 输出)
│ ├── package.json # 依赖: Next.js 16.2, React 19.2, Tailwind CSS 4
│ └── tsconfig.json # TypeScript 配置
├── server.py # FastAPI 后端入口 (SSE + REST API + 生命周期管理)
├── app.py # Streamlit 开发调试面板
├── config.py # 全局配置 (pydantic-settings, 单例, 多平台 provider)
├── requirements.txt # Python 依赖
├── Dockerfile.backend # 后端 Docker 镜像 (python:3.12-slim)
├── Dockerfile.frontend # 前端 Docker 镜像 (多阶段 node:22-alpine)
├── docker-compose.yml # 一键部署编排 (bridge 网络 + 健康检查)
├── .dockerignore # Docker 忽略规则
├── .env # 环境变量 (LLM_API_KEY, TAVILY_API_KEY 等, git-ignored)
├── fix-and-start.ps1 # Windows 一键修复 & 启动脚本
└── README.md
确保已安装 Docker Desktop 或 Docker Engine 20.10+。
# 1. 配置 API 密钥
# 编辑 .env,填入真实的 API Key。
# ── LLM 配置 (OpenAI 兼容协议) ──
# 方式一:使用 provider 预设(推荐,自动处理平台差异)
# LLM_PROVIDER=qwen # openai | qwen | deepseek
# LLM_API_KEY=sk-xxxx
#
# 方式二:显式指定 endpoint + model
# 阿里云百炼 DashScope (通义千问):
# LLM_API_KEY=sk-xxxxxxxxxxxxxxxxxx
# LLM_API_BASE=https://dashscope.aliyuncs.com/compatible-mode/v1
# LLM_MODEL=qwen-plus
#
# OpenAI / DeepSeek / 其他兼容 API:
# LLM_API_KEY=sk-your-key
# LLM_API_BASE=https://api.openai.com/v1 # 或 https://api.deepseek.com/v1
# LLM_MODEL=gpt-4o-mini # 或 deepseek-chat
#
# ── Tavily 搜索 API ──
# TAVILY_API_KEY=tvly-your-real-key
# 2. 构建并启动所有服务
docker compose up -d --build
# 3. 查看运行状态,确认所有服务 healthy
docker compose ps启动后可访问以下地址:
| 服务 | 地址 | 说明 |
|---|---|---|
| 前端界面 | http://localhost:3001 | Next.js 16 生产模式 |
| FastAPI 文档 | http://localhost:8000/docs | Swagger UI |
| 健康检查 | http://localhost:8000/api/health | {"status":"ok"} |
| Prometheus 指标 | http://localhost:8000/api/metrics | 文本格式 (Prometheus 抓取) |
| Prometheus UI | http://localhost:9090 | 指标查询 + 告警状态 |
| Grafana 仪表盘 | http://localhost:3002 | 登录 admin/admin → 可用性监控面板 |
容器端口映射:
| 服务 | 容器内 | 宿主机 | 说明 |
|---|---|---|---|
search-backend |
8000 | 8000 | FastAPI + uvicorn,SSE 流式聊天 |
search-frontend |
3000 | 3001 | Next.js 16 生产模式 (standalone) |
search-prometheus |
9090 | 9090 | 指标存储与查询 |
search-grafana |
3000 | 3002 | 可视化仪表盘 (admin/admin) |
常用操作:
# 查看日志
docker compose logs -f backend # 后端实时日志
docker compose logs -f frontend # 前端实时日志
docker compose logs --tail=50 backend # 后端最近 50 行
# 重启单个服务
docker compose restart backend
# 停止所有服务
docker compose down
# 完全重建(代码修改后)
docker compose down
docker compose build --no-cache
docker compose up -d
# 进入容器调试
docker exec -it search-backend bash
docker exec -it search-frontend sh镜像说明:
| 文件 | 基础镜像 | 用途 |
|---|---|---|
Dockerfile.backend |
python:3.12-slim |
安装 pip 依赖 → 启动 uvicorn |
Dockerfile.frontend |
多阶段 node:22-alpine |
npm build → 生产 runner 启动 next start |
docker-compose.yml |
— | 4 服务编排 + bridge 网络 + 健康检查 |
Windows 用户: 如遇到 Docker Desktop gRPC 问题,可直接运行:
.\fix-and-start.ps1该脚本自动检测 Docker 状态、清理旧资源、禁用 BuildKit 并启动服务。
pip install -r requirements.txt在 .env 文件中填入 API Key。本项目使用 OpenAI 兼容协议,支持多平台:
| LLM 提供商 | LLM_PROVIDER | LLM_API_BASE | 说明 |
|---|---|---|---|
| OpenAI | openai |
https://api.openai.com/v1 |
全功能 |
| 阿里云百炼 DashScope (通义千问) | qwen |
https://dashscope.aliyuncs.com/compatible-mode/v1 |
全功能 |
| DeepSeek | deepseek |
https://api.deepseek.com/v1 |
无 response_format / embedding 端点,自动降级 |
| 其他兼容代理 (OneAPI/LiteLLM) | — | 自定义 | 手动指定 LLM_API_BASE + LLM_MODEL |
# 必填
LLM_PROVIDER=qwen # 或 openai / deepseek
LLM_API_KEY=sk-xxx
TAVILY_API_KEY=tvly-xxx
# 可选 (以下为默认值)
LLM_MODEL= # 留空则用 provider 默认模型
LLM_TEMPERATURE=0.3
TAVILY_API_BASE=https://api.tavily.com# FastAPI 开发服务器 (port 8000)
uvicorn server:app --reload --port 8000
# 或直接运行
python server.pyNext.js 生产前端:
cd frontend
npm install
npm run dev
# → http://localhost:3000Streamlit 开发面板:
streamlit run app.py
# → http://localhost:8501# 全部测试 (131 条)
pytest tests/ -v
# 按模块运行
pytest tests/test_core.py -v # 单元测试 (33 条)
pytest tests/test_registry.py -v # 工具注册中心 (31 条)
pytest tests/test_graph.py -v # ReactAgent + SearchAgent (19 条)
pytest tests/test_config.py -v # 配置加载 (18 条)
pytest tests/test_production.py -v # 护栏/压缩/provider (20 条)
pytest tests/test_e2e.py -v # 端到端 (10 条)
# 行为评估 (30 用例, 80 断言)
python -m evals.evaluate # 运行全部评估
python -m evals.evaluate -r html # 生成 HTML 报告
python -m evals.evaluate -c happy_path # 按类别运行
python -m evals.evaluate --case happy-001 # 单条用例
python -m evals.benchmark # 延迟 & Token 对比摘要
python -m evals.benchmark --html # 生成 HTML 基准报告
python -m evals.benchmark --json # 输出 JSON 格式| 端点 | 方法 | 描述 |
|---|---|---|
/api/chat/stream |
POST | SSE 流式聊天 (query, session_id, model, search_depth, top_k) |
/api/session/{id} |
GET | 获取会话历史 |
/api/session/{id} |
DELETE | 清除会话 |
/api/config/defaults |
GET | 获取默认配置 (model, search_depth, top_k, llm_api_base) |
/api/health |
GET | 健康检查 (status, active_sessions) |
/api/metrics |
GET | Prometheus 文本格式指标 |
/api/metrics?format=json |
GET | JSON 格式完整统计 (含可用性 + 指标快照) |
/api/metrics?format=availability |
GET | JSON 格式可用性统计 (仅 SLA) |
event: progress → {"node":"search|generate|fallback|score","message":"..."}
event: token → {"text":"逐token文本"}
event: sources → {"sources":[{url,title,snippet}]}
event: done → {confidence,latency_ms,tokens_used,is_fallback}
event: error → {message,code}
说明: ReAct 范式中不再有独立的
rewrite节点(查询改写已并入模型推理),progress.node以search/generate/fallback为主。
项目内置生产级安全护栏(utils/guardrails.py):
| 护栏 | 机制 | 触发行为 |
|---|---|---|
| 提示注入检测 | 正则匹配「忽略指令/扮演角色/泄露系统提示/绕过限制」等模式 | 阻断请求,返回拒绝提示 |
| 敏感信息脱敏 | API Key / 邮箱 / 手机号 / 身份证 / AWS Key 模式匹配 | 日志与输出中自动掩码为 *** |
| 工具调用护栏 | 工具白名单 + query 非空/长度校验 | 越权工具或非法参数被阻断 |
| 输出护栏 | 检测回答中的可疑指令回显 | 软标记供上游决定 |
ReAct Agent 按需加载以下工具(每个工具的 docstring 即 JSON Schema 边界契约):
| 工具 | 类别 | 职责 |
|---|---|---|
search |
实时检索 | Tavily 联网搜索,返回去重排序的摘要 + 结构化来源 |
knowledge_search |
知识库 | 本地 RAG 检索(混合检索 + 时效过滤),返回知识片段 |
calculator |
计算 | 安全算术求值(AST 白名单,杜绝任意代码执行) |
current_time |
时间 | 获取当前 UTC 时间 |
底层仍保留 tools/registry.py 中的 tavily_search / rewrite_query / score_relevance / fallback_answer 四个基础函数(供组合流水线与测试复用)。
项目采用分层测试策略,131 条测试 + 30 条评估用例(80 断言)全部 mock 外部 API,无需联网即可运行。
| 测试类 | 覆盖内容 |
|---|---|
TestURLDeduplicator / TestTokenCounting / TestContentFingerprint / TestRateLimiter / TestContextTrimming / TestFormatSearchContext / TestSessionStore / TestModels |
URL 去重、Token 计数、内容指纹、限流、上下文裁剪、会话存储、数据模型 |
TestAPIConfig / TestAgentConfig / TestSingletonFunctions / TestConfigCompleteness / TestProjectRoot |
环境变量加载、SecretStr 安全、默认值、单例、字段完整性 |
TestPromptInjection / TestRedaction / TestToolGuardrail |
提示注入检测、敏感脱敏、工具护栏 |
TestContextCompression |
分层历史压缩、工具结果裁剪 |
TestProviderConfig |
多平台 provider 预设与能力探测 |
| 测试类 | 覆盖内容 |
|---|---|
TestTavilySearch / TestRewriteQuery / TestScoreRelevance / TestFallbackAnswer / TestSearchAndFilterPipeline / TestToolRegistryMetadata |
工具函数与组合流水线(签名保持稳定) |
TestReactAgentHelpers / TestReactAgentRun / TestSearchAgentClass / TestReactSystemPrompt |
ReAct 循环、结果提取、会话管理、系统提示 |
| 测试类 | 覆盖路径 |
|---|---|
TestAgentPipelineE2E |
ReAct 正常流程 / 搜索失败→降级 / 生成失败→二次降级 / 多轮对话 / 历史裁剪 |
TestSessionManagement |
自动 session + 清除会话 |
TestResultValidation |
来源去重 + 延迟记录 + 流式输出契约 |
| 类别 | 用例 | 覆盖场景 |
|---|---|---|
happy_path |
6 | 正常 ReAct 流程 (事实/对比/教程/新闻) |
degradation |
2 | 降级路径 (空答案→降级 / 图异常→二次降级) |
tool_behavior |
6 | 工具行为 (搜索/改写/打分/降级/流水线) |
multi_turn |
4 | 多轮对话 (历史累积/裁剪/清除) |
state_integrity |
2 | 状态完整性 (AgentState 键/GeneratedAnswer 字段) |
edge_case |
5 | 边缘情况 (空查询/问候/超长/emoji) |
guardrails |
3 | 护栏 (注入检测/正常放行/脱敏) |
rag |
1 | RAG 检索质量 (相关性排序) |
provider |
1 | 多平台能力探测 (DeepSeek 差异) |
| 故障类型 | 恢复策略 |
|---|---|
| 搜索 API 超时 | 异步指数退避重试 3 次 → LLM 降级回答 |
| 查询改写失败 (JSON 解析/网络异常) | 回退到原始用户输入 |
| 相关性打分失败 | 使用 Tavily 原始分数 (已默认跳过 LLM 打分) |
| LLM API 故障 | 友好错误提示 + 二次降级 |
| 提示注入 | 请求级阻断,返回拒绝提示 |
| 配额耗尽 | 滑动窗口限流,提前拦截 |
| ReAct 死循环 | recursion_limit 递归上限 + max_react_iterations 迭代上限 |
- 正常期可用性: ≈100%
- 异常期可用性: 95%+ (Grafana 实时监控)
- ReAct 自主决策: LLM 按需加载工具,避免固定流水线的冗余调用
- 上下文压缩: 分层历史摘要 + 前缀稳定化,降低跨轮 token 与 KV 占用
- 连接池复用: 消除每次 HTTP 调用的 TCP/TLS 握手开销
- 实时新闻: "今天有什么重大新闻?"
- 股价查询: "苹果公司现在的股价是多少?"
- 热点事件: "最近发生的 AI 领域大事件有哪些?"
- 对比分析: "GPT-4 和 Claude 哪个更强?"
- 教程指南: "最新的 Python 3.13 有哪些新特性?"
- 内部知识: "公司的报销流程是什么?"(走 RAG 知识库)
MIT


