Files
zen-agent/examples/cookbook_drive_guide.ipynb

24 KiB

Cookbook: Drive Guide

In this cookbook, we will demonstrate how to query the distance between two locations and create a driving plan using an agent.

Install Requirements

We will use Qwen-Agent in this book. For demonstration, we will need at least the mcp functionality of Qwen-Agent.

In [ ]:
!pip3 install -U "qwen-agent[gui,rag,code_interpreter,mcp]"
# `pip install -U qwen-agent` will install the minimal requirements.
# The optional requirements, specified in double brackets, are:
#   [gui] for Gradio-based GUI support;
#   [rag] for RAG support;
#   [code_interpreter] for Code Interpreter support;
#   [mcp] for MCP support.

Step 1: Create an Agent

Create an agent that is capable of utilizing map functionalities provided by Amap.

An api key for Amap is needed, instructions are at https://lbs.amap.com/api/mcp-server/summary

In [1]:
from qwen_agent.agents import Assistant
from qwen_agent.utils.output_beautify import typewriter_print
# `typewriter_print` prints streaming messages in a non-overlapping manner for a clear view.
In [2]:
llm_cfg = {
    'model': 'qwen3-32b',
    'model_server': 'dashscope',
    'api_key': '' # **fill your dashscope api key here**

    # Use a model service compatible with the OpenAI API, such as vLLM or Ollama:
    # 'model': 'Qwen3-8B',
    # 'model_server': 'http://localhost:8000/v1',  # base_url, also known as api_base
    # 'api_key': 'EMPTY'
}

tools = [
    {
        "mcpServers": {
            # enumeration of mcp server configs
            "amap-amap-sse": {
                "url": "https://mcp.amap.com/sse?key=YOUR_KEY" # **fill your amap mcp key**
            }
        }
    }
]

agent = Assistant(
    llm=llm_cfg, 
    function_list=tools
)
2025-05-01 21:12:51,768 - mcp_manager.py - 110 - INFO - Initializing MCP tools from mcp servers: ['amap-amap-sse']

Step 2: Calculate the Distance

We can query the distance between two locations by prompting the agent, which will then provide an answer utilizing the MCP server.

In [3]:
query = "How far is it between Zhejiang University (more specifically, the Zijingang Campus) and Hangzhou Xiaoshan airport?"
messages = [{'role': 'user', 'content': query}]
In [4]:
response_plain_text = ''

for ret_messages in agent.run(messages):
    response_plain_text = typewriter_print(ret_messages, response_plain_text)
[THINK]
Okay, the user is asking for the distance between Zhejiang University's Zijingang Campus and Hangzhou Xiaoshan Airport. Let me think about how to approach this.

First, I need to get the coordinates for both locations. For Zijingang Campus, I can use the amap-amap-sse-maps_geo function to convert the address into coordinates. The address would be something like "Zijingang Campus, Zhejiang University, Hangzhou, China". Similarly, for Hangzhou Xiaoshan Airport, the address is "Hangzhou Xiaoshan International Airport, Hangzhou, China".

Once I have both sets of coordinates, I can use the amap-amap-sse-maps_distance function to calculate the distance. The type parameter should be set to 1 for driving distance, as the user probably wants the driving distance rather than straight-line or walking.

Wait, but maybe I should check if there's a direct function for distance between two addresses. But looking at the available tools, the maps_distance function requires coordinates. So first, I need to get the coordinates for both places.

Let me outline the steps:
1. Use maps_geo for Zijingang Campus to get its latitude and longitude.
2. Use maps_geo for Xiaoshan Airport to get its coordinates.
3. Then use maps_distance with the obtained coordinates, specifying type 1 for driving distance.

But since I can't perform multiple function calls in one response, I need to handle this step by step. However, the user's query might expect a single answer. Wait, in the tools provided, there's the maps_distance function which can take origins and destination. But origins can be multiple, but here we need just one origin and one destination.

So first, I need to get the coordinates for both locations. Let me start by calling maps_geo for Zijingang Campus.

Wait, but the user mentioned Zijingang Campus specifically. Let me make sure the address is accurate. Maybe include the city as Hangzhou to help the geocoding.

Once I have the coordinates for both points, then call the distance function. But in the current setup, I have to make separate tool calls. However, in the problem statement, the assistant is supposed to call one or more functions. So I need to first call the geo function for both locations, then the distance function.

But the user's question is straightforward, so maybe there's a way to chain these calls. But according to the instructions, each turn the assistant can call one function. Wait, the user is asking for the distance between two places. The assistant needs to first get the coordinates for both, then calculate the distance. But since each tool call is separate, perhaps the assistant needs to make multiple steps.

