天天看點

把ChatGPT加入開發,會有怎樣的體驗?

作者:Freemen聊技術

哈喽大家好,Freemen 程式員求職App又和大家見面了,今天也要加油鴨!

ChatGPT 最近一直處于技術圈的讨論焦點。它除了可作為普通使用者的日常 AI 助手,還可以幫助開發者加速開發進度。開發者 "小猿" 就基于 ChatGPT 做了一場實驗。僅 40 分鐘就實作了一個互動直播 Demo。他是怎麼做的呢?下面就是他記錄的整個過程。

“遇事不決,AI 力學” ~ ChatGPT 可以說是 2023 開年最熱門的話題, 它不僅在極短時間内風靡了整個技術圈,更是病毒式地席卷了圈外的各個行業,并對各大企業都起到了實質性影響:

  • 谷歌緊急推出 “Bard” 對抗 ChatGPT
  • 微軟釋出新 Bing 內建 ChatGPT
  • 複旦釋出首個類 ChatGPT 模型 MOSS
  • 國内阿裡、百度、昆侖萬維、網易、京東都開始新一輪 AI 軍備

那 ChatGPT 究竟有什麼魔力能讓 “群雄折腰”?這和 ChatGPT 的實作有很大關系:

與以往的統計模型不行,ChatGPT 不是那種「一切都從語料統計裡學習」的 AI,相反 ChatGPT 具備有臨場學習的能力,業内稱之為 in-context learning ,這也是為什麼 ChatGPT 可以在上下文中學習的原因。

ChatGPT 屬于 AI 領域在商用技術上的重大突破,當然,本篇我們不是要讨論 ChatGPT 的實作邏輯,而是 ChatGPT 會怎麼樣加速我們的開發?

PS:在此之前有人通過訓示在 ChatGPT 界面下實作了一個虛拟機,雖然這是一個極端的例子,但是可以很直覺地感受到:「ChatGPT 對我們開發的影響是肉眼可見」。

那 ChatGPT 在實際工作中是如何影響我們的開發?為了更直覺,下面我們用一個開發場景來模拟這個流程。

目錄

  • 開發之前
  • 開始開發
  • 進階開發
  • 結論

基于 ChatGPT 開發

01 開發之前

假設我們現在有一個開發「直播」的需求,那我們可以直接求助 ChatGPT:

「開發一個直播 app,是使用第三方 SDK 好還是自己從 0 開發好」?

如下圖所示,從回答上可以看到,AI 建議我們根據團隊實際情況去選擇,而在知曉「我的團隊隻有 5 個人」的情況後,它建議我選擇采用 “接入第三方 SDK” 的方式更合理。

把ChatGPT加入開發,會有怎樣的體驗?
把ChatGPT加入開發,會有怎樣的體驗?

那麼選擇 “接入第三方 SDK” ,接下來的問題就是:「選擇做直播,在中國推薦使用哪些廠家的 SDK」?

如下圖所示,這個問題 ChatGPT 同樣提供了多個選項,從選項裡看 * 聲網、騰訊雲和阿裡雲 * 好像都符合我們要求,而在接着的「優勢問題」對比上看,這三個選項都 “不相伯仲”,那我們就在再細化問題。

把ChatGPT加入開發,會有怎樣的體驗?
把ChatGPT加入開發,會有怎樣的體驗?

假設我們希望直播可以有更多 “互動能力”,那麼把問題修改為 「做互動直播,更推薦使用哪一個廠家的 SDK」 ,截圖如下圖所示,這次我們得到了更明确的答複,看來聲網的 SDK 會更貼合我們的需求。

把ChatGPT加入開發,會有怎樣的體驗?

為了更放心這個選擇,我們通過 「聲網 SDK 的優勢」 和 「什麼産品使用了聲網 SDK」 兩個問題進行提問,如下圖所示,從回複上看聲網作為一個全球化的廠家,在音視訊領域還是值得相信。同時,還有包括小米、陌陌等産品都使用了聲網的服務。那麼就按照 AI 的建議選擇聲網 SDK 吧。

把ChatGPT加入開發,會有怎樣的體驗?
把ChatGPT加入開發,會有怎樣的體驗?
有沒有發現,在擷取資料的檢索方式上,ChatGPT 确實比搜尋引擎更直覺且高效。

那麼敲定完 SDK ,接下來我們需要選擇應用的開發架構,我們把需求限定在 Android 和 iOS,更好是能相容 Web,覆寫整個移動端 ,因為團隊人數不多,是以我們希望采用跨平台開發來節約成本,那麼問題就是:

