0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

鸿蒙开发实战-手写文心一言AI对话APP

jf_46214456 来源:jf_46214456 作者:jf_46214456 2024-01-24 18:02 次阅读

运行环境

(后面附有API9版本,可修改后在HarmonyOS4设备上运行)

DAYU200:4.0.10.16

SDK:4.0.10.15

IDE:4.0.600

在DAYU200:4.0.10.16上运行

一、创建应用

1.点击File->new File->Create Progect

2.选择模版

OpenHarmony】Empty Ability

3.填写项目名,WenXinTalk,应用包名com.WenXinTalk,应用存储位置XXX(不要有中文,特殊字符,空格)

Compile SDK10,Model :Stage

Device Type 默认就可以。

node,建议16.20.1

完成以上配置以后点击Finish

4.选择在新窗口打开,等待依赖加载完毕。如图所示。

如果大家加载依赖报错的话,检查自己的网络

二、运行HelloWord

1.给开发板供电,并连接开发板到电脑,如图所示

2.签名

签名的步骤:

点击File->Project struct

点击Apply或者ok就可以,。

现在点击按钮运行项目。

控制台打印信息

01/12 16:13:40: Launching com.myapplication
$ hdc uninstall com.myapplication
$ hdc shell mkdir data/local/tmp/39ca9a16978647c98d8ac8bdf4a45279
$ hdc file send "E:studyHarmonyOSprojectWenXinTalkentrybuilddefaultoutputsdefaultentry-default-signed.hap" "data/local/tmp/39ca9a16978647c98d8ac8bdf4a45279"
$ hdc shell bm install -p data/local/tmp/39ca9a16978647c98d8ac8bdf4a45279 
$ hdc shell rm -rf data/local/tmp/39ca9a16978647c98d8ac8bdf4a45279
$ hdc shell aa start -a EntryAbility -b com.myapplication

证明项目已经成功运行在开发板上。

如果报错

01/09 14:38:39: Install Failed: error: failed to install bundle.
code:9568320
error: no signature file.
Open signing configs
Error while Deploy Hap

则需要去签名

三、修改图标和名称

修改应用图标和名称:

目录在AppScope/app.json5

{
  "app": {
    "bundleName": "com.myapplication",
    "vendor": "example",
    "versionCode": 1000000,
    "versionName": "1.0.1",
    "icon": "$media:iconAi",
    "label": "$string:app_name"
  }
}

修改完毕之后如图所示

修改成功之后,如图所示

打开方式,在设置-应用管理一栏。

修改桌面图标和名称

修改src/main/module.json5中如图所示的label和icon。

我们修改label的时候,修改中文目录下的就可以

{
  "module": {
    "requestPermissions": [
      {
        "name": "ohos.permission.INTERNET"
      }
    ],
    "name": "entry",
    "type": "entry",
    "description": "$string:module_desc",
    "mainElement": "EntryAbility",
    "deviceTypes": [
      "default",
      "tablet"
    ],
    "deliveryWithInstall": true,
    "installationFree": false,
    "pages": "$profile:main_pages",
    "abilities": [
      {
        "name": "EntryAbility",
        "srcEntry": "./ets/entryability/EntryAbility.ets",
        "description": "$string:EntryAbility_desc",
        "icon": "$media:iconAi",
        "label": "$string:EntryAbility_label",
        "startWindowIcon": "$media:startIcon",
        "startWindowBackground": "$color:start_window_background",
        "exported": true,
        "skills": [
          {
            "entities": [
              "entity.system.home"
            ],
            "actions": [
              "action.system.home"
            ]
          }
        ]
      }
    ]
  }
}

修改中文目录的即可

修改结果如下

四、添加相关权限

因为需要用到网络数据,所以添加initent权限。

在src/main/module.json5中modele中添加配置,然后按sync就可以。

"requestPermissions": [{
      "name": "ohos.permission.INTERNET"
    }],

五、定义数据模型

1.在ets目录下新建model文件夹

2.新建TS File

export class WenXinReturn {
  id: string = ""
  object: string = ""
  created: string = ""
  result: string = ""
  is_truncated: Boolean = false
  need_clear_history: Boolean = false
  finish_reason: string = ""
  usage: Usage = new Usage()
}

export class Usage {
  prompt_tokens: number = 0
  completion_tokens: number = 0
  total_tokens: number = 0
}