But in the initial response, the assistant can only make one tool call. Wait, the user's question is a single query, but the assistant might need to perform multiple steps. However, the way the tools are set up, each turn allows for one tool call. So perhaps the assistant would first call the geo function for Zijingang Campus, then in the next step, call the geo function for the airport, then the distance function.

But since the user is asking for a single answer, the assistant needs to handle this in one go. Wait, maybe the assistant can use the maps_distance function directly if it can infer the coordinates. But without the exact coordinates, it can't. So the correct approach is to first get the coordinates for both locations using the geo function, then use the distance function.

Therefore, the first step is to call the maps_geo function for Zijingang Campus. Let me structure the first tool call for that.
[TOOL_CALL] amap-amap-sse-maps_geo
{"address": "Zijingang Campus, Zhejiang University, Hangzhou, China", "city": "Hangzhou"}
[TOOL_RESPONSE] amap-amap-sse-maps_geo
{"results":[{"country":"中国","province":"浙江省","city":"杭州市","citycode":"0571","district":"西湖区","street":[],"number":[],"adcode":"330106","location":"120.088667,30.304176","level":"住宅区"},{"country":"中国","province":"浙江省","city":"金华市","citycode":"0579","district":"婺城区","street":[],"number":[],"adcode":"330702","location":"119.636361,29.125844","level":"住宅区"},{"country":"中国","province":"浙江省","city":"台州市","citycode":"0576","district":"玉环市","street":[],"number":[],"adcode":"331083","location":"121.279790,28.089858","level":"住宅区"},{"country":"中国","province":"浙江省","city":"温州市","citycode":"0577","district":"瑞安市","street":[],"number":[],"adcode":"330381","location":"120.284507,27.761291","level":"住宅区"}]}
[THINK]
Okay, the user asked for the distance between Zhejiang University's Zijingang Campus and Hangzhou Xiaoshan Airport. First, I need to get the coordinates for both locations.

I started by using the maps_geo function for Zijingang Campus. The response gave several results, but the most relevant one is in Hangzhou's Xihu District with coordinates 120.088667,30.304176. That's the campus location.

Next, I need the coordinates for Hangzhou Xiaoshan Airport. I'll use the maps_geo function again with the address "Hangzhou Xiaoshan International Airport, Hangzhou, China". Let me make sure to specify the city as Hangzhou to avoid any confusion with other airports.

Once I get the airport's coordinates, I can use the maps_distance function to calculate the driving distance between the two points. The type parameter should be set to 1 for driving distance. Let me call the geo function for the airport now.
[TOOL_CALL] amap-amap-sse-maps_geo
{"address": "Hangzhou Xiaoshan International Airport, Hangzhou, China", "city": "Hangzhou"}
[TOOL_RESPONSE] amap-amap-sse-maps_geo
{"results":[{"country":"中国","province":"浙江省","city":"杭州市","citycode":"0571","district":"萧山区","street":[],"number":[],"adcode":"330109","location":"120.427708,30.228153","level":"住宅区"}]}
[THINK]
Okay, I need to find the distance between Zhejiang University's Zijingang Campus and Hangzhou Xiaoshan Airport. I've already used the maps_geo function to get the coordinates for both locations.

The campus is at 120.088667,30.304176 and the airport is at 120.427708,30.228153. Now, I should use the maps_distance function to calculate the driving distance between these two points. The parameters required are origins and destination, with type set to 1 for driving distance.

Let me format the origins as the campus coordinates and destination as the airport coordinates. I'll make sure to specify the type as 1 to get the driving distance. That should give the user the information they need.
[TOOL_CALL] amap-amap-sse-maps_distance
{"origins": "120.088667,30.304176", "destination": "120.427708,30.228153", "type": "1"}
[TOOL_RESPONSE] amap-amap-sse-maps_distance
{"results":[{"origin_id":"1","dest_id":"1","distance":"40386","duration":"2923"}]}
[THINK]
Okay, the user asked for the distance between Zhejiang University's Zijingang Campus and Hangzhou Xiaoshan Airport. I used the maps_geo function to get the coordinates of both locations. Then, I called the maps_distance function with the coordinates and type 1 for driving distance. The response came back with a distance of 40,386 meters and a duration of 2,923 seconds.

Now, I need to convert these numbers into a user-friendly answer. Let me start by converting meters to kilometers. 40,386 meters is 40.386 kilometers. For the duration, 2,923 seconds divided by 60 gives approximately 48.72 minutes. So, the driving distance is about 40.4 kilometers, and it takes roughly 48.7 minutes. I should present this information clearly, mentioning both the distance and the estimated time. Also, maybe add a note that traffic conditions can affect the actual travel time. That should cover the user's query effectively.
The driving distance between Zhejiang University's Zijingang Campus and Hangzhou Xiaoshan Airport is approximately **40.4 kilometers**, with an estimated travel time of **48.7 minutes** under normal traffic conditions. 

