面向 ChatGPT 开发 ,我是如何被 AI 从 “逼疯” 到 “觉悟” ,未来又如何落地
本文正在参加✍技术视角深入 ChatGPT 征文活动
对于 ChatGPT 现在咱们应该都不陌生,通过这么长期的「调戏」,信任咱们应该都感受用 ChatGPT 「替代」搜索引擎的魅力,例如写周报、定位 Bug、翻译文档等等,而其间不乏一些玩的很「花」的场景,例如:
-
ChatPDF :使用 ChatPDF 读取 PDF 之后,你能够和 PDF 文件进行「攀谈」,就好像它是一个彻底了解内容的「人」相同,通过它能够总结中心思想,解读专业论文,生成内容摘要,翻译外籍,并且还支持中文输出等。
-
BiBiGPT : 一键总结视频内容,主要依靠字幕来做总结,肯定是「二创」作者的摸鱼利器。
所以把 ChatGPT 了解为「搜索引擎」其实并不正确,从上述介绍的两个落地完结上看, ChatGPT 不是单纯的统计模型,它的中心并不是彻底依靠于它的「语料库」,更多来自于临场学习的才能「 in-context learning」,这便是 ChatGPT 不同于以往传统 NLP「全部都从语料的统计里学习」的原因。
当然,我自身并非人工智能范畴的开发者,而作为一个一般开发者,我更关怀的是 ChatGPT 能够怎么提升我的开(mo)发(yu)功率,仅仅没想到随手一试,我会被 ChatGPT 的 「 in-context learning」 给「逼疯」。
ChatGPT & UI
信任咱们平时「面向」 ChatGPT 开发时,也是通过它来输出「算法」或者「 CURD」 等逻辑居多,由于这部分输出看起来相对会比较直观,而用 ChatGPT 来绘制前端 UI 的人应该不多,由于 UI 作用从代码上看并不直观 ,并且 ChatGPT 对与 UI 的了解现在还处于 「人工智障」的阶段。
可是我偏偏不信邪。。。。。
由于近期开发需求里刚好需要绘制一个具有动画作用的 ⭐️ 按键,面对这么「没有挑战性」的工作我决定测验交给 ChatGPT 来完结,所以我向 ChatGPT 发起了第一个命令:
「用 Flutter 画一个黄色的五角星」
![]() |
![]() |
---|
成果不负众望,要害部分如下代码所示,Flutter 很快就供给了完好的 Dart 代码,并且还针对代码供给了代码相关完结的解说,不过运转之后能够看到,这时分的 ⭐️ 的款式并不满意咱们的需求。
此刻顶部的角也太「肥」了 。
![]() |
![]() |
---|
所以我跟着提出了调整,期望五角星的五个角能够相同大,仅仅没想到我的描绘,开端让 ChatGPT 放飞自我 。
或许是我的描绘并不精确?
在我满怀等待的 cv
代码并运转之后,猝不及防的「五角星」差点没让我喷出一口老血,尽管这也有五个角,可是你管这个叫 「五角星」 ???
这难道不是某个红白机游戏里的小飞机??
![]() |
![]() |
---|
乃至于在看到后续 ChatGPT 关于代码的相关解说时,我觉得它现已开端在「不苟言笑的胡言乱语」,像极了今天早上刚给我提需求的产品经理。
哪里能够看出五个角相同了???
接着我持续纠正我的需求,表示我要的是 「一个五个角相同大的黄色五角星」
,我认为这样的描绘应过比较贴切,须不知
如下代码所示,其实在看到代码输出 for
循环时我就觉得不对了,可是秉承着「全部以实物为准」的理念,在运转后不出意外的发生了意外,确实是五个角相同大,不过是一个等边五边形。
算一个发胖的 ⭐️ 能解(jiao)释(bian)曩昔不?
![]() |
![]() |
---|
再看 ChatGPT 对于代码的描绘,我发现我错了,本来它像的是「了解错需求还在嘴硬的我」,仅仅它在说「这是一个五角星」的时分眼皮都不会眨一下。
AI:确实五个角相同大,五个角相同大的五边形为什么就不能是五角星?你这是轻视体型吗?
所以我持续要求:「我要的是五角星,不是五边形」
,还好 ChatGPT 的临场学习才能不错,他又一次「重新定义五角星」,不过我此刻我也不抱期望,便是单纯想看看它还能给出什么「惊喜」。
不出意外,这个「离谱」的多边形让我心头一紧,就在我想着是否抛弃的时分,身为人类无法征服 AI 「既爱又恨」的杂乱心情,让我终究坚持必定要让 ChatGPT 给我画出一个 ⭐️。
![]() |
![]() |
---|
不过心灰意冷之下,我挑选让 ChatGPT 重新画一个黄色五角星,没想道这次却有了意外的惊喜,从下面的图片能够看到,此刻的 ⭐️ 除了视点不对,形状现已彻底满意需求。
所以一个问题我多问几遍,或许就能接近我要的答案?
事实上这也是现在 ChatGPT 的现状,由于「临场学力」才能等因素影响,同一个问题它或许会给出不同的答案,而有的答案其实和咱们要的根本不沾边。
![]() |
![]() |
---|
那么,接下来只要让 ChatGPT 把 ⭐️ 旋转一下视点,应该就能够完结需求了吧?所以我提出「帮我旋转 180度」
的要求。
成果不出意外的仍是发生了意外,或许 ChatGPT 了解的 180 度和我不大相同,如下图所示,确实旋转了,仅仅仍是歪的,而根据前面的测验,我觉得有必要再给它一次机会。
![]() |
![]() |
---|
总算,在我换了以下描绘之后,ChatGPT 好像「开窍」了,总算让我如愿以偿的得到了我想要的 ⭐️ 代码。
能够看到,其实这段代码并不杂乱,你自己写或者去搜索引擎扒一扒大概会比用 ChatGPT 更快,可是 ChatGPT 的魅力就在于:它或许会错,可是总有一次它会「蒙对」,假如现在还不对,那么未来也会有算对的时分,这便是我感受到的 AI 魅力所在。
![]() |
![]() |
---|
既然五角星都出来,那么接下来咱们来完结最终一步的动画作用,咱们期望的是点击 ⭐️ 的时分能够有一个爆破粒子的动画,所以我提出了:
「期望加上一个动画作用,便是点击的时分星星爆破成颗粒的动画作用」
成果仍是「一口老血」,如下图所示,「星星确实爆破了」,仅仅这个爆破动画看起来是那么的「一言难尽」,感兴趣的能够 cv 下面的源代码自己体会下,不出意外接下来又是新的一轮人类和 AI 的「斗智斗勇」。
class YellowStar extends StatefulWidget {
@override
_YellowStarState createState() => _YellowStarState();
}
class _YellowStarState extends State<YellowStar> with TickerProviderStateMixin {
bool _isExploded = false;
late AnimationController _animationController;
late Animation<double> _animation;
@override
void initState() {
super.initState();
_animationController = AnimationController(
duration: const Duration(milliseconds: 500),
vsync: this,
);
_animation = CurvedAnimation(
parent: _animationController,
curve: Curves.easeInOut,
);
}
@override
void dispose() {
_animationController.dispose();
super.dispose();
}
void _handleTapDown(TapDownDetails details) {
setState(() {
_isExploded = true;
_animationController.forward(from: 0.0);
});
}
void _resetStar() {
setState(() {
_isExploded = false;
_animationController.reset();
});
}
@override
Widget build(BuildContext context) {
return GestureDetector(
onTapDown: _handleTapDown,
onTap: _resetStar,
child: AnimatedContainer(
duration: const Duration(milliseconds: 500),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: _isExploded
? BorderRadius.circular(50)
: BorderRadius.zero,
),
child: _isExploded
? _buildParticles()
: Container(
width: 100,
height: 100,
child: CustomPaint(
painter: YellowStarPainter(),
),
),
),
);
}
Widget _buildParticles() {
return AnimatedBuilder(
animation: _animation,
builder: (context, child) {
return Container(
width: 100,
height: 100,
child: Stack(
children: List.generate(
50,
(index) {
double radius = _animation.value * 50;
double angle = 2 * pi * index / 50;
double x = 50 + cos(angle) * radius;
double y = 50 + sin(angle) * radius;
return Positioned(
left: x,
top: y,
child: Container(
width: 4,
height: 4,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.yellow,
),
),
);
},
),
),
);
},
);
}
}
class YellowStarPainter extends CustomPainter {
final double starSizeRatio = 0.4;
final double centerOffsetRatio = 0.2;
final double rotationOffset = -pi / 2;
@override
void paint(Canvas canvas, Size size) {
double starSize = min(size.width, size.height) * starSizeRatio;
double centerX = size.width / 2;
double centerY = size.height / 2;
double centerOffset = starSize * centerOffsetRatio;
Path path = Path();
Paint paint = Paint()
..color = Colors.yellow
..style = PaintingStyle.fill;
for (int i = 0; i < 5; i++) {
double radians = 2 * pi / 5 * i + rotationOffset;
double x = centerX + cos(radians) * starSize / 2;
double y = centerY + sin(radians) * starSize / 2;
if (i == 0) {
path.moveTo(x, y);
} else {
path.lineTo(x, y);
}
radians += 2 * pi / 10;
x = centerX + cos(radians) * centerOffset;
y = centerY + sin(radians) * centerOffset;
path.lineTo(x, y);
}
path.close();
canvas.drawPath(path, paint);
}
@override
bool shouldRepaint(CustomPainter oldDelegate) => false;
}
通过一轮「激战」如下图所示,面对同一个问题,ChatGPT 总能找到不同的完结方式来答复你,仅仅这些完结里有的无法运转的,有的是运转没有作用的,有的乃至是给你输出了一个 //TODO 爆破动画
,总归便是让你「血压飙升」。
当然,「胜利终将属于人类」,如下图所示,在阅历了无数次「血压飙升」的场景之后,终究我仍是得到了我想要的:点击 ⭐️,然后呈现了的动画作用,尽管仍是不完美,可是根本满意了我后续开发的需求。
这个代码完彻底全由 ChatGPT 输出,我一句没改,完好代码贴在了后面。
class YellowStarPage extends StatefulWidget {
@override
_YellowStarPageState createState() => _YellowStarPageState();
}
class _YellowStarPageState extends State<YellowStarPage>
with SingleTickerProviderStateMixin {
late AnimationController _animationController;
bool _isExploded = false;
@override
void initState() {
super.initState();
_animationController =
AnimationController(vsync: this, duration: Duration(milliseconds: 500))
..addListener(() {
setState(() {});
});
}
@override
void dispose() {
_animationController.dispose();
super.dispose();
}
void _handleStarTap() {
if (!_isExploded) {
_isExploded = true;
_animationController.forward(from: 0);
Future.delayed(Duration(milliseconds: 500), () {
setState(() {
_isExploded = false;
});
});
}
setState(() {});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Yellow Star')),
body: Center(
child: GestureDetector(
onTap: _handleStarTap,
child: Container(
width: 300,
height: 300,
child: AnimatedBuilder(
animation: _animationController,
builder: (context, child) {
return CustomPaint(
painter: YellowStarPainter(_animationController.value,
isExploded: _isExploded),
);
},
),
),
),
),
);
}
}
class YellowStarPainter extends CustomPainter {
final double starSizeRatio = 0.4;
final double centerOffsetRatio = 0.2;
final double rotationOffset = -pi / 2;
final double animationValue;
final bool isExploded;
YellowStarPainter(this.animationValue, {this.isExploded = false});
@override
void paint(Canvas canvas, Size size) {
double starSize = min(size.width, size.height) * starSizeRatio;
double centerX = size.width / 2;
double centerY = size.height / 2;
double centerOffset = starSize * centerOffsetRatio;
Path path = Path();
Paint paint = Paint()
..color = Colors.yellow
..style = PaintingStyle.fill;
if (isExploded) {
double particleSize = starSize / 30;
paint.strokeWidth = 1;
paint.style = PaintingStyle.fill;
paint.color = Colors.yellow;
Random random = Random();
for (int i = 0; i < 30; i++) {
double dx = random.nextDouble() * starSize - starSize / 2;
double dy = random.nextDouble() * starSize - starSize / 2;
double x = centerX + dx * (1 + animationValue);
double y = centerY + dy * (1 + animationValue);
canvas.drawCircle(Offset(x, y), particleSize, paint);
}
} else {
for (int i = 0; i < 5; i++) {
double radians = 2 * pi / 5 * i + rotationOffset;
double x = centerX + cos(radians) * starSize / 2;
double y = centerY + sin(radians) * starSize / 2;
if (i == 0) {
path.moveTo(x, y);
} else {
path.lineTo(x, y);
}
radians += 2 * pi / 10;
x = centerX + cos(radians) * centerOffset;
y = centerY + sin(radians) * centerOffset;
path.lineTo(x, y);
}
path.close();
canvas.drawPath(path, paint);
}
}
@override
bool shouldRepaint(CustomPainter oldDelegate) => true;
}
最终,给咱们赏识一下我让 ChatGPT 画一只米老鼠的「心路历程」,很明显这一次「人类落花流水」,从现在的支持上看,让 ChatGPT 输出杂乱图画内容并不抱负,由于它不的笔画「不会拐弯」。
![]() |
![]() |
![]() |
![]() |
---|
真的是又爱又恨。
最终
通过上面的一系列「折腾」,能够看到 ChatGPT 并没有咱们幻想中智能,假如面向 GPT 去开发,乃至或许并不靠谱,由于它并不对单一问题给出固定答案,乃至许多内容都是临场瞎编的,这也是由于大语言模型自身怎么保证「正确」是一个杂乱的问题,可是 ChatGPT 的魅力也来自于此:
它并不是彻底根据语料来的统计来给答案。
当然这也和 ChatGPT 自身的属性有关系, ChatGPT 现在的火爆有很大一部分属于「意外」,现在看它不是一个被精心产品化后的 2C 产品,反而 ChatPDF 和 BiBiGPT 这种场景化的包装落地会是它未来的方向之一。
而现在 OpenAI 发布了多模态预练习大模型 CPT-4 ,GPT-4 按照官方的说法是又得到了腾跃式提升:强大的识图才能;文字输入限制提升至 2.5 万字;答复精确性明显提高;能够生成歌词、构思文本,完结风格变化等等
所以我很等待 ChatGPT 能够用 Flutter 帮我画出一只米老鼠, 尽管 ChatGPT 现在或许会让你由于得到 1+1=3
这样的答案而「发疯”」,可是 AI 的魅力在于,它终有一天能得到精确的成果 。