export class MsgOutput {
  content: string = ""
}

export class MsgInput {
  id: string = ""
  role: string = ""
  content: string = ""
}

六、加载网络数据

接口说明

准备好数据,

接口地址:[ https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/completions_pro]

请求方法:POST

请求参数

Header参数

名称
Content-Typeapplication/json

Query参数

名称类型必填描述
access_tokenstring通过API Key和Secret Key获取的access_token,参考Access Token获取

Body参数

名称类型必填描述
messagesList(message)聊天上下文信息。说明: (1)messages成员不能为空,1个成员表示单轮对话,多个成员表示多轮对话 (2)最后一个message为当前请求的信息,前面的message为历史对话信息 (3)必须为奇数个成员,成员中message的role必须依次为user(or function)、assistant (4)最后一个message的content长度(即此轮对话的问题)不能超过2400 token;如果messages中content总长度大于2400 token,系统会依次遗忘最早的历史会话,直到content的总长度不超过2400 token
temperaturefloat说明: (1)较高的数值会使输出更加随机,而较低的数值会使其更加集中和确定 (2)默认0.95,范围 (0, 1.0],不能为0 (3)建议该参数和top_p只设置1个 (4)建议top_p和temperature不要同时更改
top_pfloat说明: (1)影响输出文本的多样性,取值越大,生成文本的多样性越强 (2)默认0.8,取值范围 [0, 1.0] (3)建议该参数和temperature只设置1个 (4)建议top_p和temperature不要同时更改
penalty_scorefloat通过对已生成的token增加惩罚,减少重复生成的现象。说明: (1)值越大表示惩罚越大 (2)默认1.0,取值范围:[1.0, 2.0]
streambool是否以流式接口的形式返回数据,默认false
systemstring模型人设,主要用于人设设定,例如,你是xxx公司制作的AI助手,说明: (1)长度限制1024个字符 (2)如果使用functions参数,不支持设定人设system
user_idstring表示最终用户的唯一标识符,可以监视和检测滥用行为,防止接口恶意调用

在这个WenXinTalk App中我们主要使用参数messages

测试接口

测试如图所示

返回数据

{
    "id": "as-7gxj35bftb",
    "object": "chat.completion",
    "created": 1705068746,
    "result": "您好,我是文心一言,英文名是ERNIE Bot。我能够与人对话互动,回答问题,协助创作,高效便捷地帮助人们获取信息、知识和灵感。",
    "is_truncated": false,
    "need_clear_history": false,
    "finish_reason": "normal",
    "usage": {
        "prompt_tokens": 3,
        "completion_tokens": 33,
        "total_tokens": 36
    }
}

创建HTTP请求

1.导入http模块

import http from '@ohos.net.http';
import { BusinessError } from '@ohos.base';

2.创建createHttp

let httpRequest = http.createHttp();

3.填写HTTP地址

httpRequest.request(
      `https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/completions_pro?access_token=${access_token}`,
      {
        method: http.RequestMethod.POST,
        header: [{
          'Content-Type': 'application/json'
        }],
        extraData: {
          "messages": MsgArray
        }
      }

4.对网络数据的处理

if (!err) {
        
        let MsgReturn: WenXinReturn = JSON.parse(data.result.toString())
        this.MsgResult.content = MsgReturn.result
        let MsgIn: MsgInput = new MsgInput()
        MsgIn.role = "assistant" //文心一言返回的结果中令role为"assistant"
        MsgIn.content = this.MsgResult.content
        MsgIn.id = this.MsgArray.length.toString() //id作为MsgArray中的标识,用以后续循环渲染
        this.MsgArray.push(MsgIn) //将文心一言返回的结果同样作为参数加入到MsgArray的末尾
        httpRequest.destroy();
      } else {
        this.message = JSON.stringify(err)
        console.error('error:' + JSON.stringify(err));
        httpRequest.off('headersReceive');
        // 当该请求使用完毕时,调用destroy方法主动销毁
        httpRequest.destroy();
      }

完成以上配置以后

5.在应用程序里测试网络请求

build() {

    Column() {

      Button("测试网络请求").onClick(() = > {
        this.httpData()
      })
    }.width("100%").height("100%").justifyContent(FlexAlign.Center)
  }
}

如图所示

测试成功

如果2300006错误码,请检查网络

如果201错误码,请检查module.json中网络权限是否配置!

七、UI

