动动小手学鸿蒙 HarmonyOS APP(04)AI聊天页面

ChatGpt类产品在输出答案的时候有一个明显特征,回答问题的文字是一个一个字蹦出来的。这种展示方式基于人工智能答案生成原理而设计。因为大语言模型在生成答案时就是逐字逐句一点点生成的。如果等整篇答案完全生成后再返回给前端,用户等待的时间就太长了。会严重影响用户体验。

根据ChatGpt介绍可以了解到,前端请求并不是使用webSocket,由于WebSocket需要client和server都持续占用一个socket,server侧成本比较高。ChatGPT使用的是一种折中方案: server-sent event(简称SSE).

SSE 模式下,client只需要向server发送一次请求,server就能持续输出,直到需要结束。 SSE仍然使用HTTP作为应用层传输协议,充分利用HTTP的长连接能力,实现服务端推送能力。

从代码层面来看,SSE模式与单次HTTP请求不同的点有:

  1. client端需要开启 keep-alive,保证连接不会超时。
  2. HTTP响应的Header包含 Content-Type=text/event-stream,Cache-Cnotallow=no-cache 等。
  3. HTTP响应的body一般是 "data: ..." 这样的结构。
  4. HTTP响应里可能有一些空数据,以避免连接超时。

看到这里,我们可以了解到通过这种SSE请求的方式,前端正是逐字得到的答案,所以在展示时就是按请求返回来展示出陆陆续续得到的文本答案。

了解了原理,本篇主要展示在鸿蒙中模拟展示这种逐字文本展示的AI聊天界面。

先看下效果:

本demo中仅实现UI效果,并未真正发送请求来获得数据。通过预置文本和定时器来实现一个字一个字蹦出来的效果。

聊天页面中外层为Stack布局,底部是输入TextInput和发送按钮,上部按顺序展示用户输入和系统回答文本。

正式项目中需要考虑加入加载动画,请求异常处理,代码以及表格图片等展示组件,聊天区域的滚动展示等问题。

非常简单,就直接贴代码了

ts 复制代码
build() {
  Stack({ alignContent: Alignment.Bottom }) {
    Column() {
      Row() {
        Text('你好呀我是聊天助手,有什么话想对我说吗?希望可以和你一起分享生活中的点点滴滴!')
          .fontSize(18)
          .fontColor('#1a1c1f')
          .padding(12)
          .backgroundColor('#f4f6f9')
          .margin({top: 12})
          .clip(new Rect({ width: '100%', height: '100%', radius: 12 }))
      }
      .width('100%')
      .justifyContent(FlexAlign.Start)

      if (this.answer.length > 0) {
        Row() {
          Text(this.question)
            .fontSize(18)
            .fontColor('#fefbf9')
            .padding(12)
            .margin({top: 12})
            .backgroundColor('#2e74f7')
            .clip(new Rect({ width: '100%', height: '100%', radius: 12 }))
        }
        .width('100%')
        .justifyContent(FlexAlign.End)

        Row() {
          Text(this.answer)
            .fontSize(18)
            .fontColor('#1a1c1f')
            .padding(12)
            .backgroundColor('#f4f6f9')
            .margin({top: 12})
            .clip(new Rect({ width: '100%', height: '100%', radius: 12 }))
        }
        .width('100%')
        .justifyContent(FlexAlign.Start)
      }
    }
    .height('100%')
    .width('100%')
    .padding(12)

    Row() {
      TextInput()
        .fontSize(18)
        .width('80%')
        .fontColor('#fefbf9')
        .padding(12)
        .clip(new Rect({ width: '100%', height: '100%', radius: 12 }))

      Blank().width(12)

      Text('发送')
        .fontSize(18)
        .padding(8)
        .fontColor('#fefbf9')
        .backgroundColor('#2e74f7')
        .clip(new Rect({ width: '100%', height: '100%', radius: 12 }))
        .onClick(() => {
          this.answer = '';
          this.pos = 0;
          clearInterval(this.intervalID);
          setTimeout(() => {
            this.intervalID = setInterval(() => {
              if (this.pos < this.text.length) {
                this.answer = this.answer.concat(this.text.charAt(this.pos))
                this.pos += 1;
              } else {
                clearInterval(this.intervalID);
              }
            }, 100)
          }, 500);
        })
    }
    .width('100%')
    .height(80)
    .padding({left: 12, right: 12})
    .alignItems(VerticalAlign.Center)
    .justifyContent(FlexAlign.End)
  }
}

通过本例可以熟悉这些知识:基础组件布局组件定时器等常用鸿蒙开发知识。

边学边写,欢迎留言。感谢各位大佬点赞

相关推荐
wk灬丨3 分钟前
Android Kotlin Flow 冷流 热流
android·kotlin·flow
千雅爸爸4 分钟前
Android MVVM demo(使用DataBinding,LiveData,Fresco,RecyclerView,Room,ViewModel 完成)
android
晨曦_子画39 分钟前
编程语言之战:AI 之后的 Kotlin 与 Java
android·java·开发语言·人工智能·kotlin
孤客网络科技工作室1 小时前
AJAX 全面教程:从基础到高级
android·ajax·okhttp
长弓三石1 小时前
鸿蒙网络编程系列44-仓颉版HttpRequest上传文件示例
前端·网络·华为·harmonyos·鸿蒙
Mr Lee_2 小时前
android 配置鼠标右键快捷对apk进行反编译
android
顾北川_野3 小时前
Android CALL关于电话音频和紧急电话设置和获取
android·音视频
&岁月不待人&3 小时前
Kotlin by lazy和lateinit的使用及区别
android·开发语言·kotlin
SameX3 小时前
鸿蒙 Next 电商应用安全支付与密码保护实践
前端·harmonyos
SuperHeroWu74 小时前
【HarmonyOS】键盘遮挡输入框UI布局处理
华为·harmonyos·压缩·keyboard·键盘遮挡·抬起