【鸿蒙】大模型对话应用(四):页面发起请求实现对话能力

Demo介绍

本demo对接阿里云和百度的大模型API,实现一个简单的对话应用。

DecEco Studio版本:DevEco Studio 3.1.1 Release

HarmonyOS SDK版本:API9

关键点:ArkTS、ArkUI、UIAbility、网络http请求、列表布局、层叠布局

定义接口响应数据

根据大模型对话应用(一)中接口返回JSON格式,定义大模型接口返回数据

TypeScript 复制代码
export class ALiYunResponse {
  request_id: string
  output: ALiYunResp_output
  usage: ALiYunResp_usage
}

class ALiYunResp_output {
  text: string
}

class ALiYunResp_usage {
  output_tokens: string
  input_tokens: string
}

输入框发送消息

在 ChatPageALiYun.ets文件,struct ChatPage { ... } 结构中,定义两个变量 submitMsg 和 textInputMsg

  • submitMsg:提交消息绑定变量,用于保存输入框输入文本信息,
  • textInputMsg:输入框输入信息绑定变量,可控制在发送消息后,清除文本输入框内容
TypeScript 复制代码
@State submitMsg: string = ''
@State textInputMsg: string = ''

完善输入文本框TextInput的 .onChange() 方法和.onSubmit() 方法

.onChange()方法中,当输入框内容变化时,同步更新this.submitMsg和this.textInputMsg的值

.onSubmit()方法中,当输入框内容提交时,表示消息发送。

  1. 将 this.textInputMsg 变量置空,会驱动输入框显示内容更新为空
  2. 将输入框输入的文本加入页面展示的聊天列表集合this.messageArr 之中,页面展示我方发送 的消息
  3. 页面展示聊天消息的列表滑动至底端,展示最新消息
  4. 使用输入框输入的文本作为参数,调用大模型http接口,发起对话请求
  5. 调用大模型http接口成功后,将接口返回的对话文本加入页面展示的聊天列表集合this.messageArr 之中,页面展示对方(大模型)应答的消息
  6. 页面展示聊天消息的列表滑动至底端,展示最新消息
TypeScript 复制代码
@Builder function inputBox(scroller: Scroller, messageArr: MessageVO[]) {
  Row() {
    Stack() {
      TextInput({placeholder: '有问题尽管问我~', text: this.textInputMsg})
        .height(50)
        .enterKeyType(EnterKeyType.Send)
        .onChange((text) => {
          this.submitMsg = text
          this.textInputMsg = text
        })
        .onSubmit(() => {
          this.textInputMsg = '' // 点击发送后 输入框置空
          this.messageArr.push(new MessageVO(MessageRoleEnum.Mine, this.submitMsg)) // 立刻展示我方对话
          scroller.scrollEdge(Edge.Bottom) // 消息发送后 将列表滚动到底端
          // 发送http请求
          ALiYunHttpUtils.request(this.submitMsg, (responseText: string) => {
            this.messageArr.push(new MessageVO(MessageRoleEnum.Other, responseText)) // 展示对方对话
            scroller.scrollEdge(Edge.Bottom) // 消息显示后 将列表滚动到底端
          })
        })
      Image($r('app.media.ic_public_send'))
        .margin({right:10})
        .height(35)
        .onClick(() => {
          // 参照文本输入框TextInput 的onSubmit事件实现
        })
    }
    .alignContent(Alignment.End)
    .height('10%')
  }
  .width('90%')
}

ALiYunHttpUtils处理回调

完善先前写好的ALiYunHttpUtils,为request() 方法入参添加一个回调函数,用于更新页面数据

TypeScript 复制代码
import http from '@ohos.net.http';
import hilog from '@ohos.hilog';
import { ALiYunResponse } from '../model/ALiYunResponse';
class ALiYunHttpUtils {

  request(question: string, callback: Function) {
    hilog.info(0x0000, 'testTag', 'ALiYunHttpUtils request invoke. question: %{public}s', question);
    // 1 createHttp接口创建请求
    let httpRequest = http.createHttp();
    // 2 发起请求
    httpRequest.request(
      // 请求地址
      "https://dashscope.aliyuncs.com/api/v1/services/aigc/text-generation/generation",
      // 请求options: HttpRequestOptions
      {
        // 请求方式
        method: http.RequestMethod.POST,
        // 请求头
        header: {
          "Content-Type": "application/json",
          // 这里的Authorization 就是刚才工作台查看的 API-KEY
          "Authorization": "sk-0bxxxxxxxxx1c3"
        },
        // 请求体
        extraData: {
          "model": "qwen-plus", // 指定用于对话的通义千问模型名
          "input": {
            "messages": [
              {
                "role": "user",
                "content": question // 请求发起方传入的问题
              }
            ]
          }
        }
      }, (err, data: http.HttpResponse) => {
        if (err) {
          hilog.error(0x0000, 'testTag', 'Failed to request ALiYun. Cause: %{public}s', JSON.stringify(err) ?? '');
          httpRequest.destroy();
        } else {
          hilog.info(0x0000, 'testTag', 'Request ALiYun success. data: %{public}s', JSON.stringify(data.result));
          let resp: ALiYunResponse = JSON.parse(data.result.toString())
          hilog.info(0x0000, 'testTag', 'Request ALiYunHttpUtils-Result. data: %{public}s', JSON.stringify(resp.output.text));
          httpRequest.destroy();
          callback(resp.output.text)
        }
      })
  }
}
export default new ALiYunHttpUtils;

预览效果

打开预览器,在输入文本框中输入内容后,敲击Enter键,可与大模型进行简单的对话

真机(pad)调试效果:

petal_20240203_171933

至此,一个简单的对话Demo就实现完成了;

本项目仅实现了很基础的简单功能,仍有许多细节需要完善,如:等待接口返回过程的加载交互动效、接口异常处理、数据持久化、对话头像的设置等。

有更精巧、更兼容的实现方案,欢迎大家评论指正~

相关推荐
逢生博客8 小时前
Mac 搭建仓颉语言开发环境(Cangjie SDK)
macos·华为·鸿蒙
青柠_项目管理8 小时前
PMP证书持有者,在华为、腾讯一般能拿多少薪资?
华为·pmp
小强在此12 小时前
【基于开源鸿蒙(OpenHarmony)的智慧农业综合应用系统】
华为·开源·团队开发·智慧农业·harmonyos·开源鸿蒙
Reuuse13 小时前
【HCIA-Datacom】华为VRP系统
服务器·网络·华为
PlumCarefree15 小时前
基于鸿蒙API10的RTSP播放器(四:沉浸式播放窗口)
华为·harmonyos
中关村科金19 小时前
中关村科金推出得助音视频鸿蒙SDK,助力金融业务系统鸿蒙化提速
华为·音视频·harmonyos
繁依Fanyi19 小时前
828 华为云征文|华为 Flexus 云服务器部署 RustDesk Server,打造自己的远程桌面服务器
运维·服务器·开发语言·人工智能·pytorch·华为·华为云
小强在此1 天前
基于OpenHarmony(开源鸿蒙)的智慧医疗综合应用系统
华为·开源·团队开发·健康医疗·harmonyos·开源鸿蒙
奔跑的露西ly1 天前
【鸿蒙 HarmonyOS NEXT】popup弹窗
华为·harmonyos