数据获取到之后,我们就剩在页面上显示了。

首页

U I布局如图所示。

build() {
    Column() {
      Column() {
        Scroll() {
          Column() {
            ForEach(this.MsgArray, (item: MsgInput, index: number) = > {
              if (item.role == "user") {
                Row() {
                  Text(item.content)
                    .width("50%")
                    .padding(15.5)
                    .backgroundColor("#95EC69")
                    .borderRadius(4)
                  Image($r("app.media.user"))
                    .backgroundColor(Color.White)
                    .objectFit(ImageFit.Fill)
                    .width(50)
                    .height(50)
                    .borderRadius(4)
                    .margin({ left: 8, right: 8 })
                }
                .margin({ top: index === 0 ? 0 : 12 })
                .width("100%")
                .alignItems(VerticalAlign.Top)
                .justifyContent(FlexAlign.End)
              } else if (item.role == "assistant") {
                Row() {
                  Image($r("app.media.iconAi"))
                    .backgroundColor(Color.White)
                    .objectFit(ImageFit.Fill)
                    .width(50)
                    .height(50)
                    .borderRadius(4)
                    .margin({ left: 8, right: 8 })
                  Text(item.content)
                    .width("50%")
                    .padding(15.5)
                    .backgroundColor(Color.White)
                    .borderRadius(4)
                    .margin({ right: 0 })
                }
                .margin({ top: index === 0 ? 0 : 12 })
                .width("100%")
                .alignItems(VerticalAlign.Top)
                .justifyContent(FlexAlign.Start)
              }
            }, (item: MsgInput) = > item.id) //循环渲染时,键值匹配规则使用item.id
          }
          .padding({ top: 12, bottom: 12 })
        }

        .width("100%")
      }
      .backgroundColor("#EDEDED")
      .layoutWeight(1)

      Row() {
        TextInput({
          placeholder: "来和文心一言聊天吧", text: this.message
        })
          .backgroundColor(Color.White)
          .layoutWeight(8)
          .height(60)
          .onChange((msg: string) = > {
            this.message = msg
          })
          .margin({ top: 10, bottom: 10, left: 4, right: 4 })
        Button("提交")
          .margin(4)
          .layoutWeight(2)
          .onClick(() = > {
            let MsgIn: MsgInput = new MsgInput()
            MsgIn.id = this.MsgArray.length.toString()
            MsgIn.role = "user"
            MsgIn.content = this.message
            this.MsgArray.push(MsgIn)
            this.httpData(this.MsgArray)
            this.message = ""
          })
      }
      .backgroundColor("#F7F7F7")
    }
    .width("100%")
    .height("100%")
    .justifyContent(FlexAlign.SpaceBetween)
  }
}

八、完整源码

import { MsgInput, MsgOutput, WenXinReturn } from '../model/WexXinClass';
import http from '@ohos.net.http';
import { BusinessError } from '@ohos.base';

@Entry
@Component
struct Index {
  @State message: string = 'Hello World';
  @State WXReturn: WenXinReturn = new WenXinReturn()
  @State MsgResult: MsgOutput = new MsgOutput()
  @State MsgInputSample: MsgInput = new MsgInput()
  @State MsgArray: Array< MsgInput > = []

  aboutToAppear() {
    this.message = "请介绍一下你自己"
  }

  httpData(MsgArray: Array< MsgInput >) {
    let httpRequest = http.createHttp();
    httpRequest.request(
      "https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/completions_pro?access_token=24.c8909e4016b8a223464e02f463f1d1ac.2592000.1707464478.282335-46746495",
      {
        method: http.RequestMethod.POST,
        header: [{
          'Content-Type': 'application/json'
        }],
        extraData: {
          "messages": MsgArray
        }
      }, (err: BusinessError, data: http.HttpResponse) = > {
      if (!err) {

        let MsgReturn: WenXinReturn = JSON.parse(data.result.toString())
        this.MsgResult.content = MsgReturn.result
        let MsgIn: MsgInput = new MsgInput()
        MsgIn.role = "assistant"
        MsgIn.content = this.MsgResult.content
        MsgIn.id = this.MsgArray.length.toString()
        this.MsgArray.push(MsgIn)
        httpRequest.destroy();
      } else {
        this.message = JSON.stringify(err)
        console.error('error:' + JSON.stringify(err));
        httpRequest.off('headersReceive');
        // 当该请求使用完毕时,调用destroy方法主动销毁
        httpRequest.destroy();
      }
    }
    )

  }

