首页 >> 大全

HarmonyOS 开发实例—蜜蜂 AI 助手

2023-12-29 大全 33 作者:考证青年

开发实例—蜜蜂 AI 助手 1. 前言

自华为宣布 NEXT 全面启动,近期新浪、B 站、小红书、支付宝等各领域头部企业纷纷启动鸿蒙原生应用开发。据媒体统计,如今 Top20 的应用里,已经有近一半开始了鸿蒙原生应用开发。虽然目前 NEXT 还未面向个人开发者开放,但我们可以体验并使用最新的 API9 和开发工具,尝试开发元服务,这个鸿蒙新的应用形态。体验未来在 NEXT 上实现的应用开发。但需要注意的是, 基于 API9 开发的应用或元服务是不可以适配 NEXT 版本的,大家也可以期待一下明年推出的适配 NEXT 新版本。

本文主要是基于蜜蜂 AI 元服务的开发案例,主要的功能有

元服务内部功能:

1、提供两个 Tabs,首页和我的;

2、用户只有登录之后才可以去使用蜜蜂 AI 的功能;

3、目前现有的知识库包括知识百科小助手,节日小助手,文本翻译小助手,产品名称小助手,以及道歉信小助手等;

4、用户使用小助手之后,我们可以保存对话到列表内,下次快速的进行访问。

元服务卡片

1、提供 2-4 的卡片,卡片界面展示每日妙语,点击即可刷新;

2、提供 1-2 的卡片,实现快速访问首页;

3、提供 2-2 卡片,可以快速使用包括知识百科小助手,节日小助手,文本翻译小助手,产品名称小助手;

4、提供 4-4 卡片,可以快速到达登陆页面,访问小助手等。

开发实例—蜜蜂 AI 助手演示视频

1.1

是华为公司开发的操作系统,它的设计理念是面向未来的全场景智慧体验,可在各种设备上运行,包括手机、平板电脑、智能手表、智能音箱等。 采用分布式技术,可以将不同设备之间的计算资源连接起来,实现设备间的协同工作,提高系统的性能和稳定性。此外, 还拥有高度自适应的界面、多屏协同等特性,使用户能够在不同设备上实现无缝的体验。

1.2 元服务

在万物互联时代,人均持有设备量不断攀升,设备和场景的多样性,使应用开发变得更加复杂、应用入口更加多样。在此背景下,应用提供方和用户迫切需要一种新的服务提供方式,使应用开发更简单、服务(如听音乐、打车等)的获取和使用更便捷。为此, 除支持传统方式的需要安装的应用(以下简称传统应用)外,还支持更加方便快捷的免安装的应用(即元服务)。

1.3 介绍 (AGC)

(简称 AGC)致力于为应用的创意、开发、分发、运营、经营各环节提供一站式服务,构建全场景智慧化的应用生态体验。

1.4 蜜蜂 AI 元服务助手背景

目前 AI 正火,而我自己也有辛参与到大模型的训练中来,于是有了蜜蜂这个作品。

元服务与传统应用对比 项目元服务传统应用

软件包形态

App Pack(.app)

App Pack(.app)

分发平台

由应用市场()管理和分发

由应用市场()管理和分发

安装后有无桌面 icon

无桌面 icon,但可手动添加到桌面,显示形式为服务卡片

有桌面 icon

HAP 免安装要求

所有HAP(包括 Entry HAP 和 HAP)均需满足免安装要求

所有 HAP(包括 Entry HAP 和 HAP)均为非免安装的

新建元服务应用

开通

AI 平台

登陆账号

如何运行

2. 准备工作 2.1 应用开发环境

工欲善其事,必先利其器,我们首先要做的就是搭建开发环境

这里面我们分为三步走

2.1.1 环境安装

首先在这边安装最新的 IDE:

下载链接:#

我的是 M1,所以我们下载这一个就可以

2.1.2 环境配置

下载完成之后,我们就开始配置开发环境。下载 SDK 及工具链,首次使用 ,工具的配置向导会引导您下载 SDK 及工具链。配置向导默认下载 API 9 的 SDK 及工具链,我们选择默认就好

下载 和 ohpm,记得最好 SDK 路径中不能包含中文字符。

下载完成之后,我们下载 SDK

在弹出的 SDK 下载信息页面,单击Next,并在弹出的 窗口,阅读 协议,需同意 协议后,单击Next。

目前最新的应该是 3.2.13.5。

