This commit is contained in:
Nelson
2026-04-06 12:36:04 +08:00
commit 514723dbe7
23 changed files with 7529 additions and 0 deletions

View File

@@ -0,0 +1,388 @@
# 第02章快速开始 — Hello World
## 📌 本章目标
- 使用 `adk create` 创建第一个 Agent 项目
- 理解 Agent 项目结构
- 编写一个带有自定义工具的 Agent
- 通过 CLI 和 Web UI 两种方式运行 Agent
---
## 2.1 创建 Agent 项目
### 2.1.1 使用 CLI 创建项目
```bash
# 在工作目录下创建一个新的 Agent 项目
adk create hello_world
# 创建完成后,会生成以下目录结构:
# hello_world/
# ├── agent.py # Agent 主代码文件(核心)
# ├── .env # 环境变量配置文件API Key 等)
# └── __init__.py # Python 包初始化文件
```
### 2.1.2 项目结构说明
```
hello_world/
├── agent.py # 🔑 核心文件:定义 Agent 的行为和工具
│ # - root_agent 变量是 ADK 的入口点
│ # - 可以定义自定义工具函数
├── .env # 🔑 配置文件:存储 API Key 等敏感信息
│ # - GOOGLE_API_KEY="your_key_here"
│ # - 不会被提交到版本控制
└── __init__.py # Python 包标识文件
# - 使目录成为 Python 包
# - 通常为空文件
```
> ⚠️ **重要**`agent.py` 中的 `root_agent` 是 ADK 识别 Agent 的入口点,这个变量名**不能修改**。
---
## 2.2 编写第一个 Agent
### 2.2.1 最简单的 Agent
打开 `agent.py`,编写最基础的 Agent
```python
"""
第一个 Google ADK Agent 示例
这是一个最简单的 Agent不包含任何自定义工具
"""
# 从 ADK 的 agents 模块导入 Agent 类
# Agent 是 LlmAgent 的别名,是最常用的智能体类型
from google.adk.agents import Agent
# 定义 root_agent —— 这是 ADK 的入口点
# ADK 会自动查找名为 root_agent 的变量
root_agent = Agent(
name="hello_agent", # Agent 的名称,用于标识和日志
model="gemini-2.0-flash", # 使用的 LLM 模型
instruction="你是一个友好的助手。", # 系统指令,定义 Agent 的角色和行为
)
```
### 2.2.2 带工具的 Agent
让我们给 Agent 添加一个获取当前时间的工具:
```python
"""
带自定义工具的 Hello World Agent
演示如何为 Agent 添加自定义函数工具
"""
# 导入 ADK 的 Agent 类
from google.adk.agents import Agent
# 导入标准库:日期时间处理
import datetime # 用于获取当前时间
from zoneinfo import ZoneInfo # 用于处理时区信息
# ========================================
# 定义自定义工具函数
# ========================================
def get_current_time(city: str) -> dict:
"""
获取指定城市的当前时间
这个函数会被 ADK 自动转换为工具FunctionTool
Agent 可以在对话中调用这个工具来获取时间信息。
Args:
city (str): 需要查询时间的城市名称,例如"北京""东京""纽约"
Returns:
dict: 包含状态和结果的字典
- status: "success""error"
- report: 时间信息或错误消息
"""
# 定义城市到时区的映射字典
city_timezone_map = { # 常见城市对应的时区
"北京": "Asia/Shanghai", # 北京使用上海时区
"上海": "Asia/Shanghai", # 上海使用上海时区
"东京": "Asia/Tokyo", # 东京时区
"纽约": "America/New_York", # 纽约时区
"伦敦": "Europe/London", # 伦敦时区
"巴黎": "Europe/Paris", # 巴黎时区
}
# 查找城市对应的时区标识符
tz_identifier = city_timezone_map.get(city) # 从字典中获取时区
# 如果找不到该城市的时区信息
if not tz_identifier:
return { # 返回错误信息
"status": "error", # 状态标记为错误
"error_message": f"未找到'{city}'的时区信息,请尝试其他城市。" # 错误描述
}
# 根据时区标识符创建时区对象
tz = ZoneInfo(tz_identifier) # 创建 ZoneInfo 时区对象
# 获取该时区的当前时间
now = datetime.datetime.now(tz) # 获取指定时区的当前时间
# 格式化时间字符串
time_str = now.strftime( # 将时间格式化为字符串
"%Y-%m-%d %H:%M:%S %Z%z" # 格式:年-月-日 时:分:秒 时区
)
# 返回成功结果
return { # 返回包含时间信息的字典
"status": "success", # 状态标记为成功
"city": city, # 城市名称
"time": time_str # 格式化后的时间字符串
}
# ========================================
# 定义 Agent
# ========================================
root_agent = Agent(
name="hello_agent", # Agent 的唯一标识名称
model="gemini-2.0-flash", # 使用 Gemini 2.0 Flash 模型
description="一个能查询城市时间的友好助手。", # Agent 的描述,用于多 Agent 场景
instruction=( # 系统指令(多行字符串)
"你是一个友好的助手,可以帮助用户查询世界各城市的当前时间。\n"
"当用户询问某个城市的时间时,使用 get_current_time 工具来获取。\n"
"如果工具返回错误,请友好地告知用户并建议尝试其他城市。\n"
"回复时请使用中文。"
),
tools=[get_current_time], # 将自定义函数注册为 Agent 的工具
)
```
---
## 2.3 配置 API Key
在运行 Agent 之前,需要配置 API Key
```bash
# 方法一:在 .env 文件中配置(推荐)
echo 'GOOGLE_API_KEY="你的_GEMINI_API_KEY"' > hello_world/.env
# 方法二:通过环境变量设置
export GOOGLE_API_KEY="你的_GEMINI_API_KEY"
# 方法三:直接在代码中设置(不推荐,有安全风险)
```
> 💡 **获取 API Key**:访问 [Google AI Studio](https://aistudio.google.com/app/apikey),点击 "Create API Key" 即可免费获取。
---
## 2.4 运行 Agent
### 2.4.1 命令行交互模式CLI
```bash
# 在项目父目录下运行(不是在 hello_world 目录内)
adk run hello_world
# 运行后进入交互式对话界面:
# Running agent hello_agent, type exit to exit.
# [user]: 北京现在几点?
# [hello_agent]: 北京当前时间是 2025-04-05 14:30:00 CST+0800。
# [user]: exit
```
### 2.4.2 Web UI 模式
```bash
# 启动 Web 服务器(默认端口 8000
adk web --port 8000
# 浏览器打开 http://localhost:8000
# 在左上角选择 Agent然后输入问题进行对话
```
Web UI 提供以下功能:
- 💬 **对话界面**:与 Agent 进行交互式对话
- 📊 **Event 面板**:查看工具调用和事件流
- 📋 **Request/Response**:查看原始请求和响应数据
- 🔍 **调试信息**:帮助排查问题
### 2.4.3 代码方式运行
除了 CLI 和 Web UI还可以通过 Python 代码直接运行 Agent
```python
"""
通过 Python 代码直接运行 Agent
适用于集成到自己的应用中
"""
# 导入必要的模块
from google.adk.agents import Agent # Agent 类
from google.adk.runners import Runner # 运行器,负责执行 Agent
from google.adk.sessions import InMemorySessionService # 内存会话服务
from google.genai import types # Google GenAI 类型定义
# 导入异步运行支持
import asyncio # 异步编程库
# ========================================
# 定义工具函数
# ========================================
def get_current_time(city: str) -> dict:
"""获取指定城市的当前时间"""
import datetime # 导入日期时间模块
from zoneinfo import ZoneInfo # 导入时区模块
city_timezone_map = { # 城市时区映射
"北京": "Asia/Shanghai",
"上海": "Asia/Shanghai",
"东京": "Asia/Tokyo",
"纽约": "America/New_York",
"伦敦": "Europe/London",
}
tz_identifier = city_timezone_map.get(city) # 查找时区
if not tz_identifier: # 如果找不到时区
return { # 返回错误
"status": "error",
"error_message": f"未找到'{city}'的时区信息"
}
tz = ZoneInfo(tz_identifier) # 创建时区对象
now = datetime.datetime.now(tz) # 获取当前时间
time_str = now.strftime("%Y-%m-%d %H:%M:%S %Z%z") # 格式化时间
return { # 返回结果
"status": "success",
"city": city,
"time": time_str
}
# ========================================
# 定义 Agent
# ========================================
root_agent = Agent(
name="hello_agent", # Agent 名称
model="gemini-2.0-flash", # 使用 Gemini 模型
instruction="你是一个友好的时间查询助手。使用工具获取城市时间。", # 系统指令
tools=[get_current_time], # 注册工具
)
# ========================================
# 定义运行逻辑
# ========================================
# 定义应用名称、用户ID和会话ID
APP_NAME = "hello_world_app" # 应用名称,用于标识
USER_ID = "user_001" # 用户唯一标识
SESSION_ID = "session_001" # 会话唯一标识
async def main():
"""主函数:异步运行 Agent"""
# 第一步:创建会话服务
# InMemorySessionService 将会话数据存储在内存中
# 适用于开发和测试,数据在程序重启后会丢失
session_service = InMemorySessionService()
# 第二步:创建会话
# 会话Session代表一次对话交互
# 包含消息历史、状态数据等
session = await session_service.create_session(
app_name=APP_NAME, # 关联的应用名称
user_id=USER_ID, # 用户标识
session_id=SESSION_ID, # 会话标识
)
# 第三步:创建运行器
# Runner 是 ADK 的核心执行引擎
# 负责协调 Agent、会话服务和工具调用
runner = Runner(
agent=root_agent, # 要运行的 Agent
app_name=APP_NAME, # 应用名称
session_service=session_service, # 会话服务
)
# 第四步:构造用户消息
# Content 对象表示一条消息
# role='user' 表示这是用户发送的消息
content = types.Content(
role='user', # 消息角色:用户
parts=[types.Part(text='北京现在几点?')] # 消息内容
)
# 第五步:运行 Agent 并获取响应
# run_async 返回一个异步事件流
# 我们需要遍历所有事件来获取最终响应
events = runner.run_async(
user_id=USER_ID, # 用户标识
session_id=SESSION_ID, # 会话标识
new_message=content, # 用户消息
)
# 第六步:处理事件流
async for event in events: # 遍历所有事件
if event.is_final_response(): # 如果是最终响应事件
# 从事件中提取文本内容
final_response = event.content.parts[0].text
print(f"Agent 回复: {final_response}") # 打印 Agent 的回复
# 运行主函数
if __name__ == "__main__": # 当脚本被直接运行时
asyncio.run(main()) # 使用 asyncio 运行异步主函数
```
---
## 2.5 理解 Agent 的核心参数
`Agent` 构造函数接受以下关键参数:
| 参数 | 类型 | 必需 | 说明 |
|------|------|------|------|
| `name` | str | ✅ | Agent 的唯一标识名称 |
| `model` | str | ✅ | 使用的 LLM 模型名称 |
| `instruction` | str | ❌ | 系统指令,定义 Agent 的角色和行为 |
| `description` | str | ❌ | Agent 描述,用于多 Agent 场景中的路由 |
| `tools` | list | ❌ | Agent 可用的工具列表 |
| `sub_agents` | list | ❌ | 子 Agent 列表,用于多 Agent 系统 |
| `output_key` | str | ❌ | 输出保存到 State 的键名 |
| `before_model_callback` | func | ❌ | 模型调用前的回调函数 |
| `after_model_callback` | func | ❌ | 模型调用后的回调函数 |
| `before_tool_callback` | func | ❌ | 工具调用前的回调函数 |
| `after_tool_callback` | func | ❌ | 工具调用后的回调函数 |
---
## 2.6 完整代码示例
详见 `code/hello_world.py` — 包含完整的带工具的 Hello World Agent 示例。
---
## 📌 本章小结
- 使用 `adk create` 快速创建 Agent 项目
- `agent.py` 中的 `root_agent` 是 ADK 的入口点
- 自定义工具就是普通的 Python 函数ADK 会自动转换为 FunctionTool
- 三种运行方式CLI`adk run`、Web UI`adk web`)、代码调用
- Runner 是 ADK 的核心执行引擎,负责协调 Agent 和会话
**下一章**[第03章 - LLM 智能体详解](./03-llm-agent-in-depth.md) → 深入了解 LlmAgent 的配置和高级用法。