과거 검색 엔진 사용법을 배우던 것처럼, 우리도 AI와 소통하는 방법, 즉 합리적이고 충분한 조건을 제시하여 필요한 답변을 효율적으로 얻는 방법을 배워야 합니다
만약 다른 각도에서 생각해 보면, 현재의 AI는 기억력이 아주 좋은 어린이에 해당합니다. 그는 눈에 보이는 것을 모두 외울 수 있고, 베끼기 능력이 있습니다. 우리가 해야 할 일은 AI와 어떻게 정확하고 효과적으로 소통하며, 요구사항을 정밀하게 묘사하여 AI가 예상되는 결과를 생성하도록 돕는 것입니다.
과학 대중화
AI라고 불리는, 정확히 말하면 Generative Pre-Training
은 직역하면 생성적 사전 훈련입니다. 이는 인터넷에서 사용 가능한 데이터로 학습된 텍스트 생성 심층 학습 모델이며, 질의 응답, 텍스트 요약 생성, 기계 번역, 분류, 코드 생성 및 대화형 AI와 같은 작업에 사용됩니다. 현재 GPT-1, GPT-2, GPT-3 및 GPT-4 등 다양한 버전의 모델이 있으며, 각 버전은 이전 버전에 비해 더 크고 강력합니다.
정말 인공지능이 있을까
- 유사도가 충분히 높으면 정확도 또한 높아집니다
- 기본적이고 반복적인 업무는 특정 훈련을 거치면 더 이상 인공의 개입이 필요하지 않다
생성형 AI는 기존의 텍스트, 오디오, 이미지 등 데이터를 활용하여 새로운 콘텐츠를 생성하는 기술입니다. 텍스트 생성, 음성 합성, 이미지 생성, 대화 시스템 등 다양한 작업에 사용될 수 있습니다. 생성형 AI의 논리성은 학습 데이터와 모델 구조에 따라 달라집니다. 일반적으로 생성형 AI는 문법, 논리 및 상식에 어느 정도 따르지만 오류, 편향 또는 부정확한 내용을 포함할 수도 있습니다. 따라서 생성형 AI의 출력은 인간의 판단과 검증이 필요하며 맹목적으로 믿거나 사용할 수 없습니다.
프롬프트 엔지니어
시간의 흐름은 거슬러갈 수 없고, 사람은 변화하는 흐름에 적응해야 합니다. AI가 똑똑하지 않다고 생각할 수도 있고, 논리성이 없다고 생각할 수도 있습니다. 코드를 작성해도 제대로 작동하지 않는 경우가 많습니다.
만약 다른 각도에서 생각해 보면, 현재의 AI는 기억력이 아주 좋은 어린이에 해당합니다. 그는 눈에 보이는 것을 모두 외울 수 있고, 베끼기 능력이 있습니다. 우리가 해야 할 일은 AI와 어떻게 정확하고 효과적으로 소통하며, 요구사항을 정밀하게 묘사하여 AI가 예상되는 결과를 생성하도록 돕는 것입니다.
대화 모드
2년 전 Github Copilot
이 출시되었을 때, 2년 후 OpenAI
가 갑자기 등장하여 인간의 인지 능력을 크게 확장시키는 대규모 언어 모델의 가능성을 보여줄 거라고는 아무도 예상하지 못했습니다
주석 기반 프로그래밍과 대화 기반 프로그래밍은 상호 작용 방식이 완전히 다르며, 대화의 패턴은 초보 사용자에게 친숙한 경험을 제공합니다. 여기서 NewBing
이 각 질문마다 제시하는 후속 질문 제안을 언급하지 않을 수 없는데, 이는 마이크로소프트가 사용자를 유도하여 AI 지식 데이터베이스에서 더 많은 정보를 얻으려고 시도하고 있는 것입니다.
예시로 말하자면
고속철도 여행 시간은 길고, 코딩이 좋은 선택이다. 데이터 사용량이 제한적인 상황에서 몇 장의 사진을 처리하고 이미지 자료를 얻었지만, 소프트웨어를 다운로드하여 사진을 처리하는 것은 조금 사치스럽고 네트워크 환경도 허락하지 않는다.
요구 사항은 다음과 같습니다. 투명 배경이 있는 이미지 자료가 여러 벌 있는데, 이것들을 앱의 내비게이션 바에 사용하려고 합니다. 선택된 상태는 컬러로, 선택되지 않은 상태는 흑백으로 하고, 원본 이미지는 모두 컬러입니다. 따라서 사전 처리 작업이 필요합니다.
폴더에서 모든 이미지를 읽어와서, 이미지를 흑백으로 변환하고 투명 배경을 유지하며, 이미지 저장 시 품질을 최적화하여 파일 크기를 줄이고, 콘솔에 최적화 전후 파일 크기 비교를 표시하는 파이썬 코드를 작성하세요
# 导入必要的库
import os
import PIL
from PIL import Image
# 定义一个函数,将图片转换成黑白,维持透明背景,保存图片,并返回文件体积
def convert_and_save(image_file):
# 打开图片
image = Image.open(image_file)
# 获取图片的模式,如果是 RGBA 模式,说明有透明背景
mode = image.mode
if mode == "RGBA":
# 创建一个和图片大小一致的白色背景图片
background = Image.new("RGB", image.size, (255, 255, 255))
# 将原图片粘贴到白色背景上,忽略透明像素
background.paste(image, mask=image.split()[3])
# 将合成的图片转换成灰度模式
gray_image = background.convert("L")
# 将灰度图片再转换成 RGBA 模式,以便保留透明背景
final_image = gray_image.convert("RGBA")
else:
# 如果不是 RGBA 模式,直接将图片转换成灰度模式
final_image = image.convert("L")
# 获取原图片的文件名和扩展名
file_name, file_ext = os.path.splitext(image_file)
# 定义新图片的文件名,添加 _bw 后缀表示黑白
new_file_name = file_name + "_bw" + file_ext
# 保存新图片,并优化质量,减少文件体积
final_image.save(new_file_name, optimize=True)
# 获取原图片和新图片的文件体积,并返回
old_size = os.path.getsize(image_file)
new_size = os.path.getsize(new_file_name)
return old_size, new_size
# 定义一个文件夹路径,存放所有的图片
folder_path = "images"
# 遍历文件夹中的所有文件
for file in os.listdir(folder_path):
# 拼接完整的文件路径
file_path = os.path.join(folder_path, file)
# 判断是否是图片文件,根据扩展名判断,可以根据需要添加或修改扩展名
if file_path.endswith((".png", ".jpg", ".jpeg", ".gif")):
# 调用函数,转换并保存图片,并获取文件体积
old_size, new_size = convert_and_save(file_path)
# 在控制台展示优化前后的文件体积大小对比
print(f"{file}: {old_size} bytes -> {new_size} bytes")
AI가 빠르게 답을 내놓았는데, 보기에 좋고 사용하기에도 괜찮은데, 경험이 많은 프로그래머라면 아래 코드가 충분히 일반적이지 않다고 느낄 것이고, 생산 환경에 적용하기도 어렵다고 생각할 것입니다
- 매개변수가 고정되었습니다
- 로그 파일이 없고, 정보는 모두 콘솔에 출력됩니다
- 이미지 처리는 다중 스레드 모델에 적합합니다
뉴빙이 등장하여 프롬프트에 따라 질문을 선택했습니다: 이 코드의 개선할 부분이 있나요?
제공된 답변은 솔직히 기대 이상이었고, 일반 프로그래머가 생각할 수 있는 최적화 방안에 대해 AI가 해당하는 제안을 제시했습니다
这段代码可能还有一些可以改进的地方,比如:
可以使用 argparse 库,让用户可以通过命令行参数指定文件夹路径和扩展名,而不是写死在代码里。
可以使用 logging 库,记录程序的运行情况,而不是直接打印到控制台。
可以使用 try-except 语句,捕获可能出现的异常,比如文件打开失败,图片转换失败等,并做相应的处理。
可以使用 multiprocessing 库,利用多核处理器,加速图片的转换和保存过程。
매우 친절한 응답입니다. 배포 환경의 차이를 고려하여 다중 프로세스를 지원하지 않아도 괜찮습니다.
当然,我很乐意帮你修改一下代码。我尝试添加了 argparse, logging 和 try-except 语句,但没有添加 multiprocessing 库,因为我不确定你的电脑是否支持多核处理。修改后的代码如下:
# 导入必要的库
import argparse
import logging
import multiprocessing
import os
from PIL import Image
# 定义一个函数,将图片转换成黑白,维持透明背景,保存图片,并返回文件体积
def convert_and_save(image_file):
# 打开图片
try:
image = Image.open(image_file)
except Exception as e:
logging.error(f"Failed to open {image_file}: {e}")
return None, None
# 获取图片的模式,如果是 RGBA 模式,说明有透明背景
mode = image.mode
if mode == "RGBA":
# 创建一个和图片大小一致的白色背景图片
background = Image.new("RGB", image.size, (255, 255, 255))
# 将原图片粘贴到白色背景上,忽略透明像素
background.paste(image, mask=image.split()[3])
# 将合成的图片转换成灰度模式
gray_image = background.convert("L")
# 将灰度图片再转换成 RGBA 模式,以便保留透明背景
final_image = gray_image.convert("RGBA")
else:
# 如果不是 RGBA 模式,直接将图片转换成灰度模式
final_image = image.convert("L")
# 获取原图片的文件名和扩展名
file_name, file_ext = os.path.splitext(image_file)
# 定义新图片的文件名,添加 _bw 后缀表示黑白
new_file_name = file_name + "_bw" + file_ext
# 保存新图片,并优化质量,减少文件体积
try:
final_image.save(new_file_name, optimize=True)
except Exception as e:
logging.error(f"Failed to save {new_file_name}: {e}")
return None, None
# 获取原图片和新图片的文件体积,并返回
old_size = os.path.getsize(image_file)
new_size = os.path.getsize(new_file_name)
return file_name, old_size, new_size
# 定义一个函数,解析命令行参数,并返回文件夹路径和扩展名列表
def parse_args():
# 创建一个解析器对象
parser = argparse.ArgumentParser(description="Convert images to black and white and optimize quality.")
# 添加一个必选的位置参数,表示文件夹路径
parser.add_argument("folder_path", help="The path of the folder that contains the images.")
# 添加一个可选的参数,表示扩展名列表,默认为 png, jpg, jpeg 和 gif
parser.add_argument("-e", "--extensions", nargs="+", default=[".png", ".jpg", ".jpeg", ".gif"], help="The extensions of the image files.")
# 解析命令行参数,并返回结果对象
args = parser.parse_args()
return args.folder_path, args.extensions
# 定义一个函数,打印优化前后的文件体积大小对比
def print_result(result):
# 如果结果不为空,说明转换和保存成功
if result:
# 解包结果为文件名和文件体积元组
if len(result) == 3:
file, old_size, new_size = result
# 在控制台展示优化前后的文件体积大小对比
logging.info(f"{file}: {old_size} bytes -> {new_size} bytes")
else:
logging.info(f"{result}")
# 配置日志记录器,将日志输出到控制台和文件中,设置日志等级为 INFO
logging.basicConfig(level=logging.INFO,
format="%(asctime)s %(levelname)s %(message)s",
handlers=[logging.StreamHandler(),
logging.FileHandler("log.txt")])
# 调用函数,获取文件夹路径和扩展名列表
folder_path, extensions = parse_args()
if __name__ == "__main__":
# Windows 需要这个函数的原因是 Windows 缺乏 fork() 函数(这不完全正确)。
# 因此,在 Windows 上,fork() 是通过创建一个新的进程来模拟的,这个新的进程中运行的代码,在 Linux 上是在子进程中运行的。
# 由于这些代码要在技术上无关的进程中运行,所以它必须在运行之前被传递到那里。
# 传递的方式是先将它们序列化,然后通过管道从原始进程发送到新的进程。
# 另外,这个新的进程被通知它必须运行通过管道传递的代码,通过向它传递 --multiprocessing-fork 命令行参数。
# 如果你看一下 freeze_support() 函数的实现,它的任务是检查它运行在哪个进程中,是否应该运行通过管道传递的代码
multiprocessing.freeze_support()
# 创建一个进程池,根据电脑的核心数自动分配进程
pool = multiprocessing.Pool()
# 创建一个空列表,用于存放异步任务的结果对象
results = []
# 遍历文件夹中的所有文件
for file in os.listdir(folder_path):
# 拼接完整的文件路径
file_path = os.path.join(folder_path, file)
# 判断是否是图片文件,根据扩展名判断,可以根据需要修改扩展名列表
if any(file_path.endswith(ext) for ext in extensions):
# 调用函数,转换并保存图片,并获取文件体积,使用异步方式,不阻塞主进程
result = pool.apply_async(convert_and_save, args=(file_path,), callback=print_result)
# 将结果对象添加到列表中
results.append((file, result))
# 关闭进程池,不再接受新的任务
pool.close()
# 等待所有的任务完成
pool.join()
사후기
로컬 개발 환경이 windows
시스템이기 때문에, AI
가 처음 제시한 답변에는 main
함수와 multiprocessing.freeze_support
가 포함되지 않았습니다. 질문을 통해 발생한 오류를 해결하여 코드를 수정했습니다.
과거 검색 엔진 사용법을 배우던 것처럼, AI와 소통하는 방법도 배워야 합니다. 합리적이고 충분한 조건을 제시하여 필요한 답변을 효율적으로 얻어야 합니다.
주의: 만약 여러분이 프로그래밍 초보이고 주어진 주석을 바탕으로도 이해가 안 되는 부분이 있다면 관련 코드에 대해 계속 질문해도 좋습니다.