Actual travel time may vary depending on traffic, road closures, or other unforeseen circumstances.
In [5]:
messages += ret_messages # extending the context with new `ret_messages`.

Step 3: Make a Drive Plan

We can create a drive plan by asking follow-up questions, and the agent will generate the plan for us.

In [6]:
messages += [{'role': 'user', 'content': 'Okay, how can i drive?'}]
In [7]:
response_plain_text = ''

for ret_messages in agent.run(messages):
    response_plain_text = typewriter_print(ret_messages, response_plain_text)
[THINK]
Okay, the user asked for driving directions from Zhejiang University's Zijingang Campus to Hangzhou Xiaoshan Airport. I need to figure out which function to use.

First, I remember that there's a function for driving route planning. Let me check the tools provided. The function is called "amap-amap-sse-maps_direction_driving". It requires origin and destination coordinates. 

Earlier, I used the "amap-amap-sse-maps_geo" function to get the coordinates for both locations. The Zijingang Campus is at 120.088667,30.304176 and the airport is at 120.427708,30.228153. So those coordinates should be used as the origin and destination parameters.

I need to make sure the parameters are correctly formatted. The origin and destination should be strings in "经度,纬度" format. The function doesn't require any other parameters, so just those two should be enough. 

Let me structure the tool call with the correct function name and arguments. Double-checking the required fields, both origin and destination are mandatory. Everything looks good. Time to generate the tool call.
[TOOL_CALL] amap-amap-sse-maps_direction_driving
{"origin": "120.088667,30.304176", "destination": "120.427708,30.228153"}
[TOOL_RESPONSE] amap-amap-sse-maps_direction_driving
{"origin":"120.088667,30.304176","destination":"120.427708,30.228153","paths":[{"path":"","distance":"40466","duration":"2944","steps":[{"instruction":"向东行驶42米右转","road":"","distance":"42","orientation":"东","duration":"13"},{"instruction":"向南行驶99米左转","road":"","distance":"99","orientation":"南","duration":"36"},{"instruction":"向东行驶50米右转","road":"","distance":"50","orientation":"东","duration":"16"},{"instruction":"沿藕舫南路向南行驶661米左转","road":"藕舫南路","distance":"661","orientation":"南","duration":"96"},{"instruction":"沿藕舫南路向东南行驶62米左转","road":"藕舫南路","distance":"62","orientation":"东南","duration":"17"},{"instruction":"沿遵义西路向东行驶189米右转","road":"遵义西路","distance":"189","orientation":"东","duration":"41"},{"instruction":"沿紫荆花北路向南行驶205米左转","road":"紫荆花北路","distance":"205","orientation":"南","duration":"56"},{"instruction":"沿余杭塘路向东行驶182米靠左","road":"余杭塘路","distance":"182","orientation":"东","duration":"12"},{"instruction":"沿余杭塘路向东行驶225米直行进入隧道","road":"余杭塘路","distance":"225","orientation":"东","duration":"7"},{"instruction":"沿丰古隧道途径余杭塘路向东行驶1.8千米靠左","road":"丰古隧道","distance":"1783","orientation":"东","duration":"134"},{"instruction":"沿余杭塘路向东行驶268米直行进入隧道","road":"余杭塘路","distance":"268","orientation":"东","duration":"12"},{"instruction":"沿余杭塘路隧道途径余杭塘路向东行驶1.6千米右转","road":"余杭塘路隧道","distance":"1619","orientation":"东","duration":"209"},{"instruction":"沿教工路向南行驶503米左转","road":"教工路","distance":"503","orientation":"南","duration":"140"},{"instruction":"沿文一路辅路向东行驶324米向左前方行驶进入主路","road":"文一路辅路","distance":"324","orientation":"东","duration":"33"},{"instruction":"沿文一路入口途径文一路向东行驶89米靠左沿主路行驶","road":"文一路入口","distance":"89","orientation":"东","duration":"6"},{"instruction":"沿文一路途径德胜快速路向东行驶1.6千米靠左沿主路行驶","road":"文一路","distance":"1607","orientation":"东","duration":"134"},{"instruction":"沿德胜快速路向东行驶7.3千米向右前方行驶进入匝道","road":"德胜快速路","distance":"7276","orientation":"东","duration":"557"},{"instruction":"沿德胜互通向东行驶591米靠右","road":"德胜互通","distance":"591","orientation":"东","duration":"43"},{"instruction":"沿德胜互通途径空港高架路向南行驶1.9千米靠左沿主路行驶","road":"德胜互通","distance":"1894","orientation":"南","duration":"105"},{"instruction":"沿空港高架路途径彭埠大桥向东南行驶14.6千米靠左","road":"空港高架路","distance":"14596","orientation":"东南","duration":"692"},{"instruction":"沿空港高架路向东行驶112米减速行驶到达收费站","road":"空港高架路","distance":"112","orientation":"东","duration":"9"},{"instruction":"沿S2杭甬高速向东行驶566米靠左沿主路行驶","road":"S2杭甬高速","distance":"566","orientation":"东","duration":"33"},{"instruction":"沿S2杭甬高速途径G92杭州湾环线高速向东行驶2.3千米向右前方行驶进入匝道","road":"S2杭甬高速","distance":"2260","orientation":"东","duration":"110"},{"instruction":"沿机场互通向东行驶1.1千米减速行驶到达收费站","road":"机场互通","distance":"1136","orientation":"东","duration":"74"},{"instruction":"沿机场互通途径S4机场公路、S4机场公路出口、机场1号路向东行驶3.0千米右转","road":"机场互通","distance":"3022","orientation":"东","duration":"166"},{"instruction":"沿航安路向东南行驶266米左转","road":"航安路","distance":"266","orientation":"东南","duration":"57"},{"instruction":"沿翔飞路向东北行驶675米右转","road":"翔飞路","distance":"675","orientation":"东北","duration":"79"},{"instruction":"向东南行驶49米左转","road":"","distance":"49","orientation":"东南","duration":"24"},{"instruction":"向东北行驶115米到达目的地","road":"","distance":"115","orientation":"东北","duration":"33"}]}]}
[THINK]
Okay, the user asked for driving directions from Zhejiang University's Zijingang Campus to Hangzhou Xiaoshan Airport. I need to process the tool response that was provided.

