# ai-agent **Repository Path**: Le2hanG/ai-agent ## Basic Information - **Project Name**: ai-agent - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-04-24 - **Last Updated**: 2026-04-24 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 🤖 AI Agent 项目:从 RAG 到多 Agent 协作系统 > 这是我在学习 AI Agent 相关知识时,结合 AI 辅助开发完成的实战项目。 > 项目从零开始,分三个阶段递进式构建,最终实现一个能够联网搜索、查询知识库、执行代码、多 Agent 协同工作的完整 AI 系统。 > > **开发者背景:** 武汉大学软件工程本科生,Web 全栈开发经验(JS/TS 为主),Python 基础,正在学习 AI Agent 开发,目标冲刺深圳 AI Agent 方向实习。 --- ## 📖 项目是什么?能做什么? 这个项目是一个网页应用,左侧有三个导航按钮,对应三个功能页面: **📚 RAG 知识库问答(页面一)** 上传你自己的 PDF 文档,然后用自然语言提问,AI 会严格基于你上传的文档内容回答,并标注答案来自哪个文档的第几页。适合用来"问文档",比如上传公司规章制度、学术论文、产品手册后进行精准问答。 **🤖 多工具 Agent(页面二)** 一个能自主决策的 AI 助手。它可以联网搜索最新资讯、查询你上传的知识库、执行 Python 代码做计算,并且会把思考过程(调用了哪些工具、查到了什么)展示给你看。适合复杂的开放性问题。 **👥 多 Agent 协作(页面三)** 输入一个复杂任务(比如"分析新能源汽车行业现状"),系统会自动调度五个专职 AI:协调者拆解任务,研究员收集资料,分析师深度分析,撰写者写出报告,审核者把关质量。你可以实时看到每个 AI 的工作进度。 --- ## 🗂 项目结构总览 ``` ai-agent/ ├── .env # 存放 API Key 等敏感配置(不提交到 git) ├── .env.example # 配置文件模板,告诉你需要填哪些内容 ├── .gitignore # 告诉 git 哪些文件不需要提交 │ ├── backend/ # 后端:Python 程序,处理 AI 逻辑 │ ├── main.py # 后端入口文件,把所有功能模块组装在一起 │ ├── requirements.txt # Python 依赖包清单 │ ├── venv/ # Python 虚拟环境(不提交 git) │ ├── data/chroma/ # 向量数据库存储目录(自动生成) │ ├── uploads/ # 上传的 PDF 文件存储目录(自动生成) │ │ │ ├── core/ │ │ └── config.py # 读取 .env 配置文件,将配置项暴露给其他模块 │ │ │ ├── phase1_rag/ # 阶段一:RAG 知识库功能 │ │ ├── router.py # 定义 /rag/* 相关的网络接口 │ │ ├── ingest.py # 处理 PDF 上传:提取文字、切割、转向量、存库 │ │ ├── retriever.py # 根据问题检索最相关的文档片段 │ │ └── chat.py # 将检索结果和问题组合,调用 AI 生成答案 │ │ │ ├── phase2_agent/ # 阶段二:多工具 Agent 功能 │ │ ├── __init__.py # Python 包标识文件(空文件) │ │ ├── router.py # 定义 /agent/* 相关的网络接口 │ │ ├── graph.py # Agent 核心:LangGraph 编排 AI 思考和工具调用循环 │ │ └── tools/ │ │ ├── __init__.py # Python 包标识文件(空文件) │ │ ├── search.py # 联网搜索工具(调用 Tavily API) │ │ ├── rag_tool.py # 知识库查询工具(复用阶段一的检索逻辑) │ │ └── code_runner.py # Python 代码执行工具(在沙箱中运行代码) │ │ │ └── phase3_multi_agent/ # 阶段三:多 Agent 协作功能 │ ├── __init__.py # Python 包标识文件(空文件) │ ├── router.py # 定义 /multi/* 相关的网络接口 │ ├── state.py # 定义多个 Agent 之间共享的状态数据结构 │ ├── graph.py # 编排五个 Agent 的执行流程和流转逻辑 │ ├── orchestrator.py # 协调者 Agent:分析用户需求,制定工作计划 │ └── agents/ │ ├── __init__.py # Python 包标识文件(空文件) │ ├── researcher.py # 研究员 Agent:联网搜索 + 知识库检索,整合资料 │ ├── analyst.py # 分析师 Agent:深度分析,必要时执行代码计算 │ ├── writer.py # 撰写者 Agent:基于研究和分析撰写完整回答 │ └── reviewer.py # 审核者 Agent:质量把关,不合格则打回重写 │ └── frontend/ # 前端:React 网页,用户直接看到和操作的界面 ├── package.json # 前端依赖包清单和项目配置 ├── vite.config.ts # Vite 构建工具配置,含接口代理设置 ├── tsconfig.json # TypeScript 语言配置 ├── index.html # 网页入口 HTML 文件 └── src/ ├── main.tsx # React 应用启动入口 ├── App.tsx # 应用根组件:左侧图标导航 + 路由配置 ├── index.css # 全局样式(Tailwind CSS 入口) ├── api/ │ ├── rag.ts # 封装阶段一的所有后端接口调用 │ ├── agent.ts # 封装阶段二的后端接口调用(流式) │ └── multi.ts # 封装阶段三的后端接口调用(流式) ├── types/ │ └── index.ts # TypeScript 类型定义(数据结构约定) ├── pages/ │ ├── ChatPage.tsx # 页面一:RAG 知识库问答页面 │ ├── AgentPage.tsx # 页面二:多工具 Agent 页面 │ └── MultiPage.tsx # 页面三:多 Agent 协作页面 └── components/ ├── FileUpload.tsx # 组件:PDF 拖拽上传框 ├── DocList.tsx # 组件:已上传文档列表(支持选择和删除) ├── ChatWindow.tsx # 组件:对话窗口(流式打字机效果) ├── SourceCard.tsx # 组件:来源引用卡片(文档名+页码+相似度,可折叠) └── ThinkingSteps.tsx # 组件:Agent 思考步骤展示(工具调用过程,可折叠) ``` --- ## 🔧 技术栈详解 ### 后端技术 | 技术 | 是什么 | 在项目里做什么 | |------|--------|---------------| | **Python** | 编程语言 | 整个后端的开发语言 | | **FastAPI** | Python Web 框架 | 提供网络接口(API),让前端能发请求过来 | | **uvicorn** | 服务器程序 | 运行 FastAPI 应用的服务器 | | **DeepSeek API** | AI 大语言模型服务 | 提供 AI 对话能力,兼容 OpenAI 接口格式 | | **openai SDK** | Python 库 | 用来调用 DeepSeek API(DeepSeek 兼容此格式) | | **LangChain** | AI 开发框架 | 提供 `@tool` 装饰器等工具,简化 Agent 开发 | | **LangGraph** | Agent 流程编排框架 | 用图(Graph)的方式定义 Agent 的思考和执行流程 | | **sentence-transformers** | 本地 AI 模型库 | 将文字转换成向量数字(用于相似度检索) | | **ChromaDB** | 向量数据库 | 存储文档向量,支持语义相似度搜索 | | **PyMuPDF** | PDF 处理库 | 从 PDF 文件中提取纯文字内容 | | **Tavily** | 联网搜索服务 | 提供实时网络搜索能力(每月免费 1000 次) | | **python-dotenv** | 配置读取库 | 从 `.env` 文件读取 API Key 等配置 | | **pydantic** | 数据验证库 | 验证和定义 API 接口的请求/响应数据格式 | | **httpx** | HTTP 客户端库 | 发送 HTTP 请求(固定 0.27.0 版本避免冲突) | ### 前端技术 | 技术 | 是什么 | 在项目里做什么 | |------|--------|---------------| | **React** | 前端 UI 框架 | 构建用户界面,组件化开发 | | **TypeScript** | JavaScript 的类型扩展 | 给 JS 加上类型检查,减少低级错误 | | **Vite** | 前端构建工具 | 开发服务器和项目打包工具,速度极快 | | **Tailwind CSS v4** | CSS 样式框架 | 用工具类名直接写样式,无需单独写 CSS 文件 | | **react-router-dom** | 前端路由库 | 实现多页面切换(左侧三个导航按钮) | | **axios** | HTTP 请求库 | 发送普通的 HTTP 请求(上传文件、查列表等) | | **lucide-react** | 图标库 | 提供项目中用到的所有图标(搜索、上传等) | | **原生 fetch API** | 浏览器内置功能 | 处理流式响应(SSE),接收 AI 逐字输出 | --- ## 🧠 核心概念简介 ### 什么是 RAG? RAG(Retrieval-Augmented Generation,检索增强生成)是让 AI 回答问题时先去"翻资料"的技术。普通 AI 只能用训练时学到的知识回答,RAG 让 AI 能先搜索你提供的文档,再基于搜到的内容回答,所以答案更准确、有出处。 ### 什么是向量/Embedding? 把文字变成一串数字(向量),相似含义的文字会变成"距离相近"的数字。这样就能用数学方法找到"意思最相近"的文档片段,而不仅仅是关键词匹配。 ### 什么是 Agent? 让 AI 不只是"回答问题",而是能"使用工具、自主决策、完成任务"。Agent 会自己判断:我需要搜网络吗?需要查文档吗?需要算一下吗?然后自己去做,做完再继续思考下一步。 ### 什么是 SSE(流式输出)? Server-Sent Events,服务器持续推送数据到浏览器。AI 生成文字时不是等全部生成完再一次性返回,而是生成一个字就推送一个字,前端实时显示,就是"打字机效果"的实现原理。 ### 什么是 LangGraph? 把 Agent 的执行流程画成一张"图"(有节点、有边、有条件判断)。阶段二用它实现 ReAct 循环(思考→调用工具→看结果→再思考),阶段三用它编排五个 Agent 的先后顺序和条件跳转(审核不通过就打回重写)。 --- ## 🚀 如何运行项目 ### 前置条件 - Python 3.11 或更高版本 - Node.js 18 或更高版本 - 一个 DeepSeek API Key(在 [platform.deepseek.com](https://platform.deepseek.com) 免费注册) - 一个 Tavily API Key(在 [tavily.com](https://tavily.com) 免费注册,每月 1000 次免费) ### 第一步:配置环境变量 在项目根目录创建 `.env` 文件(复制 `.env.example` 然后填入你的 Key): ``` DEEPSEEK_API_KEY=你的DeepSeek API Key DEEPSEEK_BASE_URL=https://api.deepseek.com DEEPSEEK_MODEL=deepseek-chat TAVILY_API_KEY=你的Tavily API Key CHROMA_PERSIST_DIR=./data/chroma UPLOAD_DIR=./uploads ``` ### 第二步:安装后端依赖 ```powershell # 进入后端目录 cd backend # 创建虚拟环境(只需要做一次) python -m venv venv # 激活虚拟环境(Windows) venv\Scripts\activate # 安装依赖包 pip install -r requirements.txt ``` ### 第三步:安装前端依赖 ```powershell # 新开一个终端,进入前端目录 cd frontend # 安装依赖包(只需要做一次) npm install ``` ### 第四步:启动项目 需要同时开两个终端: **终端一(后端):** ```powershell cd backend venv\Scripts\activate uvicorn main:app --reload ``` 启动成功后访问 http://localhost:8000/docs 可以看到接口文档。 **终端二(前端):** ```powershell cd frontend npm run dev ``` 启动成功后访问 http://localhost:5173 即可使用。 --- ## 🔄 三个阶段的运行流程详解 ### 阶段一:RAG 知识库问答 ``` 【上传文档】 用户拖拽 PDF 到上传框 → 前端用 axios 发送到 POST /rag/upload → ingest.py 用 PyMuPDF 逐页提取文字 → 按 500 字符切割成小片段(chunk) → sentence-transformers 将每个 chunk 转成 384 维向量 → 向量 + 原文 + 元数据(文档名、页码)一起存入 ChromaDB 【提问】 用户输入问题,按回车 → 前端用 fetch 发送到 POST /rag/chat/stream → retriever.py 将问题也转成向量 → 在 ChromaDB 中计算余弦相似度,找出最相关的 5 个 chunk → chat.py 将这 5 个 chunk + 用户问题拼成 Prompt → 调用 DeepSeek API 流式生成答案 → 通过 SSE 逐字推送给前端(打字机效果) → 同时返回来源信息(文档名 + 页码 + 相似度分数) ``` ### 阶段二:多工具 Agent ``` 用户输入任务(如"帮我查一下今天的 A 股行情") → 前端用 fetch 发送到 POST /agent/run → graph.py 启动 LangGraph ReAct Agent 【ReAct 循环开始】 → LLM 思考:我需要联网搜索 → 调用 web_search 工具 → Tavily 搜索返回结果 → SSE 推送 tool_start 和 tool_end 事件给前端(前端显示思考步骤) → LLM 再思考:够了,我可以回答了 → 生成最终答案,SSE 逐字推送给前端 【ReAct 循环结束】 三个可用工具: - web_search:调用 Tavily 搜索互联网 - knowledge_base_search:查询 ChromaDB 中的本地文档 - python_runner:用 exec() 执行 Python 代码,返回输出结果 ``` ### 阶段三:多 Agent 协作 ``` 用户输入复杂任务(如"分析人工智能在教育领域的应用现状") → 前端用 fetch 发送到 POST /multi/run → router.py 生成唯一任务 ID,初始化 LangGraph StateGraph 【五个 Agent 依次执行,共享同一份状态数据】 1. 🎯 协调者(orchestrator) → 分析用户需求,制定研究计划(研究什么、分析什么、交付什么) → SSE 推送 agent_update 事件(前端显示协调者卡片) 2. 🔍 研究员(researcher) → 并发调用:联网搜索(Tavily)+ 知识库检索(ChromaDB) → LLM 整合两路结果,输出结构化研究摘要 → SSE 推送 agent_update 事件 3. 📊 分析师(analyst) → 基于研究摘要进行深度分析 → 如需计算,自动生成并执行 Python 代码 → SSE 推送 agent_update 事件 4. ✍️ 撰写者(writer) → 整合研究 + 分析结果,撰写完整回答 → 如有审核反馈,针对性修改 → SSE 推送 agent_update + draft 事件 5. ✅ 审核者(reviewer) → 判断内容是否充分回答了用户需求 → PASS:输出最终结果,SSE 推送 final 事件 → REVISE:将修改意见写入共享状态,流程回到撰写者重写 → 最多重写 2 次,避免死循环 ``` --- ## 📡 接口文档 ### 阶段一接口(/rag) | 方法 | 路径 | 说明 | |------|------|------| | POST | `/rag/upload` | 上传 PDF 文件,触发向量化入库 | | GET | `/rag/docs` | 获取已上传的文档列表 | | DELETE | `/rag/docs/{doc_id}` | 删除指定文档及其所有向量数据 | | POST | `/rag/chat` | 非流式问答(一次性返回完整答案) | | POST | `/rag/chat/stream` | 流式问答(SSE,逐字返回) | ### 阶段二接口(/agent) | 方法 | 路径 | 说明 | |------|------|------| | POST | `/agent/run` | 提交任务,SSE 流式返回思考步骤和答案 | ### 阶段三接口(/multi) | 方法 | 路径 | 说明 | |------|------|------| | POST | `/multi/run` | 提交任务,SSE 流式返回各 Agent 状态和最终结果 | ### SSE 事件格式 **阶段一流式问答:** ``` data: 答案文字片段 data: [DONE] ``` **阶段二 Agent:** ```json {"type": "text", "content": "正在生成的文字片段"} {"type": "tool_start", "tool": "web_search", "input": "查询内容"} {"type": "tool_end", "tool": "web_search", "output": "搜索结果"} {"type": "error", "content": "错误信息"} ``` **阶段三多 Agent:** ```json {"type": "agent_update", "agent": "researcher", "status": "done", "output": "研究摘要内容"} {"type": "draft", "content": "撰写者的草稿内容"} {"type": "final", "content": "审核通过的最终内容"} {"type": "error", "content": "错误信息"} ``` --- ## 📦 依赖包说明 ### 后端 requirements.txt ``` # Web 框架 fastapi # 构建 API 接口的框架,自动生成接口文档 uvicorn # 运行 FastAPI 的 ASGI 服务器 python-multipart # 支持文件上传(处理 multipart/form-data 请求) # AI 调用 openai==1.30.0 # 调用 AI API 的客户端(DeepSeek 兼容此格式,必须固定此版本) httpx==0.27.0 # openai SDK 的底层 HTTP 库(必须固定此版本,高版本有参数冲突) # RAG 相关 chromadb # 向量数据库,存储和检索文档向量 pymupdf # PDF 文字提取库(import 时用 fitz) sentence-transformers # 本地 Embedding 模型,将文字转向量 # Agent 相关 langchain # AI Agent 开发框架,提供工具定义等功能 langchain-openai # LangChain 对 OpenAI 格式 API 的适配 langgraph # Agent 流程编排,用图定义执行流程 tavily-python # Tavily 搜索 API 的 Python 客户端 # 工具类 pydantic # 数据验证,定义请求/响应的数据结构 python-dotenv # 从 .env 文件读取配置变量 ``` ### 前端主要依赖(package.json) ``` react / react-dom # React 核心库,构建 UI 组件 typescript # JavaScript 的类型扩展 vite # 前端开发服务器和构建工具 @vitejs/plugin-react # Vite 的 React 支持插件 @tailwindcss/vite # Tailwind CSS v4 的 Vite 插件(无需额外配置) react-router-dom # 前端路由,实现多页面切换 axios # 发送普通 HTTP 请求(上传、查列表、删除) lucide-react # React 图标组件库 ``` --- ## ⚠️ 开发踩坑记录 这里记录了开发过程中遇到的关键问题,供参考: 1. **openai + httpx 版本冲突**:openai 必须固定 `1.30.0`,httpx 必须固定 `0.27.0`,高版本 httpx 的 `proxies` 参数被移除,会报冲突错误。 2. **LangGraph 升级连锁反应**:安装 langgraph 会自动升级 langchain-core 到新版,需要同步执行 `pip install --upgrade langchain langchain-openai langsmith`,否则会有版本不兼容警告。 3. **retriever 返回字段名**:`retriever.py` 返回的字典中文本字段是 `text`,不是 `content`,在 `rag_tool.py` 中取值必须用 `chunk['text']`。 4. **config.py 导入方式**:配置变量直接导出(没有 `settings` 对象),正确导入方式是 `from core.config import DEEPSEEK_API_KEY`,不是 `from core.config import settings`。 5. **Tailwind CSS v4 配置方式**:v4 不需要 `npx tailwindcss init -p`,不需要 `postcss.config.js`,只需安装 `@tailwindcss/vite`,在 `index.css` 中写 `@import "tailwindcss"` 即可。 6. **前端流式请求用 fetch 不用 EventSource**:EventSource 只支持 GET 请求,无法发送请求体,所以流式接口用原生 `fetch` + `ReadableStream` 实现。 7. **LangGraph checkpointer 需要 thread_id**:使用 `MemorySaver` 时,`graph.astream()` 必须传入 `config={"configurable": {"thread_id": "唯一ID"}}`,否则报错。 --- ## 🔑 获取 API Key **DeepSeek API Key:** 1. 访问 [platform.deepseek.com](https://platform.deepseek.com) 2. 注册账号,进入控制台 3. 创建 API Key,复制填入 `.env` **Tavily API Key:** 1. 访问 [app.tavily.com](https://app.tavily.com) 2. 注册账号(支持 Google 登录) 3. 直接在首页复制 API Key,每月免费 1000 次搜索 --- ## 🔗 参考资源 - [DeepSeek API 文档](https://platform.deepseek.com/api-docs/) - [FastAPI 文档](https://fastapi.tiangolo.com/) - [LangChain 文档](https://python.langchain.com/docs/) - [LangGraph 文档](https://langchain-ai.github.io/langgraph/) - [ChromaDB 文档](https://docs.trychroma.com/) - [sentence-transformers 文档](https://www.sbert.net/) - [Tavily 搜索 API](https://tavily.com/) - [Tailwind CSS v4 文档](https://tailwindcss.com/docs) - [react-router-dom 文档](https://reactrouter.com/) --- ## 📝 .env.example ``` DEEPSEEK_API_KEY=your_deepseek_api_key_here DEEPSEEK_BASE_URL=https://api.deepseek.com DEEPSEEK_MODEL=deepseek-chat TAVILY_API_KEY=your_tavily_api_key_here CHROMA_PERSIST_DIR=./data/chroma UPLOAD_DIR=./uploads ``` --- ## 🚫 .gitignore ``` .env __pycache__/ *.pyc venv/ .venv/ backend/data/ backend/uploads/ node_modules/ dist/ .vscode/settings.json .idea/ ```