亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

在小程序中實(shí)現(xiàn)ChatGPT?聊天打字兼自動(dòng)滾動(dòng)效果

 更新時(shí)間:2023年06月19日 11:43:11   作者:我不是外星人  
ChatGPT已經(jīng)長(zhǎng)時(shí)間大火,未來(lái)將會(huì)是AI的天下,們需要更多地學(xué)習(xí)和掌握AI,而不是被AI所取代,在?ChatGPT?的背景下,我們今天來(lái)聊聊在小程序中怎么實(shí)現(xiàn)類似?chatGPT?的聊天打字效果,并且實(shí)現(xiàn)滾動(dòng)效果

一 前言

ChatGPT 已經(jīng)長(zhǎng)時(shí)間大火,未來(lái)將會(huì)是AI的天下。人們需要更多地學(xué)習(xí)和掌握AI,而不是被AI所取代。

目前市面上已經(jīng)有很多類似 chatGPT 的智能應(yīng)用,應(yīng)用有可能是 web h5 應(yīng)用,也有可能是小程序或者是 Native 應(yīng)用。隨著 ChatGPT 深入,移動(dòng)端也會(huì)再次火爆起來(lái)。

在 ChatGPT 的背景下,我們今天來(lái)聊聊在小程序中怎么實(shí)現(xiàn)類似 chatGPT 的聊天打字效果,并且實(shí)現(xiàn)滾動(dòng)效果,具體如下:

這篇文章將深入一下內(nèi)容:

  • 小程序怎么樣實(shí)現(xiàn)動(dòng)態(tài)打字效果。
  • 怎么實(shí)現(xiàn)隨打字效果滾動(dòng)。
  • 請(qǐng)求分片知識(shí)點(diǎn)。
  • scroll-view 細(xì)節(jié)處理等。

二 實(shí)現(xiàn)打字效果

2.1.預(yù)熱內(nèi)容—數(shù)據(jù)請(qǐng)求與接收

開(kāi)發(fā)者可以接入 openAi 提供的接口,實(shí)現(xiàn)自定義的問(wèn)答流程。在聊天會(huì)話中,我們問(wèn) chatGPT 一句話:

介紹一下跨端開(kāi)發(fā)

那么和平常的請(qǐng)求不同的是,數(shù)據(jù)并不是一次性返回的,而是采用 stream 流式返回的。我們可以在 Network 中看到 response 的大體結(jié)構(gòu):

如上可以看到返回的 text 是分片處理的,每次會(huì)返回一小段內(nèi)容,只要前端根據(jù)返回這一小段內(nèi)容就可以了,也就自然形成了打字的效果。

可能會(huì)有同學(xué)好奇,這種分片的數(shù)據(jù)結(jié)構(gòu),前端應(yīng)該怎么接收呢?實(shí)際很簡(jiǎn)單,我們拿 axios 為例子,開(kāi)發(fā)者可以通過(guò)監(jiān)聽(tīng)onDownloadProgress 事件來(lái)接受服務(wù)端返回的文本片段。具體例子如下:

axios({
  method: 'post',
  url: 'https:xxx.xxx,
  onDownloadProgress: function({ event  }) {
    const xhr = event.target
    const { responseText } = xhr
    /* 獲取返回的內(nèi)容,本質(zhì)上是 json 字符串 */
    let chunk = responseText
    try{
        /* 序列化返回的內(nèi)容 */
       const data = JSON.parse(chunk)
       /* chatGPT 返回的內(nèi)容 */
       console.log(data.text)
    }catch(e){
    }
  }
})

這里描述請(qǐng)求的流程,通過(guò) onDownloadProgress 來(lái)監(jiān)聽(tīng)返回的內(nèi)容,然后獲取到返回的內(nèi)容,JSON.parse 解析內(nèi)容,這里有一個(gè)注意事項(xiàng),就是對(duì)于 JSON.parse 應(yīng)該加上 try catch ,防止解析的失敗。

2.2.小程序中接口處理

小程序沒(méi)有如上 axios 里面監(jiān)聽(tīng) stream 流式響應(yīng)數(shù)據(jù)的能力,也沒(méi)有處理 onDownloadProgress 的回調(diào)函數(shù)。簡(jiǎn)單來(lái)說(shuō) onDownloadProgress 的實(shí)現(xiàn),本質(zhì)上是 axios 在瀏覽器發(fā)起 http 請(qǐng)求,會(huì)創(chuàng)建一個(gè) XHR 對(duì)象,其用于發(fā)送請(qǐng)求和接收響應(yīng),在創(chuàng)建 XHR 對(duì)象后,axios 會(huì)注冊(cè)一個(gè) progress 事件監(jiān)聽(tīng)器到 XHR 對(duì)象上,用于獲取下載的進(jìn)度信息。