确认设置项的信息,点击Next开始安装。

等待 Node.js、ohpm 和 SDK 下载完成后,单击,界面会进入到 欢迎页。

2.1.3 创建

1.在 的欢迎页,选择 开始创建一个新工程。

2.根据工程创建向导,在 页签,选择“Empty ”模板,单击 Next。

3.单击 Next,各个参数保持默认值即可,单击 ,

2.1.4 运行

1.将搭载 手机与电脑连接。

2.单击 File> > > 界面勾选“支持 ,以及 ”,等待自动签名完成即可,单击 OK。如右所示:。

3.在编辑窗口右上角的工具栏,单击运行,等待编译完成即可便运行在设备上。

这个时候真机就可以看到 。接下来我们就创建蜜蜂 AI 元服务。

2.2 创建蜜蜂 AI 元服务

这里我们的模版就不再选空模板了,而是直接选择最后一个端云一体化模版

然后其他的就按照上面的配置就可以。完成项目的配置。

这里有个区别就是我们需要关联云资源。所以我们创建的应用包名要牢记,这个要在后面我们云端配置的时候使用。

为工程关联云开发所需的资源,即在 中选择您的华为开发者账号加入的开发者团队,将该团队在 AGC 的同包名应用关联到当前工程,具体操作如下:

单击“Team”下拉框,选择开发团队。选中团队后,系统根据工程包名自动查询团队下的同包名应用。若为首次创建且团队下未创建同包名的应用,则提示需要在 AGC 平台创建应用。

单击“ ”打开 AGC 应用创建向导,填写应用信息,单击“确认”按钮创建应用。

完成以上操作后, 即可获取到同包名应用对应的项目信息。

2.3 AGC 配置

我们登陆云侧,创建元服务

然后我们开通手机登陆和邮箱登录服务。

3. 实现登录

当前 AGC 认证服务为 应用/服务提供的登录认证方式有手机、邮箱两种方式。本工程使用“手机号码+验证码”的方式作为应用的登录入口。而且我们在前面已经开通。

在登陆这一块,用户首次登陆的时候,我们会首先利用首选项检查他的登陆状态。

首选项工具类

/*** 首选项操作类*/
import { PreferenceDBUtil } from '../utils/PreferencesDBUtil';const preDbService = new PreferenceDBUtil();
preDbService.getPreStorage();export const getDBPre = async (key: string) => {const value = await preDbService.getPreVal(key);return value;
};export const putDBPre = async (key: string, value: string) => {await preDbService.putPreData(key, value);
};

然后跳用调用.de申请验证码,在entry/src/main/ets//Auth.ts认证工具类中添加邮箱验证码获取方法。

import { MainPage } from "@hw-agconnect/auth-component-ohos"
import router from '@ohos.router'
import { LogUtil } from '../common/utils/LogUtil';
import { Constants } from '../common/Constants';
import { putPre } from '../common/service/PreService';
import { UserInfo } from '../common/UserInfo';@Entry
@Component
struct Index {@State icon: Resource = router.getParams()['icon'];@State isAgreement:boolean = router.getParams()['isAgreement'];@State agreementContent:string = router.getParams()['agreementContent'];@State onSuccess: Function = router.getParams()['onSuccess'];@State onError: Function = router.getParams()['onError'];build() {Column() {MainPage({icon: this.icon,agreement: {isAgreement: this.isAgreement,agreementContent: this.agreementContent,},onSuccess: async (user) => {LogUtil.info(`登录用户信息:${JSON.stringify(user)}`);const loginUser = user['user'];const userInfo: UserInfo = {uid: loginUser['uid'],email: loginUser['email'],phone: loginUser['phone'] === undefined ? "" : loginUser['phone'].split('-')[1],displayName: loginUser['displayName'] === undefined ? "" : loginUser['displayName'],photoUrl: loginUser['photoUrl'] === undefined ? "/common/imgs/ic_user.svg" : loginUser['photoUrl']}await putPre(Constants.LOGIN_USER_KEY, JSON.stringify(userInfo));router.back();},onError: (err) => {LogUtil.error(`登录用户信息:${JSON.stringify(err)}`);}})}}aboutToAppear() {}
}

未登录弹窗