「移動端哪個跨平台架構更适合做直播」?

如下圖所示,得到的答案有 React Native 和 Flutter ,而恰好在 Flutter 回複裡可以看到聲網 SDK 的存在,是以我們可以敲定 App 開發架構就選 Flutter 了。

把ChatGPT加入開發,會有怎樣的體驗?

最後,在開發之前,我們還需要繼續提問 「如何擷取聲網 SDK 」 和 「使用聲網 SDK 需要做什麼」,這樣我們就可以在開始開發之前提前準備好需要的東西。

把ChatGPT加入開發,會有怎樣的體驗?
把ChatGPT加入開發,會有怎樣的體驗?
關于注冊擷取 App ID 等步驟這裡就省略了,畢竟目前這部分 ChatGPT 也無能為力。

02 開始開發

那麼到這裡我們就假定大家已經準備好了開發環境,接下來可以直接進行開發。

我們還是繼續面向 ChatGPT 開發,首先我們的提問是:「用聲網的 Flutter SDK agora_rtc_engine 6.1.0 寫一個視訊通話頁面,給我 dart 代碼」 ,結果如下 GIF 所示,可以看到 ChatGPT 開始了瘋狂的輸出:

為什麼關鍵詞是「視訊通話」?因為它比直播場景更精準簡單,生成的代碼更靠譜(經過提問測試),而基于視訊通話部分,後面我們可以快速拓展為互動直播場景;而指定版本是為了避免 AI 使用舊版本 API。
把ChatGPT加入開發,會有怎樣的體驗?

從上門的代碼生成可以看到,ChatGPT 生産的代碼是自帶中文注釋,更貼心的是,如下圖所示,在生成的代碼末尾還給你解釋了這段代碼的實作邏輯,就像一個 “知心大姐姐”。

把ChatGPT加入開發,會有怎樣的體驗?
從這裡也可以感覺到 ,ChatGPT 不是一個單純的完全隻會基于語料答複整合的 AI 。

當然,直接複制生成的代碼後會發現這段代碼會報錯,這和 ChatGPT 目前的模型資料版本有一定關系,是以針對生成的代碼我們需要做一定手動調整,比如:

  • 采用 createAgoraRtcEngine 和 initialize 建立和初始化 RtcEngine
  • 将 setEventHandler 修改為最新的 registerEventHandler
  • 将 AgoraRenderWidget 修改為 AgoraVideoView

最後修改代碼如下,其中 80% 以上的邏輯都來自 ChatGPT 的自動生成,雖然沒辦法做到 “直出”,這無疑大大提高了開發的生産力。

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<VideoCallPage> {
  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<void> 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),
        ),
      ),
    );
  }
}
           

接下來,如下圖所示,在将項目運作到手機和 PC 端之後,可以看到我們就完成了最簡單的直播視訊場景,而基于我們打算做直播的念頭僅僅過去了 40 分鐘,這其中還包含了注冊聲網賬号和申請 App ID 的過程,我們通過簡單的提問、複制、粘貼、修改,就完成了一個直播需求的 demo。

把ChatGPT加入開發,會有怎樣的體驗?
紅色方塊是後期加上的打碼~

那麼到這裡,雖然目前為止 demo 項目還不是互動直播,但是基于這個 demo 實作互動直播場景不會太難,因為你已經跑通了整個 SDK 的鍊路流程了。

03 進階開發

那假設我們需要繼續往互動直播的方向開發,那麼我們肯定會遇到 “互動” 這個需求,比如「收到使用者發送的一段内容後畫面彈出一個動畫」 這樣的需求。

那麼首先我們要知道聲網 SDK 如何監聽使用者發送的内容,是以接下來我們繼續提問:「如何使用聲網的 agora_rtc_engine 6.1.0 監聽别人發送的文本消息」 ?

這裡為什麼還強制寫 agora_rtc_engine 6.1.0 ?因為如果不寫,預設可能會輸出 4.x 版本的老 API。

盡管得到的答案并不是 Dart 代碼而是 OC ,但是關鍵詞 registerEventHandler 和 Message 我們捕抓到了,簡單對比一下,就是 Flutter SDK 裡的 registerEventHandler 對象,可以發現平替的接口就是 onStreamMessage 回調。

把ChatGPT加入開發,會有怎樣的體驗?

那麼接着就是彈出什麼内容,因為我們沒有素材,假設還沒有設計師,那不如就讓 ChatGPT 幫我們畫一隻兔子吧,不過測試結果并不好,如下圖所示,從輸出結果上看 ,這并不是我們想要的。

