项目结构设计:模块化拆分原则,配置管理,日志系统搭建,项目骨架代码生成
说实话,很多同学做Agent项目时,一开始都挺嗨的。代码全塞在一个文件里,跑通了就觉得自己牛了。但等到要部署、要迭代、要多人协作时,那个文件就变成了「谁都不敢动」的定时炸弹。我见过太多这样的项目了——改一行代码,崩三个功能。
所以这一章,咱们聊聊怎么把项目结构搭好。说白了,就是给代码「分家」。分得清楚,后面才活得轻松。
模块化拆分:别让代码「一锅炖」
模块化拆分,核心就一句话:各司其职,互不干扰。每个模块只做一件事,并且把这件事做好。
我个人习惯把Agent项目拆成这几个核心模块:
- core/ —— 核心逻辑,比如Agent的主循环、推理引擎
- tools/ —— 工具集,比如搜索、计算、文件操作
- memory/ —— 记忆模块,管理短期和长期记忆
- config/ —— 配置管理,所有可变的参数放这里
- utils/ —— 工具函数,日志、异常处理等
你想想看,如果这些全混在一起,改个日志格式都要翻遍整个项目,多痛苦。
核心原则:
- 高内聚:模块内部功能紧密相关
- 低耦合:模块之间通过接口通信,不直接依赖内部实现
- 单向依赖:上层模块依赖下层,避免循环引用
我在项目中遇到过最典型的反面教材:一个工具函数里调用了核心Agent的某个方法,结果改工具时把Agent搞崩了。嗯,从那以后我定了个规矩——工具模块绝对不能反向依赖核心模块。
配置管理:把「硬编码」赶出你的代码
配置管理,说白了就是把「会变的东西」从代码里抽出来。API密钥、模型参数、路径、超参数……这些都不该写在代码里。
我建议用 yaml 或 json 文件来管理配置。为什么?因为可读性强,改起来方便,而且支持注释。
来看一个典型的配置结构:
# config/default.yaml
agent:
name: "my-agent"
model: "gpt-4"
temperature: 0.7
max_tokens: 2048
memory:
type: "redis"
ttl: 3600
logging:
level: "INFO"
file: "logs/agent.log"
然后写一个配置加载器,统一读取:
import yaml
from pathlib import Path
class Config:
def __init__(self, path="config/default.yaml"):
with open(path, "r") as f:
self._config = yaml.safe_load(f)
def get(self, key, default=None):
keys = key.split(".")
value = self._config
for k in keys:
value = value.get(k)
if value is None:
return default
return value
# 使用
config = Config()
model = config.get("agent.model") # "gpt-4"
小技巧: 我习惯把敏感信息(如API密钥)放在环境变量里,然后在配置文件中用占位符引用。比如 api_key: ${OPENAI_API_KEY},加载时自动替换。这样既安全又灵活。
日志系统搭建:别等出事了才后悔
日志这东西,平时没人关心。但一旦线上出问题,它就是你的「救命稻草」。我曾经因为日志没打全,排查一个Bug花了整整两天。从那以后,我对日志的要求就三个字:够详细。
Python自带的 logging 模块其实够用,但需要好好配置。我一般这样搭:
import logging
import sys
from pathlib import Path
def setup_logger(name, log_file="logs/agent.log", level=logging.INFO):
# 创建日志目录
Path(log_file).parent.mkdir(parents=True, exist_ok=True)
# 创建logger
logger = logging.getLogger(name)
logger.setLevel(level)
# 文件处理器 - 记录所有日志
file_handler = logging.FileHandler(log_file)
file_handler.setLevel(level)
file_formatter = logging.Formatter(
"%(asctime)s - %(name)s - %(levelname)s - %(message)s"
)
file_handler.setFormatter(file_formatter)
# 控制台处理器 - 只记录WARNING及以上
console_handler = logging.StreamHandler(sys.stdout)
console_handler.setLevel(logging.WARNING)
console_formatter = logging.Formatter(
"%(levelname)s: %(message)s"
)
console_handler.setFormatter(console_formatter)
# 添加处理器
logger.addHandler(file_handler)
logger.addHandler(console_handler)
return logger
# 使用
logger = setup_logger("my_agent")
logger.info("Agent started")
logger.error("Something went wrong")
注意: 日志级别要合理设置。开发环境用DEBUG,生产环境用INFO或WARNING。别把敏感信息(如API密钥、用户数据)打到日志里,这是安全红线。
项目骨架代码生成:从零到一,一步到位
每次新建项目都手动搭结构?太累了。我习惯写一个脚手架脚本,一键生成项目骨架。这样团队里所有人都用同一套结构,省心省力。
来看一个简单的生成器:
import os
from pathlib import Path
def create_project(name):
base = Path(name)
# 目录结构
dirs = [
"core",
"tools",
"memory",
"config",
"utils",
"logs",
"tests"
]
# 文件结构
files = {
"core/__init__.py": "",
"core/agent.py": "# Agent main loop\n",
"tools/__init__.py": "",
"tools/search.py": "# Search tool\n",
"memory/__init__.py": "",
"memory/short_term.py": "# Short-term memory\n",
"config/default.yaml": "# Default config\n",
"utils/__init__.py": "",
"utils/logger.py": "# Logger setup\n",
"tests/test_agent.py": "# Tests\n",
"main.py": "# Entry point\n",
"requirements.txt": "# Dependencies\n",
}
# 创建目录
for d in dirs:
(base / d).mkdir(parents=True, exist_ok=True)
# 创建文件
for path, content in files.items():
file_path = base / path
file_path.parent.mkdir(parents=True, exist_ok=True)
file_path.write_text(content)
print(f"Project {name} created successfully!")
# 使用
create_project("my_agent")
运行后,你会得到这样的结构:
my_agent/
├── core/
│ ├── __init__.py
│ └── agent.py
├── tools/
│ ├── __init__.py
│ └── search.py
├── memory/
│ ├── __init__.py
│ └── short_term.py
├── config/
│ └── default.yaml
├── utils/
│ ├── __init__.py
│ └── logger.py
├── tests/
│ └── test_agent.py
├── logs/
├── main.py
└── requirements.txt
为什么这样设计?
- core/ 放核心逻辑,是项目的心脏
- tools/ 放外部能力,是Agent的手脚
- memory/ 放记忆管理,是Agent的大脑皮层
- config/ 放所有可变参数,是项目的「调节旋钮」
- utils/ 放通用工具,是项目的「工具箱」
- tests/ 放测试代码,是项目的「安全网」
知识体系总览
下面这张图,把本章的核心逻辑串起来了。你可以看到模块之间如何协作,数据如何流动:
嗯,到这里,项目骨架就搭好了。你可能会问:「就这些?」对,就这些。但别小看这个结构,它是我踩了无数坑之后总结出来的。用这个骨架,你可以快速开始写真正的业务逻辑,而不是每次都在「该把文件放哪」这种问题上纠结。
我的建议: 把这个骨架脚本放到你的个人工具库里。以后每开一个新项目,跑一下脚本,三秒钟搞定。省下来的时间,多喝杯咖啡不香吗?