init
This commit is contained in:
674
ADKLearning/google-adk-tutorial/10-advanced-topics.md
Normal file
674
ADKLearning/google-adk-tutorial/10-advanced-topics.md
Normal file
@@ -0,0 +1,674 @@
|
||||
# 第10章:高级主题
|
||||
|
||||
## 📌 本章目标
|
||||
|
||||
- 掌握 ADK 的安全最佳实践
|
||||
- 了解 A2A(Agent-to-Agent)协议
|
||||
- 学习多模型混合使用策略
|
||||
- 掌握自定义 Agent 的开发方法
|
||||
- 了解性能优化技巧
|
||||
|
||||
---
|
||||
|
||||
## 10.1 安全最佳实践
|
||||
|
||||
### 10.1.1 输入安全
|
||||
|
||||
```python
|
||||
"""
|
||||
输入安全:防止注入攻击和不当输入
|
||||
"""
|
||||
|
||||
from google.adk.agents import Agent # 导入 Agent 类
|
||||
from google.adk.agents.invocation_context import InvocationContext # 导入上下文
|
||||
import re # 导入正则表达式模块
|
||||
|
||||
|
||||
# ========================================
|
||||
# 输入过滤器
|
||||
# ========================================
|
||||
|
||||
async def input_filter_callback(
|
||||
callback_context, # 回调上下文
|
||||
invocation_context: InvocationContext, # 调用上下文
|
||||
):
|
||||
"""
|
||||
输入安全过滤回调
|
||||
在模型调用前检查用户输入的安全性
|
||||
"""
|
||||
|
||||
# 获取用户消息
|
||||
# 从调用上下文中获取最近的用户消息
|
||||
events = invocation_context.session.events # 获取会话事件
|
||||
user_messages = [ # 筛选用户消息
|
||||
e for e in events
|
||||
if hasattr(e, 'content') and e.content.role == 'user'
|
||||
]
|
||||
|
||||
if not user_messages: # 如果没有用户消息
|
||||
return # 直接返回
|
||||
|
||||
last_message = user_messages[-1] # 获取最后一条用户消息
|
||||
user_text = last_message.content.parts[0].text # 提取文本
|
||||
|
||||
# ========================================
|
||||
# 检查1:提示注入检测
|
||||
# ========================================
|
||||
injection_patterns = [ # 注入攻击模式
|
||||
r"忽略.*指令", # "忽略之前的指令"
|
||||
r"ignore.*instruction", # 英文注入
|
||||
r"你现在是", # 角色切换
|
||||
r"pretend.*you are", # 英文角色切换
|
||||
r"system\s*:", # 系统提示伪造
|
||||
]
|
||||
|
||||
for pattern in injection_patterns: # 遍历模式
|
||||
if re.search(pattern, user_text, re.IGNORECASE): # 如果匹配
|
||||
print(f"[安全] 检测到可能的注入攻击: {pattern}") # 记录警告
|
||||
# 在实际应用中,可以拒绝处理或返回安全提示
|
||||
|
||||
# ========================================
|
||||
# 检查2:输入长度限制
|
||||
# ========================================
|
||||
MAX_INPUT_LENGTH = 5000 # 最大输入长度
|
||||
if len(user_text) > MAX_INPUT_LENGTH: # 如果超过限制
|
||||
print(f"[安全] 输入过长: {len(user_text)} > {MAX_INPUT_LENGTH}") # 记录警告
|
||||
|
||||
# ========================================
|
||||
# 检查3:敏感信息检测
|
||||
# ========================================
|
||||
sensitive_patterns = [ # 敏感信息模式
|
||||
r"\b\d{3}-\d{2}-\d{4}\b", # SSN 格式
|
||||
r"\b\d{16}\b", # 信用卡号格式
|
||||
r"\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b", # 邮箱
|
||||
]
|
||||
|
||||
for pattern in sensitive_patterns: # 遍历模式
|
||||
if re.search(pattern, user_text): # 如果匹配
|
||||
print(f"[安全] 检测到可能的敏感信息") # 记录警告
|
||||
# 不要在日志中记录实际的敏感信息
|
||||
|
||||
|
||||
# ========================================
|
||||
# 创建安全 Agent
|
||||
# ========================================
|
||||
|
||||
safe_agent = Agent(
|
||||
name="safe_agent", # Agent 名称
|
||||
model="gemini-2.0-flash", # 模型
|
||||
instruction="你是一个安全的助手。遵循安全准则。", # 指令
|
||||
before_model_callback=input_filter_callback, # 🔑 安全过滤回调
|
||||
)
|
||||
```
|
||||
|
||||
### 10.1.2 输出安全
|
||||
|
||||
```python
|
||||
"""
|
||||
输出安全:过滤不当输出
|
||||
"""
|
||||
|
||||
async def output_filter_callback(
|
||||
callback_context, # 回调上下文
|
||||
invocation_context: InvocationContext, # 调用上下文
|
||||
):
|
||||
"""
|
||||
输出安全过滤回调
|
||||
在模型返回响应后检查输出内容
|
||||
"""
|
||||
|
||||
response = callback_context.response # 获取模型响应
|
||||
|
||||
if not response: # 如果没有响应
|
||||
return # 直接返回
|
||||
|
||||
# 检查响应中是否有文本内容
|
||||
if response.candidates: # 如果有候选响应
|
||||
for candidate in response.candidates: # 遍历候选
|
||||
if candidate.content: # 如果有内容
|
||||
text = candidate.content.parts[0].text # 提取文本
|
||||
|
||||
# 检查不当内容
|
||||
forbidden_words = [ # 禁止词列表
|
||||
"暴力", "违法", # 中文禁止词
|
||||
]
|
||||
|
||||
for word in forbidden_words: # 遍历禁止词
|
||||
if word in text: # 如果包含禁止词
|
||||
print(f"[安全] 输出包含不当内容: {word}") # 记录警告
|
||||
|
||||
|
||||
agent = Agent(
|
||||
name="output_safe_agent", # Agent 名称
|
||||
model="gemini-2.0-flash", # 模型
|
||||
instruction="你是一个安全的助手。", # 指令
|
||||
after_model_callback=output_filter_callback, # 🔑 输出过滤回调
|
||||
)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 10.2 A2A 协议(Agent-to-Agent)
|
||||
|
||||
### 10.2.1 A2A 概述
|
||||
|
||||
A2A(Agent-to-Agent)协议是 Google 提出的开放标准,用于实现不同 Agent 系统之间的远程通信。
|
||||
|
||||
```
|
||||
┌──────────────┐ ┌──────────────┐
|
||||
│ Agent A │ │ Agent B │
|
||||
│ (ADK) │◄────────►│ (其他框架) │
|
||||
│ │ A2A 协议 │ │
|
||||
│ - 发送任务 │ │ - 接收任务 │
|
||||
│ - 接收结果 │ │ - 返回结果 │
|
||||
└──────────────┘ └──────────────┘
|
||||
```
|
||||
|
||||
### 10.2.2 A2A 集成示例
|
||||
|
||||
```python
|
||||
"""
|
||||
A2A 协议集成示例
|
||||
让 ADK Agent 与远程 Agent 通信
|
||||
"""
|
||||
|
||||
from google.adk.agents import Agent # 导入 Agent 类
|
||||
from google.adk.tools import AgentTool # 导入 AgentTool
|
||||
|
||||
# ========================================
|
||||
# 创建远程 Agent 客户端
|
||||
# ========================================
|
||||
|
||||
# 假设有一个远程 Agent 服务运行在 http://remote-agent:3000
|
||||
# 可以通过 A2A 协议与之通信
|
||||
|
||||
# 在实际使用中,需要安装 A2A 客户端库
|
||||
# pip install a2a-sdk
|
||||
|
||||
# 创建远程 Agent 的代理
|
||||
# remote_agent_proxy = create_remote_agent_proxy(
|
||||
# url="http://remote-agent:3000", # 远程 Agent 地址
|
||||
# agent_name="RemoteExpert", # 远程 Agent 名称
|
||||
# )
|
||||
|
||||
# 将远程 Agent 包装为工具
|
||||
# remote_tool = AgentTool(agent=remote_agent_proxy)
|
||||
|
||||
# ========================================
|
||||
# 在本地 Agent 中使用远程 Agent
|
||||
# ========================================
|
||||
|
||||
local_agent = Agent(
|
||||
name="local_agent", # 本地 Agent 名称
|
||||
model="gemini-2.0-flash", # 模型
|
||||
instruction=( # 指令
|
||||
"你是一个协调助手。\n"
|
||||
"对于本地可以处理的问题,直接回答。\n"
|
||||
"对于需要专业知识的问题,使用远程 Agent 工具。"
|
||||
),
|
||||
# tools=[remote_tool], # 注册远程 Agent 工具
|
||||
)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 10.3 自定义 Agent 开发
|
||||
|
||||
### 10.3.1 继承 BaseAgent
|
||||
|
||||
```python
|
||||
"""
|
||||
自定义 Agent 开发
|
||||
通过继承 BaseAgent 实现独特的 Agent 逻辑
|
||||
"""
|
||||
|
||||
from google.adk.agents import BaseAgent # 导入基础 Agent 类
|
||||
from google.adk.agents.invocation_context import InvocationContext # 导入调用上下文
|
||||
from google.adk.events import Event, EventActions # 导入事件类型
|
||||
from typing import AsyncGenerator # 导入异步生成器
|
||||
import json # 导入 JSON 模块
|
||||
import random # 导入随机数模块
|
||||
|
||||
|
||||
# ========================================
|
||||
# 示例一:随机决策 Agent
|
||||
# ========================================
|
||||
|
||||
class RandomDecisionAgent(BaseAgent):
|
||||
"""
|
||||
随机决策 Agent
|
||||
随机选择一个子 Agent 来处理请求
|
||||
"""
|
||||
|
||||
async def _run_async_impl(
|
||||
self,
|
||||
ctx: InvocationContext, # 调用上下文
|
||||
) -> AsyncGenerator[Event, None]: # 返回事件生成器
|
||||
"""异步执行方法"""
|
||||
|
||||
# 获取子 Agent 列表
|
||||
sub_agents = self.sub_agents # 获取子 Agent
|
||||
|
||||
if not sub_agents: # 如果没有子 Agent
|
||||
yield Event( # 生成错误事件
|
||||
author=self.name, # 作者
|
||||
content="没有可用的子 Agent。", # 错误消息
|
||||
)
|
||||
return # 退出
|
||||
|
||||
# 随机选择一个子 Agent
|
||||
chosen = random.choice(sub_agents) # 随机选择
|
||||
print(f"[随机] 选择了 {chosen.name}") # 打印选择结果
|
||||
|
||||
# 将选择结果保存到状态
|
||||
ctx.session.state["temp:chosen_agent"] = chosen.name # 保存选择
|
||||
|
||||
# 生成事件,指示委派给选中的 Agent
|
||||
yield Event( # 生成委派事件
|
||||
author=self.name, # 作者
|
||||
actions=EventActions( # 事件动作
|
||||
transfer_to_agent=chosen.name, # 委派给选中的 Agent
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
# ========================================
|
||||
# 示例二:规则引擎 Agent
|
||||
# ========================================
|
||||
|
||||
class RuleEngineAgent(BaseAgent):
|
||||
"""
|
||||
规则引擎 Agent
|
||||
基于预定义规则处理请求,不使用 LLM
|
||||
"""
|
||||
|
||||
def __init__(self, rules: dict, **kwargs):
|
||||
"""
|
||||
初始化规则引擎
|
||||
|
||||
Args:
|
||||
rules: 规则字典,key 为匹配模式,value 为响应
|
||||
"""
|
||||
super().__init__(**kwargs) # 调用父类初始化
|
||||
self.rules = rules # 保存规则
|
||||
|
||||
async def _run_async_impl(
|
||||
self,
|
||||
ctx: InvocationContext, # 调用上下文
|
||||
) -> AsyncGenerator[Event, None]: # 返回事件生成器
|
||||
"""异步执行方法"""
|
||||
|
||||
# 获取用户消息
|
||||
events = ctx.session.events # 获取会话事件
|
||||
user_events = [ # 筛选用户消息
|
||||
e for e in events
|
||||
if hasattr(e, 'content') and e.content.role == 'user'
|
||||
]
|
||||
|
||||
if not user_events: # 如果没有用户消息
|
||||
yield Event( # 生成提示事件
|
||||
author=self.name,
|
||||
content="请输入您的问题。",
|
||||
)
|
||||
return # 退出
|
||||
|
||||
user_text = user_events[-1].content.parts[0].text # 提取文本
|
||||
|
||||
# 匹配规则
|
||||
matched_response = None # 匹配的响应
|
||||
for pattern, response in self.rules.items(): # 遍历规则
|
||||
if pattern.lower() in user_text.lower(): # 如果匹配
|
||||
matched_response = response # 保存响应
|
||||
break # 跳出循环
|
||||
|
||||
if matched_response: # 如果匹配到规则
|
||||
yield Event( # 生成响应事件
|
||||
author=self.name, # 作者
|
||||
content=matched_response, # 响应内容
|
||||
)
|
||||
else: # 如果没有匹配
|
||||
yield Event( # 生成默认响应
|
||||
author=self.name,
|
||||
content="抱歉,我无法处理您的请求。请尝试其他问题。",
|
||||
)
|
||||
|
||||
|
||||
# ========================================
|
||||
# 使用自定义 Agent
|
||||
# ========================================
|
||||
|
||||
# 创建规则引擎 Agent
|
||||
faq_agent = RuleEngineAgent(
|
||||
name="FAQBot", # Agent 名称
|
||||
rules={ # 规则字典
|
||||
"价格": "我们的产品价格请参考官网定价页面。", # 价格相关
|
||||
"地址": "我们的地址是北京市海淀区xxx路xxx号。", # 地址相关
|
||||
"电话": "客服电话:400-xxx-xxxx。", # 电话相关
|
||||
"营业时间": "营业时间:周一至周五 9:00-18:00。", # 营业时间
|
||||
},
|
||||
)
|
||||
|
||||
# 创建随机决策 Agent
|
||||
random_agent = RandomDecisionAgent(
|
||||
name="RandomRouter", # Agent 名称
|
||||
sub_agents=[ # 子 Agent 列表
|
||||
faq_agent, # FAQ Agent
|
||||
],
|
||||
)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 10.4 多模型混合策略
|
||||
|
||||
```python
|
||||
"""
|
||||
多模型混合使用
|
||||
根据任务类型选择不同的模型
|
||||
"""
|
||||
|
||||
from google.adk.agents import LlmAgent # 导入 LlmAgent
|
||||
from google.adk.models.lite_llm import LiteLlm # 导入 LiteLLM
|
||||
|
||||
|
||||
# ========================================
|
||||
# 策略一:不同 Agent 使用不同模型
|
||||
# ========================================
|
||||
|
||||
# 简单任务使用快速模型
|
||||
simple_agent = LlmAgent(
|
||||
name="SimpleAgent", # 简单任务 Agent
|
||||
model="gemini-2.0-flash", # 快速模型
|
||||
description="处理简单的问答和翻译任务。", # 描述
|
||||
instruction="快速准确地回答简单问题。", # 指令
|
||||
)
|
||||
|
||||
# 复杂推理使用强力模型
|
||||
reasoning_agent = LlmAgent(
|
||||
name="ReasoningAgent", # 推理 Agent
|
||||
model="gemini-2.5-pro-preview-05-06", # 强力模型
|
||||
description="处理需要深度推理的复杂任务。", # 描述
|
||||
instruction="仔细分析问题,给出深入的推理过程。", # 指令
|
||||
)
|
||||
|
||||
# 代码生成使用专用模型
|
||||
code_agent = LlmAgent(
|
||||
name="CodeAgent", # 代码 Agent
|
||||
model=LiteLlm( # 使用 LiteLLM
|
||||
model="deepseek/deepseek-coder", # DeepSeek Coder
|
||||
api_key="your_api_key", # API Key
|
||||
),
|
||||
description="处理代码生成和调试任务。", # 描述
|
||||
instruction="编写高质量的代码。", # 指令
|
||||
)
|
||||
|
||||
# 协调器使用快速模型
|
||||
coordinator = LlmAgent(
|
||||
name="Coordinator", # 协调器
|
||||
model="gemini-2.0-flash", # 快速模型
|
||||
instruction=( # 指令
|
||||
"根据任务复杂度分配给合适的 Agent:\n"
|
||||
"- 简单问答 → SimpleAgent\n"
|
||||
"- 复杂推理 → ReasoningAgent\n"
|
||||
"- 代码相关 → CodeAgent"
|
||||
),
|
||||
sub_agents=[simple_agent, reasoning_agent, code_agent], # 子 Agent
|
||||
)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 10.5 性能优化技巧
|
||||
|
||||
### 10.5.1 指令优化
|
||||
|
||||
```python
|
||||
"""
|
||||
指令优化技巧
|
||||
减少 token 使用,提高响应速度
|
||||
"""
|
||||
|
||||
# ❌ 冗长的指令(浪费 token)
|
||||
verbose_instruction = """
|
||||
你是一个非常专业的、经验丰富的、知识渊博的助手。
|
||||
你擅长回答各种各样的问题,包括但不限于技术问题、
|
||||
生活问题、工作问题、学习问题等等。
|
||||
当用户问你问题时,你应该:
|
||||
1. 首先理解用户的问题
|
||||
2. 然后分析问题
|
||||
3. 最后给出答案
|
||||
请始终使用中文回答。
|
||||
"""
|
||||
|
||||
# ✅ 精简的指令(节省 token)
|
||||
concise_instruction = """
|
||||
你是专业助手。用中文简洁回答。
|
||||
"""
|
||||
|
||||
# ✅ 使用结构化指令
|
||||
structured_instruction = """
|
||||
## 角色
|
||||
技术助手
|
||||
|
||||
## 规则
|
||||
1. 使用中文
|
||||
2. 简洁回答(<200字)
|
||||
3. 不确定时说"不确定"
|
||||
"""
|
||||
```
|
||||
|
||||
### 10.5.2 工具优化
|
||||
|
||||
```python
|
||||
"""
|
||||
工具优化技巧
|
||||
减少不必要的工具调用
|
||||
"""
|
||||
|
||||
# ❌ 工具描述过于详细(浪费 token)
|
||||
def bad_tool(query: str) -> dict:
|
||||
"""
|
||||
这是一个非常详细的工具描述,包含了大量的信息,
|
||||
但是大部分信息对 LLM 来说是不必要的。
|
||||
LLM 需要读取所有这些文本来理解工具的功能,
|
||||
这会消耗大量的 token 并降低响应速度。
|
||||
"""
|
||||
return {"result": "done"}
|
||||
|
||||
# ✅ 精简的工具描述
|
||||
def good_tool(query: str) -> dict:
|
||||
"""搜索知识库并返回相关文档片段。"""
|
||||
return {"result": "done"}
|
||||
|
||||
# ✅ 合并相似工具
|
||||
# 如果有多个功能相似的工具,考虑合并
|
||||
def unified_search(
|
||||
query: str, # 搜索关键词
|
||||
search_type: str = "all", # 搜索类型:all/doc/faq
|
||||
) -> dict:
|
||||
"""
|
||||
统一搜索工具
|
||||
|
||||
Args:
|
||||
query: 搜索关键词
|
||||
search_type: 搜索类型,可选 "all"(全部)、"doc"(文档)、"faq"(FAQ)
|
||||
"""
|
||||
return {"status": "success", "results": []}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 10.6 完整实战项目:智能客服系统
|
||||
|
||||
```python
|
||||
"""
|
||||
完整实战项目:多智能体客服系统
|
||||
整合本教程所有知识点
|
||||
"""
|
||||
|
||||
from google.adk.agents import ( # 导入所有 Agent 类型
|
||||
Agent, # LLM Agent
|
||||
LlmAgent, # LLM Agent(完整名)
|
||||
SequentialAgent, # 顺序工作流
|
||||
ParallelAgent, # 并行工作流
|
||||
LoopAgent, # 循环工作流
|
||||
BaseAgent, # 基础 Agent
|
||||
)
|
||||
from google.adk.events import Event, EventActions # 导入事件类型
|
||||
from google.adk.agents.invocation_context import InvocationContext # 导入上下文
|
||||
from google.adk.tools import google_search # 导入 Google 搜索
|
||||
from typing import AsyncGenerator # 导入异步生成器
|
||||
import asyncio # 导入异步库
|
||||
|
||||
|
||||
# ========================================
|
||||
# 第一步:定义工具
|
||||
# ========================================
|
||||
|
||||
def search_faq(query: str) -> dict:
|
||||
"""搜索常见问题解答"""
|
||||
faq_db = { # FAQ 数据库
|
||||
"退款": "退款将在3-5个工作日内处理完成。", # 退款
|
||||
"配送": "标准配送3-5天,加急配送1-2天。", # 配送
|
||||
"退换货": "7天无理由退换货,请保持商品完好。", # 退换货
|
||||
}
|
||||
for key, value in faq_db.items(): # 遍历 FAQ
|
||||
if key in query: # 如果匹配
|
||||
return {"status": "success", "answer": value} # 返回答案
|
||||
return {"status": "not_found", "answer": "未找到相关FAQ。"} # 未找到
|
||||
|
||||
|
||||
def create_ticket(
|
||||
category: str, # 工单类别
|
||||
description: str, # 问题描述
|
||||
priority: str = "normal", # 优先级
|
||||
) -> dict:
|
||||
"""创建客户工单"""
|
||||
ticket_id = f"TK{len(description)}" # 生成工单号
|
||||
return { # 返回工单信息
|
||||
"status": "success",
|
||||
"ticket_id": ticket_id,
|
||||
"message": f"工单 {ticket_id} 已创建,我们会尽快处理。",
|
||||
}
|
||||
|
||||
|
||||
# ========================================
|
||||
# 第二步:定义子 Agent
|
||||
# ========================================
|
||||
|
||||
# FAQ Agent:处理常见问题
|
||||
faq_agent = LlmAgent(
|
||||
name="FAQBot", # FAQ 机器人
|
||||
model="gemini-2.0-flash", # 快速模型
|
||||
description="处理常见问题,如退款、配送、退换货等。", # 描述
|
||||
instruction="你是FAQ助手,使用 search_faq 工具查找答案。", # 指令
|
||||
tools=[search_faq], # FAQ 搜索工具
|
||||
)
|
||||
|
||||
# 搜索 Agent:处理需要联网查询的问题
|
||||
search_agent = LlmAgent(
|
||||
name="SearchBot", # 搜索机器人
|
||||
model="gemini-2.0-flash", # 快速模型
|
||||
description="处理需要搜索互联网的问题。", # 描述
|
||||
instruction="使用 Google Search 搜索最新信息。", # 指令
|
||||
tools=[google_search], # Google 搜索工具
|
||||
)
|
||||
|
||||
# 工单 Agent:处理需要人工介入的问题
|
||||
ticket_agent = LlmAgent(
|
||||
name="TicketBot", # 工单机器人
|
||||
model="gemini-2.0-flash", # 快速模型
|
||||
description="创建客户工单,转交人工处理。", # 描述
|
||||
instruction="收集用户问题描述,使用 create_ticket 创建工单。", # 指令
|
||||
tools=[create_ticket], # 创建工单工具
|
||||
)
|
||||
|
||||
# ========================================
|
||||
# 第三步:定义协调器
|
||||
# ========================================
|
||||
|
||||
coordinator = LlmAgent(
|
||||
name="CustomerServiceCoordinator", # 客服协调器
|
||||
model="gemini-2.0-flash", # 快速模型
|
||||
description="智能客服主协调器,负责路由用户请求。", # 描述
|
||||
instruction=( # 系统指令
|
||||
"你是一个智能客服协调器。\n"
|
||||
"根据用户问题类型,分配给合适的子 Agent:\n"
|
||||
"- 退款、配送、退换货等常见问题 → FAQBot\n"
|
||||
"- 需要最新信息的问题 → SearchBot\n"
|
||||
"- 无法自动解决的问题 → TicketBot\n"
|
||||
"使用 transfer_to_agent 进行任务分配。"
|
||||
),
|
||||
sub_agents=[ # 注册子 Agent
|
||||
faq_agent, # FAQ 机器人
|
||||
search_agent, # 搜索机器人
|
||||
ticket_agent, # 工单机器人
|
||||
],
|
||||
)
|
||||
|
||||
# ========================================
|
||||
# 第四步:添加监控回调
|
||||
# ========================================
|
||||
|
||||
async def monitoring_callback(cb_ctx, inv_ctx):
|
||||
"""监控回调:记录所有操作"""
|
||||
agent_name = inv_ctx.agent.name # 获取 Agent 名称
|
||||
print(f"[监控] Agent '{agent_name}' 正在处理请求") # 打印日志
|
||||
|
||||
|
||||
coordinator.before_model_callback = monitoring_callback # 添加监控
|
||||
|
||||
# ========================================
|
||||
# 第五步:设置 root_agent
|
||||
# ========================================
|
||||
|
||||
root_agent = coordinator # 设置根 Agent
|
||||
|
||||
print("✅ 智能客服系统构建完成!") # 打印成功信息
|
||||
print(f"根 Agent: {root_agent.name}") # 打印根 Agent 名称
|
||||
print(f"子 Agent 数量: {len(root_agent.sub_agents)}") # 打印子 Agent 数量
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📌 本章小结
|
||||
|
||||
- 输入安全:检测注入攻击、限制输入长度、过滤敏感信息
|
||||
- 输出安全:过滤不当内容、记录审计日志
|
||||
- A2A 协议:实现不同 Agent 系统间的远程通信
|
||||
- 自定义 Agent:继承 BaseAgent 实现独特逻辑
|
||||
- 多模型策略:根据任务类型选择合适的模型
|
||||
- 性能优化:精简指令、合并工具、合理选择模型
|
||||
|
||||
---
|
||||
|
||||
## 🎉 教程完结
|
||||
|
||||
恭喜你完成了 Google ADK 完整教程的学习!
|
||||
|
||||
### 学习路径回顾
|
||||
|
||||
```
|
||||
第01章 环境搭建 → 第02章 Hello World
|
||||
↓
|
||||
第03章 LLM Agent → 第04章 自定义工具
|
||||
↓
|
||||
第05章 多智能体 → 第06章 会话状态
|
||||
↓
|
||||
第07章 回调机制 → 第08章 评估
|
||||
↓
|
||||
第09章 部署 → 第10章 高级主题
|
||||
```
|
||||
|
||||
### 后续学习建议
|
||||
|
||||
1. **实践项目**:基于教程知识,构建自己的 Agent 应用
|
||||
2. **阅读源码**:深入研究 [adk-python](https://github.com/google/adk-python) 源码
|
||||
3. **社区参与**:关注 ADK 的更新和社区讨论
|
||||
4. **探索生态**:了解 ADK 的 Java、Go 版本和 Web 版本
|
||||
|
||||
### 官方资源
|
||||
|
||||
- 📖 [官方文档](https://google.github.io/adk-docs/)
|
||||
- 💻 [GitHub 仓库](https://github.com/google/adk-python)
|
||||
- 📦 [示例代码](https://github.com/google/adk-samples)
|
||||
Reference in New Issue
Block a user