写好提示词(序篇)
明确需求和要求,提供语境和上下文,结构化描述需求。
写好提示词
提示词之于AI,正如编程语言之于计算设备,甜言蜜语之于女人,像一种魔法。
使用好 AI,提示词是入门必修功课。长期写博客的人,天然具有一种优势,因为长久的训练写作,使得他们通常思路清晰有条理,更擅长表达和描述,也更容易写出好的提示词。
提示词有多重要?AI 未来绝对会超过 99.99999999999999999...%的人类。善驭AI者,如执上帝之手。提示词是通往AI之门的一把有效的初级钥匙。
做一件事,必然有其要点和要领。掌握好要点和要领,就会事半功倍。写好提示词的要点是:明确需求和要求,提供语境和上下文,结构化描述需求。
一个例子
现在给一个例子,说明不同的提示词对输出的结果影响。主要以 deepseek 为主。
提示词一:
写一个 python 程序,实现文件重命名功能。
import os
import sys
from pathlib import Path
def rename_files(directory, old_pattern, new_pattern):
"""
重命名指定目录下的文件
Args:
directory (str): 目录路径
old_pattern (str): 旧文件名模式
new_pattern (str): 新文件名模式
"""
try:
# 将目录路径转换为Path对象
dir_path = Path(directory)
# 检查目录是否存在
if not dir_path.exists():
print(f"错误: 目录 {directory} 不存在")
return
# 遍历目录中的所有文件
for file_path in dir_path.glob(old_pattern):
if file_path.is_file():
# 构建新文件名
new_name = file_path.name.replace(old_pattern, new_pattern)
new_path = file_path.parent / new_name
try:
# 重命名文件
file_path.rename(new_path)
print(f"已重命名: {file_path.name} -> {new_name}")
except Exception as e:
print(f"重命名文件 {file_path.name} 时出错: {e}")
except Exception as e:
print(f"处理过程中出错: {e}")
def main():
if len(sys.argv) != 4:
print("用法: python rename_files.py <目录路径> <旧文件名模式> <新文件名模式>")
print("示例: python rename_files.py ./files *.txt *.md")
return
directory = sys.argv[1]
old_pattern = sys.argv[2]
new_pattern = sys.argv[3]
rename_files(directory, old_pattern, new_pattern)
if __name__ == "__main__":
main()
你看,实现的功能是你想要的吗?这个提示词的问题就是需求不明确。就像对AI说:我想要一辆汽车。AI 会天马行空,给你一辆看上去是汽车的车,可能只是四轮驱动车。
这样的提示词,给不同的 AI,就会有迥异的结果。不信,你用 deepseek, chatgpt3, claude3.5,通义千问等去试试。千奇百怪。
提示词二:
写一个 python 程序,实现文件重命名功能。要求对指定目录的所有文件进行重新编号,前缀是 image_,后面一个五位的数字,是从 1 开始计数。扩展名不变。不同的扩展名分别计数。比如 sdkfjsal.png, wierwsdfs.jpg, wioeijq.png,sdkfssldkkf.jpg 会变成 image_00001.png, image_00002.png, image_00001.jpg, image_00002.jpg。
import os
from collections import defaultdict
def rename_files_with_numbering(directory):
"""
对指定目录的文件按扩展名分别重新编号
格式: image_XXXXX.ext (XXXXX是从1开始的五位数编号)
"""
if not os.path.isdir(directory):
print(f"错误: 目录 '{directory}' 不存在!")
return
# 按扩展名分组文件
ext_groups = defaultdict(list)
# 获取目录中的所有文件
for filename in os.listdir(directory):
filepath = os.path.join(directory, filename)
if os.path.isfile(filepath):
name, ext = os.path.splitext(filename)
ext = ext.lower() # 统一小写处理扩展名
ext_groups[ext].append(filepath)
# 对每种扩展名的文件分别进行编号重命名
for ext, files in ext_groups.items():
# 按文件名排序,确保每次运行结果一致
files.sort()
# 为每个文件生成新名称
for i, old_path in enumerate(files, 1):
# 生成五位数的编号
number = f"{i:05d}"
new_filename = f"image_{number}{ext}"
new_path = os.path.join(directory, new_filename)
# 避免名称冲突
if os.path.exists(new_path):
print(f"警告: 文件 {new_filename} 已存在,跳过重命名 {old_path}")
continue
try:
os.rename(old_path, new_path)
print(f"重命名: {os.path.basename(old_path)} -> {new_filename}")
except Exception as e:
print(f"错误: 无法重命名 {old_path}: {e}")
if __name__ == "__main__":
print("文件重命名工具 - 按扩展名编号")
print("格式: image_XXXXX.ext (XXXXX是从1开始的五位数编号)")
print("=" * 50)
# 获取用户输入的目录路径
directory = input("请输入要处理的目录路径: ").strip()
# 确认操作
confirm = input(f"将对目录 '{directory}' 中的所有文件进行重命名,继续吗? (y/n): ")
if confirm.lower() == 'y':
rename_files_with_numbering(directory)
print("操作完成!")
else:
print("操作已取消。")
执行:

嗯,这个程序实现了基本功能,但还不是我想要的。因为通常场景都希望是自动化的,而不需要人工参与。而且,它的实现写死了前缀 image_,不够灵活,如果我希望指定文件目录,使用不同前缀呢 ?
提示词三:
写一个 python 程序,实现文件重命名功能。要求对指定目录的所有文件进行重新编号,前缀是指定的前缀,后面一个五位的数字,是从 1 开始计数。扩展名不变。不同的扩展名分别计数。比如 sdkfjsal.png, wierwsdfs.jpg, wioeijq.png,sdkfssldkkf.jpg 会变成 image_00001.png, image_00002.png, image_00001.jpg, image_00002.jpg。要求使用命令行选项模式。
python rename_files.py -d directory -p prefix .
将指定路径 directory 下的所有文件按照上述方式进行指定前缀 prefix 进行编号。
import os
import argparse
from collections import defaultdict
def rename_files(directory, prefix):
"""
对指定目录的文件按扩展名分别重新编号
格式: prefix_XXXXX.ext (XXXXX是从1开始的五位数编号)
"""
if not os.path.isdir(directory):
print(f"错误: 目录 '{directory}' 不存在!")
return False
# 按扩展名分组文件
ext_groups = defaultdict(list)
# 获取目录中的所有文件
for filename in os.listdir(directory):
filepath = os.path.join(directory, filename)
if os.path.isfile(filepath):
name, ext = os.path.splitext(filename)
ext = ext.lower() # 统一小写处理扩展名
ext_groups[ext].append(filepath)
# 对每种扩展名的文件分别进行编号重命名
success_count = 0
for ext, files in ext_groups.items():
# 按文件名排序,确保每次运行结果一致
files.sort()
# 为每个文件生成新名称
for i, old_path in enumerate(files, 1):
# 生成五位数的编号
number = f"{i:05d}"
new_filename = f"{prefix}_{number}{ext}"
new_path = os.path.join(directory, new_filename)
# 避免名称冲突
if os.path.exists(new_path):
print(f"警告: 文件 {new_filename} 已存在,跳过重命名 {old_path}")
continue
try:
os.rename(old_path, new_path)
print(f"重命名: {os.path.basename(old_path)} -> {new_filename}")
success_count += 1
except Exception as e:
print(f"错误: 无法重命名 {old_path}: {e}")
return success_count > 0
def main():
# 设置命令行参数解析
parser = argparse.ArgumentParser(description='文件重命名工具 - 按扩展名编号')
parser.add_argument('-d', '--directory', required=True,
help='要处理的目录路径')
parser.add_argument('-p', '--prefix', required=True,
help='文件名前缀')
args = parser.parse_args()
print("文件重命名工具 - 按扩展名编号")
print(f"目录: {args.directory}")
print(f"前缀: {args.prefix}")
print(f"格式: {args.prefix}_XXXXX.ext (XXXXX是从1开始的五位数编号)")
print("=" * 50)
# 确认操作
confirm = input(f"将对目录 '{args.directory}' 中的所有文件进行重命名,继续吗? (y/n): ")
if confirm.lower() == 'y':
if rename_files(args.directory, args.prefix):
print("操作成功完成!")
else:
print("操作完成,但可能存在问题。请检查输出信息。")
else:
print("操作已取消。")
if __name__ == "__main__":
main()
执行:

