将 Kaleidr Chat 连接到 Mapbox 地图
完成本指南后,网页将展示 Mapbox GL JS 地图以及嵌入地图的聊天面板。访客提问时,回答会逐步显示在面板中,其中的地点作为标记出现在 Mapbox 地图上,相机也会移动以展示这些位置。所有套餐(包括 Free)都支持,只需要可公开使用的密钥。提问会消耗组织的 AI 点数。
开始之前
- 从 kaleidr.com/api-keys 获取 Kaleidr 可公开使用的密钥(
kld_pk_live_…)。新密钥默认带有聊天所需的ai权限。参阅获取 API 密钥。 - 如果密钥设置了允许来源,网页来源必须包含在该列表中。本地开发可添加
http://localhost:8080。 - 从 Mapbox 账户获取 Mapbox 访问令牌(
pk.…)。Mapbox 对地图收费,Kaleidr 对提问收费,二者互不影响。 - 通过 script 标签加载 Mapbox GL JS,保证存在
window.mapboxgl。如果从 npm 导入 Mapbox,请先阅读将 npm 库公开为页面全局对象。 - 通过 HTTP 提供网页,例如
npx serve或python -m http.server 8080。不能直接从磁盘打开文件。 - 如果网站设置了内容安全策略,请允许内容安全策略中列出的主机。
第 1 步:布置地图和聊天层
将地图和聊天挂载目标放在同一个定位容器中。聊天层覆盖在地图上方,但允许指针事件穿透。
<div id="mapHost" style="position:relative; height:520px">
<div id="map" style="position:absolute; inset:0; z-index:0"></div>
<div id="chat" style="position:absolute; inset:0; z-index:1; pointer-events:none"></div>
</div>
**预期结果:**此时还没有地图,只显示一个高度为 520 px 的空白块。主题与布局解释了各项声明的作用。
第 2 步:加载 Mapbox GL JS 并创建地图
在网页 head 中加载样式表,并在自己的代码之前加载脚本。样式表必不可少,否则地图无法正确显示。
<link rel="stylesheet" href="https://api.mapbox.com/mapbox-gl-js/v3.9.4/mapbox-gl.css" />
<script src="https://api.mapbox.com/mapbox-gl-js/v3.9.4/mapbox-gl.js"></script>
<script>
mapboxgl.accessToken = 'pk.…';
const map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/streets-v12',
center: [-0.12, 51.5],
zoom: 11,
});
</script>
**预期结果:**显示伦敦市中心的 Mapbox 地图,可以拖动和缩放。
第 3 步:加载 kaleidr.js
在 Mapbox 脚本之后、挂载聊天面板的代码之前加入 Kaleidr 加载器。
<script src="https://cdn.kaleidr.com/embed/v1/kaleidr.js"></script>
**预期结果:**网页不会发生明显变化。在控制台中,Kaleidr.version 会返回版本字符串。
第 4 步:挂载聊天面板
传入密钥和实际运行的地图对象。
const handle = Kaleidr.mount('#chat', {
product: 'chat',
publishableKey: 'kld_pk_live_…',
map,
contained: true,
});
无需等待地图的 load 事件。Kaleidr.mount 会立即返回;聊天程序包加载完成且密钥交换为会话后,面板就会出现。
**预期结果:**地图左上角出现写有“Ask Kaleidr”的输入栏。
完整页面
将文件保存为 index.html,替换两个密钥并通过 HTTP 提供文件夹。
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Kaleidr Chat on Mapbox</title>
<link rel="stylesheet" href="https://api.mapbox.com/mapbox-gl-js/v3.9.4/mapbox-gl.css" />
<style>
body { margin: 0; font-family: system-ui, sans-serif; }
#mapHost { position: relative; height: 100vh; }
#map { position: absolute; inset: 0; z-index: 0; }
#chat { position: absolute; inset: 0; z-index: 1; pointer-events: none; }
</style>
</head>
<body>
<div id="mapHost">
<div id="map"></div>
<div id="chat"></div>
</div>
<script src="https://api.mapbox.com/mapbox-gl-js/v3.9.4/mapbox-gl.js"></script>
<script src="https://cdn.kaleidr.com/embed/v1/kaleidr.js"></script>
<script>
mapboxgl.accessToken = 'pk.…';
const map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/streets-v12',
center: [-0.12, 51.5],
zoom: 11,
});
const handle = Kaleidr.mount('#chat', {
product: 'chat',
publishableKey: 'kld_pk_live_…',
map,
contained: true,
});
</script>
</body>
</html>
工作原理
| 访客操作 | 聊天面板 | Mapbox 地图 |
|---|---|---|
| 提交问题 | 展开聊天窗口,逐步显示回答文本。 | 暂无变化。 |
| 等待回答 | 为回答中的每个地点显示一张结果卡片。 | 每找到一个地点就显示标记。只有一个地点时,相机飞向该位置;多个地点时,调整视野并留出空间避开聊天面板。 |
| 点击标记或结果 | 打开包含概况、照片和路线工具的地点卡片。 | 点击结果将相机移动到该地点。 |
| 请求路线 | 显示路线距离和耗时。 | 绘制并框选路线。 |
| 继续提问 | 在同一对话中追加消息。 | 新标记被添加,旧标记保留。 |
| 关闭聊天 | 恢复到输入栏并结束对话。 | 删除标记和路线。 |
Mapbox GL JS 的具体行为:
- 标记使用包含 HTML 元素的 Mapbox
Marker对象,与您自行添加的标记相互独立。 - 路线使用面板向样式添加的 source 和 layer 绘制,之后会被移除。您自己的数据源和图层不会被更改。
- 面板挂载期间会在后台续期会话,您无需管理令牌。
检查是否正常工作
在网页中
- Ask Kaleidr 输入栏显示在地图左上角。
- 输入
Show me three museums in London并按 Enter,回答文字逐步出现,地图上显示三个标记并调整视野以容纳它们。
在控制台中
- 没有包含
[kaleidr的错误或警告。
在 Network 面板中
| 请求 | 预期结果 |
|---|---|
GET https://cdn.kaleidr.com/embed/v1/kaleidr.js | 200 |
GET https://cdn.kaleidr.com/embed/v1/chat.js | 200 |
POST https://api.kaleidr.com/inference-api/b2b/v1/sdk/sessions | 200,返回类似下方示例的 JSON |
POST https://api.kaleidr.com/inference-api/b2b/v1/chat/control/stream(提问后) | 200,content-type: text/event-stream |
{ "session_token": "kld_sess_live_…", "expires_in": 900, "product": "chat" }
无法正常工作时
SDK 会记录简短信息,不会重复服务器给出的详细原因。请求失败时,请在 Network 面板中打开它并查看 JSON 响应。403 和 404 的错误代码位于 detail;429 的代码位于 error,说明文字位于 detail。
| 现象 | 原因 | 解决方法 |
|---|---|---|
无面板,控制台提示 …/sdk/sessions 的 CORS 错误和 [kaleidr:chat] 错误 | 密钥无效、已撤销或网页来源未被允许。API 仅为允许的来源返回 CORS 头。 | 检查密钥,并在 kaleidr.com/api-keys 添加完整来源,包括协议和端口。 |
[kaleidr:chat] kaleidr session exchange failed (403) | 密钥有效,但无权打开 Chat。detail 可能为 insufficient_scope(缺少 ai)、product_not_allowed(仅限其他产品)或 tier_capability_not_allowed。 | 使用包含 ai 且允许 chat 产品的密钥。 |
[kaleidr:chat] Kaleidr: a server key (kld_sk_…) must never be used in the browser … | 传入了服务器密钥,因此未发送请求。 | 使用可公开使用的密钥(kld_pk_live_…)。如服务器密钥曾出现在公开网页中,请撤销它。 |
[kaleidr:chat] mount target not found: #chat | 选择器找不到目标。 | 在目标元素存在 后再调用 mount,或直接传入元素。 mount |
[kaleidr:chat] [kaleidr] failed to load https://cdn.kaleidr.com/embed/v1/chat.js | 程序包被内容安全策略或广告拦截器阻止。 | 在 script-src 中允许 https://cdn.kaleidr.com。 |
Kaleidr is not defined | 代码早于 kaleidr.js 执行,例如脚本使用 async 或 defer。 | 先用普通 script 标签加载 kaleidr.js,或在脚本 load 事件中运行代码。 |
[kaleidr] embed is disabled — … | 启用控制阻止了挂载。 | 消息会说明由哪个设置引起。参阅 kaleidr.js。 |
| 面板位于浏览器窗口左上角,而不是地图上方 | 缺少 contained,或 #chat 未定位。 | 添加 contained: true 和第 1 步的样式。 |
| 面板能回答,但不显示标记,地图也不移动 | map 参数传入的对象未被识别。 | 传入真正的 mapboxgl.Map 实例。参阅支持的地图。 |
| 相机能飞向单个地点,但无标记且无法框选多个地点 | 不存在 window.mapboxgl。单地点移动只需地图对象,标记和多地点适配需要全局对象。 | 如果从 npm 导入 Mapbox,请在挂载前设置 window.mapboxgl。参阅npm 导入。 |
| 面板始终显示“Sorry — that didn't go through. Please try again.” | 密钥被撤销或允许来源发生变化,导致会话失效。 | 检查密钥并刷新网页。 |
| 面板显示“You've reached your usage limit for now. ” | 429 错误:组织的 AI 点数耗尽或密钥触发速率限制。同一密钥的所有访客共享速率上限。 | 参阅配额和速率限制。 |
| 无法拖动地图 | 聊天层拦截了地图交互。 | 为 #chat 添加 pointer-events:none。 |
更多问题请参阅故障排查。
限制
- 网页不会从聊天面板收到回调或事件,因此不能通过代码响应提问、回答或标记点击。
- 助手无法看到您的图层、标记或当前地图可视区域。提问时仅发送缩放级别。
- 不能通过聊天面板向助手提供自定义指令或自己的数据。
- 回答语言、面板标题和输入框占位文字是挂载选项(
lang、title、placeholder),详见 Chat 参考文档。其他界面标签为英文。 - 对聊天挂载调用
handle.setCamera()不起作用,且会输出警告。请使用 Mapbox 自身的 API 移动相机。 - 在单页应用中,地图视图移除时调用
handle.destroy(),视图返回时再重新挂载。
完整清单见功能和限制。