跳到主要内容

将 Kaleidr Chat 添加到 Google 地图

完成本指南后,网页将显示 Google 地图及嵌入其中的聊天面板。访客提出问题时,回答会逐步显示,涉及的地点也会作为标记出现在 Google 地图上,相机随之移动以展示这些地点。所有套餐(包括 Free)均可使用公开密钥启用。问题会消耗组织的 AI 积分。

Google Maps 密钥与 Kaleidr 密钥相互独立。Google 对地图使用计费,Kaleidr 对提问计费。Kaleidr 不会收到您的 Google 密钥。

开始之前​

  • 从 kaleidr.com/api-keys 获取 Kaleidr 公开密钥 (kld_pk_live_…)。新密钥带有聊天所需的 ai 权限。参阅获取 API 密钥。
  • 如果密钥设置了允许的来源,请加入页面来源;本地测试可使用 http://localhost:8080。
  • 来自 Google Cloud 项目的 Google Maps JavaScript API 密钥,并启用 Maps JavaScript API,在其 Referer 限制中允许页面来源。
  • HTTP 网页服务器,例如 npx serve 或 python -m http.server 8080。直接打开磁盘文件无法运行。
  • 如果网页使用内容安全策略,还需允许 Content Security Policy 中列出的 Kaleidr 服务及 Google Maps 所需服务。

Google Maps JavaScript API 始终提供全局变量 google.maps,因此不需要额外将地图 API 暴露给聊天组件。

第 1 步:布置地图和聊天层​

将地图和聊天挂载目标放在同一个定位容器中。聊天层覆盖在地图上方,但允许指针事件穿透。

<div id="mapHost" style="position:relative; height:520px">
<div id="map" style="position:relative; height:100%; z-index:0"></div>
<div id="chat" style="position:absolute; inset:0; z-index:1; pointer-events:none"></div>
</div>

地图元素通过 height:100% 填满包装容器。使用 position:relative 和 z-index:0,可让 Google 地图自身的图层保持在地图元素内部,并位于聊天图层之下。

**预期结果:**目前只显示一个 520 像素高的空白区域。

第 3 步:加载 kaleidr.js​

使用普通 script 标签加载 Kaleidr 脚本,确保地图回调函数运行前 Kaleidr 已经定义。

<script src="https://cdn.kaleidr.com/embed/v1/kaleidr.js"></script>

**预期结果:**网页不会发生明显变化。在控制台中,Kaleidr.version 会返回版本字符串。

第 3 步:定义创建地图并挂载聊天面板的回调函数​

Google Maps 脚本加载完成后会调用您指定的函数。请在该函数内部创建地图并挂载聊天面板,因为脚本完成加载前 google.maps 尚不存在。

<script>
function initMap() {
const map = new google.maps.Map(document.getElementById('map'), {
center: { lat: 51.5, lng: -0.12 },
zoom: 11,
});

Kaleidr.mount('#chat', {
product: 'chat',
publishableKey: 'kld_pk_live_…',
map,
contained: true,
});
}
</script>

**预期结果:**仍不显示内容。函数已经定义,但还没有被调用。

第 4 步:在回调定义之后加载 Google Maps 脚本​

将 Google script 标签放在定义 initMap 的脚本之后。

<script async
src="https://maps.googleapis.com/maps/api/js?key=YOUR_GOOGLE_KEY&callback=initMap&loading=async&v=weekly"></script>

顺序很重要。Google 脚本使用 async,浏览器下载完成后会立即执行并调用 initMap。如果把该脚本放在前面,可能在浏览器读取到函数定义之前就执行,导致 Google 报错:initMap 不是函数。先定义回调就能避免竞态条件。 (initMap)

**预期结果:**显示伦敦市中心的 Google 地图,左上角有写着 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 Google Maps</title>
<style>
body { margin: 0; font-family: system-ui, sans-serif; }
#mapHost { position: relative; height: 100vh; }
#map { position: relative; height: 100%; 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>

<!-- 1. The Kaleidr loader. -->
<script src="https://cdn.kaleidr.com/embed/v1/kaleidr.js"></script>

<!-- 2. The callback, defined before the Google script can call it. -->
<script>
function initMap() {
const map = new google.maps.Map(document.getElementById('map'), {
center: { lat: 51.5, lng: -0.12 },
zoom: 11,
});

Kaleidr.mount('#chat', {
product: 'chat',
publishableKey: 'kld_pk_live_…',
map,
contained: true,
});
}
</script>

<!-- 3. The Google Maps script, last. -->
<script async
src="https://maps.googleapis.com/maps/api/js?key=YOUR_GOOGLE_KEY&callback=initMap&loading=async&v=weekly"></script>
</body>
</html>

工作原理​

访客聊天面板Google 地图
提交问题展开对话窗口并逐步显示回答暂时不变化
等待回答为回答中的每个地点显示结果卡片找到地点后逐个放置标记。单个地点会平移并调整缩放;多个地点会以四边 56 像素边距适配显示。
点击标记或结果打开含简介、照片和路线工具的地点卡片点击结果时移动至该地点
请求路线显示距离与耗时绘制并适配路线
继续提问延续同一对话新标记添加到地图,原标记保留
关闭聊天恢复输入栏并结束对话清除标记和路线

