【腾讯位置服务开发者征文大赛】手把手教你用AI+腾讯位置服务开发智能对话式地图应用
·
写在前面:腾讯位置服务开放了丰富的地图API,结合AI大模型的能力,可以开发出智能对话式地图应用。本文将手把手教你如何从零开发一个能够「听懂人话」的智能地图助手。
文章目录
一、项目概述
1.1 我们要做什么?
🎯 项目目标:
开发一个智能对话式地图应用,用户可以用自然语言查询:
✅ "帮我找附近人少、有插座、好喝的咖啡馆"
✅ "从公司到机场最优路线推荐"
✅ "明天去深圳开会,帮我规划行程"
核心能力:
- 自然语言理解意图
- 调用腾讯地图API获取数据
- 智能推荐和展示结果
1.2 技术架构
🏗️ 系统架构:
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ 用户输入 │ ──▶ │ 意图识别 │ ──▶ │ 地图API │
│ (自然语言) │ │ (AI大模型) │ │ (腾讯位置) │
└─────────────┘ └─────────────┘ └─────────────┘
│ │
▼ ▼
┌─────────────┐ ┌─────────────┐
│ 参数提取 │ │ 结果展示 │
│ (经纬度) │ │ (地图呈现) │
└─────────────┘ └─────────────┘
二、准备工作
2.1 申请腾讯位置服务Key
# 1. 访问腾讯位置服务官网:https://lbs.qq.com/
# 2. 注册/登录腾讯账号
# 3. 控制台 → 我的Key → 创建新Key
# 4. 勾选 WebServiceAPI 和 JavaScriptAPI
2.2 安装依赖
# 创建项目
mkdir ai-map-app
cd ai-map-app
npm init -y
# 安装依赖
npm install express body-parser axios dotenv
npm install tencentcloud-sdk-nodejs
三、核心代码实现
3.1 后端服务 - 意图识别与API调用
// server.js
const express = require('express');
const axios = require('axios');
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.json());
// 腾讯地图API配置
const TENCENT_MAP_KEY = process.env.TENCENT_MAP_KEY;
// 意图识别prompt
const intentPrompt = `
你是一个地图助手,请分析用户的查询意图,并提取关键信息。
用户可能的意图:
1. search_poi - 搜索地点(如:附近的咖啡馆、医院)
2. route_plan - 路线规划(如:怎么去、从哪到哪)
3. nearby_search - 周边搜索(如:附近有什么)
请以JSON格式返回:
{
"intent": "意图类型",
"params": {
"keyword": "搜索关键词",
"location": "位置描述",
"start": "起点",
"end": "终点"
}
}
用户查询:{{query}}
`;
// 意图识别与参数提取
async function recognizeIntent(query) {
const prompt = intentPrompt.replace('{{query}}', query);
// 这里调用AI大模型API(如DeepSeek、文心一言等)
const response = await axios.post('https://api.deepseek.com/v1/chat/completions', {
model: 'deepseek-chat',
messages: [{role: 'user', content: prompt}],
temperature: 0.3
}, {
headers: {'Authorization': `Bearer ${process.env.AI_API_KEY}`}
});
return JSON.parse(response.data.choices[0].message.content);
}
// 搜索POI
async function searchPOI(keyword, location) {
let url = `https://apis.map.qq.com/ws/place/v1/search?`;
url += `keyword=${encodeURIComponent(keyword)}`;
url += `&key=${TENCENT_MAP_KEY}`;
url += `&boundary=nearby(${location.lat},${location.lng},5000)`;
url += `&output=json`;
const response = await axios.get(url);
return response.data;
}
// 路线规划
async function routePlanning(from, to, mode = 'driving') {
let url = `https://apis.map.qq.com/ws/direction/v1/${mode}?`;
url += `from=${encodeURIComponent(from)}`;
url += `&to=${encodeURIComponent(to)}`;
url += `&key=${TENCENT_MAP_KEY}`;
const response = await axios.get(url);
return response.data;
}
// 对话接口
app.post('/api/chat', async (req, res) => {
try {
const {message, userLocation} = req.body;
// 1. 意图识别
const intentResult = await recognizeIntent(message);
// 2. 根据意图调用不同API
let result;
switch (intentResult.intent) {
case 'search_poi':
const searchLoc = userLocation || intentResult.params.location;
result = await searchPOI(
intentResult.params.keyword,
{lat: 39.9042, lng: 116.4074} // 默认北京
);
break;
case 'route_plan':
result = await routePlanning(
intentResult.params.start || '我的位置',
intentResult.params.end
);
break;
default:
result = {status: 0, message: '理解了你的问题,请稍等...'};
}
res.json({
success: true,
intent: intentResult,
data: result
});
} catch (error) {
res.json({success: false, error: error.message});
}
});
app.listen(3000, () => {
console.log('🚀 AI地图助手服务已启动: http://localhost:3000');
});
3.2 前端页面 - 地图展示
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AI智能地图助手</title>
<!-- 引入腾讯地图JSAPI -->
<script src="https://map.qq.com/api/js?v=2.exp&key=YOUR_TENCENT_MAP_KEY"></script>
<style>
* {margin: 0; padding: 0; box-sizing: border-box;}
body {font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;}
.container {display: flex; height: 100vh;}
/* 左侧聊天区域 */
.chat-panel {width: 400px; background: #f5f5f5; display: flex; flex-direction: column;}
.chat-header {padding: 20px; background: #1890ff; color: white; font-size: 18px;}
.chat-messages {flex: 1; padding: 20px; overflow-y: auto;}
.message {margin-bottom: 15px; padding: 12px 16px; border-radius: 8px; max-width: 85%;}
.message.user {background: #1890ff; color: white; margin-left: auto;}
.message.ai {background: white; box-shadow: 0 2px 8px rgba(0,0,0,0.1);}
.chat-input {padding: 20px; background: white; display: flex; gap: 10px;}
.chat-input input {flex: 1; padding: 12px; border: 1px solid #ddd; border-radius: 6px; font-size: 14px;}
.chat-input button {padding: 12px 24px; background: #1890ff; color: white; border: none; border-radius: 6px; cursor: pointer;}
/* 右侧地图区域 */
.map-panel {flex: 1; position: relative;}
#map-container {width: 100%; height: 100%;}
.poi-list {position: absolute; top: 20px; right: 20px; width: 300px; background: white; border-radius: 8px; box-shadow: 0 2px 12px rgba(0,0,0,0.15); max-height: 500px; overflow-y: auto;}
.poi-item {padding: 15px; border-bottom: 1px solid #f0f0f0; cursor: pointer;}
.poi-item:hover {background: #f9f9f9;}
.poi-name {font-weight: bold; margin-bottom: 5px; color: #333;}
.poi-address {font-size: 12px; color: #666;}
</style>
</head>
<body>
<div class="container">
<!-- 聊天面板 -->
<div class="chat-panel">
<div class="chat-header">🤖 AI智能地图助手</div>
<div class="chat-messages" id="messages">
<div class="message ai">你好!我是AI地图助手,用自然语言告诉我你想去哪里~</div>
</div>
<div class="chat-input">
<input type="text" id="userInput" placeholder="例如:帮我找附近的咖啡馆" />
<button onclick="sendMessage()">发送</button>
</div>
</div>
<!-- 地图面板 -->
<div class="map-panel">
<div id="map-container"></div>
<div class="poi-list" id="poiList" style="display: none;"></div>
</div>
</div>
<script>
// 初始化地图
const center = new qq.maps.LatLng(39.9042, 116.4074); // 北京
const map = new qq.maps.Map(document.getElementById('map-container'), {
center: center,
zoom: 14
});
// 用户位置
let userLocation = null;
// 获取用户位置
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(position => {
userLocation = {
lat: position.coords.latitude,
lng: position.coords.longitude
};
map.setCenter(new qq.maps.LatLng(userLocation.lat, userLocation.lng));
});
}
// 发送消息
async function sendMessage() {
const input = document.getElementById('userInput');
const message = input.value.trim();
if (!message) return;
// 添加用户消息
addMessage(message, 'user');
input.value = '';
// 添加AI等待消息
addMessage('正在思考中...', 'ai');
try {
const response = await fetch('/api/chat', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({message, userLocation})
});
const result = await response.json();
// 移除等待消息
const messages = document.querySelectorAll('.message.ai');
messages[messages.length - 1].remove();
if (result.success) {
// 显示结果
showResult(result);
} else {
addMessage('抱歉,出错了:' + result.error, 'ai');
}
} catch (error) {
addMessage('网络错误,请重试', 'ai');
}
}
// 添加消息
function addMessage(text, type) {
const div = document.createElement('div');
div.className = `message ${type}`;
div.textContent = text;
document.getElementById('messages').appendChild(div);
document.getElementById('messages').scrollTop = document.getElementById('messages').scrollHeight;
}
// 显示结果
function showResult(result) {
const {intent, data} = result;
if (intent.intent === 'search_poi' && data.data) {
// 显示POI列表
const poiList = document.getElementById('poiList');
poiList.style.display = 'block';
poiList.innerHTML = '<div style="padding:15px;font-weight:bold;">搜索结果</div>';
const pois = data.data;
pois.forEach((poi, index) => {
const div = document.createElement('div');
div.className = 'poi-item';
div.innerHTML = `
<div class="poi-name">${index + 1}. ${poi.title}</div>
<div class="poi-address">${poi.address}</div>
`;
div.onclick = () => {
const location = new qq.maps.LatLng(poi.location.lat, poi.location.lng);
map.setCenter(location);
map.setZoom(16);
};
poiList.appendChild(div);
// 地图上添加标记
const marker = new qq.maps.Marker({
position: new qq.maps.LatLng(poi.location.lat, poi.location.lng),
map: map,
title: poi.title
});
});
addMessage(`找到 ${pois.length} 个结果,已在地图上标注`, 'ai');
}
}
// 回车发送
document.getElementById('userInput').addEventListener('keypress', e => {
if (e.key === 'Enter') sendMessage();
});
</script>
</body>
</html>
四、效果演示
4.1 使用效果
💬 对话示例:
用户:帮我找附近人少、有插座、好喝的咖啡馆
AI:好的,正在搜索附近的咖啡馆...
结果:找到 5 家咖啡馆,已在地图上标注
用户:从公司到首都机场怎么走
AI:为您规划了驾车路线,全程约 45 分钟,35 公里
4.2 功能特点
✨ 项目特点:
1. 自然语言理解
- 无需记住复杂指令
- 像聊天一样使用地图
2. 智能意图识别
- 自动识别搜索/导航/周边查询
- 提取关键参数
3. 实时地图展示
- 搜索结果直接在地图标注
- 点击切换查看详情
4. 多轮对话支持
- 记住上下文
- 支持追问
五、进阶优化
5.1 添加更多AI能力
// 智能推荐 - 根据用户偏好推荐
async function smartRecommend(userId, location) {
const prompt = `
用户ID: ${userId}
位置: ${location}
历史行为: [咖啡, 书店, 公园]
请推荐 3 个适合该用户的地点,解释推荐理由。
`;
// 调用AI生成推荐
}
// 行程规划 - 多目的地规划
async function planTrip(places, preferences) {
const prompt = `
目的地: ${places.join(', ')}
偏好: ${preferences}
请规划最优路线和时间安排。
`;
// 调用AI规划行程
}
5.2 添加MCP协议支持
// MCP服务器示例
const mcpServer = {
name: 'tencent-map',
version: '1.0.0',
tools: [
{
name: 'search_poi',
description: '搜索地点POI',
parameters: {
type: 'object',
properties: {
keyword: {type: 'string', description: '搜索关键词'},
location: {type: 'string', description: '位置'},
radius: {type: 'number', description: '搜索半径(米)'}
},
required: ['keyword']
}
},
{
name: 'route_plan',
description: '路线规划',
parameters: {
type: 'object',
properties: {
from: {type: 'string', description: '起点'},
to: {type: 'string', description: '终点'},
mode: {type: 'string', enum: ['driving', 'walking', 'bicycling']}
},
required: ['from', 'to']
}
}
]
};
六、完整代码获取
6.1 项目结构
ai-map-assistant/
├── server.js # 后端服务
├── public/
│ └── index.html # 前端页面
├── .env # 环境变量
└── package.json # 依赖配置
6.2 配置说明
# .env 文件
TENCENT_MAP_KEY=your_tencent_map_key
AI_API_KEY=your_ai_api_key
七、总结
📊 项目成果:
✅ 完成功能:
- 自然语言查询地点
- 智能路线规划
- 实时地图展示
- POI搜索与标注
🔧 技术栈:
- 前端:HTML + JS + 腾讯地图JSAPI
- 后端:Node.js + Express
- AI:DeepSeek/文心一言/通义千问
- 地图:腾讯位置服务API
💡 扩展方向:
- 添加MCP协议支持
- 多轮对话优化
- 个性化推荐
- 行程智能规划
作者:刘~浪地球
本文声明:原创不易,转载需授权!
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)