Coze + 高德 :智能导游

前言

前端时间了解到 mapbox 出了一个车机端的 MapGPT,可以做到智能的路线规划等一系列功能。我发现目前还没有人把AI和旅游很好的结合在一起。

于是我打算用我们国产软件去做一个简单的 AI导游案例,希望能给各位带来启发。

选型

AI

AI方面我选择了可以预定义人设的 Coze,给他一个AI导游、充当后台服务的角色。

人设如下

image.png

这样我们就得到了一个可以返回标准 json 的 AI。

image.png

将此 AI 发布到Bot as APIWeb SDK 以便可以在前端调用。

地图

地图当然选择了 高德地图,高德地图提供的 Loca API 可以华丽的实现各种可视化效果,其中就包括我们需要的 镜头动画

案例地址:lbs.amap.com/demo/loca-v…

QQ2024912-16571.webp

实现

Coze API

这个项目技术上不存在什么难点,重点在于对现有技术的整合利用,打造出一个有用的产品。

话不多说,直接进入编码阶段

首先我们使用常规的 axios 快速将 coze 提供的 接口封装一个函数。

import axios from "axios";
import autolog from 'autolog.js';
​
​
const service = axios.create({
  baseURL: "https://api.coze.cn/open_api/v2",
  timeout: 60000,
  headers: {
    "Content-Type": "application/json",
    'Authorization': `Bearer ${import.meta.env.VITE_COZE_TOKEN}`
  },
});
service.interceptors.request.use(
  (config) => {
    return config;
  },
  (error) => {
    autolog.log('请求错误', 'error');
    return Promise.reject(error);
  }
);
const getAnswer = async (question: string) => {
  const res = await service.post("/chat", {
    query: question,
    user: "githubPages",
    bot_id: "7413640476366602275",
    stream: false
  });
  return res.data;
}
export default getAnswer;

这里我使用的是 coze v2 版本,参数比较简单,便于大家理解,bot_id 即 coze 机器人主页 url 的最后一串数字,大家也可以在 Coze 商店直接体验我的机器人。

地址:www.coze.cn/store/bot/7…

虽然此 bot 没有使用高德接口额外扩展,但是经过实测发现,它本身给的经纬度也是非常准确的。

调用此接口,我们将得到如下回复:

image.png

content 里就是我们给它预设的回复内容,使用 JSON.parse 即可得到我们想要的内容。

高德地图 Loca 镜头动画

高德为可视化专门提供了另一套API服务,即 Loca。

我这里使用的是 Loca 2.0。

安装并引入 @amap/amap-jsapi-loader

  AMap = await AMapLoader.load({
    key: import.meta.env.VITE_AMAP_KEY, 
    version: "2.0", 
    plugins: ["AMap.GeoJSON"], 
    Loca: {                
      "version": '2.0.0'  
    },
  })

注意这里需要手动将 Loca 在初始化地图是就加上,不然会获取不到该变量。

地图加载完成后,我们需要 初始化 Loca

async function initLoca() {
  
  loca = new Loca.Container({
    map,
  })
  console.log('loca::: ', loca);
}

由于 Loca 是高德直接注入的,所以这里TS并不会识别,只好先忽略一下。

按照官网案例,我们可以很轻松的让镜头动画跑起来。

function animate() {
  let end = endPoint.value
  var speed = 1;
  // 镜头动画

  loca.viewControl.addAnimates(
    [{
      pitch: {
        value: 0,
        control: [[0, 20], [1, 0]],
        timing: [0, 0, 0.8, 1],
        duration: 3000 / speed,
      },
    }]
    , function () {

      loca.viewControl.addAnimates([
        // 寻迹
        {
          zoom: {
            value: 16,
            control: [[map.getZoom(), 3], [map.getZoom(), 15]],
            timing: [0.3, 0, 0.9, 1],
            duration: 5000 / speed,
          },
          center: {
            value: map.getCenter(),
            control: [map.getCenter(), end],
            timing: [0.3, 0, 0.1, 1],
            duration: 8000 / speed,
          },
        }, {
          // 环绕
          pitch: {
            value: 50,
            control: [[0, 40], [1, 50]],
            timing: [0.3, 0, 1, 1],
            duration: 7000 / speed,
          },
          rotation: {
            value: 260,
            control: [[0, -80], [1, 260]],
            timing: [0, 0, 0.7, 1],
            duration: 7000 / speed,
          },
          zoom: {
            value: 17,
            control: [[0.3, 16], [1, 17]],
            timing: [0.3, 0, 0.9, 1],
            duration: 5000 / speed,
          },
        },
      ],
        function () {
          setTimeout(animate, 2000);
          console.log('结束');
        });
    });
}