First, the response includes a detailed path with multiple steps. The total distance is 40,466 meters (about 40.5 km) and the duration is 2944 seconds, which is roughly 49 minutes. The steps list each turn and the road names, but some of the road names are in Chinese. I should translate those to make it user-friendly.

I'll start by summarizing the key details: distance, time, and main route. Then, break down the steps into a more readable format. The user might want to know the major highways or roads they'll take, like the余杭塘路, 文一路, 德胜快速路, and 空港高架路. Also, mention the toll stations and the final approach to the airport via 航安路 and 翔飞路.

I should check if all the steps are necessary to include. Maybe group similar steps together if they're repetitive. For example, there are several instances of following the same road for different distances. Also, ensure that the directions are clear, like when to turn, enter a tunnel, or take an exit.

Finally, end with a note about traffic conditions affecting travel time. Make sure the instructions are concise and easy to follow, avoiding any technical jargon. Double-check the translations of the road names to ensure accuracy.
Here's the driving route from Zhejiang University (Zijingang Campus) to Hangzhou Xiaoshan Airport:

**Total Distance:** ~40.5 km  
**Estimated Time:** ~49 minutes  

---

**Key Route Summary:**
1. **Start** at Zijingang Campus, follow 藕舫南路 and 遵义西路 eastward.
2. Enter **余杭塘路**, pass through **丰古隧道** and **余杭塘路隧道**.
3. Continue on **文一路**, merge onto **德胜快速路** → **空港高架路**.
4. Take the **S2杭甬高速** exit, then **机场互通** to reach the airport area.
5. Final approach via **航安路** and **翔飞路** to the airport terminal.

---

**Step-by-Step Directions (simplified):**
- Follow campus roads → 余杭塘路 → 文一路 → 德胜快速路 → 空港高架路 → S2杭甬高速 → 机场互通 → 航安路/翔飞路 → Hangzhou Xiaoshan Airport.

⚠️ Note: Actual travel time may vary due to traffic, especially during peak hours. Use navigation apps for real-time updates.

Use the GUI

We have explored the capabilities of the Qwen-Agent framework and Qwen models in providing travel suggestions. We can also achieve this by using the GUI.

In [8]:
from qwen_agent.gui import WebUI

agent = Assistant(
    name="Qwen Guide",
    description="I can help with your travel needs, ask me anything!",
    llm=llm_cfg,
    function_list=tools
)

WebUI(agent).run()
2025-05-01 21:14:00,386 - mcp_manager.py - 110 - INFO - Initializing MCP tools from mcp servers: ['amap-amap-sse']
* Running on local URL:  http://127.0.0.1:7861

To create a public link, set `share=True` in `launch()`.
In [ ]: