谷歌第七版Prompt Engineering—提示技术(3)

16 阅读7分钟

Prompt Engineering

Author: Lee Boonstra

第二章提示技术的 Code prompting 小节

www.kaggle.com/whitepaper-…

github.com/Vocal-map/G…

本书主要是以Google自己的平台为主进行介绍,但将这些操作迁移到其他平台上可存在可行性。

Code prompting

LLM 主要专注于处理文本信息,这其中也包括生成代码

Prompts for writing code

LLM 不仅可以作为开发助手,还能用你熟悉的任何编程语言帮你编写代码。对开发者来说,这能显著加快编码的效率。

举个例子,假设你电脑上有一个包含数百个文件的文件夹,你需要重命名这些文件。手动一个个修改显然非常耗时。虽然你可以用自己掌握的 Bash 写个脚本来自动化处理,但这也需要花时间编写和调试。这个时候,不妨试试通过 prompt 让 LLM 来帮你完成这个任务。

Name1_bash_rename_files_in_folder
GoalWrite a prompt to write code in Bash to rename files in a folder.
Modelgemini-pro
Temperature0.1
Token Limit1024
Top-KN/A
Top-P1
Prompt请写一段 Bash 脚本,要求用户输入一个文件夹名称,接着脚本会遍历该文件夹中的所有文件,并在每个文件名的开头添加 “draft” 来批量重命名这些文件。
Output如下所示
#!/bin/bash

# Ask for the folder name
echo "Enter the folder name: "
read folder_name

# Check if the folder exists
if [ ! -d "$folder_name" ]; then
echo "Folder does not exist."
exit 1
fi

