首页IT科技chat gpt免费手机版(把 ChatGPT 加入 Flutter 开发,会有怎样的体验?)

chat gpt免费手机版(把 ChatGPT 加入 Flutter 开发,会有怎样的体验?)

时间2025-07-31 03:32:02分类IT科技浏览4534
导读:前言...

前言

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 开发

开发之前

假设我们现在有一个开发「直播」的需求              ,那我们可以直接求助 ChatGPT:

「开发一个直播app                    ,是使用第三方SDK好还是自己从0开发好」?

如下图所示      ,从回答上可以看到       ,AI 建议我们根据团队实际情况去选择                    ,而在知晓「我的团队只有 5 个人」的情况后             ,它建议我选择采用 “接入第三方 SDK             ” 的方式更合理              。

那么选择 “接入第三方 SDK                    ”        ,接下来的问题就是:「选择做直播                    ,在中国推荐使用哪些厂家的 SDK」?

如下图所示             ,这个问题 ChatGPT 同样提供了多个选项,从选项里看*声网                    、腾讯云和阿里云*好像都符合我们要求                    ,而在接着的「优势问题」对比上看                   ,这三个选项都“不相伯仲       ”,那我们就在再细化问题      。

假设我们希望直播可以有更多“互动能力      ”              ,那么把问题修改为 「做互动直播                   ,更推荐使用哪一个厂家的 SDK」       ,截图如下图所示              ,这次我们得到了更明确的答复                    ,看来声网的 SDK 会更贴合我们的需求                   。

为了更放心这个选择      ,我们通过 「声网 SDK 的优势」「什么产品使用了声网SDK」 两个问题进行提问       ,如下图所示                    ,从回复上看声网作为一个全球化的厂家             ,在音视频领域还是值得相信              。同时       ,还有包括小米       、陌陌等产品都使用了声网的服务。那么就按照 AI 的建议选择声网 SDK 吧                   。

有没有发现                    ,在获取资料的检索方式上             ,ChatGPT 确实比搜索引擎更直观且高效                    。

那么敲定完 SDK ,接下来我们需要选择应用的开发框架                    ,我们把需求限定在 Android 和 iOS                   ,更好是能兼容 Web,覆盖整个移动端               ,因为团队人数不多                   ,所以我们希望采用跨平台开发来节约成本      ,那么问题就是:

「移动端哪个跨平台框架更适合做直播」?

如下图所示              ,得到的答案有 React Native 和 Flutter                    ,而恰好在 Flutter 回复里可以看到声网 SDK 的存在      ,所以我们可以敲定 App 开发框架就选 Flutter 了。

最后       ,在开发之前                    ,我们还需要继续提问 「如何获取声网 SDK 」「使用声网 SDK 需要做什么」             ,这样我们就可以在开始开发之前提前准备好需要的东西             。

关于注册获取 App ID 等步骤这里就省略了       ,毕竟目前这部分 ChatGPT 也无能为力                    。

02 开始开发

那么到这里我们就假定大家已经准备好了开发环境                    ,接下来可以直接进行开发       。

我们还是继续面向 ChatGPT 开发             ,首先我们的提问是:「用声网的 Flutter SDK agora_rtc_engine 6.1.0 写一个视频通话页面,给我 dart 代码」                     ,结果如下 GIF 所示                   ,可以看到 ChatGPT 开始了疯狂的输出:

为什么关键词是「视频通话」?因为它比直播场景更精准简单,生成的代码更靠谱(经过提问测试)              ,而基于视频通话部分                   ,后面我们可以快速拓展为互动直播场景;而指定版本是为了避免

AI 使用旧版本 API             。

从上门的代码生成可以看到      ,ChatGPT 生产的代码是自带中文注释              ,更贴心的是                    ,如下图所示      ,在生成的代码末尾还给你解释了这段代码的实现逻辑       ,就像一个“知心大姐姐                    ”                    。

从这里也可以感觉到                    ,ChatGPT 不是一个单纯的完全只会基于语料答复整合的 AI       。