那么小程序中如何實(shí)現(xiàn)分片流式下載呢?在小程序中,統(tǒng)一收口到 request 中,在 request 中可以用 RequestTask 的 onChunkReceived 來(lái)接收服務(wù)端的分片數(shù)據(jù)。這個(gè)方法可以監(jiān)聽(tīng) Transfer-Encoding Chunk Received 事件。當(dāng)接收到新的 chunk 時(shí)觸發(fā)。

我們來(lái)看看具體怎么使用:

const requestTask = wx.request({ 
    enableChunked:true,  // 開(kāi)啟分片模式
    ...
})
requestTask.onChunkReceived((res)=>{
    // 接收分片的數(shù)據(jù)
})

這樣就可以通過(guò)分片來(lái)實(shí)現(xiàn)打字的效果。

2.3.打字效果實(shí)現(xiàn)

接下來(lái)我們看一下小程序是如何實(shí)現(xiàn)打字效果的,先不考慮返回的數(shù)據(jù)是 stream 流式結(jié)構(gòu),先認(rèn)為返回的數(shù)據(jù)格式是整個(gè)文本,那么應(yīng)該怎么樣處理文本呢。

首先我們聊天的內(nèi)容如下所示:

如上, 每一個(gè)消息都是一個(gè) message-item ,所有的 message 保存到了 messageList 列表中,在 wxml 中如下所示:

<view wx:for="{{messageList}}" wx:key="id" id="item-{{item.id}}">
    <message-item 
        data-index="{{index}}" 
        role="{{item.role}}" 
        content="{{item.content}}"
        finished="{{item.finished}}" 
        bind:share="handleMessageShare" 
    />
</view>

如上,可以看到 message-item 保存了一條會(huì)話內(nèi)容。

當(dāng)我們發(fā)一條信息的時(shí)候,產(chǎn)生一條 message-item 。接下來(lái) chatGPT 返回內(nèi)容后,也會(huì)產(chǎn)生一條 message-item ,要實(shí)現(xiàn)打字效果就是這條 message-item 。

我們只需要將這條 message-item 的內(nèi)容,通過(guò) setData 方式分片渲染就可以了。比如我們想打字實(shí)現(xiàn) ‘您好GPT’,那么分五次 setData 渲染就可以了,比如如下:

  • 您好
  • 您好G
  • 您好GP
  • 您好GPT

如上就是分五次渲染,每一次渲染的結(jié)果。接下來(lái)就是代碼的實(shí)現(xiàn)。

this.handleRequestResolve(data.text)

比如 chatGPT 每次返回一條內(nèi)容,都用 handleRequestResolve 函數(shù)處理返回的內(nèi)容??匆幌?handleRequestResolve 的核心實(shí)現(xiàn)。

handleRequestResolve(result){
    const timestamp = Date.now();
    const index = this.data.messageList.length
    const newMessageList = `messageList[${index}]`
    const contentCharArr = result.trim().split("")
    const content_key = `messageList[${index}].content`
    const finished_key = `messageList[${index}].finished`
    this.setData({
        thinking: false,
        [newMessageList]: {
            id: timestamp,
            role: 'assistant',
            finished: false
        }
    })
    currentContent = ''
    this.showText(0, content_key, finished_key, contentCharArr);
}

在 handleRequestResolve 中會(huì)構(gòu)建一條新的 message-item ,然后就是 showText 展示內(nèi)容,來(lái)看一下 showText 怎么處理內(nèi)容。

 showText(key = 0, content_key, finished_key, value) {
     /* 所有內(nèi)容展示完成 */
    if (key >= value.length) {
        this.setData({
            loading: false,
            [finished_key]: true
        })
        wx.vibrateShort()
        return;
    }
    currentContent = currentContent + value[key]
    /* 渲染回話內(nèi)容 */
    this.setData({
        [content_key]: currentContent,
    })
    setTimeout(() => {
        /* 遞歸渲染內(nèi)容 */
        this.showText(key + 1, content_key, finished_key, value);
    }, 50);
},

