3.1 新建adk_agent_tool_parallel python包
错误:module 'adk_agent_tool_parallel.agent' has no attribute 'root_agent'
0 环境准备
- ollama已部署推理模型qwen3:8b
- 已安装miniconda环境
- 具备科学上网条件
1 开发环境准备
1.1 创建项目python环境
通过conda命令创建项目的python开发环境
conda create -n mcp_demo python=3.10
1.2 在pycharm创建项目
- 解释器类型:选择自定义环境
- 环境:选择现有
- 类型:选择conda
- 环境:选择上一步创建的环境
1.3 安装项目依赖
安装adk、litellm相关依赖
安装python-dotenv python读取环境配置文件依赖
pip install google-adk litellm python-dotenv httpx
2 资源准备
本项目中需要调用天气接口获取城市的天气信息,因此需要注册天气API网站,并且获取调用key。
具体流程请参考以下链接的第二章节:MCP实战-基于Ollama+qwen2.5以sse方式实现MCP协议工具调用_mcp sse-CSDN博客
3 adk agent构建
3.1 新建adk_agent_tool_parallel python包
adk在识别agent时是一个python包一个agent,包名就是agent名字,因此我们需要新建一个目录,此例中是adk_agent_tool_parallel,如下图所示:
3.2 编辑__init__.py文件
from . import agent
这样可以是adk_agent_tool_parallel的内容可以被导入,adk可以识别并调用adk_agent_tool_parallel。
4 配置env
4.1 新建.env文件
4.2 编辑.env文件
填充模型,open weather等配置参数
OLLAMA_API_BASE=http://localhost:11434
MODEL=qwen3:8b
EMBEDDINGS_MODEL=quentinz/bge-large-zh-v1.5:latest
OPENAI_API_KEY=ollama
OPENWEATHER_API_KEY=5082xxxxd4cddffd1051163cb
OPENWEATHER_BASE_URL=https://api.openweathermap.org/data/2.5/weather
USER_AGENT=weather-app/1.0
注意将key换成自己的key,按照参考博客一步步申请。
5 agent逻辑实现
5.1 新建agent.py文件
5.2 导入相关依赖包
import json
import os
import httpx
from dotenv import load_dotenv
from google.adk.agents import LlmAgent, ParallelAgent
from google.adk.models.lite_llm import LiteLlm
5.3 加载配置文件
load_dotenv()
model_name = os.getenv('MODEL')
openweather_api_key = os.getenv('OPENWEATHER_API_KEY')
openweather_base_url = os.getenv('OPENWEATHER_BASE_URL')
user_agent = os.getenv('USER_AGENT')
5.4 定义请求天气接口方法
async def get_weather(city):
"""
从OpenWeather API 获取天气信息
:param city: 城市名称(需要试用英文,如 beijing)
:return: 天气数据字典;若发生错误,返回包含error信息的字典
"""
params = {
"q": city,
"appid": openweather_api_key,
"units": "metric",
"lang": "zh_cn",
}
headers = {"User-Agent": user_agent}
async with httpx.AsyncClient() as client:
try:
response = await client.get(openweather_base_url, params=params, headers=headers, timeout=30)
response.raise_for_status()
return response.json()
except httpx.HTTPStatusError as e:
return {"error": f"HTTP请求错误:{e}"}
except Exception as e:
return {"error": f"发生错误:{e}"}
5.5 定义格式化天气结果方法
def format_weather_data(data):
"""
格式化天气数据
:param data: 天气数据字典
:return: 格式化后的字符串;若发生错误,返回包含error信息的字符串
"""
# 如果传入的是字符串,则先转换成字典
if isinstance(data, str):
data = json.loads(data)
if "error" in data:
return data["error"]
weather = data["weather"][0]["description"]
temperature = data["main"]["temp"]
city = data["name"]
country = data["sys"]["country"]
humidity = data["main"]["humidity"]
wind = data["wind"]["speed"]
return f"城市:{city}, {country}\n天气:{weather}\n温度:{temperature}°C\n湿度:{humidity}%\n风速:{wind}m/s"
5.6 定义获取天气工具方法
async def get_weather_tool(city: str):
"""
查询即时天气函数
:param city: 必要参数,字符串类型,用于表示查询天气的具体城市名称,\
注意,中国的城市需要用对应城市的英文名称代替,例如如果需要查询北京市天气,则city参数需要输入'Beijing';
:return:OpenWeather API查询即时天气的结果,具体URL请求地址为:https://api.openweathermap.org/data/2.5/weather\
返回结果对象类型为解析之后的JSON格式对象,并用字符串形式进行表示,其中包含了全部重要的天气信息
"""
weather_data = await get_weather(city)
return format_weather_data(weather_data)
5.7 定义天气agent
weather_agent = LlmAgent(
name = "天气查询agent",
model=LiteLlm(model=f"ollama_chat/{model_name}"),
description = ("回答城市天气情况的问题"),
instruction = ("你是一个天气助手,根据输入的城市输出该城市的天气情况"),
tools = [get_weather_tool]
)
5.8 定义并行agent
paral_agent = ParallelAgent(
name = "并行agent",
sub_agents = [weather_agent],
description = ("你是一个并行agent,你可以并行执行多个子agent,你需要根据输入的问题,选择合适的子agent执行")
)
root_agent = paral_agent
注意一定要定义root_agent,adk必须要定义,否则无法识别。
6 测试
进入mcp_demo目录,执行adk web可以运行adk程序,这种方式是adk提供的web调用agent的方式,在此web页面可以看到完整的agent调用流程及过程参数和结果。
6.1 启动adk
adk web
在mcp_demo执行以上命令可以看到命令行输出信息,可以看到web访问地址如下图:
6.2 访问web地址
打开浏览器,地址栏输入http://localhost:8000/ ,如下图:
选中的是刚刚实现的adk_agent_tool_parallel工具。
6.3 输入问题
在聊天框输入”北京和武汉今天的天气怎么样“,可以看到adk调用的工具及调用结果如下图:
6.4 查看调试信息
点击聊天框内的get_weather_tool可以查看adk调用agent工具的过程、参数及调用结果。可以看到产生了长度为2的数组,通过functioncall的方式分别获取了北京和武汉的天气,如下图:
在后台日志中可以观察时间戳,看到两个chat几乎同时生成。
7 完整代码
import json
import os
import httpx
from dotenv import load_dotenv
from google.adk.agents import LlmAgent, ParallelAgent
from google.adk.models.lite_llm import LiteLlm
load_dotenv()
model_name = os.getenv('MODEL')
openweather_api_key = os.getenv('OPENWEATHER_API_KEY')
openweather_base_url = os.getenv('OPENWEATHER_BASE_URL')
user_agent = os.getenv('USER_AGENT')
async def get_weather(city):
"""
从OpenWeather API 获取天气信息
:param city: 城市名称(需要试用英文,如 beijing)
:return: 天气数据字典;若发生错误,返回包含error信息的字典
"""
params = {
"q": city,
"appid": openweather_api_key,
"units": "metric",
"lang": "zh_cn",
}
headers = {"User-Agent": user_agent}
async with httpx.AsyncClient() as client:
try:
response = await client.get(openweather_base_url, params=params, headers=headers, timeout=30)
response.raise_for_status()
return response.json()
except httpx.HTTPStatusError as e:
return {"error": f"HTTP请求错误:{e}"}
except Exception as e:
return {"error": f"发生错误:{e}"}
def format_weather_data(data):
"""
格式化天气数据
:param data: 天气数据字典
:return: 格式化后的字符串;若发生错误,返回包含error信息的字符串
"""
# 如果传入的是字符串,则先转换成字典
if isinstance(data, str):
data = json.loads(data)
if "error" in data:
return data["error"]
weather = data["weather"][0]["description"]
temperature = data["main"]["temp"]
city = data["name"]
country = data["sys"]["country"]
humidity = data["main"]["humidity"]
wind = data["wind"]["speed"]
return f"城市:{city}, {country}\n天气:{weather}\n温度:{temperature}°C\n湿度:{humidity}%\n风速:{wind}m/s"
async def get_weather_tool(city: str):
"""
查询即时天气函数
:param city: 必要参数,字符串类型,用于表示查询天气的具体城市名称,\
注意,中国的城市需要用对应城市的英文名称代替,例如如果需要查询北京市天气,则city参数需要输入'Beijing';
:return:OpenWeather API查询即时天气的结果,具体URL请求地址为:https://api.openweathermap.org/data/2.5/weather\
返回结果对象类型为解析之后的JSON格式对象,并用字符串形式进行表示,其中包含了全部重要的天气信息
"""
weather_data = await get_weather(city)
return format_weather_data(weather_data)
weather_agent = LlmAgent(
name = "天气查询agent",
model=LiteLlm(model=f"ollama_chat/{model_name}"),
description = ("回答城市天气情况的问题"),
instruction = ("你是一个天气助手,根据输入的城市输出该城市的天气情况"),
tools = [get_weather_tool]
)
paral_agent = ParallelAgent(
name = "并行agent",
sub_agents = [weather_agent],
description = ("你是一个并行agent,你可以并行执行多个子agent,你需要根据输入的问题,选择合适的子agent执行")
)
root_agent = paral_agent
附录:
项目目录结构
可能存在的问题
调用天气查询方法是连接超时,请检查是否开启科学上网。
错误:module 'adk_agent_tool_parallel.agent' has no attribute 'root_agent'
一定要定义root_agent变量,adk必须要定义,否则无法识别。最好agent.py以root_agent结尾。