当然             ,直接复制生成的代码后会发现这段代码会报错       ,这和 ChatGPT 目前的模型数据版本有一定关系                    ,所以针对生成的代码我们需要做一定手动调整             ,比如:

采用 createAgoraRtcEngineinitialize 创建和初始化 RtcEnginesetEventHandler 修改为最新的 registerEventHandlerAgoraRenderWidget 修改为 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                    。

红色方块是后期加上的打码~

那么到这里       ,虽然目前为止 demo 项目还不是互动直播                    ,但是基于这个 demo 实现互动直播场景不会太难             ,因为你已经跑通了整个 SDK 的链路流程了              。

03 进阶开发

那假设我们需要继续往互动直播的方向开发       ,那么我们肯定会遇到“互动      ”这个需求                    ,比如「收到用户发送的一段内容后画面弹出一个动画」 这样的需求      。

那么首先我们要知道声网 SDK 如何监听用户发送的内容             ,所以接下来我们继续提问:「如何使用声网的 agora_rtc_engine 6.1.0 监听别人发送的文本消息」 ?

这里为什么还强制写 agora_rtc_engine 6.1.0 ?因为如果不写,默认可能会输出 4.x 版本的老 API                   。

尽管得到的答案并不是 Dart 代码而是 OC                     ,但是关键词 registerEventHandlerMessage 我们捕抓到了                   ,简单对比一下,就是 Flutter SDK 里的 registerEventHandler 对象              ,可以发现平替的接口就是 onStreamMessage 回调              。

那么接着就是弹出什么内容                   ,因为我们没有素材      ,假设还没有设计师              ,那不如就让 ChatGPT 帮我们画一只兔子吧                    ,不过测试结果并不好      ,如下图所示       ,从输出结果上看                    ,这并不是我们想要的。

这里是我自己加的粉色             ,不然都是白色会糊成一坨       ,不得不说 ChatGPT 在绘制能力上“很抽象                   ”                   。

所以 ChatGPT 有时候也不是很智能                    ,可能目前在绘画理解上它还没那么成熟             , 但是没问题, ChatGPT 是可以通过上下文学习“调教              ”的                    ,比如我们觉得兔子的耳朵形状太离谱                   ,那么我们可以让 ChatGPT 给我们调整                    。

如下所示,虽然调整之后依然不对              ,但是比起一开始是不是好很多了?

这就是 ChatGPT 在每次会话上下文里学习的表现。

然后我们在兔子耳朵的基础上再让 ChatGPT 补全兔子头                   ,虽然最终的效果依然不理想      ,但是比起一开始已经进步了很多             。

同时我们还让 ChatGPT 给我们画了一个“星星”              ,然后结合这两个 Canvas 绘制的素材                    ,我们在代码里设置接收到 “兔子                   ” 和 星星 文本的时候      ,就弹出一个放大动画效果                    。

最终运行后效果如下 GIF 所示       ,看起来很简陋                    ,但是要知道             ,我们只是经过了简单的复制/粘贴就完成了这样的效果       ,这难道不是开发效率的极大提高?

源码在后面       。

来自 ChatGPT 的兔子头代码:

class BunnyPainter extends CustomPainter { @override void paint(Canvas canvas, Size size) { // 设置画笔 final paint = Paint() ..color = Colors.white ..style = PaintingStyle.fill; final path = Path(); // 绘制左耳 path.moveTo(size.width / 2 - 40, size.height / 2 - 80); path.lineTo(size.width / 2 - 60, size.height / 2 - 120); path.quadraticBezierTo(size.width / 2 - 70, size.height / 2 - 135, size.width / 2 - 50, size.height / 2 - 160); path.lineTo(size.width / 2 - 30, size.height / 2 - 120); path.quadraticBezierTo(size.width / 2 - 40, size.height / 2 - 100, size.width / 2 - 40, size.height / 2 - 80); // 绘制路径 canvas.drawPath(path, paint); final path2 = Path(); // 绘制右耳 path2.moveTo(size.width / 2 + 40, size.height / 2 - 80); path2.lineTo(size.width / 2 + 60, size.height / 2 - 120); path2.quadraticBezierTo(size.width / 2 + 70, size.height / 2 - 135, size.width / 2 + 50, size.height / 2 - 160); path2.lineTo(size.width / 2 + 30, size.height / 2 - 120); path2.quadraticBezierTo(size.width / 2 + 40, size.height / 2 - 100, size.width / 2 + 40, size.height / 2 - 80); // 绘制路径 canvas.drawPath(path2, paint); final path3 = Path(); // 绘制头部 final rect = Rect.fromLTWH(size.width / 2 - 60, size.height / 2 - 140, 120, 120); path3.addOval(rect); // 绘制路径 canvas.drawPath(path3, paint); final path4 = Path(); // 绘制眼睛 final leftEyeCenter = Offset(size.width / 2 - 20, size.height / 2 - 80); final rightEyeCenter = Offset(size.width / 2 + 20, size.height / 2 - 80); final eyeRadius = 8.0; path4.addArc( Rect.fromCircle(center: leftEyeCenter, radius: eyeRadius), 0, pi * 2); path4.addArc( Rect.fromCircle(center: rightEyeCenter, radius: eyeRadius), 0, pi * 2); // 设置画笔 final paint2 = Paint() ..color = Colors.black ..style = PaintingStyle.fill; // 绘制路径 canvas.drawPath(path4, paint2); final path5 = Path(); // 绘制鼻子 final noseCenter = Offset(size.width / 2, size.height / 2 - 50); final noseRadius = 10.0; path5.addArc( Rect.fromCircle(center: noseCenter, radius: noseRadius), 0, pi * 2); // 绘制路径 canvas.drawPath(path5, paint2); } @override bool shouldRepaint(BunnyPainter oldDelegate) => 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 的啊~

04 最后

到这里                   ,相信大家应该能感受到,在使用 ChatGPT 之后              ,**整个开发效率能够得到很大的提升                   ,特别是内容检索的高效和准确上比搜索引擎更加靠谱      ,**另外也能帮我们完成一些“体力活                    ”形式的代码                    。

当然我们也看到了目前 ChatGPT 并不能完全替代人工              ,因为它在很多方面生成的内容并不完美                    ,特别是很多代码还是需要我们人工调整      ,但是这并不影响 ChatGPT 的价值       。

最后引用我曾经看到过的关于 ChatGPT 的一些评价:

「当你抱怨 ChatGPT鬼话连篇满嘴跑火车的时候       ,这可能有点像你看到一只猴子在沙滩上用石头写下1+1=3      。它确实算错了                    ,但这不是重点                    。它有一天会算对的              。」

我相信 AI 并不是直接取代人类的方式             ,因为它对社会的挤压不是从水平上碾压       ,而是劣币驱逐良币                    ,比如有位大佬就说过:「乙方最讨厌甲方什么都不懂还bb             ,但乙方的议价权恰恰来源于甲方什么都不懂还 bb」 ,而现在 ChatGPT 在慢慢消磨掉整个议价权      。

总的来说「ChatGPT 只是一个产品                    ,它不代表的整个技术的“上限”                    ,它代表的是技术已经到达商用的临界点」                   。

现在,它在慢慢成为开发圈子里的习惯              ,和曾经的 Copilot 一样                   ,而同时它在其他领域如文字编排等的能力      ,甚至远超它在开发领域的价值              。

欢迎开发者们也尝试体验声网 SDK              ,实现实时音视频互动场景。现注册声网账号下载 SDK                    ,可获得每月免费 10000 分钟使用额度                   。如在开发过程中遇到疑问      ,可在声网开发者社区与官方工程师交流                    。

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
《文心》(“国产版ChatGPT”文心一言发布会现场Demo硬核复现) 如何准确选择?(学习有效的选取技巧)