HarmonyOS NEXT鸿蒙开发 ArkTS:openai 调用阿里云大模型 作者:马育民 • 2025-12-17 17:54 • 阅读:10010 # 介绍 OpenAI 请求工具库,基本保留原 npm 库 TypeScript 定义。 ### 官方API ``` https://ohpm.openharmony.cn/#/cn/detail/@iuroc%2Fopenai/v/1.0.0 ``` # 安装使用 ``` ohpm install @iuroc/openai ``` # 使用方法一 ``` import { OpenAI } from '@iuroc/openai' const openai = new OpenAI({ apiKey: 'sk-xxxx', baseURL: 'https://api.openai.com/v1' }) const result = openai.chat.completions.create({ model: 'gpt-4o-mini', messages: [ { role: 'user', content: 'hello' } ] }) const response = result.response const session = result.session ``` ### 等待请求完成 ##### Promise 方式 ``` const resp = await completion.response ``` ##### Callback 方式 ``` response.then( resp => { }) ``` ### resp结果 上面 `resp` 结果: ``` { "choices": [ { "message": { "role": "assistant", "content": "我是通义千问,阿里巴巴集团旗下的超大规模语言模型。我能够回答问题、创作文字,比如写故事、写公文、写邮件、写剧本等等,还能进行逻辑推理、编程等任务。如果你有任何问题或需要帮助,欢迎随时告诉我!" }, "finish_reason": "stop", "index": 0, "logprobs": null } ], "object": "chat.completion", "usage": { "prompt_tokens": 22, "completion_tokens": 57, "total_tokens": 79, "prompt_tokens_details": { "cached_tokens": 0 } }, "created": 1765956702, "system_fingerprint": null, "model": "qwen-plus", "id": "chatcmpl-fdb9e303-863a-4a20-a7b4-533dc71b4024" } ``` 取出正文内容: ``` const json = resp.toJSON() if(json!=null) { // console.log(TAG, "json---------",json['choices'][0].message.content) this.message = json['choices'][0].message.content // console.log(TAG,"message--",this.message) } ``` # 终止请求 ``` session.cancel() ``` # 使用方法二-流式输出 **提示:**官网的流式输出有bug ``` const onDataCallback: OnDataCallback = (chunks:ChatCompletionChunk[]) => { // const newContent = chunks.map(chunk => chunk.choices[0].delta.content).join('') // console.log(TAG,newContent) // this.answer += newContent for(let chunk of chunks){ // 过滤空内容(避免无效数据) if (!chunk.choices || chunk.choices.length === 0) continue; const choice = chunk.choices[0]; const content = choice.delta?.content || ''; // 增量内容 // 1. 核心判断:finish_reason 存在 → 输出结束 if (choice.finish_reason) { // isFinished = true; console.log(TAG,`流式输出结束,结束原因:${choice.finish_reason}`); this.resetSendBtn() break; // 终止遍历 } // 拼接并打印增量内容 if (content) { this.answer += content } } } const onErrorCallback = (error: Error) => { console.error(TAG,JSON.stringify(error)) } const options : ChatCompletionsCreateOptions = { onData:onDataCallback, onError:onErrorCallback, } const result = openai.chat.completions.create({ model: 'gpt-4o-mini', messages: [ { role: 'user', content: 'hello' } ], stream: true }, options) ``` # 案例 ### 安装 markdown 本例子使用第三方 **markdown** 组件,可以正常显示大模型返回的 markdown内容 安装: ``` ohpm install @luvi/lv-markdown-in ``` ### 阿里百炼 api网址如下: https://bailian.console.aliyun.com/?tab=api#/api/?type=model&url=2712576 需要注册、申请api key ### 代码 **提示:**将阿里百炼API Key填到下面 `apiKey` 中 ``` import { OpenAI } from '@iuroc/openai' import { Markdown } from '@luvi/lv-markdown-in' import { rcp } from '@kit.RemoteCommunicationKit'; import { OnDataCallback,ChatCompletionsCreateOptions } from '@iuroc/openai/src/main/ets/ChatCompletions'; import { ChatCompletionChunk } from '@iuroc/openai/src/main/ets/openai@4.73.1/resources'; const openai = new OpenAI( { // 若没有配置环境变量,请用百炼API Key将下行替换为:apiKey: "sk-xxx", apiKey: "", baseURL: "https://dashscope.aliyuncs.com/compatible-mode/v1" } ); const TAG = "HealthPage-------" /** * 发送按钮-未发送 */ const SENDBTN_NOT_SEND = 0 /** * 发送按钮-正在发送 */ const SENDBTN_SEND = 1 const SENDBTN_TEXT_SEND = "发送" const SENDBTN_TEXT_STOP = "停止" @Entry @Component struct HealthPage { @State answer: string = '' @State question: string = '冬季如何补气血' // 发送按钮是否可用 @State btnEnabled:boolean = true // 发送按钮显示内容 @State btnText:string = SENDBTN_TEXT_SEND @State sendBtnStatus:number = SENDBTN_NOT_SEND session!:rcp.Session|null build() { Column(){ Text("我是您的健康小助手,有什么问题:") .width("100%") .margin({ top:20 }) TextArea({ text:$$this.question, placeholder:"您有什么问题尽管问我哈" }) .height(100) .margin({ top:5 }) Row() { Blank() Button(this.btnText) .onClick(async () => { this.send() }) .enabled(this.btnEnabled) } .width("100%") .margin({ top:10 }) Scroll() { Markdown({ text: this.answer }) } .margin({ top: 10 }) } .height("70%") .padding({ left:10, right:10, }) } async send(){ if(this.sendBtnStatus == SENDBTN_NOT_SEND) { this.answer = "" console.log(TAG,"send 开始----------") // this.btnEnabled = false this.btnText = SENDBTN_TEXT_STOP this.sendBtnStatus = SENDBTN_SEND // 普通输出 // const completion = openai.chat.completions.create({ // model: "qwen-plus", //此处以qwen-plus为例,可按需更换模型名称。模型列表:https://help.aliyun.com/zh/model-studio/getting-started/models // messages: [ // { role: "system", content: "你是养生专家" }, // { role: "user", content: this.question } // ], // }); // const resp = await completion.response // this.session = completion.session // console.log(TAG, "send 结束----------") // // console.log(TAG,JSON.stringify(resp)) // const json = resp.toJSON() // // if (json != null ) { // // console.log(TAG, "json---------",json['choices'][0].message.content) // this.answer = json['choices'][0].message.content // // console.log(TAG,"message--",this.message) // } // 下面是流式输出--------------------- const onDataCallback: OnDataCallback = (chunks:ChatCompletionChunk[]) => { // const newContent = chunks.map(chunk => chunk.choices[0].delta.content).join('') // console.log(TAG,newContent) // this.answer += newContent for(let chunk of chunks){ // 过滤空内容(避免无效数据) if (!chunk.choices || chunk.choices.length === 0) continue; const choice = chunk.choices[0]; const content = choice.delta?.content || ''; // 增量内容 // 1. 核心判断:finish_reason 存在 → 输出结束 if (choice.finish_reason) { // isFinished = true; console.log(TAG,`流式输出结束,结束原因:${choice.finish_reason}`); this.resetSendBtn() break; // 终止遍历 } // 拼接并打印增量内容 if (content) { this.answer += content } } } const onErrorCallback = (error: Error) => { console.error(TAG,JSON.stringify(error)) } const options : ChatCompletionsCreateOptions = { onData:onDataCallback, onError:onErrorCallback, } const completion = openai.chat.completions.create({ model: "qwen-plus", //此处以qwen-plus为例,可按需更换模型名称。模型列表:https://help.aliyun.com/zh/model-studio/getting-started/models messages: [ { role: "system", content: "你是养生专家" }, { role: "user", content: this.question } ], stream: true },options); this.session = completion.session }else { console.log(TAG,"send 手动停止----------") if(this.session) { this.session.cancel() } this.resetSendBtn() } } /** * 重置发送按钮 */ resetSendBtn(){ this.btnText = SENDBTN_TEXT_SEND this.sendBtnStatus = SENDBTN_NOT_SEND this.session = null } } export default HealthPage ``` 原文出处:http://malaoshi.top/show_1GW2QL9E6nnf.html