Files
Agent-Docs/ADKLearning/google-adk-tutorial/02-quick-start-hello-world.md
Nelson 514723dbe7 init
2026-04-06 12:36:04 +08:00

389 lines
13 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 第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 的配置和高级用法。