封面图由DALL·E生成:ai write code
本文最后含彩蛋:ChatGPT 竟然会推销自己,甚至发现了我在做的事情
作为一个程序员,在使用 ChatGPT 的过程中,我也问了很多技术性的问题,总体来说他对复杂问题可以帮你拆解提供思路,简单问题可以直接给你答案。但是这些答案都是需要去仔细甄别的。另外,在使用时,提问的方式也有一些学问。下面,我会针对几个问题对其回答进行论证。
对 ChatGPT 的编程问答测试分为我的问题和网友的问题,如 CSDN 问答等,问题的难度有简单的也有复杂的,下面让我们一起来看看大智若妖的 ChatGPT 能否经得住考验。
1. 简单问题
ChatGPT 对简单的具体问题,大多数情况下其回答比我们可以想到的会更详细,更全面,也更好。
1.1 简单问题:Nodejs 中 fs.readFile 的使用
问:使用fs.readFile读取文件时,是否添加格式参数,影响回调参数的dataStr形参类型。
fs.readFile('../素材/成绩.txt','utf8',function(err, dataStr) {
//判断读取文件是否成功
if (err) {
return console.log('读取文件失败:' + err.message)
}
//当未指定编码格式时,dataStr是对象类型,而非字符串!!
console.log(dataStr);
console.log(typeof dataStr);
console.log('读取文件成功:' + dataStr);
})
ChatGPT 答(只复制标题):
是的,在使用fs.readFile读取文件时,可以使用一个可选的第二个参数来指定文件的编码格式。如果未指定,则默认为 null,表示返回的数据是一个 Buffer 对象。如果指定了编码格式,则返回的数据将是一个字符串。例如,如果指定了编码格式为 utf8,则 fs.readFile 的回调函数中的 dataStr 参数将是一个字符串,而不是一个 Buffer 对象。
fs.readFile('file.txt', 'utf8', function(err, dataStr) {
if (err) throw err;
// dataStr is a string containing the contents of the file
});
请注意,不同的文件可能使用不同的编码格式,因此在使用 fs.readFile 读取文件时,最好指定正确的编码格式。
以上答案非常完美,但是仔细阅读提问者的内容你会发现,它并没有完全解释提问者的疑惑,此时需要我们继续提问引导,将其疑惑输入:为什么在这个代码里未设置utf-8时直接 console.log(dataStr) 是buffer,但是 console.log("输出"+dataStr)出来的是字符串 。
ChatGPT 答:
在没有指定编码格式的情况下,fs.readFile 默认将返回一个 Buffer 对象。如果直接输出这个 Buffer 对象,则会显示它的内容(即二进制数据)。但是,如果将 Buffer 对象与字符串进行字符串拼接,则 Node.js 会自动将 Buffer 对象转换为字符串。因此,当你在 console.log 中将 Buffer 对象与字符串进行拼接时,实际输出的是字符串。
例如,以下代码中,第一个 console.log 输出的是 Buffer 对象,而第二个 console.log 输出的是字符串:
fs.readFile('file.txt', function(err, dataStr) {
if (err) throw err;
// Outputs a Buffer object
console.log(dataStr);
// Outputs a string
console.log("输出" + dataStr);
});
在这种情况下,为了确保每次都输出字符串,最好指定编码格式,并将返回的数据转换为字符串。例如:
fs.readFile('file.txt', 'utf8', function(err, dataStr) {
if (err) throw err;
// Outputs a string
console.log(dataStr);
// Outputs a string
console.log("输出" + dataStr);
});
在这种情况下,fs.readFile 的回调函数中的 dataStr 参数就是一个字符串,无需再进行转换。
经过以上引导式的询问,ChatGPT 可以非常优秀的回答我们简单的编程问题,可以看出其对编程初学者还是比较友好的,但是还是建议初学者可以有人帮忙做好鉴别。
1.2 简单问题:Python 输出
问:python已知列表score = [62, 89, 100, 92, 89, 75, 79, 84 ],循环score列表,输出每个元素的索引值和元素
ChatGPT 答:
在 Python 中,可以使用内置的 enumerate 函数来循环列表并输出每个元素的索引值和元素。例如:
score = [62, 89, 100, 92, 89, 75, 79, 84]
for index, element in enumerate(score):
print(f'Index: {index}, Element: {element}')
这段代码的输出结果如下:
Index: 0, Element: 62
Index: 1, Element: 89
Index: 2, Element: 100
Index: 3, Element: 92
Index: 4, Element: 89
Index: 5, Element: 75
Index: 6, Element: 79
Index: 7, Element: 84
请注意,enumerate 函数返回的是一个 enumerate 对象,它是一个可迭代的对象,包含了元素的索引值和元素本身。因此,在循环这个对象时,可以使用两个变量来捕获索引值和元素。如果要从 1 开始计数,则可以在调用 enumerate 函数时传递一个参数,指定起始索引值。例如,将起始索引值设为 1,则可以使用以下代码:
score = [62, 89, 100, 92, 89, 75, 79, 84]
for index, element in enumerate(score, start=1):
print(f'Index: {index}, Element: {element}')
这段代码的输出结果如下:
Index: 1, Element: 62
Index: 2, Element: 89
Index: 3, Element: 100
Index: 4, Element: 92
Index: 5, Element: 89
Index: 6, Element: 75
Index: 7, Element: 79
Index: 8, Element: 84
除了使用 enumerate 函数之外,还可以使用下标(索引)来循环列表。
ChatGPT 的回答可谓非常惊艳,给出了答案和输出结果,并提供了 enumerate 指定起始索引值的知识点和使用这个方法的要点和注意事项,它给出的答案完全没有问题。
1.3 简单问题:Python 文本操作
问:使用 Jupyter notebook 在D盘根目录下创建一个“data.txt”文档,写入整数86,70,58,每个整数占一行。读取"data.txt"文件,并将其按升序排列,重新写入data.txt文件。
ChatGPT 答:
如果要在 Jupyter Notebook 中执行这个操作,可以执行以下步骤:
- 在 Jupyter Notebook 中打开一个新的代码单元,并导入必要的模块。例如:
import os
from pathlib import Path
- 在代码单元中,使用 os 模块的 chdir 函数将当前工作目录设为 D 盘的根目录。例如:
os.chdir('D:\\')
- 使用 Path 类的 open 方法以写入模式打开一个名为 data.txt 的文件。如果文件不存在,则会自动创建它。例如:
data_file = Path('data.txt').open('w')
- 使用 write 方法将整数 86、70、58 写入 data_file。注意,每个整数需要占一行。例如:
data_file.write('86\n')
data_file.write('70\n')
data_file.write('58\n')
- 使用 close 方法关闭 data_file。例如:
data_file.close()
- 使用 Path 类的 open 方法以读取模式打开名为 data.txt 的文件。例如:
data_file = Path('data.txt').open()
- 使用 readlines 方法读取 data_file 中的所有行,并将它们存储在一个名为 lines 的列表中。例如:
lines = data_file.readlines()
- 关闭 data_file。例如:
data_file.close()
- 使用列表的 sort 方法将 lines 按升序排列。例如:
lines.sort()
- 使用 Path 类的 open 方法以写入模式打开名为 data.txt 的文件。如果文件已存在,则会被覆盖。例如:
data_file = Path('data.txt').open('w')
- 使用 writelines 方法将排序后的行列表写入 data_file。例如:
data_file.writelines(lines)
- 关闭 data_file。例如:
data_file.close()
完整的代码示例如下:
import os
from pathlib import Path
# Change the working directory to D:\\
os.chdir('D:\\')
# Open data.txt in write mode and write the integers 86, 70, and 58 to it
data_file = Path('data.txt').open('w')
data_file.write('86\n')
data_file.write('70\n')
data_file.write('58\n')
data_file.close()
# Open data.txt in read mode and read all lines into a list
data_file = Path('data.txt').open()
lines = data_file.readlines()
data_file.close()
# Sort the list of lines in ascending order
lines.sort()
# Open data.txt in write mode and write the sorted lines to it
data_file = Path('data.txt').open('w')
data_file.writelines(lines)
data_file.close()
执行完上述步骤后,data.txt 文件中将会包含排序后的三个整数:58、70、86。
可以看出 ChatGPT 针对此问题的回答简直是保姆级手把手教学,一行一个注释直接分了十二个步骤,最后贴心的给出完整代码并告诉你执行后的结果。
更可怕的是,这完全是他自己学会的,而且听得懂我们的意图!
1.4 简单问题:获取某月有多少天
问:python 用input()获取用户输入的月份,输出该月有多少天,考虑闰年
ChatGPT 非常迅速的给出了回复,并最后提示:请注意,这仅是一个示例,实际情况可能会有所不同。如果您希望在实际项目中使用该代码,则需要根据实际情况进行修改和完善。
因为问题中有更详细的要求,我们继续:input不要添加额外提示,input输入年月类似这样2022,1
这次 ChatGPT 的输出只是偷懒处理输入,中间的处理它并没有重复一遍。但是,就算我们将之前的代码进行整合,也是有问题的,因为之前的代码输入的月份它是英文的。我们将条件合并再次提问:
python 用input()获取用户输入的月份,输出该月有多少天,考虑闰年,input不要添加额外提示,input输入年月用逗号隔开类似这样2022,1
这次的结果看起来,没什么问题了。我们继续引导它将注释换为中文。
这样还没有结束,题目中对它的输出并不满意,我们只需要天数。但是这个时候有一个细节,我继续提问时,打错了好几个字:“请继续修改上门的代码,在输入结果时我只需要天数即可”
ChatGPT 答:
如果您只需要输出天数,可以使用以下代码:
# 从用户输入中读取年份和月份
year, month = input().split(',')
# 将年份和月份转换为整数
year = int(year)
month = int(month)
# 检查年份是否为闰年
if year % 400 == 0 or (year % 4 == 0 and year % 100 != 0):
leap_year = True
else:
leap_year = False
# 检查月份是否有 31 天
if month in [1, 3, 5, 7, 8, 10, 12]:
num_days = 31
elif month == 2:
# 如果是闰年,则二月有 29 天,否则有 28 天
if leap_year:
num_days = 29
else:
num_days = 28
else:
num_days = 30
# 输出结果
print(num_days)
1.5 简单问题总结
经过这几天的试用并结合群友的交流,发现 ChatGPT 的针对简单编程问题的处理上可谓是非常惊艳,特别是对 Python 问题的解答上。它会比我们人类更有耐心,有时会画出重点并扩展更多的相关知识帮助你去解决问题掌握技术,由此来看 ChatGPT 无疑是非常棒的。
但是也有弊端,它对长文本的处理能力还是有限,太多的文本会让它抓不住主题,答非所问。需要我们简化问题,逐步深入,对其进行引导。
在上面的测试过程中,除了发现有些许小的水土不服外,没有什么大的问题。最让我震惊的是,最后一个问答中,我无意间的输入错误,它竟然也能正确的理解我的意图。我抱着试试看的态度,询问了它:
Q: 我上一个提问你是怎么理解我的意图的?
ChatGPT:上一个问题中,您说:python 用input()获取用户输入的月份,输出该月有多少天,考虑闰年,input不要添加额外提示,input输入年月用逗号隔开类似这样2022,1
我通过阅读您的问题,理解到您希望用 input 函数读取用户输入的年份和月份,然后计算出该月份有多少天,并考虑闰年的情况。您还提到,在调用 input 函数时,不需要添加额外的提示,并且用户输入的年份和月份是用逗号隔开的。所以我回答了您的问题,并且提供了一段代码示例。
Q:你是怎么理解我之后对你提出的额外要求?
ChatGPT:您随后提出了额外的要求,说:请继续修改上门的代码,在输入结果时我只需要天数即可
我通过阅读您的要求,理解到您希望对我之前提供的代码进行修改,以便只输出天数。所以我又提供了一段新的代码示例,来满足您的需求。
他我已经不敢称为“它”了,这理解力堪称满分,真的是大智若妖。我甚至迫不及待想听听他对我的评价:
好吧,我一直都承认他是一个非常优秀的客服,极力解释并再次回避了我评价的要求。
2. 复杂问题
因为 ChatGPT 也在不断的被优化和调教,每次获得的答案也会不一致。另外,复杂问题的论证也需要更多的精力,这里我只展示几个我认为有代表性的问题。
2.1 复杂问题:TS 写一个md转html的类
问:帮我写用TS写一个md转html的类
这个问题他给我写个了个 TODO ???,然后告诉我:
在这个类中,我们定义了一个 MarkdownToHtmlConverter 类,它有一个构造函数,用于接收一个 Markdown 文本,并将它保存到类的私有成员 markdown 中。
在这个类中,我们还定义了一个 convert 方法,用于将 markdown 文本转换成 HTML 文本。在这个方法中,我们可以使用 Markdown 转换库(比如 marked)来实现转换逻辑。
所以他是回答了还是没有回答呢?我还不能说他做错了。在我告诉他我不想使用第三方库后,他的回答似乎像那么回事了:
但是触发了长文本截断机制,在代码中截断的话,基本就没办法续上了。
2.2 复杂问题:用代码绘制一个足球
这个问题其实是 CSDN 征文的一个问题,我近期准备做来着。我们先来看看 ChatGPT 的水平如何:
这里我们并没有限制他使用的语言,第一次他使用 JS:
我将其在 HTML 中整理测试,其结果如下:
可以看到他并没有实现我们的要求,画了伞骨架样子的东西。当我再次重试时,他使用 Python 输入了一段代码:
这段代码似乎看上去就不是那么靠谱,我们来运行一下:
很显然关于这个问题 ChatGPT 无能为力。
2.3 复杂问题:ROS 机器人绘制图形
问题是关于 ROS 机器人系统,说简单也简单,是让小海龟绘制一个 PWM 方波,大概效果如下:
首先我们提问:ROS里面怎么用C++让海龟画类似于PWM方波?
ChatGPT 给出的答案因为是不正确的,这里直接放截图:
这个回答不仅告诉自己去看教程,还捏造了一个类出来,难道是要让我自己写这个类?
更有意思的是,当我们使用英文再次提问时:How to use C++ in ROS to make the turtle draw similar to PWM square wave ?
他不仅写的看起来靠谱了,还洋洋洒洒,从创建包到运行的步骤都有:
似乎他的回答非常有用,调整ROS小乌龟的位置,更改了画笔颜色,但是核心的移动小乌龟的代码处出现了截断,无法显示,第五步和第六步与之前的运动处理冲突,其他步骤代码倒是问题不大,但是总体来说缺少了核心代码还是回答了个寂寞。
但是当今天我再次询问他时,他变得格外谨慎起来:
ChatGPT 答:
在 ROS 中,您可以使用 C++ 编写一个节点来控制海龟绘图程序。具体来说,您需要完成以下步骤:
- 在 ROS 中创建一个 C++ 节点。
- 在节点中创建一个 PWM 波形,具体方法可以参考 PWM 的相关文档。
- 在节点中调用海龟绘图程序,并将 PWM 波形作为参数传递给海龟绘图程序。
- 在节点中调用海龟绘图程序,让海龟根据 PWM 波形绘制图形。
在完成以上步骤后,您就可以使用 ROS 实现海龟画 PWM 波形的功能。具体实现方法可能会因您使用的 ROS 版本和开发环境而有所不同,建议您参考 ROS 官方文档和相关教程来获取更多信息。
并且在我细化了版本和环境之后,他的回答也并不能令人满意,并一直强调版本问题。
2.4 复杂问题总结
以上来看,ChatGPT 在处理复杂问题上成功率非常低,甚至会出现捏造的情况。并且在大多数情况下,提问者的问题披露往往不完全,需要有经验的人去追问以获取更多的有效信息来进行正确的解答。
但 ChatGPT 针对复杂问题并不是完全没有帮助,他往往可以凭借自己庞大的知识库提供一些解题的有用线索和方向。同时我们也可以尝试分解复杂的问题,逐步递进的问话方式来得到自己想要的答案。
当然在上面的测试中我们可以发现,ChatGPT 的上下文联想和纠错能力非常棒,你甚至怀疑和你对话的是一个人类,要不对面的服务器就是一个个缸中培养的大脑。
这个是我让他帮我润色本文摘要的一段对话截图,前面我一直在测试他关于 ROS 的知识,大家可感受一下 ChatGPT 是有多厉害。
使用 ChatGPT 问答的要点
上面我们已经介绍了一些使用 ChatGPT 的要点,那么结合 ChatGPT 自己说的我们总结如下:
- 拆分复杂的问题,让问题具体化,逐步深入的对其进行引导。
- 给出尽可能详细的信息,包括问题的背景,使用的语言、框架、环境等。
- 可以在问题中提供一些示例代码,这样 ChatGPT 就可以更好地理解问题,并给出更为准确的回答。
- 注意 ChatGPT 知识库的截止日期,提问的问题是在该截止时间之后的,那么 ChatGPT 可能无法回答。
另外根据 ChatGPT 在明白我在测试他后的回复,在这里代他再次自我介绍:
ChatGPT 是一个大型语言模型,由 OpenAI 训练而成,具有高度的语言理解能力,可以用来解决各种语言问题。它的主要优势在于可以根据上下文环境进行自然的对话,并且能够提供准确、丰富的回答。尽管 ChatGPT 的性能非常出色,但是它也存在一些局限性。首先,它是一个语言模型,并不具备编程能力,所以它无法直接解决编程问题。其次,它是一个自然语言处理模型,只能理解和回答。
最后
因为每次给出的结果会不一致,并且 ChatGPT 会不断的学习进化,以上的测试仅针对当时的回答情况,当然样本数也肯定是不足的,本文的关键仅供大家参考。
另外,如你使用 ChatGPT 进行辅助问答,请确保你熟悉你要回答的问题的领域,对 ChatGPT 答案进行仔细的甄别和考证,并对生成的代码进行实际的运行和确认,对提问者和自己负责。
所以我还是不建议没有编程经验的人直接使用 ChatGPT 来解答编程上的问题,他的答案看似完美,却无法保证一定正确。我们希望有一个拥有一定权威的教授,而不是一个搜索捏造“真实答案”的工具。虽然 ChatGPT 在不断的被技术人员修正调教,但是现阶段以此来看,Stack Overflow 对其封禁是有道理的。但是相信以后还是会被接纳和作为参考,毕竟等待一个问题的答案也是一个痛苦的折磨的过程。也许,就算它没有给出完美的答案,些许的参考和启发对我们也是有意义的。