前言
老顾花了很多的篇幅已经介绍了关于DeerFlow项目中的AI Agent多智能体相关的源码。需要了解的人可以看前面的文章。
这篇文章老顾给大家介绍一下DeerFlow工程方面的技术点,也是值得我们学习的地方。
工程结构
diff
-DEER-FLOW
--docs
----xx.md
--examples
----yy.md
--src
--tests
--web
--.env
--.python-version
--bootstrap.bat
--bootstrap.sh
--conf.yaml
--docker-compose.yml
--Dockerfile
--main.py
--Makefile
--pyproject.toml
--server.py
--uv.lock
上面是deerflow的工程目录结构,我们来看一下各自的作用
**docs:**存放着相关核心介绍,如怎么使用配置
**examples:**md格式的文档,一些案例的报告
**src:**项目的Python的源代码就在此目录下
**tests:**单元测试
**web:**前端页面代码
**.env:**项目的全局的环境变量都在此处
**.python-version:**uv虚拟环境配置的python版本
**bootstrap.bat:**windows版本的执行脚本,启动后端和前端
**bootstrap.sh:**linux版本的执行脚本,启动后端和前端
**conf.yaml:**大模型相关的配置
**docker-compose.yml:**容器的编排文件
**Dockerfile:**容器的镜像文件配置
**main.py:**支持用户通过命令行或交互式界面提问
**Makefile:**提供一组用于开发、测试、格式化和运行项目的命令
**pyproject.toml:**里面包含了依赖的包,打包方式等
**server.py:**项目后端的启动入口
**uv.lock:**uv虚拟环境的系统文件
我们来重点看一下**pyproject.toml文件,**里面的信息是比较重要的
pyproject.toml
1. 构建系统配置
ini
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
- 作用:定义项目使用的构建工具。
- 说明:
- requires:指定构建项目所需的依赖项,这里使用了 hatchling。
- build-backend:指定构建后端使用的模块,这里是 hatchling.build。
2. 项目基本信息
ini
[project]
name = "deer-flow"
version = "0.1.0"
description = "DeerFlow project"
readme = "README.md"
requires-python = ">=3.12"
- 作用:定义项目的基本信息。
- 说明:
- name:项目的名称,这里是 deer-flow。
- version:项目的当前版本号,这里是 0.1.0。
- description:项目的简短描述,这里是 DeerFlow project。
- readme:项目的 README 文件路径,这里是 README.md。
- requires-python:项目所需的 Python 版本,这里是 >=3.12。
3. 项目依赖
ini
dependencies = [
"httpx>=0.28.1",
"langchain-community>=0.3.19",
"langchain-experimental>=0.3.4",
...
]
- 作用:定义项目运行所需的依赖项。
- 说明:
- 列出了所有必需的 Python 包及其版本要求,例如:
- httpx>=0.28.1:要求 httpx 的版本至少为 0.28.1。
- langchain-community>=0.3.19:要求 langchain-community 的版本至少为 0.3.19。
4. 可选依赖
ini
[project.optional-dependencies]
dev = [
"black>=24.2.0",
"langgraph-cli[inmem]>=0.2.10",
]
test = [
"pytest>=7.4.0",
"pytest-cov>=4.1.0",
"pytest-asyncio>=1.0.0",
]
- 作用:定义可选的依赖组,用户可以根据需要安装。
- 说明:
- dev:开发环境所需的依赖,例如代码格式化工具 black。
- test:测试环境所需的依赖,例如测试框架 pytest。
5. 测试配置
ini
[tool.pytest.ini_options]
testpaths = ["tests"]
python_files = ["test_*.py"]
addopts = "-v --cov=src --cov-report=term-missing"
filterwarnings = [
"ignore::DeprecationWarning",
"ignore::UserWarning",
]
- 作用:定义 pytest 测试框架的配置选项。
- 说明:
- testpaths:指定测试文件所在的目录,这里是 tests。
- python_files:指定测试文件的命名模式,这里是 test_*.py。
- addopts:指定测试时的附加选项:
- -v:详细输出。
- --cov=src:计算 src 目录的代码覆盖率。
- --cov-report=term-missing:在终端显示未覆盖的代码行。
- filterwarnings:忽略特定的警告信息,例如 DeprecationWarning 和 UserWarning。
6. 覆盖率报告配置
ini
[tool.coverage.report]
fail_under = 25
- 作用:定义代码覆盖率的报告配置。
- 说明:
- fail_under:如果代码覆盖率低于 25%,则测试失败。
7. 构建目标配置
ini
[tool.hatch.build.targets.wheel]
packages = ["src"]
- 作用:定义构建 wheel 包时包含的代码包。
- 说明:
- packages:指定构建时包含的目录,这里是 src。
8. 代码格式化工具配置
ini
[tool.black]
line-length = 88
target-version = ["py312"]
include = '.pyi?$'
extend-exclude = '''
^/build/
'''
- 作用:定义代码格式化工具 black 的配置。
- 说明:
- line-length:指定每行代码的最大长度为 88。
- target-version:指定目标 Python 版本为 3.12。
- include:指定需要格式化的文件类型,这里是 .py 和 .pyi。
- extend-exclude:指定不需要格式化的目录,这里是 build。
该 pyproject.toml 文件定义了项目的构建工具、基本信息、依赖项、可选依赖、测试配置、代码覆盖率、构建目标以及代码格式化规则。它是现代 Python 项目的标准配置文件,能够帮助开发者快速配置和管理项目。
下面我们来看看src目录下面有哪些点,可以值得学习的
src源码
一、config
里面存放了项目的配置信息,其中里面有个configuration.py文件,
此文件 configuration.py 用于定义程序的配置类 Configuration ,它提供了一种结构化的方式来管理应用程序的可配置参数。这些参数可以来源于环境变量或 RunnableConfig 对象。
以下是对代码的详细解释:
- 配置管理:通过 dataclass 定义了程序运行所需的配置项,如资源列表、最大迭代次数、报告风格等。
- 灵活的配置来源:支持从环境变量或传入的 RunnableConfig 中读取配置值,提供了灵活性。
- 默认值管理:为每个配置项提供了默认值或默认工厂函数,确保即使没有显式提供配置,程序也能正常运行。
二、prompts
此目录下面存放了智能体中所需要的提示词文件,里面template.py文件定义了获取提示词模板的方法。
三、server
此目录中app.py是与前端交互的请求入口地址,里面采用了fastapi框架;里面有个比较重要的Stream流失输出的技术点 ,StreamingResponse中media_type="text/event-stream" ,
media_type="text/event-stream" 的作用是设置 HTTP 响应的内容类型为 Server-Sent Events (SSE) 流。SSE 是一种允许服务器向客户端(通常是浏览器)持续推送数据的技术。
1、作用:
- 实时数据推送:服务器可以持续不断地向客户端发送数据,而不需要客户端反复发起请求。
- 单向通信:数据从服务器推送到客户端,适用于服务器主动更新客户端的场景。
- **轻量级协议:**相比 WebSocket,SSE 更简单,适合不需要双向通信的场景。
2、一般应用场景:
- 实时日志更新:如监控系统、任务执行日志的实时展示。
- 实时通知:用户消息提醒、系统告警。
- 流式数据传输:AI 生成文本的逐步返回(如 ChatGPT 类型的流式回复)。
- 股票价格、天气更新等:需要服务器持续推送数据更新的场景。
3、前端如何接收:
前端使用 EventSource 对象来接收 text/event-stream 数据。
4、示例代码:
ini
const eventSource = new EventSource('/api/chat/stream');
eventSource.onmessage = function(event) {
console.log('Received data:', event.data);
// 处理服务器发送的数据
const data = JSON.parse(event.data);
if (data.event === "stream_end") {
console.log("Stream has ended");
eventSource.close(); // 主动关闭连接
return;
}
};
eventSource.onerror = function(err) {
console.error('EventSource failed:', err);
};
5、消息格式说明
服务器发送的数据需要遵循 SSE 协议格式,例如:
css
event: message
data: {"content": "Hello", "role": "assistant"}
里面的其他目录,都是以不同的Agent作为文件夹归类的,如:rag、ppt、podcast等Agent
四、日志装饰
我们来看一下src/tools/decorators.py这个文件,里面就是对logger日志做一些增强。
1. 函数装饰器 log_io
python
def log_io(func: Callable) -> Callable:
- 这是一个装饰器函数,用于记录被装饰函数的输入参数和返回值
- 使用 @functools.wraps(func) 保持原函数的元信息
- 在函数调用前后分别记录参数和返回值到日志中
2. 混入类 LoggedToolMixin
kotlin
class LoggedToolMixin:
这是一个混入类,为工具类提供日志记录功能:
- _log_operation 方法:记录类方法调用的参数信息
- _run 方法:重写基类的 _run 方法,添加输入输出日志记录
- 通过 super()._run(*args, **kwargs) 调用原始方法实现
3. 工厂函数 create_logged_tool
python
def create_logged_tool(base_tool_class: Type[T]) -> Type[T]:
- 这是一个工厂函数,用于动态创建带日志功能的工具类
- 创建的新类同时继承 LoggedToolMixin 和原始工具类
- 自动为新类生成更具描述性的名称(添加"Logged"前缀)
这套系统允许开发者通过简单的装饰器或类工厂方式,为现有的工具函数和类添加自动化的输入输出日志记录功能,便于调试和监控工具的执行情况。
server.py
这段代码是一个用于运行 DeerFlow API 服务的服务器脚本,主要功能是启动一个基于 uvicorn 的 ASGI 服务器。下面是代码的详细解释:
主要功能
- 启动 API 服务:使用 uvicorn 启动一个 ASGI 服务器来运行 src.server:app 应用。
- 命令行参数解析:支持通过命令行参数配置服务器的 host、port、日志级别和自动重载功能。
- 日志配置:设置日志记录格式和级别。
- 优雅关闭:注册信号处理器以实现服务器的优雅关闭。
scss
signal.signal(signal.SIGTERM, handle_shutdown)
signal.signal(signal.SIGINT, handle_shutdown)
- 注册信号处理器,分别处理终止信号(SIGTERM)和中断信号(SIGINT)。
- 使用 argparse 模块定义和解析命令行参数:
- **--reload:**启用自动重载功能(默认为 False)。
- **--host:**指定服务器绑定的主机地址(默认为 localhost)。
- **--port:**指定服务器绑定的端口号(默认为 8000)。
- **--log-level:**指定日志级别(默认为 info)。
服务器启动
ini
uvicorn.run(
"src.server:app",
host=args.host,
port=args.port,
reload=reload,
log_level=args.log_level,
)
- 使用 uvicorn.run 启动服务器:
- 加载 src.server:app 模块中的 app 应用。
- 根据命令行参数配置主机地址、端口、重载选项和日志级别。
总结
到此DeerFlow老顾介绍了工程方面的一些技术点,一些信息是值得我们学习的,尤其我们对Python工程化不是太熟悉的小伙伴。
整个DeerFlow的开源项目的介绍,这里就全部介绍完了。希望可以帮助小伙伴们学习,谢谢大家!!!