【腾讯位置服务开发者征文大赛】打造AI智能导览助手:基于MCP协议与腾讯位置服务的多轮对话地图应用实战
文章目录
-
每日一句正能量 -
引言:当地图遇见AI Agent -
一、技术架构设计:MCP协议赋能地图智能体 -
1.1 为什么选择MCP协议? -
1.2 系统架构概览 -
二、核心功能实现:从自然语言到地图动作 -
2.1 MCP工具定义:将地图能力标准化 -
2.2 Agent编排:多轮对话与意图识别 -
2.3 前端集成:腾讯地图JSAPI GL可视化 -
三、智能特性深度解析 -
3.1 多约束条件理解与分解 -
3.2 多Agent协作:专业分工提升效果 -
3.3 时空数据可视化:热力图与轨迹分析 -
四、实战案例演示 -
场景一:智能约会地点推荐 -
场景二:动态路线调整 -
五、性能优化与最佳实践 -
5.1 响应速度优化 -
5.2 错误处理与降级 -
六、总结与展望

每日一句正能量
你得有足够的实力,你的原则和底线才会被人尊重;否则,你的“Say No”,并没有多少人在乎!
引言:当地图遇见AI Agent
在移动互联网时代,地图应用早已从单纯的”导航工具”进化为”生活服务入口”。然而,传统的地图交互方式仍停留在”搜索-查看-操作”的模式:用户需要明确知道自己要找什么,手动输入关键词,然后在结果中筛选。这种交互方式在面对复杂场景时显得力不从心——比如当你说”帮我找个附近安静、有WiFi、适合工作三小时的咖啡馆”时,传统地图很难一次性理解并满足这个包含多个约束条件的自然语言需求。
这正是AI Agent(智能体)与地图服务结合的价值所在。通过大语言模型的意图识别、多轮对话能力,结合地图的时空数据服务,我们可以构建一个”能听懂人话、会主动规划”的智能导览助手。本文将分享如何基于MCP(Model Context Protocol)协议、腾讯位置服务Map Skills以及多Agent协作架构,打造一款支持自然语言交互的智能地图应用。
一、技术架构设计:MCP协议赋能地图智能体
1.1 为什么选择MCP协议?
MCP(Model Context Protocol)是Anthropic推出的开放协议,旨在标准化大语言模型与外部工具、数据源之间的交互。在地图场景下,MCP的价值体现在:
- 标准化工具调用
:将地图API(搜索、导航、路线规划等)封装为标准化工具,让AI Agent能够动态发现和使用 - 上下文管理
:维护多轮对话中的空间上下文(如当前位置、已选目的地、偏好设置等) - 多Agent协作
:支持多个专业Agent(如搜索Agent、规划Agent、推荐Agent)协同工作
1.2 系统架构概览
我们的智能导览助手采用分层架构:
┌─────────────────────────────────────────┐│ 用户交互层 (Chat UI) ││ 自然语言输入 → 意图识别 → 结果展示 │└─────────────────┬───────────────────────┘│┌─────────────────▼───────────────────────┐│ Agent编排层 (Orchestrator) ││ 对话管理Agent ←→ 任务分解 → 工具选择 │└─────────────────┬───────────────────────┘│┌─────────────┼─────────────┐▼ ▼ ▼┌────────┐ ┌────────┐ ┌────────────┐│搜索Agent│ │规划Agent│ │ 推荐Agent ││-POI检索 │ │-路线规划│ │-个性化排序 ││-周边查询│ │-时间预估│ │-场景匹配 │└────┬───┘ └────┬───┘ └─────┬──────┘│ │ │└───────────┼────────────┘▼┌─────────────────────────────────────────┐│ MCP工具层 (Map Skills) ││ 腾讯地图JSAPI GL │ WebService API │ LBS ││ - 地点搜索 │ - 路线规划 │定位 ││ - 周边查询 │ - 距离矩阵 │ ││ - 地理编码 │ - 实时路况 │ │└─────────────────────────────────────────┘
二、核心功能实现:从自然语言到地图动作
2.1 MCP工具定义:将地图能力标准化
首先,我们需要将腾讯位置服务的核心能力封装为MCP工具。以下是通过tencentmap-jsapi-gl-skill定义的四个核心工具:
// mcp-tools/map-tools.jsconst mapTools = [{name: "poi_search",description: "搜索特定类型的地点,支持关键词、周边搜索和筛选条件",parameters: {type: "object",properties: {keyword: { type: "string", description: "搜索关键词,如'咖啡馆'" },location: { type: "string", description: "中心点坐标,如'39.9042,116.4074'" },radius: { type: "number", description: "搜索半径(米),默认3000" },filter: { type: "string", description: "筛选条件,如'wifi:1;quiet:1'" },page_size: { type: "number", default: 10 }},required: ["keyword"]}},{name: "route_planning",description: "规划从起点到终点的路线,支持多种出行方式",parameters: {type: "object",properties: {from: { type: "string", description: "起点坐标" },to: { type: "string", description: "终点坐标" },mode: {type: "string",enum: ["driving", "walking", "transit", "bicycling"],description: "出行方式"},preference: {type: "string",enum: ["fastest", "shortest", "avoid_traffic"],description: "路线偏好"}},required: ["from", "to", "mode"]}},{name: "geocode",description: "将地址转换为坐标,或坐标转换为地址",parameters: {type: "object",properties: {address: { type: "string", description: "要解析的地址" },type: { type: "string", enum: ["encode", "decode"], default: "encode" }}}},{name: "nearby_analysis",description: "分析指定地点周边的环境特征,如商业密度、交通便利度",parameters: {type: "object",properties: {location: { type: "string", description: "中心点坐标" },radius: { type: "number", default: 1000 },categories: {type: "array",items: { type: "string" },description: "关注的POI类别,如['restaurant', 'subway', 'park']"}}}}];module.exports = { mapTools };
2.2 Agent编排:多轮对话与意图识别
核心在于DialogueAgent,它负责理解用户意图、维护对话状态、调用合适的工具:
// agents/DialogueAgent.jsconst { OpenAI } = require('openai');const { mapTools } = require('../mcp-tools/map-tools');class DialogueAgent {constructor() {this.client = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });this.conversationHistory = [];this.context = {currentLocation: null, // 当前位置selectedPOIs: [], // 已选中的地点userPreferences: {}, // 用户偏好(安静、WiFi等)conversationState: 'greeting' // 对话状态机};}async processUserInput(userInput) {// 构建系统提示词,注入当前上下文const systemPrompt = this.buildSystemPrompt();const messages = [{ role: "system", content: systemPrompt },...this.conversationHistory,{ role: "user", content: userInput }];// 调用大模型,支持函数调用const response = await this.client.chat.completions.create({model: "gpt-4-turbo",messages: messages,tools: this.formatToolsForLLM(mapTools),tool_choice: "auto"});const assistantMessage = response.choices[0].message;// 处理工具调用if (assistantMessage.tool_calls) {const toolResults = await this.executeToolCalls(assistantMessage.tool_calls);// 将工具结果返回给模型生成最终回复const finalResponse = await this.client.chat.completions.create({model: "gpt-4-turbo",messages: [...messages,assistantMessage,...toolResults.map((result, idx) => ({role: "tool",tool_call_id: assistantMessage.tool_calls[idx].id,content: JSON.stringify(result)}))]});const reply = finalResponse.choices[0].message.content;this.updateHistory(userInput, reply);return this.formatResponse(reply, toolResults);}this.updateHistory(userInput, assistantMessage.content);return { type: 'text', content: assistantMessage.content };}buildSystemPrompt() {return `你是"地图智能助手",专门帮助用户基于位置服务解决问题。当前上下文:- 用户位置:{this.context.selectedPOIs.map(p => p.name).join(', ') || '无'}- 用户偏好:{this.context.conversationState}你的能力:1. 理解自然语言查询,提取地点、约束条件(距离、评分、设施等)2. 调用地图工具获取实时数据3. 基于结果进行智能推荐和路线规划4. 维护多轮对话上下文,支持追问和条件修改回复要求:- 首次回复需友好问候并确认位置- 推荐地点时说明理由(匹配度分析)- 主动询问是否需要路线规划或更多信息`;}async executeToolCalls(toolCalls) {const results = [];for (const call of toolCalls) {const { name, arguments: args } = call.function;const parsedArgs = JSON.parse(args);// 注入上下文信息(如未提供位置则使用当前位置)if (parsedArgs.location === 'current' || !parsedArgs.location) {parsedArgs.location = this.context.currentLocation;}// 调用腾讯位置服务APIconst result = await this.callTencentMapAPI(name, parsedArgs);results.push(result);// 更新上下文if (name === 'poi_search' && result.pois) {this.context.lastSearchResults = result.pois;}}return results;}async callTencentMapAPI(toolName, params) {const axios = require('axios');const TENCENT_KEY = process.env.TENCENT_MAP_KEY;switch(toolName) {case 'poi_search':const searchRes = await axios.get('https://apis.map.qq.com/ws/place/v1/search', {params: {keyword: params.keyword,location: params.location,radius: params.radius || 3000,key: TENCENT_KEY,page_size: params.page_size,// 高级筛选:通过filter参数实现WiFi、安静等条件filter: params.filter || ''}});return this.enrichPOIData(searchRes.data);case 'route_planning':const routeRes = await axios.get('https://apis.map.qq.com/ws/direction/v1/driving', {params: {from: params.from,to: params.to,key: TENCENT_KEY,// 支持智能避堵policy: params.preference === 'avoid_traffic' ? 'TRIP_AVOID_TRAFFIC' : 'LEAST_TIME'}});return routeRes.data;default:throw new Error(`Unknown tool: {data.route.duration}分钟到达`, 'ai');} else {addMessage(data.content, 'ai');}};function displayPOIs(pois) {// 清除旧标记markers.forEach(m => m.setMap(null));markers = [];const bounds = new TMap.LatLngBounds();pois.forEach((poi, index) => {const position = new TMap.LatLng(poi.location.lat, poi.location.lng);bounds.extend(position);// 创建自定义标记const marker = new TMap.MultiMarker({map: map,styles: {'default': new TMap.MarkerStyle({width: 30,height: 40,anchor: { x: 15, y: 40 },color: index === 0 ? '#ff6b6b' : '#4ecdc4'})},geometries: [{id: poi.id,position: position,properties: { ...poi, rank: index + 1 }}]});// 信息窗体const infoWindow = new TMap.InfoWindow({map: map,position: position,content: `<div style="padding: 10px; max-width: 250px;"><h4>{index < 3 ? '🏆' : ''}</h4><p>评分:{poi.address}</p><p style="color: #666; font-size: 12px;">{poi.id}')" style="margin-top: 8px;">选为目的地</button></div>`,offset: { x: 0, y: -40 }});marker.on('click', () => infoWindow.open());markers.push(marker);});map.fitBounds(bounds, { padding: 100 });}function generatePOICards(pois) {return pois.slice(0, 5).map((poi, idx) => `<div class="poi-card" onclick="focusPOI('{idx + 1}. {poi.matchScore}分</span><br><small>📍 {poi.distance}米</small><br><small style="color: #28a745;">{poi.crowdLevel ? `<br><small>👥 拥挤度:{sender}-msg`;div.innerHTML = isHTML ? content : marked.parse(content);container.appendChild(div);container.scrollTop = container.scrollHeight;}</script></body></html>
三、智能特性深度解析
3.1 多约束条件理解与分解
系统的核心优势在于处理复杂自然语言查询。例如当用户说:
“我想找个离我公司(国贸)不太远、评分4.5以上、有WiFi、下午人不太多的咖啡馆,最好还能停车”
系统会将其分解为:
- 地理约束
:以”国贸”为中心,半径3km内 - 质量约束
:评分≥4.5 - 设施约束
:WiFi=1,停车场=1 - 时间约束
:当前时间(下午)+ 拥挤度预测 - 排序偏好
:综合距离、评分、实时拥挤度
通过腾讯位置服务的filter参数和自定义评分算法实现:
// 复杂查询解析parseComplexQuery(userInput) {const constraints = {location: this.extractLocation(userInput), // 使用NLP提取"国贸"radius: this.extractRadius(userInput), // "不太远"→3000米filters: [],sortBy: []};// 设施提取if (userInput.includes('WiFi') || userInput.includes('网络')) {constraints.filters.push('wifi:1');}if (userInput.includes('停车')) {constraints.filters.push('parking:1');}// 时间感知const hour = new Date().getHours();if (userInput.includes('下午') && hour >= 14) {constraints.crowdPreference = 'low'; // 偏好低拥挤度}return constraints;}
3.2 多Agent协作:专业分工提升效果
单一Agent难以同时擅长搜索、规划、推荐等多个任务。我们采用多Agent协作架构:
// agents/Orchestrator.jsclass AgentOrchestrator {constructor() {this.agents = {search: new SearchAgent(), // 擅长POI检索和筛选planning: new PlanningAgent(), // 擅长路线规划和时间预估recommend: new RecommendAgent(), // 擅长个性化推荐和解释memory: new MemoryAgent() // 管理用户长期偏好};}async handleTask(userIntent) {// 任务分解const subtasks = await this.decomposeTask(userIntent);// 并行执行独立子任务const results = await Promise.all(subtasks.map(task => this.agents[task.type].execute(task.params)));// 结果融合与冲突解决const finalResult = await this.mergeResults(results);// 生成解释性回复return this.agents.recommend.explain(finalResult, userIntent);}async decomposeTask(intent) {// 使用LLM判断需要哪些Agent参与const decomposition = await this.llm.chat.completions.create({messages: [{role: "system",content: "将用户意图分解为子任务,返回JSON数组,每个包含type和params"}, {role: "user",content: `意图:{JSON.stringify(intent.params)}`}]});return JSON.parse(decomposition.choices[0].message.content);}}
3.3 时空数据可视化:热力图与轨迹分析
结合腾讯位置大数据,我们可以实现商业选址分析功能:
// 热力图展示区域人流function showHeatmap(center, radius) {const heatmap = new TMap.visualization.Heat({map: map,radius: 50,max: 100,min: 0,gradient: {0.4: 'blue',0.6: 'cyan',0.8: 'yellow',1.0: 'red'}});// 获取区域人流数据(模拟,实际可接入腾讯位置大数据)fetch(`/api/heatmap-data?center={radius}`).then(res => res.json()).then(data => {heatmap.setData(data.points.map(p => ({lat: p.lat,lng: p.lng,count: p.intensity})));});}
四、实战案例演示
场景一:智能约会地点推荐
用户输入:“我和朋友约在朝阳大悦城附近见面,想找个能聊天、环境好、人均100左右的餐厅,吃完还想逛逛街”
系统处理流程:
- 意图识别
:提取”朝阳大悦城”(锚点)、“聊天”(安静)、“人均100”(价格)、“逛街”(商圈) - POI搜索
:调用 poi_search,关键词”餐厅”,位置”朝阳大悦城”,筛选”环境好、人均80-120″ - 周边分析
:调用 nearby_analysis,检查餐厅附近是否有商场/步行街 - 路线规划
:为两位用户分别规划到餐厅的路线,推荐最佳汇合时间 - 结果呈现
: -
地图标注3个推荐餐厅,显示评分、人均、距离 -
聊天面板展示推荐理由:“这家离大悦城步行5分钟,吃完可直接逛商场,当前排队较少” -
提供”发送给朋友”功能,生成包含地图链接的分享卡片
场景二:动态路线调整
对话过程:
-
用户:“导航去首都机场” -
系统:规划路线,显示预计1小时15分钟 -
用户:“要避开拥堵,我不赶时间” -
系统:重新调用 route_planning,preference改为”avoid_traffic”,虽然路程增加10km,但时间更可控,并在地图高亮显示新路线
五、性能优化与最佳实践
5.1 响应速度优化
地图API调用可能耗时,我们采用流式响应策略:
// 流式返回,先展示思考过程,再展示结果async function streamResponse(userInput, res) {// 1. 立即返回"正在思考..."res.write(JSON.stringify({ type: 'thinking', content: '正在分析您的需求...' }));// 2. 并行执行多个工具调用const [poiResult, routeResult] = await Promise.all([searchPOI(userInput),getCurrentTraffic()]);// 3. 增量返回结果res.write(JSON.stringify({ type: 'partial', pois: poiResult.slice(0, 3) }));// 4. 最终推荐const finalRecommendation = await generateRecommendation(poiResult, routeResult);res.write(JSON.stringify({ type: 'final', content: finalRecommendation }));}
5.2 错误处理与降级
当腾讯地图API限流或失败时,系统优雅降级:
async function robustAPICall(apiFunc, fallbackData) {try {return await apiFunc();} catch (error) {if (error.code === 'RATE_LIMIT') {// 切换到缓存数据return getCachedData();}if (error.code === 'TIMEOUT') {// 简化查询条件重试return apiFunc({ simplified: true });}return fallbackData;}}
六、总结与展望
本文介绍了如何基于MCP协议构建AI+地图的智能导览系统,核心创新点包括:
- 协议标准化
:通过MCP将腾讯位置服务封装为标准工具,使AI Agent能够动态调用地图能力 - 多Agent架构
:搜索、规划、推荐Agent专业分工,通过Orchestrator协调复杂任务 - 上下文感知
:维护对话状态和用户偏好,支持多轮交互和意图修正 - 可视化融合
:结合腾讯地图JSAPI GL实现自然语言与地图可视化的无缝衔接
后续改进方向:
- 多模态交互
:接入腾讯地图的AR导航能力,实现”AI语音+AR指引”的沉浸式导览 - 群体智能
:支持多人出行场景,智能推荐汇合点并协调多方路线 - 预测性服务
:基于用户历史行为和实时位置,主动推荐”你可能接下来要去的地方”
AI与地图的结合才刚刚开始。当地图从”工具”进化为”懂你的助手”,位置服务的价值将被重新定义。期待更多开发者加入腾讯位置服务生态,共同探索”AI+地图”的无限可能!
在线Demo:https://ai-map-demo.tencent.com 开发文档:https://lbs.qq.com/webApi/javascriptGL/glGuide/glOverview
转载自:https://blog.csdn.net/u014727709/article/details/159997401 欢迎 👍点赞✍评论⭐收藏,欢迎指正
夜雨聆风