现在距离我的预期更近了。不过程序还是比较原始,就像刚入门的编程新手写的。咱们给它加点要求:
提示词四:
写一个 python 程序,实现文件重命名功能。要求对指定目录的所有文件进行重新编号,前缀是指定的前缀,后面一个五位的数字,是从 1 开始计数。扩展名不变。不同的扩展名分别计数。比如 sdkfjsal.png, wierwsdfs.jpg, wioeijq.png,sdkfssldkkf.jpg 会变成 image_00001.png, image_00002.png, image_00001.jpg, image_00002.jpg。要求使用命令行选项模式。
python rename_files.py -d directory -p prefix .
将指定路径 directory 下的所有文件按照上述方式进行指定前缀 prefix 进行编号。
要求:程序模块化更可读可修改,加入错误处理保持健壮性,提取可复用函数。
#!/usr/bin/env python3
"""
文件重命名工具 - 按扩展名分组编号
功能:
1. 对指定目录的文件按扩展名分别重新编号
2. 格式: prefix_XXXXX.ext (XXXXX是从1开始的五位数编号)
3. 支持命令行参数
4. 模块化设计,易于维护和扩展
"""
import os
import argparse
from collections import defaultdict
import logging
from typing import List, Dict, Tuple
# 配置日志格式
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
handlers=[
logging.StreamHandler()
]
)
logger = logging.getLogger(__name__)
def validate_directory(directory: str) -> bool:
"""验证目录是否存在且可访问"""
if not os.path.exists(directory):
logger.error(f"目录不存在: {directory}")
return False
if not os.path.isdir(directory):
logger.error(f"路径不是目录: {directory}")
return False
if not os.access(directory, os.R_OK | os.W_OK):
logger.error(f"目录不可读写: {directory}")
return False
return True
def group_files_by_extension(directory: str) -> Dict[str, List[str]]:
"""
按扩展名分组目录中的文件
:param directory: 要扫描的目录路径
:return: 字典 {扩展名: [文件路径列表]}
"""
ext_groups = defaultdict(list)
try:
for filename in os.listdir(directory):
filepath = os.path.join(directory, filename)
if os.path.isfile(filepath):
_, ext = os.path.splitext(filename)
ext = ext.lower() # 统一小写处理扩展名
ext_groups[ext].append(filepath)
except Exception as e:
logger.error(f"扫描目录时出错: {e}")
raise
return ext_groups
def generate_new_filename(prefix: str, index: int, extension: str) -> str:
"""
生成新的文件名
:param prefix: 文件前缀
:param index: 文件序号
:param extension: 文件扩展名
:return: 新文件名 (格式: prefix_XXXXX.ext)
"""
return f"{prefix}_{index:05d}{extension}"
def rename_files_in_group(
files: List[str],
directory: str,
prefix: str,
extension: str
) -> Tuple[int, int]:
"""
重命名一组文件(相同扩展名)
:param files: 文件路径列表
:param directory: 目录路径
:param prefix: 文件前缀
:param extension: 文件扩展名
:return: (成功数, 失败数)
"""
success = 0
failure = 0
# 按文件名排序确保一致性
files.sort()
for index, old_path in enumerate(files, 1):
try:
new_filename = generate_new_filename(prefix, index, extension)
new_path = os.path.join(directory, new_filename)
if os.path.exists(new_path):
logger.warning(f"目标文件已存在,跳过: {new_path}")
failure += 1
continue
os.rename(old_path, new_path)
logger.info(f"重命名: {os.path.basename(old_path)} -> {new_filename}")
success += 1
except Exception as e:
logger.error(f"重命名失败 {old_path}: {e}")
failure += 1
return success, failure
def rename_files_with_numbering(directory: str, prefix: str) -> bool:
"""
主重命名函数
:param directory: 要处理的目录
:param prefix: 文件名前缀
:return: 是否全部成功
"""
if not validate_directory(directory):
return False
try:
ext_groups = group_files_by_extension(directory)
if not ext_groups:
logger.warning(f"目录中没有可处理的文件: {directory}")
return True
total_success = 0
total_failure = 0
logger.info(f"开始处理目录: {directory}")
logger.info(f"找到 {len(ext_groups)} 种扩展名的文件")
for ext, files in ext_groups.items():
logger.info(f"处理 {ext} 扩展名的 {len(files)} 个文件...")
success, failure = rename_files_in_group(files, directory, prefix, ext)
total_success += success
total_failure += failure
logger.info(f"操作完成. 成功: {total_success}, 失败: {total_failure}")
return total_failure == 0
except Exception as e:
logger.error(f"处理过程中发生错误: {e}")
return False
def parse_arguments():
"""解析命令行参数"""
parser = argparse.ArgumentParser(
description='文件重命名工具 - 按扩展名分组编号',
formatter_class=argparse.ArgumentDefaultsHelpFormatter
)
parser.add_argument(
'-d', '--directory',
required=True,
help='要处理的目录路径'
)
parser.add_argument(
'-p', '--prefix',
required=True,
help='文件名前缀'
)
parser.add_argument(
'--dry-run',
action='store_true',
help='试运行,不实际重命名文件'
)
parser.add_argument(
'--log-level',
default='INFO',
choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'],
help='日志级别'
)
return parser.parse_args()
def main():
"""主函数"""
args = parse_arguments()
logger.setLevel(args.log_level)
logger.info("文件重命名工具启动")
logger.info(f"目录: {args.directory}")
logger.info(f"前缀: {args.prefix}")
if args.dry_run:
logger.info("试运行模式,不会实际修改文件")
# 在实际应用中可以实现dry-run逻辑
# 这里简化为只扫描和显示计划
try:
ext_groups = group_files_by_extension(args.directory)
for ext, files in ext_groups.items():
files.sort()
for i, f in enumerate(files, 1):
new_name = generate_new_filename(args.prefix, i, ext)
logger.info(f"[DRY RUN] 将重命名: {os.path.basename(f)} -> {new_name}")
except Exception as e:
logger.error(f"试运行失败: {e}")
return
else:
if not rename_files_with_numbering(args.directory, args.prefix):
logger.error("处理过程中出现错误,请检查日志")
return
logger.info("操作完成")
if __name__ == "__main__"?
try:
main()
except KeyboardInterrupt:
logger.info("操作被用户中断")
except Exception as e:
logger.exception(f"程序发生未预期错误: {e}")
可以看到,这个程序更长了,但是更可读了,容易对其中一部分进行修改。
你还可提出一点不满。
提示词五:
这里的几个方法比如 validate_directory,rename_files_in_group, rename_files_with_numbering,group_files_by_extension 都依赖外部文件系统,不好写单测。能否将访问外部文件系统的部分与其它部分隔离,能更好编写单测?
file_system.py
# file_system.py
import os
from abc import ABC, abstractmethod
from typing import List, Dict, Tuple
class FileSystemProvider(ABC):
"""抽象文件系统接口,便于测试"""
@abstractmethod
def path_exists(self, path: str) -> bool:
pass
@abstractmethod
def is_dir(self, path: str) -> bool:
pass
@abstractmethod
def is_file(self, path: str) -> bool:
pass
@abstractmethod
def list_dir(self, directory: str) -> List[str]:
pass
@abstractmethod
def join_path(self, *parts: str) -> str:
pass
@abstractmethod
def rename_file(self, src: str, dst: str) -> None:
pass
@abstractmethod
def path_basename(self, path: str) -> str:
pass
@abstractmethod
def path_splitext(self, path: str) -> Tuple[str, str]:
pass
@abstractmethod
def path_exists(self, path: str) -> bool:
pass
class OSFileSystemProvider(FileSystemProvider):
"""实际文件系统实现"""
def path_exists(self, path: str) -> bool:
return os.path.exists(path)
def is_dir(self, path: str) -> bool:
return os.path.isdir(path)
def is_file(self, path: str) -> bool:
return os.path.isfile(path)
def list_dir(self, directory: str) -> List[str]:
return os.listdir(directory)
def join_path(self, *parts: str) -> str:
return os.path.join(*parts)
def rename_file(self, src: str, dst: str) -> None:
os.rename(src, dst)
def path_basename(self, path: str) -> str:
return os.path.basename(path)
def path_splitext(self, path: str) -> Tuple[str, str]:
return os.path.splitext(path)
def path_exists(self, path: str) -> bool:
return os.path.exists(path)
renamer.py
# renamer.py
from collections import defaultdict
from typing import List, Dict, Tuple, Optional
from file_system import FileSystemProvider
class FileRenamer:
"""文件重命名核心逻辑"""
def __init__(self, fs_provider: FileSystemProvider):
self.fs = fs_provider
def validate_directory(self, directory: str) -> bool:
"""验证目录是否存在且可访问"""
if not self.fs.path_exists(directory):
return False
if not self.fs.is_dir(directory):
return False
return True
def group_files_by_extension(self, directory: str) -> Dict[str, List[str]]:
"""
按扩展名分组目录中的文件
:return: 字典 {扩展名: [文件路径列表]}
"""
ext_groups = defaultdict(list)
for filename in self.fs.list_dir(directory):
filepath = self.fs.join_path(directory, filename)
if self.fs.is_file(filepath):
_, ext = self.fs.path_splitext(filename)
ext = ext.lower() # 统一小写处理扩展名
ext_groups[ext].append(filepath)
return ext_groups
@staticmethod
def generate_new_filename(prefix: str, index: int, extension: str) -> str:
"""生成新的文件名"""
return f"{prefix}_{index:05d}{extension}"
def rename_files_in_group(
self,
files: List[str],
directory: str,
prefix: str,
extension: str
) -> Tuple[int, int]:
"""
重命名一组文件(相同扩展名)
:return: (成功数, 失败数)
"""
success = 0
failure = 0
files.sort() # 按文件名排序确保一致性
for index, old_path in enumerate(files, 1):
new_filename = self.generate_new_filename(prefix, index, extension)
new_path = self.fs.join_path(directory, new_filename)
if self.fs.path_exists(new_path):
failure += 1
continue
try:
self.fs.rename_file(old_path, new_path)
success += 1
except Exception:
failure += 1
return success, failure
def rename_files_with_numbering(
self,
directory: str,
prefix: str,
dry_run: bool = False
) -> Tuple[bool, Dict[str, List[Tuple[str, str]]]]:
"""
主重命名函数
:return: (是否成功, 重命名计划 {扩展名: [(旧名, 新名)]})
"""
if not self.validate_directory(directory):
return False, {}
ext_groups = self.group_files_by_extension(directory)
if not ext_groups:
return True, {}
rename_plan = defaultdict(list)
total_success = 0
total_failure = 0
for ext, files in ext_groups.items():
files.sort()
for index, old_path in enumerate(files, 1):
new_filename = self.generate_new_filename(prefix, index, ext)
rename_plan[ext].append(
(self.fs.path_basename(old_path), new_filename)
)
if not dry_run:
new_path = self.fs.join_path(directory, new_filename)
if not self.fs.path_exists(new_path):
try:
self.fs.rename_file(old_path, new_path)
total_success += 1
except Exception:
total_failure += 1
success = total_failure == 0 or dry_run
return success, rename_plan
cli.py
# cli.py
import argparse
import logging
from file_system import OSFileSystemProvider
from renamer import FileRenamer
logger = logging.getLogger(__name__)
def setup_logging(log_level: str = "INFO"):
logging.basicConfig(
level=log_level,
format='%(asctime)s - %(levelname)s - %(message)s',
handlers=[logging.StreamHandler()]
)
def parse_arguments():
parser = argparse.ArgumentParser(
description='文件重命名工具 - 按扩展名分组编号',
formatter_class=argparse.ArgumentDefaultsHelpFormatter
)
parser.add_argument('-d', '--directory', required=True, help='要处理的目录路径')
parser.add_argument('-p', '--prefix', required=True, help='文件名前缀')
parser.add_argument('--dry-run', action='store_true', help='试运行,不实际重命名文件')
parser.add_argument('--log-level', default='INFO',
choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'],
help='日志级别')
return parser.parse_args()
def main():
args = parse_arguments()
setup_logging(args.log_level)
fs_provider = OSFileSystemProvider()
renamer = FileRenamer(fs_provider)
logger.info(f"开始处理目录: {args.directory}")
success, rename_plan = renamer.rename_files_with_numbering(
args.directory,
args.prefix,
args.dry_run
)
if args.dry_run:
logger.info("试运行结果:")
for ext, renames in rename_plan.items():
logger.info(f"扩展名 {ext}:")
for old_name, new_name in renames:
logger.info(f" {old_name} -> {new_name}")
else:
if success:
logger.info("文件重命名完成")
else:
logger.error("处理过程中出现错误")
if __name__ == "__main__":
try:
main()
except KeyboardInterrupt:
logger.info("操作被用户中断")
except Exception as e:
logger.exception(f"程序发生未预期错误")
测试用例
# test_renamer.py
import unittest
from unittest.mock import MagicMock
from collections import defaultdict
from renamer import FileRenamer
class MockFileSystemProvider:
def __init__(self):
self.files = defaultdict(list)
self.dirs = set()
self.exists = set()
def path_exists(self, path):
return path in self.exists
def is_dir(self, path):
return path in self.dirs
def is_file(self, path):
return any(path in files for files in self.files.values())
def list_dir(self, directory):
return [f.split('/')[-1] for f in self.exists if f.startswith(directory)]
def join_path(self, *parts):
return '/'.join(parts)
def rename_file(self, src, dst):
if src not in self.exists:
raise FileNotFoundError
self.exists.remove(src)
self.exists.add(dst)
def path_basename(self, path):
return path.split('/')[-1]
def path_splitext(self, path):
name = self.path_basename(path)
if '.' in name:
return name.rsplit('.', 1)
return name, ''
class TestFileRenamer(unittest.TestCase):
def setUp(self):
self.fs = MockFileSystemProvider()
self.renamer = FileRenamer(self.fs)
# 设置测试目录结构
self.fs.dirs.add('/test')
self.fs.exists.add('/test')
self.fs.exists.add('/test/file1.jpg')
self.fs.exists.add('/test/file2.jpg')
self.fs.exists.add('/test/doc1.pdf')
self.fs.exists.add('/test/doc2.pdf')
def test_validate_directory(self):
self.assertTrue(self.renamer.validate_directory('/test'))
self.assertFalse(self.renamer.validate_directory('/nonexistent'))
def test_group_files_by_extension(self):
groups = self.renamer.group_files_by_extension('/test')
self.assertEqual(len(groups), 2)
self.assertEqual(len(groups['.jpg']), 2)
self.assertEqual(len(groups['.pdf']), 2)
def test_generate_new_filename(self):
name = self.renamer.generate_new_filename('img', 1, '.jpg')
self.assertEqual(name, 'img_00001.jpg')
def test_rename_files_in_group(self):
files = ['/test/file1.jpg', '/test/file2.jpg']
success, failure = self.renamer.rename_files_in_group(
files, '/test', 'img', '.jpg'
)
self.assertEqual(success, 2)
self.assertEqual(failure, 0)
def test_rename_files_with_numbering(self):
success, plan = self.renamer.rename_files_with_numbering(
'/test', 'img', dry_run=True
)
self.assertTrue(success)
self.assertEqual(len(plan), 2)
self.assertEqual(len(plan['.jpg']), 2)
self.assertEqual(len(plan['.pdf']), 2)
if __name__ == '__main__':
unittest.main()
至此,这段代码离生产环境级代码就更近了。
为啥新手写得都很简单,老程序员却写得“又臭又长”?臭倒未必,因为那是通往生产环境级代码的必经之路。清晰、健壮性、易测,是生产环境级代码的最起码要求。
AI 是遇强则强。你头脑里有丰富的开发经验,就可以发掘出AI更强大的能力。相反,如果你头脑贫乏,那么即使配上火箭筒AI,也是无济于事的,弄不好还会把自己搞残。
说来奇怪。以前写博文,讲如何写出良好质量的代码;现在写博文,写如何写出好的提示词。风向真变了。程序员越来越像上世纪四十年代的操作员了,离流水钱工人越来越近了。本文只是一个极为简单的例子,说明提示词确实是很重要的。但好的提示词,来源于专业开发经验的积累,并不是凭空而来的。
本文代码均由 AI 生成,请读者自行甄别。

浙公网安备 33010602011771号