這裡是我自己加的粉色,不然都是白色會糊成一坨,不得不說 ChatGPT 在繪制能力上 “很抽象”。
把ChatGPT加入開發,會有怎樣的體驗?
把ChatGPT加入開發,會有怎樣的體驗?

是以 ChatGPT 有時候也不是很智能,可能目前在繪畫了解上它還沒那麼成熟, 但是沒問題, ChatGPT 是可以通過上下文學習 “調教” 的,比如我們覺得兔子的耳朵形狀太離譜,那麼我們可以讓 ChatGPT 給我們調整。

如下所示,雖然調整之後依然不對,但是比起一開始是不是好很多了?

把ChatGPT加入開發,會有怎樣的體驗?
把ChatGPT加入開發,會有怎樣的體驗?
這就是 ChatGPT 在每次會話上下文裡學習的表現。

然後我們在兔子耳朵的基礎上再讓 ChatGPT 補全兔子頭,雖然最終的效果依然不理想,但是比起一開始已經進步了很多。

把ChatGPT加入開發,會有怎樣的體驗?

同時我們還讓 ChatGPT 給我們畫了一個 “星星”,然後結合這兩個 Canvas 繪制的素材,我們在代碼裡設定接收到 "兔子" 和 星星 文本的時候,就彈出一個放大動畫效果。

最終運作後效果如下 GIF 所示,看起來很簡陋,但是要知道,我們隻是經過了簡單的複制 / 粘貼就完成了這樣的效果,這難道不是開發效率的極大提高?

源碼在後面。
把ChatGPT加入開發,會有怎樣的體驗?

來自 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;
  }
}
           

自己補充的監聽文本、發送文本和動畫效果代碼:

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<void> _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<AnimaWidget> createState() => _AnimaWidgetState();
}

class _AnimaWidgetState extends State<AnimaWidget> {
  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 提高開發效率的魅力,甚至你還可以把 ChatGPT 內建到你的直播場景裡,通過 Flutter 上的 chatgpt_api_client 插件,你可以在 App 裡直接向 ChatGPT 提問,比如通過 OpenAI 的 API 實作一個可以互動的虛拟主播。

我怎麼知道這個插件?肯定也是問 ChatGPT 的啊~
把ChatGPT加入開發,會有怎樣的體驗?
把ChatGPT加入開發,會有怎樣的體驗?

04 最後

到這裡,相信大家應該能感受到,在使用 ChatGPT 之後,整個開發效率能夠得到很大的提升,特别是内容檢索的高效和準确上比搜尋引擎更加靠譜,另外也能幫我們完成一些 “體力活” 形式的代碼。

當然我們也看到了目前 ChatGPT 并不能完全替代人工,因為它在很多方面生成的内容并不完美,特别是很多代碼還是需要我們人工調整,但是這并不影響 ChatGPT 的價值。

最後引用我曾經看到過的關于 ChatGPT 的一些評價:

「當你抱怨 ChatGPT 鬼話連篇滿嘴跑火車的時候,這可能有點像你看到一隻猴子在沙灘上用石頭寫下 1+1=3。它确實算錯了,但這不是重點。它有一天會算對的。」

我相信 AI 并不是直接取代人類的方式,因為它對社會的擠壓不是從水準上碾壓,而是劣币驅逐良币,比如有位大佬就說過:「乙方最讨厭甲方什麼都不懂還 bb,但乙方的議價權恰恰來源于甲方什麼都不懂還 bb」 ,而現在 ChatGPT 在慢慢消磨掉整個議價權。

總的來說「ChatGPT 隻是一個産品,它不代表的整個技術的 “上限” ,它代表的是技術已經到達商用的臨界點」。

現在,它在慢慢成為開發圈子裡的習慣,和曾經的 Copilot 一樣,而同時它在其他領域如文字編排等的能力,甚至遠超它在開發領域的價值。

文章來源:個人部落格 作者:小猿

Freemen今天也有java開發、晶片設計等IT崗位等待大家投遞~

今日推薦:

安卓開發工程師

崗位要求

1. 全日制統招大學畢業,3年左右工作經驗;

2. 精通Android進階特性和SDK的使用,熟練掌握品牌手機和Android版本之間的差別;

3. 熟練掌握Android各種調優工具,可以精确定位bug,熟練掌握IO,記憶體和CPU的優化;

4. 掌握Android端電量和流量優化技巧;

5. 掌握安卓中繪圖機制;

6.有JNI程式設計優先的考慮。

薪資:20K- 30K

工作地點:杭州

把ChatGPT加入開發,會有怎樣的體驗?