/*** 未登录弹窗*/
import common from '@ohos.app.ability.common';
import router from '@ohos.router';
import { GlobalConstant } from '../common/constants/GlobalConstant';
@CustomDialog
export struct LoginTipDialogView {loginTipCtrl: CustomDialogController;build() {Column({ space: GlobalConstant.SIZE_8 }) {Row({ space: GlobalConstant.SIZE_4 }) {Image($r('app.media.ic_tip')).width(GlobalConstant.SIZE_32).height(GlobalConstant.SIZE_32)Text('温馨提示').fontSize($r('app.float.font_size_24')).fontColor($r('app.color.tip_color')).fontWeight(FontWeight.Bolder)}.width(GlobalConstant.PAGE_FULL).height(GlobalConstant.SIZE_64).padding({ left: GlobalConstant.SIZE_16 })Text('您还未登录,请登录后体验功能!').height(GlobalConstant.SIZE_48).fontSize(Color.Black).fontSize($r('app.float.font_size_18')).fontWeight(FontWeight.Normal)Row({ space: GlobalConstant.SIZE_8 }) {Button('退出', { type: ButtonType.Normal }).borderRadius(GlobalConstant.SIZE_4).backgroundColor($r('app.color.embellishment_color')).fontColor($r('app.color.text_color_9')).onClick(() => {const ctx = getContext(this) as common.UIAbilityContext;ctx.terminateSelf();})Button('去登录', { type: ButtonType.Normal }).borderRadius(GlobalConstant.SIZE_4).backgroundColor($r('app.color.embellishment_color')).fontColor($r('app.color.auxiliary_color')).onClick(() => {this.loginTipCtrl.close();router.pushUrl({params:{isAgreement: true,agreementContent: "",icon: "",type: ["HWID_VERIFY_CODE","PHONE"]},url: '@bundle:com.jianguo.ai/common/ets/LoginComponent/LoginPage',})})}.width(GlobalConstant.PAGE_FULL).justifyContent(FlexAlign.Center)}.width(GlobalConstant.PAGE_96).padding({ bottom: GlobalConstant.SIZE_20 }).borderRadius(GlobalConstant.SIZE_16).backgroundColor(Color.White)}
}

4.实现蜜蜂 AI 助手页面

我们这个应用主要的一个功能就是 AI 助手,所以这一块我们分为三块。

4.1 蜜蜂 AI 列表页

关于列表页,我们使用一个列表就可以

/*** 首页*/
import { ConfigConstant } from '../common/constants/ConfigConstant'
import { GlobalConstant } from '../common/constants/GlobalConstant'
import { AiAppConfig } from '../common/dto/AiAppConfig';
import router from '@ohos.router'
import { getDBPre } from '../common/api/PreDbService';
@Component
export struct HomeView {@State aiAppList: Array<AiAppConfig> = ConfigConstant.DEFAULT_AI_APP_LIST;}build() {Column() {List() {ForEach(this.aiAppList, (item: AiAppConfig) => {ListItem() {Row({ space: GlobalConstant.SIZE_8 }) {Row() {Image(item.avatar).width(GlobalConstant.SIZE_64).height(GlobalConstant.SIZE_64).borderRadius(GlobalConstant.SIZE_32)}.height(GlobalConstant.PAGE_FULL).layoutWeight(1)Column({ space: GlobalConstant.SIZE_16 }) {Text(item.name).fontSize($r('app.float.font_size_18'))Text(item.intro).fontSize($r('app.float.font_size_14')).fontColor($r('app.color.text_color_9'))}.height(GlobalConstant.PAGE_FULL).layoutWeight(3).justifyContent(FlexAlign.Center).alignItems(HorizontalAlign.Start)}.width(GlobalConstant.PAGE_96).height(GlobalConstant.SIZE_100).paddingStyle().borderRadius(GlobalConstant.SIZE_16).shadow({radius: GlobalConstant.SIZE_16,color: $r('app.color.main_color')}).onClick(() => {router.pushUrl({url: "pages/detail/index",params: {"AiAppConfig": item}})})}.width(GlobalConstant.PAGE_FULL).paddingStyle().borderRadius(GlobalConstant.SIZE_16)})}.listDirection(Axis.Vertical)}.width(GlobalConstant.PAGE_FULL).height(GlobalConstant.PAGE_FULL).padding(GlobalConstant.SIZE_8)}}

效果图