  build() {
    Column() {
      Column() {
        Scroll() {
          Column() {
            ForEach(this.MsgArray, (item: MsgInput, index: number) = > {
              if (item.role == "user") {
                Row() {
                  Text(item.content)
                    .width("50%")
                    .padding(15.5)
                    .backgroundColor("#95EC69")
                    .borderRadius(4)
                  Image($r("app.media.user"))
                    .backgroundColor(Color.White)
                    .objectFit(ImageFit.Fill)
                    .width(50)
                    .height(50)
                    .borderRadius(4)
                    .margin({ left: 8, right: 8 })
                }
                .margin({ top: index === 0 ? 0 : 12 })
                .width("100%")
                .alignItems(VerticalAlign.Top)
                .justifyContent(FlexAlign.End)
              } else if (item.role == "assistant") {
                Row() {
                  Image($r("app.media.iconAi"))
                    .backgroundColor(Color.White)
                    .objectFit(ImageFit.Fill)
                    .width(50)
                    .height(50)
                    .borderRadius(4)
                    .margin({ left: 8, right: 8 })
                  Text(item.content)
                    .width("50%")
                    .padding(15.5)
                    .backgroundColor(Color.White)
                    .borderRadius(4)
                    .margin({ right: 0 })
                }
                .margin({ top: index === 0 ? 0 : 12 })
                .width("100%")
                .alignItems(VerticalAlign.Top)
                .justifyContent(FlexAlign.Start)
              }
            }, (item: MsgInput) = > item.id)
          }
          .padding({ top: 12, bottom: 12 })
        }

        .width("100%")
      }
      .backgroundColor("#EDEDED")
      .layoutWeight(1)

      Row() {
        TextInput({
          placeholder: "来和文心一言聊天吧", text: this.message
        })
          .backgroundColor(Color.White)
          .layoutWeight(8)
          .height(60)
          .onChange((msg: string) = > {
            this.message = msg
          })
          .margin({ top: 10, bottom: 10, left: 4, right: 4 })
        Button("提交")
          .margin(4)
          .layoutWeight(2)
          .onClick(() = > {
            let MsgIn: MsgInput = new MsgInput()
            MsgIn.id = this.MsgArray.length.toString()
            MsgIn.role = "user"
            MsgIn.content = this.message
            this.MsgArray.push(MsgIn)
            this.httpData(this.MsgArray)
            this.message = ""
          })
      }
      .backgroundColor("#F7F7F7")
    }
    .width("100%")
    .height("100%")
    .justifyContent(FlexAlign.SpaceBetween)
  }
}

在HarmonyOS 4.0设备上运行

(主要介绍与在OpenHarmony中开发时的不同,相同点不在赘述)

运行环境

HUAWEI Mate 40 : HarmonyOS 4.0.0

SDK:3.1.0(API 9)

IDE:4.0.600

一、在创建应用时选择第一个

如图

二、签名

签名时选择support HarmonyOS

需要登录华为账号后继续签名

三、注释掉源码中不支持API 9的部分

网络声明时直接使用即可

其余部分与在开发板上运行都相同,直接运行即可

九、总结

本文我们学习使用了基本组件的使用,网络请求以及状态管理,使用了ForEach循环渲染来构建对话界面。并且在HarmonyOS设备上成功运行, 更多的鸿蒙开发实战学习,可以前往我的主页学习更多,下面分享鸿蒙的开发知识体系曲线图

鸿蒙OpenHarmony技术进阶包看主页

十、FAQ

2300006 域名解析失败

错误信息

Couldn’t resolve host name.

错误描述

服务器的域名无法解析。

可能原因

1.传入的服务器的URL不正确。

2.网络不通畅。

处理步骤

1.请检查输入的服务器的URL是否合理。

2.请检查网络连接情况

201错误码

检查moudle.json5的网络权限是否添加

"requestPermissions": [
  {
    "name": "ohos.permission.INTERNET"
  }
],

审核编辑 黄宇

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • AI
    AI
    +关注

    关注

    87

    文章

    30753

    浏览量

    268901
  • 鸿蒙
    +关注

    关注

    57

    文章

    2343

    浏览量

    42821
  • OpenHarmony
    +关注

    关注

    25

    文章

    3716

    浏览量

    16257
  • 文心一言
    +关注

    关注

    0

    文章

    124

    浏览量

    1275