# Get the list of files in the folder
files=( "$folder_name"/* )

# Rename each file by prepending "draft" to the file name
for file in "${files[@]}"; do
new_file_name="draft_$(basename "$file")"
mv "$file" "$new_file_name"
done

echo "Files renamed successfully."

需要知道的是 LLM 并不能真正进行逻辑推理,它只是根据训练数据中的模式生成内容。因此,在使用之前,必须仔细阅读并测试所生成的代码

Prompts for explaining code

作为一名开发者,常常需要阅读并理解其他人写的代码。LLM 在这方面也能提供很大帮助。例如,可以以上面的代码为例,去掉里面的注释,然后让 LLM 来解释这段代码的功能和逻辑。具体的效果可以参考下表,它展示了模型对代码的解读结果。

Name1_bash_explain_the_code
GoalWrite a prompt to explain Bash code
Modelgemini-pro
Temperature0.1
Token Limit1024
Top-KN/A
Top-P1
Prompt如下所示
Output如下所示

Prompt

Explain to me the below Bash code:
bash
#!/bin/bash

echo "Enter the folder name: "
read folder_name

if [ ! -d "$folder_name" ]; then
echo "Folder does not exist."
exit 1
fi

files=( "$folder_name"/* )

for file in "${files[@]}"; do
new_file_name="draft_$(basename "$file")"
mv "$file" "$new_file_name"
done

echo "Files renamed successfully."

Output

这个 Bash 脚本执行以下任务:

  1. 用户输入
  • 脚本使用 echoread 命令提示用户输入一个文件夹名称。输入的文件夹名称会被存储在 folder_name 变量中。
  1. 文件夹存在性检查
  • 使用 [ ! -d "$folder_name" ] 条件检查是否存在指定名称的文件夹。如果文件夹不存在,脚本会显示错误信息Folder does not exist.,并以退出码 1 退出脚本。
  1. 文件列表
  • 使用 files=( "$folder_name"/* ) 命令列出指定文件夹中的所有文件。这会创建一个名为 files 的数组,其中包含文件夹中所有文件的路径。
  1. 文件重命名
  • 使用 for 循环遍历 files 数组中的每个文件。
  • 对于每个文件,它通过 new_file_name="draft_$(basename "$file")" 命令生成一个新的文件名。这个新文件名是将原文件名前加上字符串 "draft_" 组成的。
  • 然后使用 mv "$file" "$new_file_name" 命令对文件进行重命名,即将文件从原名称重命名为新名称。
  1. 成功消息
  • 在重命名所有文件后,脚本会显示一条成功消息Files renamed successfully.,表示重命名操作已成功完成。

Prompts for translating code

如果这个脚本能提示用户输入文件名,并且可以作为带有用户界面(UI)的独立应用程序来运行,它的实用性将会大大提高。从这一点出发,Python 会是构建应用程序时比 Bash 更合适的选择。LLM 同样可以帮助将代码从一种编程语言翻译或转换为另一种语言.

Name1_python_rename_files
GoalWrite a prompt to translate Bash code to Python
Modelgemini-pro
Temperature0.1
Token Limit1024
Top-KN/A
Top-P1
Prompt见下文
Output见下文

Prompt

Translate the below Bash code to a Python snippet.

#!/bin/bash

echo "Enter the folder name: "
read folder_name

if [ ! -d "$folder_name" ]; then
    echo "Folder does not exist."
    exit 1
fi

files=( "$folder_name"/* )

for file in "${files[@]}"; do
    new_file_name="draft_$(basename "$file")"
    mv "$file" "$new_file_name"
done

echo "Files renamed successfully."

Output

import os
import shutil

# Get the folder name from the user
folder_name = input("Enter the folder name: ")

# Check if the folder exists
if not os.path.isdir(folder_name):
    print("Folder does not exist.")
    exit(1)
# Get a list of all files in the folder
files = os.listdir(folder_name)

# Iterate over the files
for file in files:
    # Create a new file name with the prefix "draft_"
    new_file_name = f"draft_{file}"
    # Move the file to the new name
    shutil.move(os.path.join(folder_name, file), os.path.join(folder_name, new_file_name))

# Print a success message    
print("Files renamed successfully.")

阅读并审查代码。将提示生成的输出复制到一个新文件中:file_renamer.py。然后打开终端窗口,执行python file_renamer.py来测试代码:

Prompts for debugging and reviewing code

手动对代码进行一些修改。目标是让程序提示用户输入文件名前缀,并将该前缀以大写形式写入。

import os import shutil 
folder_name = input("Enter the folder name: ") 
prefix = input("Enter the string to prepend to the filename: ") 
text = toUpperCase(prefix) 
if not os.path.isdir(folder_name): 
    print("Folder does not exist.") 
    exit(1) 
files = os.listdir(folder_name) 
for file in files: 
    new_filename = f"{text}_{file}" 
shutil.move(os.path.join(folder_name, file), os.path.joi(folder_name, new_file_name)) 
print("Files renamed successfully.")

允许发现了BUG

The below Python code gives an error: 

Traceback (most recent call last): 
    File “/Users/leeboonstra/Documents/test_folder/rename_files.py”, line 7, in <module> 
    text = toUpperCase(prefix) 
NameError: name ‘toUpperCase’ is not defined

使用 LLM 帮助我们调试和审查代码。

Name1_python_debug_code
GoalWrite a prompt to debug and review Python code.
Modelgemini-pro
Temperature0.1
Token Limit1024
Top-KN/A
Top-P1
PromptThe below Python code gives an error:
Traceback (most recent call last):
File "/Users/leeboonstra/Documents/test_folder/rename_files.py", line 7, in <module>
text = toUpperCase(prefix)
NameError: name 'toUpperCase' is not defined

调试代码中的问题,并解释如何改进代码。

Prompt

import os
import shutil

# Get the folder name from the user
folder_name = input("Enter the folder name: ")
prefix = input("Enter the string to prepend to the filename: ")<br>text = toUpperCase(prefix

# Check if the folder exists
if not os.path.isdir(folder_name):
    print("Folder does not exist.")
    exit(1)
    
# Get a list of all files in the folder
files = os.listdir(folder_name)

# Iterate over the files
for file in files:
    # Create a new file name with the prefix "draft_"
    new_filename = f"{text}_{file}"
    # Move the file to the new name
    shutil.move(os.path.join(folder_name, file), os.path.join(folder_name, new_file_name))
    
    # Print a success message
    print("Files renamed successfully.")

Output

代码中调用了 toUpperCase 函数将 prefix 转换为大写,但该函数并未定义。要解决这个问题,可以使用字符串类自带的 upper() 方法,该方法可以将指定字符串转换为大写形式。修改后的代码如下所示:

import os
import shutil

# Get the folder name from the user
folder_name = input("Enter the folder name: ")
prefix = input("Enter the string to prepend to the filename: ")
text = prefix.upper()

# Check if the folder exists
if not os.path.isdir(folder_name):
    print("Folder does not exist.")
    exit(1)
    
# Get a list of all files in the folder
files = os.listdir(folder_name)

# Iterate over the files
for file in files:
    # Create a new file name with the prefix "draft_"
    new_filename = f"{text}_{file}"
    # Move the file to the new name
shutil.move(os.path.join(folder_name, file), os.path.join(folder_name, new_filename))
os.path.join(folder_name, new_filename))

# Print a success message
print("Files renamed successfully.")

此外,还可以对代码进行一些其他改进:

  1. 新文件名未保留原始文件的扩展名。建议从原文件名中提取扩展名,并将其添加到新文件名中。
  2. 代码假设文件夹名称中没有空格。但为了稳妥处理这种情况,最好将空格替换为下划线或连字符。
  3. 使用 f 字符串语法进行字符串插值比使用传统的 + 运算符更易读也更简洁。
  4. 代码没有处理重命名过程中可能出现的错误。更好的做法是将 shutil.move 调用放在 try...except 块中,以捕获任何潜在的异常。

以下是根据以上建议改进后的代码:

import os
import shutil

# Get the folder name from the user
folder_name = input("Enter the folder name: ")
prefix = input("Enter the string to prepend to the filename: ")

# Check if the folder exists
if not os.path.isdir(folder_name):
    print("Folder does not exist.")
    exit(1)
    
# Get a list of all files in the folder
files = os.listdir(folder_name)

# Iterate over the files
for file in files:
    # Get the file extension
    ext = os.path.splitext(file)[1]
    
    # Create a new file name with the prefix and the file extension
    new_filename = f"{prefix}_{os.path.splitext(file)[0]}{ext}"
    
    # Build the full paths for the original and new files
    old_path = os.path.join(folder_name, file)
    new_path = os.path.join(folder_name, new_filename)
    
    # Try to move the file
    try:
        shutil.move(old_path, new_path)
    except Exception as e:
        print(f"An error occurred while moving the file {file}: {e}")
        
# Print a success message
print("Files renamed successfully.")

这些改进使得代码更加健壮和灵活,同时也更容易阅读和理解。

What about multimodal prompting?

目前为止,提到的提示仍然使用的是普通的大语言模型。而多模态提示是一个独立但相关的概念,它指的是一种利用多种输入形式来引导模型的技术,而不仅仅依赖于文本。根据模型的能力和具体任务的不同,这些输入可以包括文本、图像、音频、代码,甚至其他格式的组合。

结语

上述有关代码生成的内容倒是没什么新东西,可能大家在写代码时就已经使用过了。故不多描述