使用 HarmonyOS NEXT和Mass快速开发NutPITalk
使用 HarmonyOS NEXT和Mass快速开发NutPITalk
运行环境
DevEco Studio:5.0Release
OpenHarmony SDK API12
开发板:润和DAYU200/Mate60 Pro
Mass
Mass(即 ModelArts Studio大模型即服务平台)是华为云面向AI开发者推出的一站式大模型开发平台,支持开发者一键体验大模型能力,快速构建大模型应用。Mass平台提供大模型训练、推理、部署、管理、监控等全生命周期管理能力,帮助开发者快速构建大模型应用,加速AI开发。
ModelArts Studio大模型即服务平台(MaaS)的应用场景:
-
业界主流开源大模型覆盖全
MaaS集成了业界主流开源大模型,含Llama、Baichuan、Yi、Qwen模型系列,所有的模型均基于昇腾AI云服务进行全面适配和优化,使得精度和性能显著提升。开发者无需从零开始构建模型,只需选择合适的预训练模型进行微调或直接应用,减轻模型集成的负担。
-
零代码、免配置、免调优模型开发
平台结合与100+客户适配、调优开源大模型的行业实践经验,沉淀了大量适配昇腾,和调优推理参数的最佳实践。通过为客户提供一键式训练、自动超参调优等能力,和高度自动化的参数配置机制,使得模型优化过程不再依赖于手动尝试,显著缩短了从模型开发到部署的周期,确保了模型在各类应用场景下的高性能表现,让客户能够更加聚焦于业务逻辑与创新应用的设计。
-
资源易获取,按需收费,按需扩缩,支撑故障快恢与断点续训
企业在具体使用大模型接入企业应用系统的时候,不仅要考虑模型体验情况,还需要考虑模型具体的精度效果,和实际应用成本。
MaaS提供灵活的模型开发能力,同时基于昇腾云的算力底座能力,提供了若干保障客户商业应用的关键能力。
保障客户系统应用大模型的成本效率,按需收费,按需扩缩的灵活成本效益资源配置方案,有效避免了资源闲置与浪费,降低了进入AI领域的门槛。
架构强调高可用性,多数据中心部署确保数据与任务备份,即使遭遇故障,也能无缝切换至备用系统,维持模型训练不中断,保护长期项目免受时间与资源损耗,确保进展与收益。
-
大模型应用开发,帮助开发者快速构建智能Agents
在企业中,项目级复杂任务通常需要理解任务并拆解成多个问题再进行决策,然后调用多个子系统去执行。MaaS基于多个优质昇腾云开源大模型,提供优质Prompt模板,让大模型准确理解业务意图,分解复杂任务,沉淀出丰富的多个智能Agent,帮助企业快速智能构建和部署大模型应用。
本案例中我们使用华为云开发者空间,基于HarmonyOS NEXT和Mass快速开发NutPITalk。
鸿蒙融合智能力,AI助力人生梦!
创新科技迎未来,Mass给接口!
我们今天来看一下Mass和鸿蒙的结合,会有什么样的火花。
免费领取云主机
如您还没有云主机,可点击链接,根据领取指南进行操作。
如您已领取云主机,可直接开始案例实践。
用到资源
资源列表 | 消耗/时 | 时长 |
---|---|---|
DevEco Studio | 免费 | 30min |
ModelArts Studio | 免费 | 30min |
合计:0元
实践
ModelArts Studio 模型服务
访问 ModelArts Studio 模型部署
进入云主机,打开浏览器,输入 https://console.huaweicloud.com/modelarts/?region=cn-east-4&locale=zh-cn#/model-studio/deployment
,即可访问ModelArts Studio。
领取免费 Token 额度
领取千万免费token额度,可用于体验Qwen、Chatglm等系列模型,免费额度仅适合用于体验模型。Qwen2.5系列预置服务还支持Function Calling,可以用于构建Agent。
获取大模型API和名称
以Qwen2.5-72B-32K
为例,点击更多-调用,获取API地址和模型名称。
创建API Key
在调用MaaS部署的模型服务时,需要填写API Key用于接口的鉴权认证。
- 登录ModelArts管理控制台。
- 在左侧导航栏中,选择“ModelArts Studio”进入ModelArts Studio大模型即服务平台。
- 在ModelArts Studio左侧导航栏中,选择“鉴权管理”。
- 在“鉴权管理”页面,单击“创建API Key”,填写描述信息后,单击“确认”会返回“您的密钥”,请复制保存密钥,单击“关闭”后将无法再次查看密钥。
左侧鉴权管理-创建API Key,保存创建的密钥信息
最多创建5个密钥,密钥只会在新建后显示一次,请妥善保存。
创建HarmonyOS NEXT项目
添加权限
"requestPermissions": [
{
"name": "ohos.permission.INTERNET"
}
],
网络请求
用流式和非流式两种,
非流式
- 从@kit.NetworkKit中导入http命名空间。
- 调用createHttp()方法,创建一个HttpRequest对象。
- 调用该对象的on()方法,订阅http响应头事件,此接口会比request请求先返回。可以根据业务需要订阅此消息。
- 调用该对象的request()方法,传入http请求的url地址和可选参数,发起网络请求。
- 按照实际业务需要,解析返回结果。
- 调用该对象的off()方法,取消订阅http响应头事件。
- 当该请求使用完毕时,调用destroy()方法主动销毁。
具体代码如下
getData() {
// 每一个httpRequest对应一个HTTP请求任务,不可复用
let httpRequest = http.createHttp();
// 用于订阅HTTP响应头,此接口会比request请求先返回。可以根据业务需要订阅此消息
// 从API 8开始,使用on('headersReceive', Callback)替代on('headerReceive', AsyncCallback)。 8+
httpRequest.on('headersReceive', (header) => {
console.info('header: ' + JSON.stringify(header));
});
httpRequest.request(
// 填写HTTP请求的URL地址,可以带参数也可以不带参数。URL地址需要开发者自定义。请求的参数可以在extraData中指定
"https://infer-modelarts.cn-east-4.myhuaweicloud.com/v1/infers/5f114f77-65c2-4e79-82df-d84b25b89d42/v1/chat/completions",
{
method: http.RequestMethod.POST, // 可选,默认为http.RequestMethod.GET
// 开发者根据自身业务需要添加header字段
header: {
'Content-Type': 'application/json',
"Authorization": "Bearer yourApiKey // 把yourApiKey替换成真实的API Key
},
// 当使用POST请求时此字段用于传递请求体内容,具体格式与服务端协商确定
extraData: {
"model": "Qwen2.5-72B-32K",
"max_tokens": 20,
"messages": [
{ "role": "system", "content": "You are a helpful assistant." },
{ "role": "user", "content": "鸿蒙坚果派,你了解多少" }
],
"stream": false,
"temperature": 1.0
},
expectDataType: http.HttpDataType.STRING, // 可选,指定返回数据的类型
usingCache: true, // 可选,默认为true
priority: 1, // 可选,默认为1
connectTimeout: 60000, // 可选,默认为60000ms
readTimeout: 60000, // 可选,默认为60000ms
usingProtocol: http.HttpProtocol.HTTP1_1, // 可选,协议类型默认值由系统自动指定
usingProxy: false, // 可选,默认不使用网络代理,自API 10开始支持该属性
}, (err: BusinessError, data: http.HttpResponse) => {
if (!err) {
// data.result为HTTP响应内容,可根据业务需要进行解析
console.info('Result:' + JSON.stringify(data.result));
console.info('code:' + JSON.stringify(data.responseCode));
// data.header为HTTP响应头,可根据业务需要进行解析
console.info('header:' + JSON.stringify(data.header));
console.info('cookies:' + JSON.stringify(data.cookies)); // 8+
// 当该请求使用完毕时,调用destroy方法主动销毁
httpRequest.destroy();
} else {
console.error('error:' + JSON.stringify(err));
// 取消订阅HTTP响应头事件
httpRequest.off('headersReceive');
// 当该请求使用完毕时,调用destroy方法主动销毁
httpRequest.destroy();
}
}
);
}
返回数据
{
"id": "chat-7bde4ec9cba949c1829e589f4fa1f8b1",
"object": "chat.completion",
"created": 1736925731,
"model": "Qwen2.5-72B-32K",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "你好!有什么可以帮到你的吗?",
"tool_calls": []
},
"logprobs": null,
"finish_reason": "stop",
"stop_reason": null
}
],
"usage": {
"prompt_tokens": 20,
"total_tokens": 30,
"completion_tokens": 10
},
"prompt_logprobs": null
}
参数说明
参数 | 参数类型 | 描述 |
---|---|---|
id | Str | 请求ID。 |
object | Str | 请求任务。 |
created | Int | 请求生成的时间戳。 |
model | Str | 调用的模型名。 |
choices | Array | 模型生成内容。 |
usage | Object | 请求输入长度、输出长度和总长度。 |
创建Model处理数据
这里使用我们坚果派开发的IDE插件就好,
搭建UI
这里面,我们可以做个对话框
流式数据
- 从@kit.NetworkKit中导入http命名空间。
- 调用createHttp()方法,创建一个HttpRequest对象。
- 调用该对象的on()方法,可以根据业务需要订阅HTTP响应头事件、HTTP流式响应数据接收事件、HTTP流式响应数据接收进度事件和HTTP流式响应数据接收完毕事件。
- 调用该对象的requestInStream()方法,传入http请求的url地址和可选参数,发起网络请求。
- 按照实际业务需要,可以解析返回的响应码。
- 调用该对象的off()方法,取消订阅响应事件。
- 当该请求使用完毕时,调用destroy()方法主动销毁。
具体代码如下:
// 引入包名
import { http } from '@kit.NetworkKit';
import { BusinessError } from '@kit.BasicServicesKit';
// 每一个httpRequest对应一个HTTP请求任务,不可复用
let httpRequest = http.createHttp();
// 用于订阅HTTP响应头事件
httpRequest.on('headersReceive', (header: Object) => {
console.info('header: ' + JSON.stringify(header));
});
// 用于订阅HTTP流式响应数据接收事件
let res = new ArrayBuffer(0);
httpRequest.on('dataReceive', (data: ArrayBuffer) => {
const newRes = new ArrayBuffer(res.byteLength + data.byteLength);
const resView = new Uint8Array(newRes);
resView.set(new Uint8Array(res));
resView.set(new Uint8Array(data), res.byteLength);
res = newRes;
console.info('res length: ' + res.byteLength);
});
// 用于订阅HTTP流式响应数据接收完毕事件
httpRequest.on('dataEnd', () => {
console.info('No more data in response, data receive end');
});
// 用于订阅HTTP流式响应数据接收进度事件
class Data {
receiveSize: number = 0;
totalSize: number = 0;
}
httpRequest.on('dataReceiveProgress', (data: Data) => {
console.log("dataReceiveProgress receiveSize:" + data.receiveSize + ", totalSize:" + data.totalSize);
});
let streamInfo: http.HttpRequestOptions = {
method: http.RequestMethod.POST, // 可选,默认为http.RequestMethod.GET
// 开发者根据自身业务需要添加header字段
header: {
'Content-Type': 'application/json'
},
// 当使用POST请求时此字段用于传递请求体内容,具体格式与服务端协商确定
extraData: "data to send",
expectDataType: http.HttpDataType.STRING,// 可选,指定返回数据的类型
usingCache: true, // 可选,默认为true
priority: 1, // 可选,默认为1
connectTimeout: 60000, // 可选,默认为60000ms
readTimeout: 60000, // 可选,默认为60000ms。若传输的数据较大,需要较长的时间,建议增大该参数以保证数据传输正常终止
usingProtocol: http.HttpProtocol.HTTP1_1 // 可选,协议类型默认值由系统自动指定
}
// 填写HTTP请求的URL地址,可以带参数也可以不带参数。URL地址需要开发者自定义。请求的参数可以在extraData中指定
httpRequest.requestInStream("EXAMPLE_URL", streamInfo).then((data: number) => {
console.info("requestInStream OK!");
console.info('ResponseCode :' + JSON.stringify(data));
// 取消订阅HTTP响应头事件
httpRequest.off('headersReceive');
// 取消订阅HTTP流式响应数据接收事件
httpRequest.off('dataReceive');
// 取消订阅HTTP流式响应数据接收进度事件
httpRequest.off('dataReceiveProgress');
// 取消订阅HTTP流式响应数据接收完毕事件
httpRequest.off('dataEnd');
// 当该请求使用完毕时,调用destroy方法主动销毁
httpRequest.destroy();
}).catch((err: Error) => {
console.info("requestInStream ERROR : err = " + JSON.stringify(err));
});
示例代码
# coding=utf-8
import requests
import json
if __name__ == '__main__':
url = "xxxxxxxxxx/v1/chat/completions"
# Send request.
headers = {
'Content-Type': 'application/json',
'Authorization': 'Bearer yourApiKey' # 把yourApiKey替换成已获取的API Key。例如,获取的API Key是“1234abcd...”时,此处填写“Bearer 1234abcd...”。
}
data = {
"model": "Qwen2-7B", # 调用时的模型名称。
"max_tokens": 20,
"messages": [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "hello"}
],
# 是否开启流式推理,默认为False,表示不开启流式推理。
"stream": False,
# 在流式输出时是否展示使用的token数目。只有当stream为True时该参数才会生效。
# "stream_options": {"include_usage": True},
# 控制采样随机性的浮点数,值较低时模型更具确定性,值较高时模型更具创造性。"0"表示贪婪取样。默认为1.0。
"temperature": 1.0
}
resp = requests.post(url, headers=headers, data=json.dumps(data), verify=False)
# Print result.
print(resp.status_code)
print(resp.text)
可以请求到数据,
FAQ
request和requestInStream使用区别在于:request接口有5M的数据,如果响应大于5M用requestinstream。
参考
https://support.huaweicloud.com/usermanual-maas-modelarts/maas-modelarts-0011.html
https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/http-request-V5
https://daqianduan.feishu.cn/docx/NSCsd3xNfoXEKvxTVqRcJTahnuh
三方库列表
https://plugins.jetbrains.com/plugin/25151-json2ets
致谢
感谢每一个关注此项目的开发者,也是希望大家对文章有任何建议,可以在https://www.nutpi.net/讨论。
- 15回答
- 17粉丝
- 11关注
- 【HarmonyOS Next开发】Navigation使用
- 【HarmonyOS Next开发】:ListItemGroup使用
- 【HarmonyOS Next开发】Tabs使用封装
- 【HarmonyOS Next开发】应用权限原理和封装
- HarmonyOS Next应用开发实战:ArkWeb使用介绍及使用举例
- 模拟器快速上手,助力HarmonyOS应用/服务高效开发
- Flutter 鸿蒙化 使用 Flutter Channel实现和Flutter和HarmonyOS交互
- HarmonyOS NEXT应用开发指南:开屏广告的使用
- HarmonyOS Next 并发 taskpool 和 worker
- 【HarmonyOS Next开发】使用两层Scroll实现一天时间轴和事件卡片的层叠显示
- HarmonyOS Next V2 @Local和@Param
- HarmonyOS Next V2 @Monitor和@Computed
- HarmonyOS Next应用开发实战:广告的使用介绍及避坑指南
- HarmonyOS NEXT应用开发实战(封装比UniApp和小程序更简单好用的网络库)
- 如何加载和使用自定义字体