Google Maps 的特别说明:

  • 标记通过自定义叠加层绘制 HTML 元素。 这样不需要 Map ID。如果您的页面加载了 Google 的 marker 库,聊天组件会改用高级标记,此时 Google 要求地图提供 mapId。
  • 单地点移动先平移再调整缩放,并非连续的飞行动画。
  • 多地点适配在四周使用相同的 56 像素边距。 不会避开聊天面板,因此地点可能被面板挡住;访客可以拖动地图或最小化面板。
  • **路线使用两条折线:**白色描边位于彩色路线下方。
  • 地图视为平面且朝北,助手不会修改朝向或倾斜。
  • 面板挂载期间会在后台自动续期会话,无需管理令牌。

检查是否正常工作​

在网页中

  • Ask Kaleidr 输入栏显示在地图左上角。
  • 输入 Show me three museums in London 并按 Enter,回答文字逐步出现,地图上显示三个标记并调整视野以容纳它们。

在控制台中

  • 控制台中没有包含 [kaleidr 的错误或警告,也没有 Google Maps API 错误。

在 Network 面板中

请求预期结果
GET https://cdn.kaleidr.com/embed/v1/kaleidr.js200
GET https://cdn.kaleidr.com/embed/v1/chat.js200
POST https://api.kaleidr.com/inference-api/b2b/v1/sdk/sessions200,返回类似下方示例的 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。

现象原因解决方法
地图不存在,Google 报错 initMap is not a function。Google 脚本比定义 initMap 的脚本更早执行。把 Google script 标签移到回调定义之后,参阅第 4 步。
无地图,或灰色地图与 Google 错误对话框。Google 密钥配置有误:未启用 Maps JavaScript API、未设置计费或来源被限制。在 Google Cloud 项目中修正;与 Kaleidr 无关。
initMap 内提示 Kaleidr is not defined。kaleidr.js 使用了 async 或 defer,或放在 Google 脚本后。先以普通 script 标签加载 kaleidr.js。
有地图但无面板,…/sdk/sessions 返回 CORS 错误并有 [kaleidr:chat] 消息。Kaleidr 密钥未知、已撤销或来源不在允许列表中。拒绝时不返回允许该来源的 CORS 头,浏览器会隐藏响应。核对密钥,在 kaleidr.com/api-keys 加入包含协议和端口的准确来源。
[kaleidr:chat] kaleidr session exchange failed (403)缺少 ai 权限(insufficient_scope)、产品受限(product_not_allowed)或套餐不允许(tier_capability_not_allowed)。使用包含 ai 权限并允许 chat 产品的密钥。 detail
[kaleidr:chat] Kaleidr: a server key (kld_sk_…) must never be used in the browser …把服务器密钥放在浏览器中。改用公开密钥 (kld_pk_live_…);如果已部署,应撤销服务器密钥。
[kaleidr:chat] [kaleidr] failed to load https://cdn.kaleidr.com/embed/v1/chat.js脚本遭到 CSP 或广告拦截器阻止。在 script-src 中允许 https://cdn.kaleidr.com。
面板位于浏览器窗口左上角而非地图上。缺少 contained 或 #chat 未正确定位。按第 1 步配置 contained: true 及样式。
面板被地图遮挡。地图元素没有独立堆叠上下文。在 #map 上使用 z-index:0,在 #chat 上使用 z-index:1。
面板回答但地图没有标记也不移动。作为 map 传入的不是 google.maps.Map 实例,如 DOM 元素或封装对象。传入 new google.maps.Map(…) 返回的对象,参阅支持的地图。
面板回答且地图移动,但没有标记。页面加载了 marker 库,但地图未设置 mapId。添加 mapId 或不加载 marker 库。
每个问题都提示“Sorry — that didn't go through. Please try again.”会话已失效,密钥被撤销或允许来源发生变化。检查密钥并重新加载页面。
提示“You've reached your usage limit for now.”429:组织 AI 积分耗尽或密钥达到速率限制;同一网页的所有访客共享密钥限制。参阅配额与速率限制。

更多问题请参阅故障排查。

限制​

  • 页面不会接收面板的回调或事件;无法通过代码对问题、回答或标记点击作出响应。
  • 助手无法读取您的叠加层、标记或当前地图显示区域;提问时只会发送缩放级别。
  • 不能通过聊天面板向助手传入自定义指令或自有数据。
  • 回答语言、面板标题及输入占位文字可用挂载选项 lang、title、placeholder 设置,参阅聊天参考;其他标签仍为英语。
  • Google Maps 的适配不会避开聊天面板。
  • 聊天挂载中调用 handle.setCamera() 不会起作用,并会产生警告;请使用 Google Maps API 移动地图。
  • 在单页应用中,地图视图移除时应调用 handle.destroy();返回时重新挂载。

完整清单见功能和限制。

后续步骤​