前言
ChatGPT 最近一直都處于技術(shù)圈的討論焦點。它除了可作為普通用戶的日常 AI 助手,還可以幫助開發(fā)者加速開發(fā)進度。聲網(wǎng)社區(qū)的一位開發(fā)者 "小猿" 就基于 ChatGPT 做了一場實驗。僅 40 分鐘就實現(xiàn)了一個互動直播 Demo。他是怎么做的呢?他將整個過程記錄了下來。 (文章轉(zhuǎn)載自開發(fā)者的個人博客,以下為正文) “遇事不決,AI 力學(xué)” ~ ChatGPT 可以說是 2023 開年最熱門的話題, 它不僅在極短時間內(nèi)風(fēng)靡了整個技術(shù)圈,更是病毒式地席卷了圈外的各個行業(yè),并對各大企業(yè)都起到了實質(zhì)性影響:
谷歌緊急推出 “Bard” 對抗 ChatGPT
微軟發(fā)布新 Bing 集成 ChatGPT
復(fù)旦發(fā)布首個類 ChatGPT 模型 MOSS
國內(nèi)阿里、百度、昆侖萬維、網(wǎng)易、京東都開始新一輪 AI 軍備
那 ChatGPT 究竟有什么魔力能讓 “群雄折腰”?這和 ChatGPT 的實現(xiàn)有很大關(guān)系:
與以往的統(tǒng)計模型不行,ChatGPT 不是那種「一切都從語料統(tǒng)計里學(xué)習(xí)」的 AI,相反 ChatGPT 具備有臨場學(xué)習(xí)的能力,業(yè)內(nèi)稱之為 in-context learning ,這也是為什么 ChatGPT 可以在上下文中學(xué)習(xí)的原因。
ChatGPT 屬于 AI 領(lǐng)域在商用技術(shù)上的重大突破,當然,本篇我們不是要討論 ChatGPT 的實現(xiàn)邏輯,而是 ChatGPT 會怎么樣加速我們的開發(fā)?
PS:在此之前有人通過指示在 ChatGPT 界面下實現(xiàn)了一個虛擬機,雖然這是一個極端的例子,但是可以很直觀地感受到:「ChatGPT 對我們開發(fā)的影響是肉眼可見」。
那 ChatGPT 在實際工作中是如何影響我們的開發(fā)?為了更直觀,下面我們用一個開發(fā)場景來模擬這個流程。
基于 ChatGPT 開發(fā)
01 開發(fā)之前
假設(shè)我們現(xiàn)在有一個開發(fā)「直播」的需求,那我們可以直接求助 ChatGPT:
「開發(fā)一個直播 app,是使用第三方 SDK 好還是自己從 0 開發(fā)好」?
如下圖所示,從回答上可以看到,AI 建議我們根據(jù)團隊實際情況去選擇,而在知曉「我的團隊只有 5 個人」的情況后,它建議我選擇采用 “接入第三方 SDK” 的方式更合理。
那么選擇 “接入第三方 SDK” ,接下來的問題就是:「選擇做直播,在中國推薦使用哪些廠家的 SDK」? 如下圖所示,這個問題 ChatGPT 同樣提供了多個選項,從選項里看 *聲網(wǎng)、騰訊云和阿里云 * 好像都符合我們要求,而在接著的「優(yōu)勢問題」對比上看,這三個選項都 “不相伯仲”,那我們就在再細化問題。
假設(shè)我們希望直播可以有更多 “互動能力”,那么把問題修改為「做互動直播,更推薦使用哪一個廠家的 SDK」,截圖如下圖所示,這次我們得到了更明確的答復(fù),看來聲網(wǎng)的 SDK 會更貼合我們的需求。
為了更放心這個選擇,我們通過「聲網(wǎng) SDK的優(yōu)勢」和「什么產(chǎn)品使用了聲網(wǎng) SDK」兩個問題進行提問,如下圖所示,從回復(fù)上看聲網(wǎng)作為一個全球化的廠家,在音視頻領(lǐng)域還是值得相信。同時,還有包括小米、陌陌等產(chǎn)品都使用了聲網(wǎng)的服務(wù)。那么就按照 AI 的建議選擇聲網(wǎng) SDK 吧。
有沒有發(fā)現(xiàn),在獲取資料的檢索方式上,ChatGPT 確實比搜索引擎更直觀且高效。
那么敲定完 SDK ,接下來我們需要選擇應(yīng)用的開發(fā)框架,我們把需求限定在 Android 和 iOS,更好是能兼容 Web,覆蓋整個移動端 ,因為團隊人數(shù)不多,所以我們希望采用跨平臺開發(fā)來節(jié)約成本,那么問題就是:
「移動端哪個跨平臺框架更適合做直播」?
如下圖所示,得到的答案有 React Native 和 Flutter ,而恰好在 Flutter 回復(fù)里可以看到聲網(wǎng) SDK 的存在,所以我們可以敲定 App 開發(fā)框架就選 Flutter 了。
最后,在開發(fā)之前,我們還需要繼續(xù)提問「如何獲取聲網(wǎng) SDK」和「使用聲網(wǎng) SDK 需要做什么」,這樣我們就可以在開始開發(fā)之前提前準備好需要的東西。
關(guān)于注冊獲取 App ID 等步驟這里就省略了,畢竟目前這部分 ChatGPT 也無能為力。
02 開始開發(fā)
那么到這里我們就假定大家已經(jīng)準備好了開發(fā)環(huán)境,接下來可以直接進行開發(fā)。 我們還是繼續(xù)面向 ChatGPT 開發(fā),首先我們的提問是:「用聲網(wǎng)的 Flutter SDK agora_rtc_engine 6.1.0寫一個視頻通話頁面,給我 dart 代碼」,結(jié)果如下 GIF 所示,可以看到 ChatGPT 開始了瘋狂的輸出:
為什么關(guān)鍵詞是「視頻通話」?因為它比直播場景更精準簡單,生成的代碼更靠譜(經(jīng)過提問測試),而基于視頻通話部分,后面我們可以快速拓展為互動直播場景;而指定版本是為了避免 AI 使用舊版本 API。
從上門的代碼生成可以看到,ChatGPT 生產(chǎn)的代碼是自帶中文注釋,更貼心的是,如下圖所示,在生成的代碼末尾還給你解釋了這段代碼的實現(xiàn)邏輯,就像一個 “知心大姐姐”。
從這里也可以感覺到 ,ChatGPT 不是一個單純的完全只會基于語料答復(fù)整合的 AI 。
當然,直接復(fù)制生成的代碼后會發(fā)現(xiàn)這段代碼會報錯,這和 ChatGPT 目前的模型數(shù)據(jù)版本有一定關(guān)系,所以針對生成的代碼我們需要做一定手動調(diào)整,比如:
采用createAgoraRtcEngine和initialize創(chuàng)建和初始化RtcEngine
將setEventHandler修改為最新的registerEventHandler
將AgoraRenderWidget修改為AgoraVideoView
最后修改代碼如下,其中 80% 以上的邏輯都來自 ChatGPT 的自動生成,雖然沒辦法做到 “直出”,這無疑大大提高了開發(fā)的生產(chǎn)力。
class VideoCallPage extends StatefulWidget { final String channelName; const VideoCallPage({Key? key, required this.channelName}) : super(key: key); @override _VideoCallPageState createState() => _VideoCallPageState(); } class _VideoCallPageState extends State接下來,如下圖所示,在將項目運行到手機和 PC 端之后,可以看到我們就完成了最簡單的直播視頻場景,而基于我們打算做直播的念頭僅僅過去了 40 分鐘,這其中還包含了注冊聲網(wǎng)賬號和申請 App ID 的過程,我們通過簡單的提問、復(fù)制、粘貼、修改,就完成了一個直播需求的 demo。{ late RtcEngine _engine; bool _localUserJoined = false; bool _remoteUserJoined = false; int? rUid; @override void initState() { super.initState(); initAgora(); } @override void dispose() { _engine.leaveChannel(); super.dispose(); } Future initAgora() async { await [Permission.microphone, Permission.camera].request(); _engine = createAgoraRtcEngine(); await _engine.initialize(RtcEngineContext( appId: config.appId, channelProfile: ChannelProfileType.channelProfileLiveBroadcasting, )); _engine.registerEventHandler(RtcEngineEventHandler( onJoinChannelSuccess: (RtcConnection connection, int elapsed) { setState(() { _localUserJoined = true; }); }, onUserJoined: (connection, remoteUid, elapsed) { setState(() { _remoteUserJoined = true; rUid = remoteUid; }); }, onUserOffline: (RtcConnection connection, int remoteUid, UserOfflineReasonType reason) { setState(() { _remoteUserJoined = false; rUid = null; }); }, )); await _engine.enableVideo(); await _engine.startPreview(); await _engine.joinChannel( token: config.token, channelId: widget.channelName, uid: config.uid, options: const ChannelMediaOptions( channelProfile: ChannelProfileType.channelProfileLiveBroadcasting, clientRoleType: ClientRoleType.clientRoleBroadcaster, ), ); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text("VideoCallPage"),), body: Center( child: Stack( children: [ _remoteUserJoined ? _remoteVideoView(rUid) : _placeholderView(), _localUserJoined ? _localVideoView() : _placeholderView(), ], ), ), ); } Widget _placeholderView() { return Container( color: Colors.black, ); } Widget _remoteVideoView(id) { return AgoraVideoView( controller: VideoViewController.remote( rtcEngine: _engine, canvas: VideoCanvas(uid: id), connection: RtcConnection(channelId: widget.channelName), ), ); } Widget _localVideoView() { return Positioned( right: 16, bottom: 16, width: 100, height: 160, child: AgoraVideoView( controller: VideoViewController( rtcEngine: _engine, canvas: const VideoCanvas(uid: 0), ), ), ); } }
紅色方塊是后期加上的打碼~
那么到這里,雖然目前為止 demo 項目還不是互動直播,但是基于這個 demo 實現(xiàn)互動直播場景不會太難,因為你已經(jīng)跑通了整個 SDK 的鏈路流程了。
03 進階開發(fā)
那假設(shè)我們需要繼續(xù)往互動直播的方向開發(fā),那么我們肯定會遇到 “互動” 這個需求,比如「收到用戶發(fā)送的一段內(nèi)容后畫面彈出一個動畫」 這樣的需求。 那么首先我們要知道聲網(wǎng) SDK 如何監(jiān)聽用戶發(fā)送的內(nèi)容,所以接下來我們繼續(xù)提問:「如何使用聲網(wǎng)的 agora_rtc_engine 6.1.0 監(jiān)聽別人發(fā)送的文本消息」 ?
這里為什么還強制寫 agora_rtc_engine 6.1.0 ?因為如果不寫,默認可能會輸出 4.x 版本的老 API。
盡管得到的答案并不是 Dart 代碼而是 OC ,但是關(guān)鍵詞registerEventHandler和Message我們捕抓到了,簡單對比一下,就是Flutter SDK里的registerEventHandler對象,可以發(fā)現(xiàn)平替的接口就是onStreamMessage回調(diào)。
那么接著就是彈出什么內(nèi)容,因為我們沒有素材,假設(shè)還沒有設(shè)計師,那不如就讓 ChatGPT 幫我們畫一只兔子吧,不過測試結(jié)果并不好,如下圖所示,從輸出結(jié)果上看 ,這并不是我們想要的。
這里是我自己加的粉色,不然都是白色會糊成一坨,不得不說 ChatGPT 在繪制能力上 “很抽象”。
所以 ChatGPT 有時候也不是很智能,可能目前在繪畫理解上它還沒那么成熟, 但是沒問題, ChatGPT 是可以通過上下文學(xué)習(xí) “調(diào)教” 的,比如我們覺得兔子的耳朵形狀太離譜,那么我們可以讓 ChatGPT 給我們調(diào)整。 如下所示,雖然調(diào)整之后依然不對,但是比起一開始是不是好很多了?
這就是 ChatGPT 在每次會話上下文里學(xué)習(xí)的表現(xiàn)。
然后我們在兔子耳朵的基礎(chǔ)上再讓 ChatGPT 補全兔子頭,雖然最終的效果依然不理想,但是比起一開始已經(jīng)進步了很多。
同時我們還讓 ChatGPT 給我們畫了一個 “星星”,然后結(jié)合這兩個 Canvas 繪制的素材,我們在代碼里設(shè)置接收到 "兔子" 和 星星 文本的時候,就彈出一個放大動畫效果。 最終運行后效果如下 GIF 所示,看起來很簡陋,但是要知道,我們只是經(jīng)過了簡單的復(fù)制 / 粘貼就完成了這樣的效果,這難道不是開發(fā)效率的極大提高?
源碼在后面。
來自 ChatGPT 的兔子頭代碼:
class StarPaint extends StatelessWidget { @override Widget build(BuildContext context) { return CustomPaint( painter: HeartPainter(), size: Size(50, 50), ); } } class StarPaint extends CustomPainter { @override void paint(Canvas canvas, Size size) { final paint = Paint() ..color = Colors.red ..style = PaintingStyle.fill; final path = Path(); final halfWidth = size.width / 2; final halfHeight = size.height / 2; final radius = halfWidth; path.moveTo(halfWidth, halfHeight + radius); path.arcToPoint( Offset(halfWidth + radius, halfHeight), radius: Radius.circular(radius), clockwise: true, ); path.arcToPoint( Offset(halfWidth, halfHeight - radius), radius: Radius.circular(radius), clockwise: true, ); path.arcToPoint( Offset(halfWidth - radius, halfHeight), radius: Radius.circular(radius), clockwise: true, ); path.arcToPoint( Offset(halfWidth, halfHeight + radius), radius: Radius.circular(radius), clockwise: true, ); canvas.drawPath(path, paint); } @override bool shouldRepaint(covariant StarPaint oldDelegate) { return false; } }來自 ChatGPT 的星星代碼:
class StarPaint extends StatelessWidget { @override Widget build(BuildContext context) { return CustomPaint( painter: HeartPainter(), size: Size(50, 50), ); } } class StarPaint extends CustomPainter { @override void paint(Canvas canvas, Size size) { final paint = Paint() ..color = Colors.red ..style = PaintingStyle.fill; final path = Path(); final halfWidth = size.width / 2; final halfHeight = size.height / 2; final radius = halfWidth; path.moveTo(halfWidth, halfHeight + radius); path.arcToPoint( Offset(halfWidth + radius, halfHeight), radius: Radius.circular(radius), clockwise: true, ); path.arcToPoint( Offset(halfWidth, halfHeight - radius), radius: Radius.circular(radius), clockwise: true, ); path.arcToPoint( Offset(halfWidth - radius, halfHeight), radius: Radius.circular(radius), clockwise: true, ); path.arcToPoint( Offset(halfWidth, halfHeight + radius), radius: Radius.circular(radius), clockwise: true, ); canvas.drawPath(path, paint); } @override bool shouldRepaint(covariant StarPaint oldDelegate) { return false; } }自己補充的監(jiān)聽文本、發(fā)送文本和動畫效果代碼:
onStreamMessage: (RtcConnection connection, int remoteUid, int streamId, Uint8List data, int length, int sentTs) { var message = utf8.decode(data); if (message == "兔子") { showDialog( context: context, builder: (context) { return AnimaWidget(Rabbit()); }); } else if (message == "星星") { showDialog( context: context, builder: (context) { return Center( child: AnimaWidget(StarPaint()), ); }); } Future.delayed(Duration(seconds: 3), () { Navigator.pop(context); }); }, Future相信到這里大家應(yīng)該可以感受到 ChatGPT 提高開發(fā)效率的魅力,甚至你還可以把 ChatGPT 集成到你的直播場景里,通過 Flutter 上的chatgpt_api_client插件,你可以在 App 里直接向 ChatGPT 提問,比如通過 OpenAI 的 API 實現(xiàn)一個可以互動的虛擬主播。_onPressSend() async { try { final streamId = await _engine.createDataStream( const DataStreamConfig(syncWithAudio: false, ordered: false)); var txt = (Random().nextInt(10) % 2 == 0) ? "星星" : "兔子"; final data = Uint8List.fromList(utf8.encode(txt)); await _engine.sendStreamMessage( streamId: streamId, data: data, length: data.length); } catch (e) { print(e); } } class AnimaWidget extends StatefulWidget { final Widget child; const AnimaWidget(this.child); @override State createState() => _AnimaWidgetState(); } class _AnimaWidgetState extends State { double animaScale = 1; @override void initState() { super.initState(); Future.delayed(Duration(seconds: 1), () { animaScale = 5; setState(() {}); }); } @override Widget build(BuildContext context) { return AnimatedScale( scale: animaScale, duration: Duration(seconds: 1), curve: Curves.bounceIn, child: Container(child: widget.child)); } }
我怎么知道這個插件?肯定也是問 ChatGPT 的啊~
04 最后
到這里,相信大家應(yīng)該能感受到,在使用 ChatGPT 之后,** 整個開發(fā)效率能夠得到很大的提升,特別是內(nèi)容檢索的高效和準確上比搜索引擎更加靠譜,** 另外也能幫我們完成一些 “體力活” 形式的代碼。 當然我們也看到了目前 ChatGPT 并不能完全替代人工,因為它在很多方面生成的內(nèi)容并不完美,特別是很多代碼還是需要我們?nèi)斯ふ{(diào)整,但是這并不影響 ChatGPT 的價值。 最后引用我曾經(jīng)看到過的關(guān)于 ChatGPT 的一些評價:
「當你抱怨 ChatGPT 鬼話連篇滿嘴跑火車的時候,這可能有點像你看到一只猴子在沙灘上用石頭寫下 1+1=3。它確實算錯了,但這不是重點。它有一天會算對的?!?/p>
我相信 AI 并不是直接取代人類的方式,因為它對社會的擠壓不是從水平上碾壓,而是劣幣驅(qū)逐良幣,比如有位大佬就說過:「乙方最討厭甲方什么都不懂還 bb,但乙方的議價權(quán)恰恰來源于甲方什么都不懂還 bb」 ,而現(xiàn)在 ChatGPT 在慢慢消磨掉整個議價權(quán)。 總的來說「ChatGPT 只是一個產(chǎn)品,它不代表的整個技術(shù)的 “上限” ,它代表的是技術(shù)已經(jīng)到達商用的臨界點」。 現(xiàn)在,它在慢慢成為開發(fā)圈子里的習(xí)慣,和曾經(jīng)的 Copilot 一樣,而同時它在其他領(lǐng)域如文字編排等的能力,甚至遠超它在開發(fā)領(lǐng)域的價值。
審核編輯 :李倩
-
AI
+關(guān)注
關(guān)注
87文章
30896瀏覽量
269107 -
SDK
+關(guān)注
關(guān)注
3文章
1036瀏覽量
45948 -
ChatGPT
+關(guān)注
關(guān)注
29文章
1561瀏覽量
7673
原文標題:把ChatGPT加入Flutter開發(fā),會有怎樣的體驗?
文章出處:【微信號:OSC開源社區(qū),微信公眾號:OSC開源社區(qū)】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論