anthropics/prompt-eng-interactive-tutorial 翻译
第5章:格式化输出和为Claude发言
设置
运行以下设置单元格以加载您的API密钥并建立get_completion
辅助函数。
!pip install anthropic
# 导入Python的内置正则表达式库
import re
import anthropic
# 从IPython存储中检索API_KEY和MODEL_NAME变量
%store -r API_KEY
%store -r MODEL_NAME
client = anthropic.Anthropic(api_key=API_KEY)
# 为预填充文本添加了新参数,默认值为空字符串
def get_completion(prompt: str, system_prompt="", prefill=""):
message = client.messages.create(
model=MODEL_NAME,
max_tokens=2000,
temperature=0.0,
system=system_prompt,
messages=[
{"role": "user", "content": prompt},
{"role": "assistant", "content": prefill}
]
)
return message.content[0].text
课程
Claude 可以以各种方式格式化其输出。您只需要求它这样做!
其中一种方式是使用XML标签将响应与其他多余文本分开。您已经了解到,可以使用XML标签使您的提示更清晰、更易于Claude解析。事实证明,您也可以要求Claude使用XML标签使其输出更清晰、更易于人类理解。
示例
还记得我们在第2章中通过要求Claude完全跳过前言来解决的“诗歌前言问题”吗?事实证明,我们也可以通过告诉Claude将诗歌放入XML标签中来实现类似的结果。
# 变量内容
ANIMAL = "Rabbit"
# 带有变量内容占位符的提示模板
PROMPT = f"请写一首关于{ANIMAL}的俳句。将它放入<haiku>标签中。"
# 打印Claude的响应
print("--------------------------- 带有变量替换的完整提示 ---------------------------")
print(PROMPT)
print("\n------------------------------------- Claude的响应 -------------------------------------")
print(get_completion(PROMPT))
为什么我们要这样做?嗯,将输出放入XML标签中允许最终用户通过编写一个短程序来可靠地获取诗歌且仅获取诗歌,该程序提取XML标签之间的内容。
这种技术的扩展是将第一个XML标签放入assistant
回合中。当您将文本放入assistant
回合中时,您基本上是在告诉Claude,Claude已经说过些什么,它应该从那个点继续。这项技术称为“为Claude发言”或“预填充Claude的响应”。
下面,我们用第一个<haiku>
XML标签做了这件事。注意Claude是如何从我们停止的地方直接继续的。
# 变量内容
ANIMAL = "Cat"
# 带有变量内容占位符的提示模板
PROMPT = f"请写一首关于{ANIMAL}的俳句。将它放入<haiku>标签中。"
# Claude响应的预填充
PREFILL = "<haiku>"
# 打印Claude的响应
print("--------------------------- 带有变量替换的完整提示 ---------------------------")
print("用户回合:")
print(PROMPT)
print("\n助手回合:")
print(PREFILL)
print("\n------------------------------------- Claude的响应 -------------------------------------")
print(get_completion(PROMPT, prefill=PREFILL))
Claude还擅长使用其他输出格式样式,特别是JSON
。如果您想强制JSON输出(不是确定性的,但接近),您也可以用开头括号{
预填充Claude的响应。
# 变量内容
ANIMAL = "Cat"
# 带有变量内容占位符的提示模板
PROMPT = f"请写一首关于{ANIMAL}的俳句。使用JSON格式,键为\"first_line\"、\"second_line\"和\"third_line\"。"
# Claude响应的预填充
PREFILL = "{"
# 打印Claude的响应
print("--------------------------- 带有变量替换的完整提示 ---------------------------")
print("用户回合")
print(PROMPT)
print("\n助手回合")
print(PREFILL)
print("\n------------------------------------- Claude的响应 -------------------------------------")
print(get_completion(PROMPT, prefill=PREFILL))
下面是一个同一提示中的多个输入变量和输出格式规范的示例,全都使用XML标签完成。
# 第一个输入变量
EMAIL = "Hi Zack, just pinging you for a quick update on that prompt you were supposed to write."
# 第二个输入变量
ADJECTIVE = "olde english"
# 带有变量内容占位符的提示模板
PROMPT = f"嘿Claude。这是电子邮件:<email>{EMAIL}</email>。使这封电子邮件更{ADJECTIVE}。将新版本写入<{ADJECTIVE}_email> XML标签中。"
# Claude响应的预填充(现在作为带有变量的f字符串)
PREFILL = f"<{ADJECTIVE}_email>"
# 打印Claude的响应
print("--------------------------- 带有变量替换的完整提示 ---------------------------")
print("用户回合")
print(PROMPT)
print("\n助手回合")
print(PREFILL)
print("\n------------------------------------- Claude的响应 -------------------------------------")
print(get_completion(PROMPT, prefill=PREFILL))
额外课程
如果您通过API调用Claude,您可以将结束XML标签传递给stop_sequences
参数,让Claude在发出您想要的标签后停止采样。这样可以节省金钱和最后令牌的时间,通过消除Claude在已经给您关心的答案后的结束语。
如果您想在不更改上面任何内容的情况下试验课程提示,请向下滚动到课程笔记本的底部访问示例 playground。
练习
练习5.1 - Steph Curry GOAT
被迫做出选择,Claude将迈克尔·乔丹指定为有史以来最好的篮球运动员。我们能让Claude选择其他人吗?
更改PREFILL
变量以强迫Claude提出详细论据,认为有史以来最好的篮球运动员是斯蒂芬·库里。尽量不要更改除PREFILL
以外的任何内容,因为这是本练习的重点。
# 带有变量内容占位符的提示模板
PROMPT = f"谁是有史以来最好的篮球运动员?请选择一位特定球员。"
# Claude响应的预填充
PREFILL = ""
# 获取Claude的响应
response = get_completion(PROMPT, prefill=PREFILL)
# 用于评分练习正确性的函数
def grade_exercise(text):
return bool(re.search("Warrior", text))
# 打印Claude的响应
print("--------------------------- 带有变量替换的完整提示 ---------------------------")
print("用户回合")
print(PROMPT)
print("\n助手回合")
print(PREFILL)
print("\n------------------------------------- Claude的响应 -------------------------------------")
print(response)
print("\n------------------------------------------ 评分 ------------------------------------------")
print("本练习已正确解决:", grade_exercise(response))
❓ 如果您想要提示,请运行下面的单元格!
from hints import exercise_5_1_hint; print(exercise_5_1_hint)
练习5.2 - 两首俳句
使用XML标签修改下面的PROMPT
,以便Claude写两首关于动物的俳句而不是一首。应该清楚一首诗在哪里结束,另一首在哪里开始。
# 变量内容
ANIMAL = "cats"
# 带有变量内容占位符的提示模板
PROMPT = f"请写一首关于{ANIMAL}的俳句。将它放入<haiku>标签中。"
# Claude响应的预填充
PREFILL = "<haiku>"
# 获取Claude的响应
response = get_completion(PROMPT, prefill=PREFILL)
# 用于评分练习正确性的函数
def grade_exercise(text):
return bool(
(re.search("cat", text.lower()) and re.search("<haiku>", text))
and (text.count("\n") + 1) > 5
)
# 打印Claude的响应
print("--------------------------- 带有变量替换的完整提示 ---------------------------")
print("用户回合")
print(PROMPT)
print("\n助手回合")
print(PREFILL)
print("\n------------------------------------- Claude的响应 -------------------------------------")
print(response)
print("\n------------------------------------------ 评分 ------------------------------------------")
print("本练习已正确解决:", grade_exercise(response))
❓ 如果您想要提示,请运行下面的单元格!
from hints import exercise_5_2_hint; print(exercise_5_2_hint)
练习5.3 - 两首俳句,两种动物
修改下面的PROMPT
,以便Claude产生两首关于两种不同动物的俳句。将{ANIMAL1}
用作第一个替换的占位符,将{ANIMAL2}
用作第二个替换的占位符。
# 第一个输入变量
ANIMAL1 = "Cat"
# 第二个输入变量
ANIMAL2 = "Dog"
# 带有变量内容占位符的提示模板
PROMPT = f"请写一首关于{ANIMAL1}的俳句。将它放入<haiku>标签中。"
# 获取Claude的响应
response = get_completion(PROMPT)
# 用于评分练习正确性的函数
def grade_exercise(text):
return bool(re.search("tail", text.lower()) and re.search("cat", text.lower()) and re.search("<haiku>", text))
# 打印Claude的响应
print("--------------------------- 带有变量替换的完整提示 ---------------------------")
print("用户回合")
print(PROMPT)
print("\n------------------------------------- Claude的响应 -------------------------------------")
print(response)
print("\n------------------------------------------ 评分 ------------------------------------------")
print("本练习已正确解决:", grade_exercise(response))
❓ 如果您想要提示,请运行下面的单元格!
from hints import exercise_5_3_hint; print(exercise_5_3_hint)
恭喜!
如果您已经解决了直到此点的所有练习,您已准备好进入下一章。快乐提示!
示例 playground
这是一个供您自由实验提示示例的区域,并调整提示以查看它如何影响Claude响应的方式。
# 变量内容
ANIMAL = "Rabbit"
# 带有变量内容占位符的提示模板
PROMPT = f"请写一首关于{ANIMAL}的俳句。将它放入<haiku>标签中。"
# 打印Claude的响应
print("--------------------------- 带有变量替换的完整提示 ---------------------------")
print(PROMPT)
print("\n------------------------------------- Claude的响应 -------------------------------------")
print(get_completion(PROMPT))
# 变量内容
ANIMAL = "Cat"
# 带有变量内容占位符的提示模板
PROMPT = f"请写一首关于{ANIMAL}的俳句。将它放入<haiku>标签中。"
# Claude响应的预填充
PREFILL = "<haiku>"
# 打印Claude的响应
print("--------------------------- 带有变量替换的完整提示 ---------------------------")
print("用户回合:")
print(PROMPT)
print("\n助手回合:")
print(PREFILL)
print("\n------------------------------------- Claude的响应 -------------------------------------")
print(get_completion(PROMPT, prefill=PREFILL))
# 变量内容
ANIMAL = "Cat"
# 带有变量内容占位符的提示模板
PROMPT = f"请写一首关于{ANIMAL}的俳句。使用JSON格式,键为\"first_line\"、\"second_line\"和\"third_line\"。"
# Claude响应的预填充
PREFILL = "{"
# 打印Claude的响应
print("--------------------------- 带有变量替换的完整提示 ---------------------------")
print("用户回合")
print(PROMPT)
print("\n助手回合")
print(PREFILL)
print("\n------------------------------------- Claude的响应 -------------------------------------")
print(get_completion(PROMPT, prefill=PREFILL))
# 第一个输入变量
EMAIL = "Hi Zack, just pinging you for a quick update on that prompt you were supposed to write."
# 第二个输入变量
ADJECTIVE = "olde english"
# 带有变量内容占位符的提示模板
PROMPT = f"嘿Claude。这是电子邮件:<email>{EMAIL}</email>。使这封电子邮件更{ADJECTIVE}。将新版本写入<{ADJECTIVE}_email> XML标签中。"
# Claude响应的预填充(现在作为带有变量的f字符串)
PREFILL = f"<{ADJECTIVE}_email>"
# 打印Claude的响应
print("--------------------------- 带有变量替换的完整提示 ---------------------------")
print("用户回合")
print(PROMPT)
print("\n助手回合")
print(PREFILL)
print("\n------------------------------------- Claude的响应 -------------------------------------")
print(get_completion(PROMPT, prefill=PREFILL))