4.2 对话页 关键代码

  build() {Column({ space: GlobalConstant.SIZE_8 }) {Stack({ alignContent: Alignment.Bottom }) {Column() {Column({ space: GlobalConstant.SIZE_4 }) {Text("蜜蜂AI助手").fontSize($r('app.float.font_size_16')).fontColor(Color.Black).fontWeight(FontWeight.Bolder)Text("介绍").fontSize($r('app.float.font_size_12')).fontColor($r('app.color.text_color_9')).fontWeight(FontWeight.Lighter)}.width(GlobalConstant.PAGE_FULL).justifyContent(FlexAlign.Center).padding({top: GlobalConstant.SIZE_4,bottom: GlobalConstant.SIZE_8})Scroll() {Column({ space: GlobalConstant.SIZE_8 }) {ForEach(this.chatContentArr, (chat: ChatInfo) => {if (chat.role === "assistant") {Row() {Row({ space: GlobalConstant.SIZE_8 }) {Image(chat.avatar).width(GlobalConstant.SIZE_24).height(GlobalConstant.SIZE_24)Row() {Text(chat.content).fontSize($r('app.float.font_size_14')).fontColor(Color.Black)}.width(chat.content.length > 15 ? GlobalConstant.PAGE_76 : 'auto').backgroundColor($r('app.color.embellishment_color')).padding({left: GlobalConstant.SIZE_16,right: GlobalConstant.SIZE_16,top: GlobalConstant.SIZE_8,bottom: GlobalConstant.SIZE_8}).borderRadius({topRight: GlobalConstant.SIZE_4,bottomLeft: GlobalConstant.SIZE_8,bottomRight: GlobalConstant.SIZE_4})}.justifyContent(FlexAlign.Start).alignItems(VerticalAlign.Top)}.width(GlobalConstant.PAGE_FULL).justifyContent(FlexAlign.Start)}if (chat.role === "user") {Row() {Row({ space: GlobalConstant.SIZE_8 }) {Row() {Text(chat.content).fontSize($r('app.float.font_size_14')).fontColor(Color.Black)}.width(chat.content.length > 15 ? GlobalConstant.PAGE_76 : 'auto').backgroundColor($r('app.color.tab_default_color')).padding({left: GlobalConstant.SIZE_16,right: GlobalConstant.SIZE_16,top: GlobalConstant.SIZE_8,bottom: GlobalConstant.SIZE_8}).borderRadius({topLeft: GlobalConstant.SIZE_4,bottomLeft: GlobalConstant.SIZE_4,bottomRight: GlobalConstant.SIZE_8})Image(chat.avatar).width(GlobalConstant.SIZE_24).height(GlobalConstant.SIZE_24)}.justifyContent(FlexAlign.End).alignItems(VerticalAlign.Top)}.width(GlobalConstant.PAGE_FULL).justifyContent(FlexAlign.End)}})}.width(GlobalConstant.PAGE_FULL)}.width(GlobalConstant.PAGE_96).scrollable(ScrollDirection.Vertical).flexShrink(1)}.width(GlobalConstant.PAGE_FULL).height(GlobalConstant.PAGE_FULL).padding({ bottom: GlobalConstant.SIZE_50 })Row({ space: GlobalConstant.SIZE_8 }) {TextInput({ placeholder: "请输入提示词...", text: this.inputValue }).height(GlobalConstant.SIZE_48).fontSize($r('app.float.font_size_16')).placeholderFont({ size: $r('app.float.font_size_16') }).placeholderColor($r('app.color.text_color_9')).borderRadius($r('app.float.size_8')).backgroundColor($r('app.color.card_bg_color')).flexShrink(1).onChange((value: string) => {this.inputValue = value;})Image($r('app.media.ic_send')).width(GlobalConstant.SIZE_32).height(GlobalConstant.SIZE_32).onClick(async () => {this.loadingCtrl.open();if (this.inputValue === "") {promptAction.showToast({message: "发送内容不能为空!"})return;}await this.getAiResult();})}.width(GlobalConstant.PAGE_FULL).padding({left: GlobalConstant.SIZE_8,right: GlobalConstant.SIZE_8}).backgroundColor($r('app.color.card_bg_color'))}.width(GlobalConstant.PAGE_FULL).height(GlobalConstant.PAGE_FULL)}.width(GlobalConstant.PAGE_FULL).height(GlobalConstant.PAGE_FULL)}

效果图

关于我们

最火推荐

小编推荐

联系我们


版权声明:本站内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 88@qq.com 举报,一经查实,本站将立刻删除。备案号:桂ICP备2021009421号
Powered By Z-BlogPHP.
复制成功
微信号:
我知道了