Python AI Agent 项目技术学习笔记(第一篇)
1. 项目整体架构
1.1 项目目录结构
api-server/
├── app/ # 应用入口
│ └── http/ # HTTP 服务配置
├── config/ # 配置管理
├── internal/ # 核心业务逻辑
│ ├── core/ # 核心功能
│ ├── exception/ # 异常处理
│ ├── extension/ # 扩展组件
│ ├── handler/ # 请求处理器
│ ├── model/ # 数据模型
│ ├── router/ # 路由管理
│ ├── schema/ # 数据验证
│ ├── server/ # 服务器配置
│ └── service/ # 业务服务
├── pkg/ # 公共包
│ ├── response/ # 响应处理
│ └── sqlalchemy/ # 数据库扩展
└── storage/ # 存储目录
└── memory/ # 聊天历史存储
1.2 核心组件关系
flowchart TD
A[app.py 入口] --> B[Http 服务器]
B --> C[Router 路由]
C --> D[AppHandler 处理器]
D --> E[AppService 服务]
D --> F[LangChain AI]
E --> G[数据库模型]
F --> H[OpenAI/Kimi API]
2. 核心组件详解
2.1 应用入口 (app.py)
文件位置: app/http/app.py
import sys
import os
# 添加项目根目录到Python路径,确保导入模块时可以找到
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "../..")))
# 先导入其他模块,确保 sys.path 已经设置好
from internal.server import Http
from internal.router import Router
from injector import Injector, Module, Binder
from config import Config
from internal.extension.database_extension import db
from pkg.sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
# 定义扩展Module,用于绑定SQLAlchemy和Migrate实例
class ExtensionModule(Module):
def configure(self, binder: Binder):
binder.bind(SQLAlchemy, to=db)
binder.bind(Migrate, to=Migrate())
# 加载环境变量
import dotenv
dotenv.load_dotenv()
inject = Injector([ExtensionModule])
# 应用配置
conf = Config()
app = Http(
__name__,
router=inject.get(Router),
db=inject.get(SQLAlchemy),
migrate=inject.get(Migrate),
conf=conf,
)
if __name__ == "__main__":
app.run(debug=True, port=5001, host='0.0.0.0')
关键概念解释:
- Python 路径设置:
sys.path.append()用于添加项目根目录到 Python 路径,确保模块导入正常 - 依赖注入:使用
Injector管理依赖,类似于前端的依赖注入容器(如 Angular 的 DI) - 环境变量:使用
dotenv加载环境变量,类似于前端的.env文件
2.2 HTTP 服务器 (Http 类)
文件位置: internal/server/http.py
from flask import Flask
from internal.router import Router
from config import Config
from internal.exception import CustomException
from pkg.response import Response, json
from pkg.response.http_code import HttpCode
from pkg.sqlalchemy import SQLAlchemy
from internal.model import App
from flask_migrate import Migrate
from flask_cors import CORS
class Http(Flask):
# HTTP服务引擎
def __init__(
self,
*args,
router: Router,
db: SQLAlchemy,
migrate: Migrate,
conf: Config,
**kwargs
):
# 初始化HTTP服务引擎
super().__init__(*args, **kwargs)
# 应用配置
self.config.from_object(conf)
# 异常错误处理
self.register_error_handler(Exception, self._register_error_handler)
# 注册数据库扩展
db.init_app(self)
# 注册CORS扩展(跨域设置)
CORS(
self,
resources={
r"/*": {
"origins": "http://localhost:5173",
"supports_credentials": True,
"allow_headers": "Content-Type",
"allow_methods": "GET, POST",
}
},
)
# 注册迁移扩展
migrate.init_app(self, db, directory="internal/migration")
# 注册路由
router.register_routes(self)
def _register_error_handler(self, error: Exception):
print("异常:", error)
# 处理自定义异常
if isinstance(error, CustomException):
return json(
Response(
code=error.code,
message=error.message,
data=error.data if error.data is not None else {},
)
)
return json(Response(code=HttpCode.FAIL, message=str(error), data={}))
关键概念解释:
- 类继承:
Http类继承自Flask,类似于前端的类继承 - 构造函数:
__init__方法用于初始化对象,接受多个参数 - CORS 配置:设置跨域资源共享,允许前端从
http://localhost:5173访问 - 异常处理:统一处理应用中的异常,返回标准格式的错误响应
2.3 路由管理 (Router 类)
文件位置: internal/router/router.py
from flask import Flask,Blueprint
from internal.handler import AppHandler
from injector import inject
from dataclasses import dataclass
@inject
@dataclass
class Router:
# 路由注册器
app_handler: AppHandler
def register_routes(self, app: Flask):
# 创建一个蓝图
bp = Blueprint("llmops", __name__,url_prefix="")
# URL与路由绑定
bp.add_url_rule("/ping", view_func=self.app_handler.ping)
bp.add_url_rule("/apps/<uuid:app_id>/debug", view_func=self.app_handler.debug, methods=["POST"])
bp.add_url_rule("/app", view_func=self.app_handler.create_app, methods=["POST"])
bp.add_url_rule("/app/<uuid:id>", view_func=self.app_handler.get_app)
bp.add_url_rule("/app/<uuid:id>", view_func=self.app_handler.update_app, methods=["POST"])
bp.add_url_rule("/app/<uuid:id>/delete", view_func=self.app_handler.delete_app, methods=["POST"])
# 注册蓝图
app.register_blueprint(bp)
关键概念解释:
- 装饰器:
@inject和@dataclass是 Python 装饰器,类似于前端的装饰器(如 React 的@useState) - 蓝图:
Blueprint是 Flask 中用于组织路由的方式,类似于前端的路由模块 - URL 规则:
add_url_rule用于绑定 URL 与处理函数 - UUID 类型:
<uuid:app_id>是 Flask 的 URL 参数类型,用于匹配 UUID 格式的参数
2.4 应用处理器 (AppHandler 类)
文件位置: internal/handler/app_handler.py
from flask import request, jsonify
from openai import OpenAI, RateLimitError
import os
from internal.schema.app_schema import CompletionReq
from internal.service.app_service import AppService
from dataclasses import dataclass
from injector import inject, Injector
from operator import itemgetter
import uuid
from langchain_classic.memory import ConversationBufferWindowMemory
from langchain_community.chat_message_histories import FileChatMessageHistory
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.runnables import RunnablePassthrough, RunnableLambda
from langchain_openai import ChatOpenAI
from pkg.response import (
success_json,
validate_error_json,
success_message,
)
# 应用控制器
@inject
@dataclass
class AppHandler:
app_service: AppService
def create_app(self):
app = self.app_service.create_app()
return success_message(f"应用创建成功,应用ID: {app.id}")
def get_app(self, id: uuid.UUID):
app = self.app_service.get_app(id)
return success_json({
"id": app.id,
"name": app.name,
"account_id": app.account_id,
"icon": app.icon,
"description": app.description,
})
def update_app(self, id: uuid.UUID):
app = self.app_service.update_app(id)
return success_message(f"应用更新成功,应用ID: {app.name}")
def delete_app(self, id: uuid.UUID):
app = self.app_service.delete_app(id)
return success_message(f"应用删除成功,应用ID: {app.id}")
def debug(self, app_id: uuid.UUID):
"""聊天接口"""
# 1.定义请求参数的验证规则
req = CompletionReq(data=request.json)
if not req.validate():
return validate_error_json(req.errors)
# 从环境变量获取API密钥
moonshot_api_key = os.getenv("MOONSHOT_API_KEY")
moonshot_api_url = os.getenv("MOONSHOT_API_URL")
# langchain 调用方式
# 2.创建prompt与记忆
prompt = ChatPromptTemplate.from_messages([
("system", "你是一个强大的聊天机器人,能根据用户的提问回复对应的问题"),
MessagesPlaceholder("history"),
("human", "{query}"),
])
memory = ConversationBufferWindowMemory(
k=3,
input_key="query",
output_key="output",
return_messages=True,
chat_memory=FileChatMessageHistory("./storage/memory/chat_history.txt"),
)
# 3.创建llm
llm = ChatOpenAI(model="kimi-k2.5", api_key=moonshot_api_key, base_url=moonshot_api_url)
# 4.创建链应用
chain = RunnablePassthrough.assign(
history=RunnableLambda(memory.load_memory_variables) | itemgetter("history")
) | prompt | llm | StrOutputParser()
# 5.调用链生成内容
chain_input = {"query": req.query.data}
content = chain.invoke(chain_input)
memory.save_context(chain_input, {"output": content})
return success_json({"content": content})
def ping(self):
return success_json({"ping": "pong"})
关键概念解释:
- 数据验证:使用
CompletionReq验证请求参数,类似于前端的表单验证 - 环境变量:使用
os.getenv()获取环境变量,类似于前端的process.env - LangChain 集成:使用 LangChain 框架构建 AI 对话系统
- Prompt:定义系统提示和用户输入模板
- Memory:使用
ConversationBufferWindowMemory保存对话历史 - LLM:使用
ChatOpenAI调用 Kimi 模型 - Chain:构建处理链,将多个组件连接起来
- UUID 类型:使用
uuid.UUID类型注解,类似于 TypeScript 的类型注解
3. AI Agent 核心实现
3.1 LangChain 链构建
核心代码:
# 2.创建prompt与记忆
prompt = ChatPromptTemplate.from_messages([
("system", "你是一个强大的聊天机器人,能根据用户的提问回复对应的问题"),
MessagesPlaceholder("history"),
("human", "{query}"),
])
memory = ConversationBufferWindowMemory(
k=3, # 保留最近3轮对话
input_key="query",
output_key="output",
return_messages=True,
chat_memory=FileChatMessageHistory("./storage/memory/chat_history.txt"),
)
# 3.创建llm
llm = ChatOpenAI(model="kimi-k2.5", api_key=moonshot_api_key, base_url=moonshot_api_url)
# 4.创建链应用
chain = RunnablePassthrough.assign(
history=RunnableLambda(memory.load_memory_variables) | itemgetter("history")
) | prompt | llm | StrOutputParser()
# 5.调用链生成内容
chain_input = {"query": req.query.data}
content = chain.invoke(chain_input)
memory.save_context(chain_input, {"output": content})
工作流程:
- 构建提示模板:定义系统消息、历史消息占位符和用户输入模板
- 初始化记忆:创建对话记忆,保存最近3轮对话
- 创建LLM实例:配置Kimi模型
- 构建处理链:
- 加载对话历史
- 应用提示模板
- 调用LLM生成回复
- 解析输出
- 执行链:传入用户查询,获取回复
- 保存上下文:将用户查询和AI回复保存到记忆中
3.2 对话记忆管理
核心代码:
memory = ConversationBufferWindowMemory(
k=3, # 保留最近3轮对话
input_key="query",
output_key="output",
return_messages=True,
chat_memory=FileChatMessageHistory("./storage/memory/chat_history.txt"),
)
# 保存对话
memory.save_context(chain_input, {"output": content})
功能说明:
- 窗口大小:
k=3表示只保留最近3轮对话,避免记忆过大 - 持久化:使用
FileChatMessageHistory将对话历史保存到文件中 - 输入输出键:指定输入和输出的键名,确保链中数据传递正确
4. 前端开发者需要了解的 Python 概念
4.1 装饰器
Python 装饰器:
@inject
@dataclass
class Router:
# 路由注册器
app_handler: AppHandler
前端类比:
- 类似于 React 的 HOC (Higher-Order Component)
- 类似于 JavaScript 的装饰器提案
- 用于增强函数或类的功能
4.2 数据类
Python 数据类:
from dataclasses import dataclass
@dataclass
class AppHandler:
app_service: AppService
前端类比:
- 类似于 TypeScript 的接口或类型
- 类似于 JavaScript 的类
- 用于定义数据结构
4.3 依赖注入
Python 依赖注入:
from injector import Injector, Module, Binder
class ExtensionModule(Module):
def configure(self, binder: Binder):
binder.bind(SQLAlchemy, to=db)
binder.bind(Migrate, to=Migrate())
inject = Injector([ExtensionModule])
app_handler = inject.get(AppHandler)
前端类比:
- 类似于 Angular 的依赖注入系统
- 类似于 React 的 Context API
- 用于管理组件依赖
4.4 类型注解
Python 类型注解:
def get_app(self, id: uuid.UUID):
app = self.app_service.get_app(id)
return success_json({...})
前端类比:
- 类似于 TypeScript 的类型注解
- 用于静态类型检查
- 提高代码可读性和可维护性
4.5 模块导入
Python 模块导入:
import sys
import os
# 添加项目根目录到Python路径
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "../..")))
from internal.server import Http
前端类比:
- 类似于 ES6 的
import语句 - 类似于 CommonJS 的
require - 用于导入其他模块的功能
5. 与前端的交互
5.1 API 接口
| 接口路径 | 方法 | 功能 |
|---|---|---|
/ping | GET | 健康检查 |
/apps/<app_id>/debug | POST | AI 聊天接口 |
/app | POST | 创建应用 |
/app/<id> | GET | 获取应用详情 |
/app/<id> | POST | 更新应用 |
/app/<id>/delete | POST | 删除应用 |
5.2 响应格式
成功响应:
{
"code": "success",
"message": "操作成功",
"data": {...}
}
失败响应:
{
"code": "fail",
"message": "错误信息",
"data": {}
}
5.3 CORS 配置
CORS(
self,
resources={
r"/*": {
"origins": "http://localhost:5173",
"supports_credentials": True,
"allow_headers": "Content-Type",
"allow_methods": "GET, POST",
}
},
)
配置说明:
origins:允许的前端域名supports_credentials:是否支持携带凭证allow_headers:允许的请求头allow_methods:允许的 HTTP 方法
6. 项目启动与运行
6.1 环境变量配置
创建 .env 文件:
# 数据库配置
DATABASE_URL="postgresql://username:password@localhost:5432/llmops"
# moonshot API 配置
MOONSHOT_API_KEY="your_api_key"
MOONSHOT_API_URL="https://api.moonshot.cn/v1"
# Flask 配置
FLASK_APP="app/http/app.py"
FLASK_ENV="development"
6.2 安装依赖
pip3 install -r requirements.txt
6.3 启动服务
python3 app/http/app.py
服务将在 http://127.0.0.1:5001 启动。
7. 代码优化建议
7.1 错误处理优化
当前实现:
def _register_error_handler(self, error: Exception):
print("异常:", error)
# 处理自定义异常
if isinstance(error, CustomException):
return json(
Response(
code=error.code,
message=error.message,
data=error.data if error.data is not None else {},
)
)
return json(Response(code=HttpCode.FAIL, message=str(error), data={}))
优化建议:
def _register_error_handler(self, error: Exception):
import traceback
# 记录详细错误信息
print("异常:", error)
traceback.print_exc()
# 处理自定义异常
if isinstance(error, CustomException):
return json(
Response(
code=error.code,
message=error.message,
data=error.data if error.data is not None else {},
)
)
# 处理不同类型的异常
if isinstance(error, RateLimitError):
return json(Response(code=HttpCode.FAIL, message="API 速率限制,请稍后再试", data={}))
elif isinstance(error, FileNotFoundError):
return json(Response(code=HttpCode.FAIL, message="文件不存在", data={}))
return json(Response(code=HttpCode.FAIL, message=str(error), data={}))
7.2 记忆管理优化
当前实现:
memory = ConversationBufferWindowMemory(
k=3,
input_key="query",
output_key="output",
return_messages=True,
chat_memory=FileChatMessageHistory("./storage/memory/chat_history.txt"),
)
优化建议:
# 使用应用ID作为文件名,实现每个应用独立的聊天历史
chat_history_file = f"./storage/memory/chat_history_{app_id}.txt"
# 确保目录存在
os.makedirs(os.path.dirname(chat_history_file), exist_ok=True)
memory = ConversationBufferWindowMemory(
k=5, # 增加历史记录数量
input_key="query",
output_key="output",
return_messages=True,
chat_memory=FileChatMessageHistory(chat_history_file),
)
7.3 配置管理优化
当前实现:
# 从环境变量获取API密钥
moonshot_api_key = os.getenv("MOONSHOT_API_KEY")
moonshot_api_url = os.getenv("MOONSHOT_API_URL")
优化建议:
# 从配置对象获取,集中管理配置
moonshot_api_key = self.conf.MOONSHOT_API_KEY
moonshot_api_url = self.conf.MOONSHOT_API_URL
# 添加配置验证
if not moonshot_api_key:
raise CustomException(code=HttpCode.FAIL, message="MOONSHOT_API_KEY 未配置")
if not moonshot_api_url:
raise CustomException(code=HttpCode.FAIL, message="MOONSHOT_API_URL 未配置")
8. 总结
本项目是一个基于 Python Flask 框架的 AI Agent 后端服务,核心功能包括:
- RESTful API:提供应用管理和 AI 聊天接口
- LangChain 集成:使用 LangChain 框架构建 AI 对话系统
- 依赖注入:使用 injector 管理组件依赖
- 数据库集成:使用 SQLAlchemy 管理数据模型
- CORS 配置:支持前端跨域访问
第二篇笔记总结中...