僅需半小時,即可實現(xiàn)純血鴻蒙版本的ChatGPT!
廢話少說,先看效果圖:

如上圖所示,這個小Demo實現(xiàn)了AI智能問答。靠右加粗的文本是用戶點擊底部提交按鈕后出現(xiàn)的;后面靠左對齊的普通文本是來自AI的回答內(nèi)容。當(dāng)然,整個內(nèi)容是可滑動瀏覽的,當(dāng)內(nèi)容被滑動時,屏幕右側(cè)將出現(xiàn)滾動條。最后,為什么UI是英文呢?因為鴻蒙的模擬器目前沒有內(nèi)置中文輸入法,恰好這個AI服務(wù)也可以用英文來回答。
值得注意的是:這個小Demo之所以我稱其為Demo,是因為它的功能實在是太簡單了。只有一個基礎(chǔ)的AI對話功能,如果要做成一個產(chǎn)品,我覺得起碼得有個數(shù)據(jù)持久化的過程,而且還能支持文本的編輯、復(fù)制、刪除,還要提供收藏功能。更重要的,UI也需要好好美化一下……
所以,這篇文章就權(quán)當(dāng)拋磚引玉,讓大家體會一下開發(fā)原生純血鴻蒙版本的App是有多么輕松。
前置條件
- DevEco 3.1.1 Release;
- 在百度智能云控制臺上創(chuàng)建好應(yīng)用,保存好API Key和Secret Key。
- 關(guān)于1:下載和安裝文檔鏈接;
- 關(guān)于2:百度智能云控制臺地址鏈接。
創(chuàng)建項目(5分鐘)
使用DevEco創(chuàng)建項目僅需兩步,第一步選擇類型,第二步填寫項目信息。
對于第一步,我們選擇Application(應(yīng)用程序)->Empty Ability(空白Ability);
對于第二步,我們選擇迄今為止最新的Compile SDK,即3.1.0(API 9),Model選擇Stage,不開啟“Enable Super Visual”。其余的內(nèi)容大家根據(jù)自身環(huán)境配置進(jìn)行填寫就好。
編碼實現(xiàn)(20分鐘)
整個編碼過程分為三個步驟,首先添加權(quán)限,然后實現(xiàn)UI,最后實現(xiàn)網(wǎng)絡(luò)操作。
添加權(quán)限(2分鐘)
在整個App的項目結(jié)構(gòu)中,找到默認(rèn)創(chuàng)建的entry模塊,依次定位到src->main->module.json5,權(quán)限在該文件中進(jìn)行配置。
這個Demo功能非常簡單,但仍需對其添加必要的網(wǎng)絡(luò)訪問權(quán)限,以確??梢源蜷_網(wǎng)絡(luò)套接字,完成HTTP請求和響應(yīng)。
代碼片段如下:
"requestPermissions": [
{
"name": "ohos.permission.INTERNET",
}
],
UI實現(xiàn)(10分鐘)
回過頭來看本文最上方的截圖,經(jīng)過布局分析后,可以得到如下結(jié)論:整個界面是縱向布局,由兩個部分構(gòu)成。一是可滾動的對話歷史;二是下方的輸入框和提交按鈕。
因此,整個UI布局最外層應(yīng)該是一個Column,表示縱向布局。其中,占據(jù)90%高度的對話歷史區(qū)域,占據(jù)10%高度的輸入框和按鈕區(qū)域。
先來看對話歷史區(qū)域,它其實本質(zhì)上也是一個Column,每個item就是一段文字。根據(jù)文字的類型來判斷是居左還是居右。在這個Column之外,為了讓整個對話歷史區(qū)域可以上下滾動查看,因此還需要Scroll組件將整個Column組件包裹起來。
代碼片段如下:
@State messagesList: Object[] = [{ 'role': 'user', 'content': 'What can I help you with?' }]
// 歷史問答
Scroll() {
Column() {
ForEach(this.messagesList, (item: Object) => {
if (item['role'] == 'user') {
Text(item['content']).fontSize(20).fontWeight(FontWeight.Bold).width('100%').textAlign(TextAlign.End)
} else {
Text(item['content']).fontSize(20).width('100%').textAlign(TextAlign.Start)
}
})
}.width('100%').alignItems(HorizontalAlign.Center)
}
.scrollable(ScrollDirection.Vertical)
.scrollBar(BarState.Auto)
.scrollBarColor(Color.Gray)
.scrollBarWidth(10)
.edgeEffect(EdgeEffect.Fade)
.height('90%')
.width('100%')
請注意這段代碼中的messagesList,它是一個對象數(shù)組。role表示角色,即該條消息是用戶發(fā)送的,還是服務(wù)器返回的;content表示文字內(nèi)容。
在由Scroll包裹的Column組件之中,使用了ArkTS提供的ForEach渲染方式進(jìn)行逐條消息的渲染,并使用if…else…條件判斷語句對角色來源進(jìn)行區(qū)分。
再來看底部的輸入框和操作按鈕,由于它們是橫向排列的,所以使用Row組件進(jìn)行布局。在此,我將文本輸入框設(shè)定了80%的寬度,提交按鈕設(shè)定了20%的寬度。
代碼片段如下:
@State questionStr: string = ''
// 文本輸入和提交
Row() {
TextInput({ placeholder: 'Please input your question', text: this.questionStr })
.type(InputType.Normal)
.onChange((value: string) => {
this.questionStr = value
})
.width('80%')
Button('提交').type(ButtonType.Capsule).onClick(() => {
this.messagesList.push({ 'role': 'user', 'content': this.questionStr })
getAnswer(this.questionStr, this.messagesList)
this.questionStr = ''
}).width('20%')
}.height('10%').width('100%')
在這段代碼中,questionStr表示輸入框中的文字字符串。getAnswer()函數(shù)發(fā)起并接收HTTP請求,向服務(wù)器提交用戶問題字符串,并等待接收響應(yīng)內(nèi)容,將問題的回答放入messagesList對象數(shù)組之中,完成整個問答流程。
最后,將上述Scroll組件和Row組件一并放入Column內(nèi),完成整個UI繪制。
網(wǎng)絡(luò)訪問(8分鐘)
根據(jù)百度官方的開發(fā)文檔,完成整個AI問答過程至少需要兩個步驟:獲取access_token和獲取問題答案。
獲取access_token的過程在程序一開始就可以進(jìn)行了,因為在后續(xù)的操作中都要用到access_token。因此,我聲明了access_token的全局變量,并將獲取該值的方法封裝為getToken()函數(shù),具體代碼如下:
var access_token: string = ''
function getToken() {
let httpRequest = http.createHttp();
httpRequest.on('headersReceive', (header) => {
console.info('header: ' + JSON.stringify(header));
});
httpRequest.request(
"https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=[你的應(yīng)用的API Key]&client_secret=[你的應(yīng)用的Secret Key]",
{
method: http.RequestMethod.POST,
header: {
'Content-Type': 'application/json',
},
expectDataType: http.HttpDataType.OBJECT,
usingCache: true,
priority: 1,
connectTimeout: 60000,
readTimeout: 60000,
usingProtocol: http.HttpProtocol.HTTP1_1,
}, (err, data) => {
if (!err) {
access_token = data.result['access_token']
} else {
httpRequest.off('headersReceive')
httpRequest.destroy()
}
});
}
getToken()函數(shù)我在回調(diào)的onPageShow()函數(shù)中使用,即程序啟動后,就獲取access_token。
最后,我們來實現(xiàn)getAnswer()函數(shù),它是向服務(wù)器提交問題和接收響應(yīng)的函數(shù),具體代碼如下:
function getAnswer(questionStr: string, messageList: Object[]) {
let httpRequest = http.createHttp();
httpRequest.on('headersReceive', (header) => {
console.info('header: ' + JSON.stringify(header));
});
httpRequest.request(
"https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/yi_34b_chat?access_token=" + access_token,
{
method: http.RequestMethod.POST,
header: {
'Content-Type': 'application/json'
},
extraData: { "messages": [{
"role": "user",
"content": questionStr
}] },
expectDataType: http.HttpDataType.OBJECT,
usingCache: true,
priority: 1,
connectTimeout: 60000,
readTimeout: 60000,
usingProtocol: http.HttpProtocol.HTTP1_1,
}, (err, data) => {
if (!err) {
messageList.push({ 'role': 'assist', 'content': data.result['result'] })
} else {
httpRequest.off('headersReceive')
httpRequest.destroy()
}
}
);
}
還需要做些別的嗎?
答案是:沒有了,真的不用了。
運行項目(5分鐘)
無論是本地模擬器,還是真機,抑或是遠(yuǎn)程模擬器,只需要啟動其中一個,然后讓這個程序跑起來吧!如無意外,你將會得到一個超級簡易的AI問答機器人,純血鴻蒙版。
當(dāng)然,這里我寫了需要5分鐘,是包括了下載模擬器鏡像的時間,如果你有真機或是使用遠(yuǎn)程模擬器的話,那就會更快了。文章來源:http://www.zghlxwxcb.cn/news/detail-813794.html
最后,我們來對比一下。我完成上述功能,Index.ets一共117行,你的呢?文章來源地址http://www.zghlxwxcb.cn/news/detail-813794.html
到了這里,關(guān)于半小時實現(xiàn)GPT純血鴻蒙版的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!