收藏 人收藏

    评论

    相关推荐

    一言放出的“时代礼物”,藏着中国科技的黄金机会

    一言开放服务,普通人怎么搭上这趟“时代顺风车”?
    的头像 发表于 09-02 16:11 1308次阅读
    <b class='flag-5'>文</b><b class='flag-5'>心</b><b class='flag-5'>一言</b>放出的“时代礼物”,藏着中国科技的黄金机会

    哪吒汽车接入百度一言通过百度Apollo融合一言的全面能力

    人工智能交互,开启强人工智能时代的汽车全新体验。   据介绍,一言(英文名:ERNIE Bot)是百度基于大模型技术推出的生成式
    发表于 02-24 11:33 544次阅读

    百度一言背后的大模型实力如何? 一言背后的它全面领先

    大模型在市场格局中处于第梯队,产品能力、生态能力、应用能力全面领先,受到行业广泛认可。     简单来说,大模型能为即将发布的生成式对话
    的头像 发表于 03-04 14:26 2648次阅读

    一言对标ChatGPT正式发布 尽管未趋完美

    一言对标ChatGPT 正式发布 尽管未趋完美 3月16日下午,百度正式发布了一言。在发
    的头像 发表于 03-16 15:20 1750次阅读
    <b class='flag-5'>文</b><b class='flag-5'>心</b><b class='flag-5'>一言</b>对标ChatGPT正式发布 尽管未趋完美

    百度一言将开启第批内测 长安逸达将首发搭载文一言

    文案创作、数理推算、中文理解、多模态生成五个使用场景中的综合能力。 图源百度官网直播      3月16日下午,百度在北京总部召开一言新闻发布会,正式发布新代大语言模型、生成式
    的头像 发表于 03-16 15:57 2960次阅读
    百度<b class='flag-5'>文</b><b class='flag-5'>心</b><b class='flag-5'>一言</b>将开启第<b class='flag-5'>一</b>批内测 长安逸达将首发搭载文<b class='flag-5'>心</b><b class='flag-5'>一言</b>

    一言,站在奥林匹亚

    我们为什么如此期待一言
    的头像 发表于 03-20 18:37 883次阅读
    <b class='flag-5'>文</b><b class='flag-5'>心</b><b class='flag-5'>一言</b>,站在奥林匹亚

    一言是什么?一言有哪些功能?

    一言 *(英文名:ERNIE Bot)* 是百度全新代知识增强大语言模型,大模型家族的
    的头像 发表于 08-31 10:02 58.1w次阅读

    一言率先全面开放 百度放大招

    一言率先全面开放 百度再放大招,一言率先全面开放。这是向全社会全面的开放。此外还有
    的头像 发表于 08-31 12:57 796次阅读

    一言率先向全社会全面开放

    8月31日,一言率先向全社会全面开放。广大用户可以在应用商店下载“一言
    的头像 发表于 08-31 15:10 840次阅读

    百度一言开放首日回答超3342万个问题

    百度一言开放首日回答超3342万个问题 8月31日,百度大模型一言
    的头像 发表于 09-02 15:58 1050次阅读

    百度一言,率先向全社会开放

    来源:证券日报 一言等国产大模型通过首批备案,向全社会开放 编辑:感知芯视界 8月31日,一言
    的头像 发表于 09-04 10:50 893次阅读

    百度一言开通会员后可解锁大模型4.0

    百度一言开通会员后可解锁大模型4.0 今天百度上线
    的头像 发表于 11-01 15:58 1262次阅读

    一言用户规模破1亿 应用已突破4000款

    一言用户规模破1亿 应用已突破4000款 在第十届WAVE SUMMIT深度学习开发者大会上百度首席技术官王海峰透露了组数据,自8月31日获准开放对公众提供服务以来,
    的头像 发表于 12-28 18:18 1065次阅读

    一言APP上线数字分身功能

    一言APP近日上线了项令人兴奋的新功能——数字分身。这功能允许用户轻松创建自己的个性化虚
    的头像 发表于 02-04 10:32 1180次阅读

    百度一言APP升级为

    百度宣布其文一言APP正式升级为,标志着百度在智能搜索领域迈出了重要步。
    的头像 发表于 09-04 16:06 487次阅读