這樣用遞歸就實(shí)現(xiàn)了打字效果。我們來(lái)看一下效果:

通過(guò)上面可以看到,在文字打印的過(guò)程中,列表不能跟隨一起滾動(dòng),當(dāng)文字內(nèi)容超出一屏幕之后,視圖就停止了(本質(zhì)上數(shù)據(jù)在后面追加),這是一個(gè)很不好的效果。

接下來(lái),我們進(jìn)行優(yōu)化處理,讓視圖可以根據(jù)內(nèi)容自動(dòng)滾動(dòng)。

三 如何實(shí)現(xiàn)視圖跟隨內(nèi)容滾動(dòng)

3.1 實(shí)現(xiàn)原理

實(shí)現(xiàn)視圖跟隨內(nèi)容滾動(dòng)實(shí)際很簡(jiǎn)單,因?yàn)?message-item 的容器本質(zhì)上就是一個(gè) scroll-view , 那么想要 scroll-view 視圖跟隨返回內(nèi)容變化,只需要?jiǎng)討B(tài)設(shè)置 scroll-view 的 scroll-top 值就可以了。

視圖跟隨內(nèi)容滾動(dòng),本質(zhì)上就是讓 scroll-view 一直自動(dòng)滾動(dòng)到底部, 如何要讓 scroll-view 一直滾動(dòng)到底部呢?先看一下如下示意圖:

如上可以看到,想讓 scroll-view 一直滾動(dòng)到底部,只需要讓 scroll-top 等于 scroll-view 內(nèi)容高度減去 scroll-view 容器本身高度就可以了。

所以需要我們給 scroll-view 里面的內(nèi)容,用一個(gè) view 包裹如下:

如上 scroll-view 的類名為 content, scroll-view 內(nèi)部元素的類名為 scroll-view-content,接下來(lái)可以通過(guò)如下代碼設(shè)置 scroll-top 值了。

   handleScollTop() {
        return new Promise((resolve) => {
            const query = wx.createSelectorQuery()
            query.select('.content').boundingClientRect()
            query.select('.scroll-view-content').boundingClientRect()
            query.exec((res) => {
                const scrollViewHeight = res[0].height
                const scrollContentHeight = res[1].height
                if (scrollContentHeight > scrollViewHeight) {
                    const scrollTop = scrollContentHeight - scrollViewHeight
                    this.setData({
                        scrollTop
                    }, () => {
                        resolve()
                    })
                }else{
                    resolve()
                }
            })
        })
    },

如上通過(guò) createSelectorQuery 分別獲取 scroll-view 和 scroll-view 內(nèi)部元素的高度,兩者的差值就是 scroll-top 值。

接下里在渲染會(huì)話內(nèi)容的時(shí)候,渲染之后,調(diào)用 handleScollTop 來(lái)動(dòng)態(tài)設(shè)置 scroll-top 就可以了。

showText(key = 0, content_key, finished_key, value) {
    if (key >= value.length) {
        this.setData({
            loading: false,
            [finished_key]: true
        })
        wx.vibrateShort()
        return;
    }
    currentContent = currentContent + value[key]
    this.setData({
        [content_key]: currentContent,
    },()=>{
        this.handleScollTop().then(()=>{
            setTimeout(() => {
                this.showText(key + 1, content_key, finished_key, value);
            }, 20);
        })
    })
},

這里有一個(gè)小細(xì)節(jié),就是在渲染上一次文本內(nèi)容之后,需要先校驗(yàn)一下 scroll-top 值,然后再次調(diào)用 showText 來(lái)渲染會(huì)話內(nèi)容。

我們來(lái)看一下效果。

后續(xù)優(yōu)化: 本質(zhì)上不需要在每次 showText 之后都通過(guò) createSelectorQuery 異步獲取元素 scroll-top 并再次渲染,這無(wú)疑是性能的浪費(fèi),實(shí)際可以控制 createSelectorQuery 到 setData 設(shè)置 scroll-top 值的頻率來(lái)提升性能。

四 總結(jié)

感興趣的同學(xué)可以自己實(shí)現(xiàn)一個(gè)會(huì)話打字效果,其中還有很多小細(xì)節(jié)這里就不講了。

