update
Browse files- .clinerules +1 -1
- .gitignore +2 -0
- __pycache__/app.cpython-312.pyc +0 -0
- __pycache__/app.cpython-39.pyc +0 -0
- __pycache__/test_app.cpython-312-pytest-8.4.1.pyc +0 -0
- app.py +56 -4
- docs/项目需求.md +40 -0
- memory-bank/activeContext.md +22 -13
- memory-bank/productContext.md +13 -9
- memory-bank/progress.md +21 -13
- memory-bank/projectbrief.md +21 -14
- memory-bank/systemPatterns.md +42 -11
- memory-bank/techContext.md +26 -21
- requirements.txt +7 -1
- test_app.py +28 -0
.clinerules
CHANGED
|
@@ -12,7 +12,7 @@ CUSTOM_INSTRUCTIONS = """
|
|
| 12 |
- 采用逐步迭代模式开发
|
| 13 |
|
| 14 |
# 知识参考
|
| 15 |
-
-
|
| 16 |
|
| 17 |
"""
|
| 18 |
|
|
|
|
| 12 |
- 采用逐步迭代模式开发
|
| 13 |
|
| 14 |
# 知识参考
|
| 15 |
+
- qwen-agent 的源码仓库:https://github.com/QwenLM/Qwen-Agent
|
| 16 |
|
| 17 |
"""
|
| 18 |
|
.gitignore
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
.env
|
| 2 |
+
.DS_Store
|
__pycache__/app.cpython-312.pyc
ADDED
|
Binary file (2.79 kB). View file
|
|
|
__pycache__/app.cpython-39.pyc
CHANGED
|
Binary files a/__pycache__/app.cpython-39.pyc and b/__pycache__/app.cpython-39.pyc differ
|
|
|
__pycache__/test_app.cpython-312-pytest-8.4.1.pyc
ADDED
|
Binary file (5.6 kB). View file
|
|
|
app.py
CHANGED
|
@@ -1,9 +1,61 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
from fastapi import FastAPI
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4 |
|
| 5 |
app = FastAPI()
|
| 6 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7 |
@app.get("/")
|
| 8 |
-
def
|
| 9 |
-
return {"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
from dotenv import load_dotenv
|
| 3 |
from fastapi import FastAPI
|
| 4 |
+
from fastapi.responses import JSONResponse
|
| 5 |
+
from qwen_agent.agents import Assistant
|
| 6 |
+
|
| 7 |
+
# Load environment variables from .env file
|
| 8 |
+
load_dotenv()
|
| 9 |
+
|
| 10 |
+
# Get API key from environment variables
|
| 11 |
+
api_key = os.getenv("API_KEY")
|
| 12 |
+
if not api_key:
|
| 13 |
+
raise ValueError("API_KEY environment variable not set.")
|
| 14 |
|
| 15 |
app = FastAPI()
|
| 16 |
|
| 17 |
+
class MainAgent:
|
| 18 |
+
def __init__(self):
|
| 19 |
+
# Initialize Qwen-Agent here
|
| 20 |
+
# For demonstration, we'll use a simple AssistantAgent
|
| 21 |
+
self.agent = Assistant(
|
| 22 |
+
llm=dict(model='gemini-2.5-flash-preview-05-20', model_server='https://gmn.ainet.ltd/v1', api_key=api_key), # Use OpenAI compatible API
|
| 23 |
+
name='assistant',
|
| 24 |
+
description='A helpful assistant agent.'
|
| 25 |
+
)
|
| 26 |
+
|
| 27 |
+
def process_query(self, query: str):
|
| 28 |
+
# Process the query using the agent
|
| 29 |
+
# Wrap the query into the expected messages format for qwen-agent
|
| 30 |
+
messages = [{'role': 'user', 'content': query}]
|
| 31 |
+
print('messages:', messages)
|
| 32 |
+
final_response_content = "" # 用于存储最终的响应内容
|
| 33 |
+
for response_item in self.agent.run(messages=messages):
|
| 34 |
+
print('response_item:', response_item) # Added for debugging
|
| 35 |
+
# qwen-agent's run method yields a list of dicts, or sometimes a single dict
|
| 36 |
+
if isinstance(response_item, list):
|
| 37 |
+
for chunk in response_item:
|
| 38 |
+
if isinstance(chunk, dict) and 'content' in chunk:
|
| 39 |
+
# 每次都更新为最新的完整内容
|
| 40 |
+
final_response_content = chunk['content']
|
| 41 |
+
elif isinstance(response_item, dict) and 'content' in response_item:
|
| 42 |
+
# 每次都更新为最新的完整内容
|
| 43 |
+
final_response_content = response_item['content']
|
| 44 |
+
# 暂时不处理其他类型的 response_item,例如 tool_calls,因为当前目标是获取文本响应
|
| 45 |
+
return final_response_content # 返回最终的完整内容
|
| 46 |
+
|
| 47 |
+
main_agent = MainAgent()
|
| 48 |
+
|
| 49 |
@app.get("/")
|
| 50 |
+
async def read_root():
|
| 51 |
+
return {"message": "Hello, FastAPI!"}
|
| 52 |
+
|
| 53 |
+
@app.post("/agent_chat")
|
| 54 |
+
async def agent_chat(query: dict):
|
| 55 |
+
user_query = query.get("query")
|
| 56 |
+
print(f"Received query: {user_query}")
|
| 57 |
+
if not user_query:
|
| 58 |
+
return JSONResponse(content={"error": "Query parameter is missing"}, status_code=400)
|
| 59 |
+
|
| 60 |
+
agent_response = main_agent.process_query(user_query)
|
| 61 |
+
return {"response": agent_response}
|
docs/项目需求.md
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 项目需求
|
| 2 |
+
|
| 3 |
+
## 阶段一:实现基本的 FastAPI 应用
|
| 4 |
+
|
| 5 |
+
### 目标
|
| 6 |
+
* 创建一个基于 FastAPI 的 Web 应用,能够响应 HTTP 请求。
|
| 7 |
+
* 确保应用能够与现有的 `Dockerfile` 文件兼容,无需修改 `Dockerfile`。
|
| 8 |
+
|
| 9 |
+
### 具体实现
|
| 10 |
+
1. **`requirements.txt` 文件**:
|
| 11 |
+
* 在项目根目录下创建或更新 `requirements.txt` 文件。
|
| 12 |
+
* 文件内容必须包含 `fastapi` 和 `uvicorn` 库,以便 Docker 镜像能够正确安装和运行 FastAPI 应用。
|
| 13 |
+
```
|
| 14 |
+
fastapi
|
| 15 |
+
uvicorn
|
| 16 |
+
```
|
| 17 |
+
2. **`app.py` 文件**:
|
| 18 |
+
* 在项目根目录下创建 `app.py` 文件。
|
| 19 |
+
* 在该文件中,初始化一个 FastAPI 应用实例,并将其命名为 `app`,以匹配 `Dockerfile` 中 `CMD ["uvicorn", "app:app", ...]` 的启动命令。
|
| 20 |
+
* 实现一个基本的 GET 路由(例如 `/`),当访问该路由时,返回一个简单的 JSON 响应,例如 `{"message": "Hello, FastAPI!"}`,用于验证应用是否正常运行。
|
| 21 |
+
|
| 22 |
+
## 阶段二:集成 Qwen-Agent
|
| 23 |
+
|
| 24 |
+
### 目标
|
| 25 |
+
* 在 FastAPI 应用中集成 `qwen-agent` 库。
|
| 26 |
+
* 定义并实例化一个 `MainAgent` 类,用于封装 `qwen-agent` 的核心逻辑。
|
| 27 |
+
|
| 28 |
+
### 具体实现
|
| 29 |
+
1. **更新 `requirements.txt` 文件**:
|
| 30 |
+
* 在 `requirements.txt` 中添加 `qwen-agent` 库。
|
| 31 |
+
```
|
| 32 |
+
fastapi
|
| 33 |
+
uvicorn
|
| 34 |
+
qwen-agent
|
| 35 |
+
```
|
| 36 |
+
2. **在 `app.py` 中定义和实例化 `MainAgent` 类**:
|
| 37 |
+
* 在 `app.py` 文件中,定义一个名为 `MainAgent` 的 Python 类。
|
| 38 |
+
* 该类应包含处理 `qwen-agent` 相关逻辑的方法。
|
| 39 |
+
* 在 `app.py` 中实例化 `MainAgent` 类。
|
| 40 |
+
* 考虑如何将 `MainAgent` 的功能暴露给 FastAPI 路由,例如,可以添加一个新的 POST 路由(例如 `/agent_chat`),接收用户输入,然后调用 `MainAgent` 的方法进行处理并返回结果。
|
memory-bank/activeContext.md
CHANGED
|
@@ -1,19 +1,28 @@
|
|
| 1 |
-
#
|
| 2 |
|
| 3 |
## 当前工作焦点
|
| 4 |
-
|
| 5 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6 |
|
| 7 |
## 下一步计划
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
- 准备Dockerfile和requirements.txt文件。
|
| 11 |
-
- 确认API功能需求。
|
| 12 |
|
| 13 |
-
##
|
| 14 |
-
|
| 15 |
-
-
|
|
|
|
| 16 |
|
| 17 |
-
##
|
| 18 |
-
|
| 19 |
-
-
|
|
|
|
| 1 |
+
# 当前上下文 (Active Context)
|
| 2 |
|
| 3 |
## 当前工作焦点
|
| 4 |
+
* FastAPI 应用与 Qwen-Agent 的集成和调试。
|
| 5 |
+
* 确保通过 OpenAI 兼容 API 成功访问 LLM。
|
| 6 |
+
* 解决 `uvicorn --reload` 模式下的环境问题。
|
| 7 |
+
* 解决 `qwen-agent` 响应流式处理的拼接问题。
|
| 8 |
+
|
| 9 |
+
## 最近的更改
|
| 10 |
+
* `app.py`:
|
| 11 |
+
* LLM 配置从 `qwen-max` 更改为 `gemini-2.5-flash-preview-05-20`,`model_server` 设置为 `https://gmn.ainet.ltd/v1`。
|
| 12 |
+
* API 密钥获取方式从硬编码更改为从 `.env` 文件中的 `API_KEY` 环境变量获取。
|
| 13 |
+
* `process_query` 方法的逻辑已调整,以正确处理 `qwen-agent` 的流式响应迭代器,确保最终返回完整且不重复的内容。
|
| 14 |
+
* `requirements.txt`:添加了 `python-dotenv` 依赖。
|
| 15 |
+
* `start.sh`:已删除,因为用户要求不使用 `conda` 运行。
|
| 16 |
|
| 17 |
## 下一步计划
|
| 18 |
+
* 总结项目记忆和文档。
|
| 19 |
+
* 等待用户进一步指示。
|
|
|
|
|
|
|
| 20 |
|
| 21 |
+
## 活跃决策和考虑
|
| 22 |
+
* **LLM API 密钥管理**:通过环境变量 `API_KEY` 进行管理,提高安全性。
|
| 23 |
+
* **`uvicorn` 运行方式**:直接使用 `python3.12 -m uvicorn` 运行,避免 `conda run` 带来的环境继承问题。
|
| 24 |
+
* **`qwen-agent` 响应处理**:已确认 `qwen-agent` 的 `run` 方法返回的是流式分块,并已在 `process_query` 中正确处理拼接逻辑,确保最终响应的正确性。
|
| 25 |
|
| 26 |
+
## 学习和项目洞察
|
| 27 |
+
* `uvicorn --reload` 在某些环境下与 `conda` 环境激活存在兼容性问题,直接使用特定 Python 版本运行 `uvicorn` 更可靠。
|
| 28 |
+
* `qwen-agent` 的 `run` 方法返回的迭代器,其 `response_item` 可能包含累积的 `content`,需要特殊处理以避免重复拼接。
|
memory-bank/productContext.md
CHANGED
|
@@ -1,14 +1,18 @@
|
|
| 1 |
-
# 产品背景 (
|
| 2 |
|
| 3 |
## 项目存在的意义
|
| 4 |
-
-
|
| 5 |
-
- **用户价值**:
|
| 6 |
|
| 7 |
-
##
|
| 8 |
-
|
| 9 |
-
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 10 |
|
| 11 |
## 用户体验目标
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
|
|
|
| 1 |
+
# 产品背景 (Product Context)
|
| 2 |
|
| 3 |
## 项目存在的意义
|
| 4 |
+
本项目旨在提供一个灵活且可扩展的后端服务,用于集成大型语言模型(LLM)能力到各种应用中。通过使用 FastAPI 和 Qwen-Agent,我们可以快速构建和部署智能对话、内容生成等 AI 驱动的功能。
|
|
|
|
| 5 |
|
| 6 |
+
## 解决的问题
|
| 7 |
+
* **LLM 集成复杂性**:简化将 LLM 集成到 Web 应用中的过程,抽象底层 API 调用和响应处理。
|
| 8 |
+
* **多模型兼容性**:通过 Qwen-Agent 的抽象层,支持多种 LLM 服务(特别是 OpenAI 兼容 API),方便未来切换或扩展模型。
|
| 9 |
+
* **开发效率**:利用 FastAPI 的高性能和易用性,以及 Qwen-Agent 的高级代理功能,加速 AI 应用的开发。
|
| 10 |
+
* **API 密钥管理**:通过环境变量安全地管理敏感信息,避免硬编码。
|
| 11 |
+
|
| 12 |
+
## 工作方式
|
| 13 |
+
用户通过 HTTP POST 请求向 `/agent_chat` 路由发送文本查询。FastAPI 应用接收到请求后,将查询传递给内部的 `MainAgent` 实例。`MainAgent` 使用配置好的 OpenAI 兼容 LLM 服务处理查询,并返回生成的响应。
|
| 14 |
|
| 15 |
## 用户体验目标
|
| 16 |
+
* **响应迅速**:API 响应时间尽可能短,提供流畅的交互体验。
|
| 17 |
+
* **易于集成**:提供清晰的 API 接口,方便前端或其他服务进行集成。
|
| 18 |
+
* **稳定可靠**:确保服务在高负载下也能稳定运行。
|
memory-bank/progress.md
CHANGED
|
@@ -1,23 +1,31 @@
|
|
| 1 |
-
#
|
| 2 |
|
| 3 |
## 已完成的工作
|
| 4 |
-
|
| 5 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6 |
|
| 7 |
## 待完成的工作
|
| 8 |
-
|
| 9 |
-
- 创建FastAPI应用的基础文件结构。
|
| 10 |
-
- 编写`requirements.txt`和`Dockerfile`。
|
| 11 |
-
- 实现API逻辑。
|
| 12 |
-
- 测试API功能。
|
| 13 |
-
- 部署到Hugging Face Space。
|
| 14 |
|
| 15 |
## 当前状态
|
| 16 |
-
-
|
| 17 |
-
|
|
|
|
| 18 |
|
| 19 |
## 已知问题
|
| 20 |
-
|
| 21 |
|
| 22 |
## 项目决策演变
|
| 23 |
-
-
|
|
|
|
|
|
| 1 |
+
# 项目进度 (Progress)
|
| 2 |
|
| 3 |
## 已完成的工作
|
| 4 |
+
* **FastAPI 应用基础搭建**:
|
| 5 |
+
* 创建了 `app.py` 文件,实现了基本的 FastAPI 应用结构,包括根路由 `/` 和代理聊天路由 `/agent_chat`。
|
| 6 |
+
* 创建了 `requirements.txt` 文件,包含了所有必要的 Python 依赖。
|
| 7 |
+
* **`qwen-agent` 集成与配置**:
|
| 8 |
+
* 在 `app.py` 中成功集成了 `qwen-agent`,并实例化了 `MainAgent` 类,其中使用了 `Assistant` 代理。
|
| 9 |
+
* `Assistant` 代理的 LLM 配置已更新为使用 OpenAI 兼容 API (`model='gemini-2.5-flash-preview-05-20'`, `model_server='https://gmn.ainet.ltd/v1'`)。
|
| 10 |
+
* API 密钥的获取方式已从硬编码更改为从 `.env` 文件中的 `API_KEY` 环境变量动态加载。
|
| 11 |
+
* **功能调试与验证**:
|
| 12 |
+
* 解决了 `uvicorn --reload` 模式下 `conda` 环境继承问题(通过移除 `conda run` 和 `start.sh` 脚本,并建议用户确保系统 Python 环境正确)。
|
| 13 |
+
* 修复了 `app.py` 中 `process_query` 方法处理 `qwen-agent` 流式响应迭代器的问题,确保最终返回完整且不重复的内容。
|
| 14 |
+
* 通过 `curl` 命令对 `/agent_chat` 路由进行了多次测试,最终确认应用能够成功与配置的 OpenAI 兼容大模型进行交互,并返回有效的响应。
|
| 15 |
+
* **单元测试**:`test_app.py` 中的所有单元测试均已通过,验证了 FastAPI 路由和代理集成的基本功能。
|
| 16 |
+
* **项目记忆文档创建**:已创建 `projectbrief.md`, `productContext.md`, `activeContext.md`, `systemPatterns.md`, `techContext.md`。
|
| 17 |
|
| 18 |
## 待完成的工作
|
| 19 |
+
* 目前没有明确的待完成工作,等待用户进一步指示。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 20 |
|
| 21 |
## 当前状态
|
| 22 |
+
* FastAPI 应用已成功运行,并能通过 `qwen-agent` 与 OpenAI 兼容的 LLM 进行交互。
|
| 23 |
+
* 响应内容已正确处理,不再出现重复拼接的问题。
|
| 24 |
+
* 项目记忆文档已初步建立。
|
| 25 |
|
| 26 |
## 已知问题
|
| 27 |
+
* 无。
|
| 28 |
|
| 29 |
## 项目决策演变
|
| 30 |
+
* 最初尝试使用 `conda run` 启动应用,但由于与 `uvicorn --reload` 的兼容性问题,改为直接使用 `python3.12 -m uvicorn`。
|
| 31 |
+
* 在处理 `qwen-agent` 的流式响应时,最初的拼接逻辑导致内容重复,后通过修改 `process_query` 方法,确保只保留最终的完整内容。
|
memory-bank/projectbrief.md
CHANGED
|
@@ -1,17 +1,24 @@
|
|
| 1 |
-
# 项目简报 (
|
| 2 |
|
| 3 |
-
##
|
| 4 |
-
-
|
| 5 |
-
- **项目目标**: 构建一个基于FastAPI的轻量级服务器接口,并部署到Hugging Face Space Docker环境。
|
| 6 |
-
- **项目范围**: 实现核心API功能,确保Docker部署流程顺畅。
|
| 7 |
|
| 8 |
-
##
|
| 9 |
-
-
|
| 10 |
-
- **主要框架/库**: FastAPI
|
| 11 |
-
- **数据库**: 待定 (根据具体需求决定,目前可能不需要)
|
| 12 |
-
- **部署环境**: Hugging Face Space Docker
|
| 13 |
|
| 14 |
-
##
|
| 15 |
-
|
| 16 |
-
-
|
| 17 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 项目简报 (Project Brief)
|
| 2 |
|
| 3 |
+
## 项目名称
|
| 4 |
+
FastAPI Qwen-Agent 集成应用
|
|
|
|
|
|
|
| 5 |
|
| 6 |
+
## 项目目标
|
| 7 |
+
构建一个基于 FastAPI 的 Web 服务,该服务能够集成 Qwen-Agent 框架,并通过 OpenAI 兼容 API 访问大型语言模型(LLM),实现智能对话功能。
|
|
|
|
|
|
|
|
|
|
| 8 |
|
| 9 |
+
## 核心需求
|
| 10 |
+
1. **FastAPI 应用**:实现一个基础的 FastAPI Web 服务,包含根路由和代理聊天路由。
|
| 11 |
+
2. **Qwen-Agent 集成**:在 FastAPI 应用中实例化 Qwen-Agent 的 `Assistant` 类。
|
| 12 |
+
3. **OpenAI 兼容 LLM 访问**:配置 `Assistant` 代理以使用 OpenAI 兼容的 LLM 服务(例如 Gemini Flash 模型),并通过环境变量安全地管理 API 密钥。
|
| 13 |
+
4. **对话功能**:`/agent_chat` 路由能够接收用户查询,并返回 LLM 生成的响应。
|
| 14 |
+
5. **可测试性**:提供单元测试以验证核心功能。
|
| 15 |
+
6. **部署兼容性**:与现有 Dockerfile 兼容(无需修改 Dockerfile)。
|
| 16 |
+
|
| 17 |
+
## 关键里程碑
|
| 18 |
+
* 完成 FastAPI 基础应用搭建。
|
| 19 |
+
* 成功集成 Qwen-Agent 并配置 OpenAI 兼容 LLM。
|
| 20 |
+
* 调试并解决 LLM 访问和响应处理中的问题。
|
| 21 |
+
* 确保应用在本地可运行和测试。
|
| 22 |
+
|
| 23 |
+
## 预期成果
|
| 24 |
+
一个功能完善的 FastAPI 应用,能够作为智能对话服务的后端,通过 Qwen-Agent 框架与 OpenAI 兼容的大模型进行交互。
|
memory-bank/systemPatterns.md
CHANGED
|
@@ -1,19 +1,50 @@
|
|
| 1 |
-
# 系统模式 (
|
| 2 |
|
| 3 |
## 系统架构
|
| 4 |
-
|
| 5 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6 |
|
| 7 |
## 关键技术决策
|
| 8 |
-
|
| 9 |
-
-
|
| 10 |
-
|
|
|
|
| 11 |
|
| 12 |
## 组件关系
|
| 13 |
-
|
| 14 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 15 |
|
| 16 |
## 关键实现路径
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 系统模式 (System Patterns)
|
| 2 |
|
| 3 |
## 系统架构
|
| 4 |
+
本项目采用客户端-服务器架构,其中:
|
| 5 |
+
* **客户端**:可以是任何能够发送 HTTP 请求的应用程序(例如 Postman、Web 浏览器、前端应用)。
|
| 6 |
+
* **服务器**:基于 FastAPI 构建的 Python Web 服务。
|
| 7 |
+
* **LLM 服务**:外部的 OpenAI 兼容 API 服务(例如 Gemini Flash 模型),通过网络请求与 FastAPI 服务交互。
|
| 8 |
+
|
| 9 |
+
```mermaid
|
| 10 |
+
graph TD
|
| 11 |
+
Client[客户端/Postman] -->|HTTP POST /agent_chat| FastAPI[FastAPI 应用]
|
| 12 |
+
FastAPI -->|LLM API 调用| LLMService[OpenAI 兼容 LLM 服务]
|
| 13 |
+
LLMService -->|LLM 响应| FastAPI
|
| 14 |
+
FastAPI -->|HTTP 响应| Client
|
| 15 |
+
```
|
| 16 |
|
| 17 |
## 关键技术决策
|
| 18 |
+
* **FastAPI**:选择 FastAPI 作为 Web 框架,因为它具有高性能、易于使用、自动生成 API 文档(Swagger UI/ReDoc)以及对异步操作的良好支持。
|
| 19 |
+
* **Qwen-Agent**:选择 Qwen-Agent 作为 LLM 交互框架,因为它提供了高级的代理抽象(如 `Assistant`),简化了与 LLM 的集成,并支持工具使用和流式响应处理。
|
| 20 |
+
* **OpenAI 兼容 API**:采用 OpenAI 兼容 API 规范,提高了 LLM 服务的可替换性,方便未来切换到其他兼容模型或自部署模型。
|
| 21 |
+
* **环境变量管理**:使用 `python-dotenv` 从 `.env` 文件加载敏感信息(如 API 密钥),确保代码的安全性、可移植性和配置的灵活性。
|
| 22 |
|
| 23 |
## 组件关系
|
| 24 |
+
* **`app.py`**:
|
| 25 |
+
* 定义 FastAPI 应用实例 (`app`)。
|
| 26 |
+
* 定义 `MainAgent` 类,封装 `qwen-agent` 的 `Assistant` 实例。
|
| 27 |
+
* 定义 API 路由 (`/`, `/agent_chat`)。
|
| 28 |
+
* `agent_chat` 路由调用 `MainAgent.process_query` 方法。
|
| 29 |
+
* **`MainAgent`**:
|
| 30 |
+
* 在初始化时创建 `qwen_agent.agents.Assistant` 实例。
|
| 31 |
+
* `process_query` 方法负责将用户查询转换为 `qwen-agent` 期望的消息格式,调用 `self.agent.run()`,并处理其流式响应。
|
| 32 |
+
* **`.env`**:存储 `API_KEY` 等环境变量。
|
| 33 |
+
* **`requirements.txt`**:列出项目的所有 Python 依赖。
|
| 34 |
+
* **`test_app.py`**:包含用于测试 FastAPI 路由和代理集成的单元测试。
|
| 35 |
|
| 36 |
## 关键实现路径
|
| 37 |
+
1. **请求处理流程**:
|
| 38 |
+
* 客户端发送 POST 请求到 `/agent_chat`。
|
| 39 |
+
* FastAPI 接收请求,解析 JSON 请求体,提取 `query`。
|
| 40 |
+
* `agent_chat` 路由调用 `main_agent.process_query(user_query)`。
|
| 41 |
+
* `process_query` 将 `user_query` 封装为 `qwen-agent` 的 `messages` 格式。
|
| 42 |
+
* `process_query` 调用 `self.agent.run(messages=messages)`,该方法与 LLM 服务进行通信。
|
| 43 |
+
* `self.agent.run()` 返回一个迭代器,`process_query` 遍历该迭代器,收集所有 `content` 分块。
|
| 44 |
+
* `process_query` 返回拼接后的完整响应字符串。
|
| 45 |
+
* `agent_chat` 路由将响应字符串封装为 JSON 格式返回给客户端。
|
| 46 |
+
|
| 47 |
+
2. **LLM 配置与密钥加载**:
|
| 48 |
+
* 应用启动时,`load_dotenv()` 从 `.env` 文件加载环境变量。
|
| 49 |
+
* `API_KEY` 从 `os.getenv("API_KEY")` 获取。
|
| 50 |
+
* `MainAgent` 初始化时,`Assistant` 实例的 `llm` 配置中包含 `model_server` 和 `api_key`。
|
memory-bank/techContext.md
CHANGED
|
@@ -1,29 +1,34 @@
|
|
| 1 |
-
# 技术背景 (
|
| 2 |
|
| 3 |
## 使用的技术
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
-
|
| 7 |
-
|
| 8 |
-
-
|
|
|
|
|
|
|
|
|
|
| 9 |
|
| 10 |
## 开发环境设置
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
-
|
| 14 |
-
|
|
|
|
| 15 |
|
| 16 |
-
##
|
| 17 |
-
|
| 18 |
-
-
|
| 19 |
-
- **可扩展性**:
|
| 20 |
-
- **兼容性**:
|
| 21 |
|
| 22 |
-
##
|
| 23 |
-
|
| 24 |
-
|
|
|
|
| 25 |
|
| 26 |
## 工具使用模式
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
-
|
|
|
|
|
|
|
|
|
| 1 |
+
# 技术背景 (Tech Context)
|
| 2 |
|
| 3 |
## 使用的技术
|
| 4 |
+
* **Python 3.12**:项目的主要开发语言。
|
| 5 |
+
* **FastAPI**:用于构建 Web API 的现代、快速(高性能)的 Web 框架。
|
| 6 |
+
* **Qwen-Agent**:阿里巴巴开源的 LLM 代理框架,用于简化 LLM 应用的开发。
|
| 7 |
+
* **Uvicorn**:ASGI 服务器,用于运行 FastAPI 应用。
|
| 8 |
+
* **python-dotenv**:用于从 `.env` 文件加载环境变量。
|
| 9 |
+
* **pytest**:Python 的测试框架,用于编写和运行单元测试。
|
| 10 |
+
* **curl**:命令行工具,用于发送 HTTP 请求进行测试。
|
| 11 |
+
* **Docker**:用于容器化应用,提供一致的运行环境。
|
| 12 |
|
| 13 |
## 开发环境设置
|
| 14 |
+
* **Python 版本**:建议使用 Python 3.12。
|
| 15 |
+
* **虚拟环境**:强烈建议使用 `conda` 或 `venv` 创建虚拟环境,以隔离项目依赖。
|
| 16 |
+
* `conda create -n airs-team python=3.12`
|
| 17 |
+
* `conda activate airs-team`
|
| 18 |
+
* **依赖安装**:通过 `pip install -r requirements.txt` 安装所有项目依赖。
|
| 19 |
|
| 20 |
+
## 依赖管理
|
| 21 |
+
* `requirements.txt` 文件列出了所有必需的 Python 包及其版本。
|
| 22 |
+
* 主要依赖包括 `fastapi`, `uvicorn`, `qwen-agent`, `python-dotenv`, `pytest`。
|
|
|
|
|
|
|
| 23 |
|
| 24 |
+
## 技术约束
|
| 25 |
+
* **LLM API 兼容性**:当前配置要求 LLM 服务提供 OpenAI 兼容的 API 接口。
|
| 26 |
+
* **API 密钥**:需要有效的 `API_KEY` 环境变量才能与 LLM 服务进行交互。
|
| 27 |
+
* **网络访问**:FastAPI 应用需要能够访问配置的 `model_server`。
|
| 28 |
|
| 29 |
## 工具使用模式
|
| 30 |
+
* **代码编辑**:主要通过修改 `app.py` 来实现业务逻辑和代理集成。
|
| 31 |
+
* **依赖管理**:通过 `requirements.txt` 管理 Python 包。
|
| 32 |
+
* **应用运行**:使用 `python3.12 -m uvicorn app:app --host 0.0.0.0 --port 7860 --reload` 在本地运行和调试应用。
|
| 33 |
+
* **API 测试**:使用 `curl` 或 Postman 等工具发送 HTTP 请求测试 API 路由。
|
| 34 |
+
* **单元测试**:使用 `pytest` 运行 `test_app.py` 中的测试用例。
|
requirements.txt
CHANGED
|
@@ -1,2 +1,8 @@
|
|
| 1 |
fastapi
|
| 2 |
-
uvicorn
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
fastapi
|
| 2 |
+
uvicorn
|
| 3 |
+
qwen-agent
|
| 4 |
+
python-dateutil
|
| 5 |
+
pytest
|
| 6 |
+
httpx
|
| 7 |
+
pytest-asyncio
|
| 8 |
+
python-dotenv
|
test_app.py
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from fastapi.testclient import TestClient
|
| 2 |
+
from app import app, main_agent
|
| 3 |
+
|
| 4 |
+
# TestClient is synchronous, so no need for pytest.mark.asyncio
|
| 5 |
+
client = TestClient(app)
|
| 6 |
+
|
| 7 |
+
def test_read_root():
|
| 8 |
+
response = client.get("/")
|
| 9 |
+
assert response.status_code == 200
|
| 10 |
+
assert response.json() == {"message": "Hello, FastAPI!"}
|
| 11 |
+
|
| 12 |
+
def test_agent_chat_missing_query():
|
| 13 |
+
response = client.post("/agent_chat", json={})
|
| 14 |
+
assert response.status_code == 400
|
| 15 |
+
assert response.json() == {"error": "Query parameter is missing"}
|
| 16 |
+
|
| 17 |
+
def test_agent_chat_with_query():
|
| 18 |
+
# Mock the agent's run method to avoid actual API calls during testing
|
| 19 |
+
original_run = main_agent.agent.run
|
| 20 |
+
main_agent.agent.run = lambda x: "Mocked agent response for: " + x
|
| 21 |
+
|
| 22 |
+
response = client.post("/agent_chat", json={"query": "Test query"})
|
| 23 |
+
|
| 24 |
+
assert response.status_code == 200
|
| 25 |
+
assert response.json() == {"response": "Mocked agent response for: Test query"}
|
| 26 |
+
|
| 27 |
+
# Restore the original run method
|
| 28 |
+
main_agent.agent.run = original_run
|