使用 HarmonyOS NEXT和Mass快速开发NutPITalk

2025-01-16 18:26:28
10次阅读
0个评论

使用 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。

image-20250115155342626

获取大模型API和名称

Qwen2.5-72B-32K为例,点击更多-调用,获取API地址和模型名称。

image-20250115155437177

创建API Key

在调用MaaS部署的模型服务时,需要填写API Key用于接口的鉴权认证。

  1. 登录ModelArts管理控制台。
  2. 在左侧导航栏中,选择“ModelArts Studio”进入ModelArts Studio大模型即服务平台。
  3. 在ModelArts Studio左侧导航栏中,选择“鉴权管理”。
  4. 在“鉴权管理”页面,单击“创建API Key”,填写描述信息后,单击“确认”会返回“您的密钥”,请复制保存密钥,单击“关闭”后将无法再次查看密钥。

左侧鉴权管理-创建API Key,保存创建的密钥信息

最多创建5个密钥,密钥只会在新建后显示一次,请妥善保存。

image-20250115155526316

创建HarmonyOS NEXT项目

image-20250115150643307

添加权限

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

网络请求

用流式和非流式两种,

非流式

  1. 从@kit.NetworkKit中导入http命名空间。
  2. 调用createHttp()方法,创建一个HttpRequest对象。
  3. 调用该对象的on()方法,订阅http响应头事件,此接口会比request请求先返回。可以根据业务需要订阅此消息。
  4. 调用该对象的request()方法,传入http请求的url地址和可选参数,发起网络请求。
  5. 按照实际业务需要,解析返回结果。
  6. 调用该对象的off()方法,取消订阅http响应头事件。
  7. 当该请求使用完毕时,调用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插件就好,

image-20250115233552534

搭建UI

这里面,我们可以做个对话框

image-20250116182410153

流式数据

  1. 从@kit.NetworkKit中导入http命名空间。
  2. 调用createHttp()方法,创建一个HttpRequest对象。
  3. 调用该对象的on()方法,可以根据业务需要订阅HTTP响应头事件、HTTP流式响应数据接收事件、HTTP流式响应数据接收进度事件和HTTP流式响应数据接收完毕事件。
  4. 调用该对象的requestInStream()方法,传入http请求的url地址和可选参数,发起网络请求。
  5. 按照实际业务需要,可以解析返回的响应码。
  6. 调用该对象的off()方法,取消订阅响应事件。
  7. 当该请求使用完毕时,调用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)

可以请求到数据,

image-20250115152915593

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/讨论。

收藏00

登录 后评论。没有帐号? 注册 一个。