以上就是小程序?qū)崿F(xiàn)ChatGPT 聊天打字兼自動(dòng)滾動(dòng)效果的詳細(xì)內(nèi)容,更多關(guān)于ChatGPT聊天自動(dòng)滾動(dòng)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • thymeleaf實(shí)現(xiàn)th:each雙重多重嵌套功能

    thymeleaf實(shí)現(xiàn)th:each雙重多重嵌套功能

    今天給大家分享一個(gè)使用 thymeleaf 實(shí)現(xiàn)一個(gè)動(dòng)態(tài)加載一二級(jí)文章分類的功能,本文通過(guò)代碼講解的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2019-11-11
  • Scala項(xiàng)目構(gòu)建工具sbt和IntelliJ IDEA環(huán)境配置詳解

    Scala項(xiàng)目構(gòu)建工具sbt和IntelliJ IDEA環(huán)境配置詳解

    這篇文章主要介紹了Scala項(xiàng)目構(gòu)建工具sbt和IntelliJ IDEA環(huán)境配置,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-10-10
  • 一文詳解kafka開(kāi)啟kerberos認(rèn)證的完整步驟

    一文詳解kafka開(kāi)啟kerberos認(rèn)證的完整步驟

    這篇文章主要為大家詳細(xì)介紹了kafka開(kāi)啟kerberos認(rèn)證的完整步驟,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2025-03-03
  • 編程知識(shí)點(diǎn)(1)關(guān)鍵詞之存儲(chǔ)類型

    編程知識(shí)點(diǎn)(1)關(guān)鍵詞之存儲(chǔ)類型

    這篇文章主要介紹了編程知識(shí)點(diǎn)(1)關(guān)鍵詞之存儲(chǔ)類型的相關(guān)知識(shí),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2020-07-07
  • win10環(huán)境安裝kettle與linux環(huán)境安裝kettle的詳細(xì)過(guò)程

    win10環(huán)境安裝kettle與linux環(huán)境安裝kettle的詳細(xì)過(guò)程

    kettle是一款免費(fèi)開(kāi)源的、可視化的、國(guó)際上比較流行的、功能強(qiáng)大的ETL必備工具,在ETL這一方面做的還不錯(cuò),下面介紹一下基于win10操作系統(tǒng)安裝kettle和linux操作系統(tǒng)安裝kettle的詳細(xì)過(guò)程,感興趣的朋友跟隨小編一起看看吧
    2022-11-11
  • UltraEdit編輯器免費(fèi)激活方法

    UltraEdit編輯器免費(fèi)激活方法

    UltraEdit?是一套功能強(qiáng)大的文本編輯器,可以編輯文本、十六進(jìn)制、ASCII?碼,完全可以取代記事本,下面小編把這款UltraEdit編輯器免費(fèi)激活方法分享給大家,需要的朋友參考下
    2021-08-08
  • 詳解HBase表的數(shù)據(jù)模型

    詳解HBase表的數(shù)據(jù)模型

    HBase 是一種列存儲(chǔ)模式與鍵值對(duì)存儲(chǔ)模式結(jié)合的 NoSQL 數(shù)據(jù)庫(kù),它具有靈活的數(shù)據(jù)模型,不僅可以基于鍵進(jìn)行快速查詢,還可以實(shí)現(xiàn)基于值、列名等的全文遍歷和檢索,下面給大家介紹HBase表的數(shù)據(jù)模型,感興趣的朋友一起看看吧
    2022-05-05
  • 百萬(wàn)行WPF項(xiàng)目代碼重構(gòu)記錄分析

    百萬(wàn)行WPF項(xiàng)目代碼重構(gòu)記錄分析

    這篇文章主要為大家介紹了一次百萬(wàn)行WPF項(xiàng)目代碼的重構(gòu)記錄,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-05-05
  • 10分鐘搞定讓你困惑的 Jenkins 環(huán)境變量過(guò)程詳解

    10分鐘搞定讓你困惑的 Jenkins 環(huán)境變量過(guò)程詳解

    這篇文章主要介紹了10分鐘搞定讓你困惑的 Jenkins 環(huán)境變量過(guò)程詳解,本文通過(guò)圖文實(shí)例相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-01-01
  • antd通過(guò) filterDropdown 自定義按某天時(shí)間搜索功能

    antd通過(guò) filterDropdown 自定義按某天時(shí)間搜索功能

    這篇文章主要介紹了antd通過(guò) filterDropdown 自定義按某天時(shí)間搜索功能,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2019-08-08

最新評(píng)論