loca.viewControl.addAnimates 的参数也很好理解,分别有:pitch、rotation、zoom等,他们的内部参数则都有:value、control、timing、duration,分别是:动画终点的值、过渡中的轨迹控制点、动画时间控制点、总持续时间。

通过调整以上参数,我们可以实现几乎所有角度的动画展示。

上面的动画表达的是:先晃动一下视角(我们要出发了),视角先拉升再放大,从当前位置飞到终点,再终点环绕展示,最后动画结束,2秒后再次执行。

原谅我不懂镜头语言,但凑合着我们可以感受到飞来飞去的视觉效果了。

结合一下

首先获取到 Coze 的回答:

async function getAnswerFromCoze() {
  if (!question.value) {
    return
  }
  loading.value = true
  conversations.value.push({
    type: 'question',
    content: question.value
  })
  let question_backup = question.value
  question.value = ''
  conversations.value.push({
    type: 'answer',
    content: "正在为您查找..."
  })
  let res = await getAnswer(question_backup)
  loading.value = false
  let answer = JSON.parse(res.messages[0].content)
  endPoint.value = toNumber(answer.lnglat)
  conversations.value[conversations.value.length - 1].content = answer.description
  loca.animate.start()
  animate()
}

在这个函数中,我们通过一个响应式变量question存储用户的询问字符串(保证同一时间只处理一个),使用conversations存储对话历史,以便待会我们渲染到对话框中,最后,将得到的结果解析后,调动高德地图启动动画。

将两者分配一下画面,Coze作为对话框在左侧,高德作为地图展示铺满全屏

image.png

当我们问询时,首先由扣子查询相关信息

image.png

image.png

coze回复的同时,高德地图也动了起来

效果

最终我们就得到了这样的效果

QQ2024912-17344.webp

QQ2024912-163739.webp

结语

此项目已在github开源:github.com/LarryZhu-de…

阅读全文
下载说明:
1、本站所有资源均从互联网上收集整理而来,仅供学习交流之用,因此不包含技术服务请大家谅解!
2、本站不提供任何实质性的付费和支付资源,所有需要积分下载的资源均为网站运营赞助费用或者线下劳务费用!
3、本站所有资源仅用于学习及研究使用,您必须在下载后的24小时内删除所下载资源,切勿用于商业用途,否则由此引发的法律纠纷及连带责任本站和发布者概不承担!
4、本站站内提供的所有可下载资源,本站保证未做任何负面改动(不包含修复bug和完善功能等正面优化或二次开发),但本站不保证资源的准确性、安全性和完整性,用户下载后自行斟酌,我们以交流学习为目的,并不是所有的源码都100%无错或无bug!如有链接无法下载、失效或广告,请联系客服处理!
5、本站资源除标明原创外均来自网络整理,版权归原作者或本站特约原创作者所有,如侵犯到您的合法权益,请立即告知本站,本站将及时予与删除并致以最深的歉意!
6、如果您也有好的资源或教程,您可以投稿发布,成功分享后有站币奖励和额外收入!
7、如果您喜欢该资源,请支持官方正版资源,以得到更好的正版服务!
8、请您认真阅读上述内容,注册本站用户或下载本站资源即您同意上述内容!
原文链接:https://www.shuli.cc/?p=20867,转载请注明出处。
0

评论0

显示验证码
没有账号?注册  忘记密码?