课程目标 #
了解 max_tokens 参数的作用
使用温度参数控制模型响应
解释 stop_sequence 的用途
与往常一样,让我们首先导入 anthropic SDK 并加载我们的 API 密钥:
from dotenv import load_dotenv
from anthropic import Anthropic
#load environment variable
load_dotenv()
#automatically looks for an "ANTHROPIC_API_KEY" environment variable
client = Anthropic()
最大 token 数 #
每次我们向 Claude 发出请求时,都必须包含 3 个必需参数:model,max_tokens,messages
到目前为止,我们在发出的每个请求中都使用了 max_tokens 参数,但我们还没有停下来讨论它是什么。
这是我们发出的第一个请求:
our_first_message = client.messages.create(
model=”claude-3-haiku-20240307″,
max_tokens=500,
messages=[
{“role”: “user”, “content”: “Hi there! Please write me a haiku about a pet chicken”}
]
)
那么 max_tokens 的用途是什么?
简而言之,max_tokens 控制 Claude 在其响应中应生成的最大 token 数。
tokens #
在我们继续之前,让我们先停下来讨论一下 tokens。
大多数大型语言模型并不用完整的单词“思考”,而是使用一系列称为 token 的单词片段。token 是 Claude 处理、理解和生成文本的文本序列的小构建块。当我们向 Claude 提供提示时,该提示首先会转换为 token 并传递给模型。然后,模型开始一次生成一个 token 的输出。
对于 Claude 来说,一个 token 大约代表 3.5 个英文字符,但具体数量可能因使用的语言而异。
使用 max_tokens #
max_tokens 参数允许我们设置 Claude 为我们生成的 token 数量的上限。举例来说,假设我们要求 Claude 为我们写一首诗,并将 max_tokens 设置为 10。Claude 将开始为我们生成 token,并在达到 10 个 token 时立即停止。这通常会导致输出被截断或不完整。让我们试试吧!
truncated_response = client.messages.create(
model="claude-3-haiku-20240307",
max_tokens=10,
messages=[
{"role": "user", "content": "Write me a poem"}
]
)
print(truncated_response.content[0].text)
Here is a poem for you: The
如果您运行上述代码,您可能会得到同样截断的不同结果。Claude 开始为我们写一首诗,然后在生成 10 个标记后立即停止。
我们还可以检查响应消息对象上的 stop_reason 属性,以查看模型停止生成的原因。在本例中,我们可以看到它的值为“max_tokens”,这告诉我们模型停止生成是因为它达到了最大标记限制!
truncated_response.stop_reason
Out[26]:’max_tokens’
当然,如果我们尝试使用更大的 max_tokens 值再次生成一首诗,我们可能会得到一整首诗:
longer_poem_response = client.messages.create(
model="claude-3-haiku-20240307",
max_tokens=500,
messages=[
{"role": "user", "content": "Write me a poem"}
]
)
print(longer_poem_response.content[0].text)
Here is a poem for you:
Whispers of the Heart
In the quiet moments,
When the world fades away,
I hear the whispers of my heart -
Gentle words that gently sway.
They speak of dreams still unfurled,
Of love that shines like the sun,
Of passions yet to be explored,
Of all that's yet to be done.
These whispers, they guide my way,
Reminding me to pause and feel,
To listen closely to the soul,
And let its truths be revealed.
For in the silence, in the calm,
The heart's true voice can be heard,
Weaving a tapestry of hope,
With every softly spoken word.
So I will heed these whispers dear,
And let them be my faithful friend,
For in their song, I find my way,
To all my heart hopes to transcend.
This is what Claude generated with max_tokens set to 500:
Here is a poem for you:
Whispers of the Wind
The wind whispers softly,
Caressing my face with care.
Its gentle touch, a fleeting breath,
Carries thoughts beyond compare.
Rustling leaves dance in rhythm,
Swaying to the breeze's song.
Enchanting melodies of nature,
Peaceful moments linger long.
The wind's embrace, a soothing balm,
Calms the restless soul within.
Embracing life's fleeting moments,
As the wind's sweet song begins.
如果我们查看此响应的 stop_reason,我们会看到“end_turn”的值,这是模型告诉我们它自然完成了生成的方式。它给我们写了一首诗,没有其他话要说,所以它停止了!
longer_poem_response.stop_reason Out[28]: 'end_turn'
需要注意的是,模型在生成内容时“不知道”max_tokens。更改max_tokens不会改变Claude生成输出的方式,它只是为模型提供了继续生成的空间(使用较高的max_tokens值)或截断输出(使用较低的max_tokens值)。
还需要注意的是,增加max_tokens并不能确保Claude实际生成特定数量的tokens。如果我们要求Claude写一个笑话并将max_tokens设置为1000,我们几乎肯定会得到比1000个tokens短得多的响应。
response = client.messages.create(
model="claude-3-haiku-20240307",
max_tokens=1000,
messages=[{"role": "user", "content": "Tell me a joke"}]
)
print(response.content[0].text)
Here's a classic dad joke for you:
Why don't scientists trust atoms? Because they make up everything!
How was that? I tried to keep it clean and mildly amusing. Let me know if you'd like to hear another joke.
print(response.usage.output_tokens)
55
在上面的例子中,我们要求 Claude“给我讲个笑话”,并给 max_tokens 赋值 1000。它产生了这个笑话:
Here’s a classic dad joke for you:
Why don’t scientists trust atoms? Because they make up everything!
How was that? I tried to keep it clean and mildly amusing. Let me know if you’d like to hear another joke.
生成的内容只有 55 个 token。我们给 Claude 设定了 1000 个 token 的上限,但这并不意味着它会生成 1000 个 token。
为什么要更改最大 token数? #
在使用 Claude 时,了解token至关重要,特别是出于以下原因:
1.API 限制:输入文本中的token数和生成的响应计入 API 使用限制。每个 API 请求可以处理的token数都有最大限制。了解token有助于您保持在 API 限制范围内并有效管理使用情况。
2.性能:Claude 生成的token数直接影响 API 的处理时间和内存使用情况。输入文本越长,max_tokens 值越高,需要的计算资源就越多。了解token有助于您优化 API 请求以获得更好的性能。
3.响应质量:设置适当的 max_tokens 值可确保生成的响应足够长并包含必要的信息。如果 max_tokens 值太低,响应可能会被截断或不完整。尝试不同的 max_tokens 值可以帮助您找到特定用例的最佳平衡。
让我们来看看 Claude 生成的token数如何影响性能。以下函数要求 Claude 三次生成两个角色之间的非常长的对话,每次的 max_tokens 值都不同。然后它打印出实际生成的标记数以及生成所用的时间。
import time
def compare_num_tokens_speed():
token_counts = [100,1000,4096]
task = """
Create a long, detailed dialogue that is at least 5000 words long between two characters discussing the impact of social media on mental health.
The characters should have differing opinions and engage in a respectful thorough debate.
"""
for num_tokens in token_counts:
start_time = time.time()
response = client.messages.create(
model="claude-3-haiku-20240307",
max_tokens=num_tokens,
messages=[{"role": "user", "content": task}]
)
end_time = time.time()
execution_time = end_time - start_time
print(f"Number of tokens generated: {response.usage.output_tokens}")
print(f"Execution Time: {execution_time:.2f} seconds\n")
compare_num_tokens_speed()
Number of tokens generated: 100
Execution Time: 1.51 seconds
Number of tokens generated: 1000
Execution Time: 8.33 seconds
Number of tokens generated: 3433
Execution Time: 28.80 seconds
如果您运行代码,您获得的确切值可能会有所不同,但这里有一个示例输出:
生成的令牌数量:100
执行时间:1.51 秒
生成的令牌数量:1000
执行时间:8.33 秒
生成的令牌数量:3433
执行时间:28.80 秒
如您所见,Claude 生成的令牌越多,所需的时间就越长!
举一个更明显的例子,我们要求 Claude 重复一段很长的文本,并使用 max_tokens 在不同的输出大小下截止生成。我们对每个大小重复 50 次,并计算平均生成时间。如您所见,随着输出大小的增加,所需的时间也会增加!请看下面的图:
停止序列 #
我们还没有看到的另一个重要参数是 stop_sequence,它允许我们为模型提供一组字符串,当在生成的响应中遇到这些字符串时,会导致生成停止。它们本质上是一种告诉 Claude 的方式,“如果你生成了这个序列,就停止生成任何其他序列!”
以下是一个不包含 stop_sequence 的请求示例:
response = client.messages.create(
model="claude-3-haiku-20240307",
max_tokens=500,
messages=[{"role": "user", "content": "Generate a JSON object representing a person with a name, email, and phone number ."}],
)
print(response.content[0].text)
Here's an example of a JSON object representing a person with a name, email, and phone number:
```json
{
"name": "John Doe",
"email": "johndoe@example.com",
"phoneNumber": "123-456-7890"
}
```
在此示例中,JSON 对象有三个键值对:
- “name”:此人的姓名,字符串值为“John Doe”。
- “email”:此人的电子邮件地址,字符串值为“johndoe@example.com”。
- “phoneNumber”:此人的电话号码,字符串值为“123-456-7890”。
您可以修改这些值以表示具有自己姓名、电子邮件和电话号码的不同人。
上面的代码要求 Claude 生成一个代表人的 JSON 对象。以下是 Claude 生成的示例输出:
以下是代表具有姓名、电子邮件和电话号码的人的 JSON 对象的示例:
{
"name": "John Doe",
"email": "johndoe@example.com",
"phoneNumber": "123-456-7890"
}
Claude 确实生成了请求的对象,但之后还包含了一个解释。如果我们想让 Claude 在生成 JSON 对象的结束“}”后立即停止生成,我们可以修改代码以包含 stop_sequences 参数。
response = client.messages.create(
model="claude-3-haiku-20240307",
max_tokens=500,
messages=[{"role": "user", "content": "Generate a JSON object representing a person with a name, email, and phone number ."}],
stop_sequences=["}"]
)
print(response.content[0].text)
Here's a JSON object representing a person with a name, email, and phone number:
{
"name": "John Doe",
"email": "john.doe@example.com",
"phone": "555-1234"
该模型生成以下输出:
这是一个 JSON 对象,表示具有姓名、电子邮件和电话号码的人:
{
"name": "John Doe",
"email": "john.doe@example.com",
"phone": "555-1234"
重要提示:请注意,结果输出不包含“}”停止序列本身。如果我们想使用并将其解析为 JSON,则需要重新添加结尾的“}”。
当我们收到 Claude 的响应时,我们可以通过检查 stop_reason 属性来检查模型停止生成文本的原因。如下所示,之前的响应因“stop_sequence”而停止,这意味着模型生成了我们提供的停止序列之一并立即停止。
response.stop_reason
‘stop_sequence’
我们还可以查看响应上的 stop_sequence 属性,以检查哪个特定的 stop_sequence 导致模型停止生成:
response.stop_sequence
‘}’
我们可以提供多个停止序列。如果我们提供多个,模型将在遇到任何停止序列时立即停止生成。响应消息上的结果 stop_sequence 属性将告诉我们遇到了哪个确切的 stop_sequence。
下面的函数要求 Claude 写一首诗,如果生成字母“b”或“c”,则停止。它执行了三次:
def generate_random_letters_3_times():
for i in range(3):
response = client.messages.create(
model="claude-3-haiku-20240307",
max_tokens=500,
messages=[{"role": "user", "content": "generate a poem"}],
stop_sequences=["b", "c"]
)
print(f"Response {i+1} stopped because {response.stop_reason}. The stop sequence was {response.stop_sequence}")
generate_random_letters_3_times()
Response 1 stopped because stop_sequence. The stop sequence was c
Response 2 stopped because stop_sequence. The stop sequence was b
Response 3 stopped because stop_sequence. The stop sequence was b
以下是示例输出:
响应 1 因 stop_sequence 而停止。停止序列为 c
响应 2 因 stop_sequence 而停止。停止序列为 b
响应 3 因 stop_sequence 而停止。停止序列为 b
第一次,Claude 停止写诗,因为它生成了字母“c”。接下来两次,它停止,因为它生成了字母“b”。您会这样做吗?可能不会!
温度系数 #
温度参数用于控制生成的响应的“随机性”和“创造性”。它的范围从 0 到 1,值越高,响应越多样化、越不可预测,措辞也越多样化。较低的温度可以产生更确定的输出,这些输出遵循最可能的措辞和答案。温度的默认值为 1。
在生成文本时,Claude 会预测下一个标记(单词或子单词)的概率分布。温度参数用于在采样下一个标记之前操纵此概率分布。如果温度较低(接近 0.0),概率分布会变得更加尖锐,最有可能的标记会分配较高的概率。这使得模型更加确定,并专注于最可能或“安全”的选择。如果温度较高(接近 1.0),概率分布会变得更加平坦,可能性较小的标记的概率会增加。这使得模型更加随机和具有探索性,从而允许更多样化和更具创造性的输出。
请参阅此图表来直观了解温度的影响:
为什么要改变温度?
对于分析任务,使用接近 0.0 的温度;对于创造性和生成性任务,使用接近 1.0 的温度。
让我们尝试一个快速演示。看看下面的函数。使用温度 0,然后使用温度 1,我们向 Claude 发出三个请求,要求它“为外星球想出一个名字。用一个单词回答。”
def demonstrate_temperature():
temperatures = [0, 1]
for temperature in temperatures:
print(f"Prompting Claude three times with temperature of {temperature}")
print("================")
for i in range(3):
response = client.messages.create(
model="claude-3-haiku-20240307",
max_tokens=100,
messages=[{"role": "user", "content": "Come up with a name for an alien planet. Respond with a single word."}],
temperature=temperature
)
print(f"Response {i+1}: {response.content[0].text}")
demonstrate_temperature()
以温度 0 提示 Claude 三次
响应 1:Xendor。
响应 2:Xendor。
响应 3:Xendor。
以温度 1 提示 Claude 三次
响应 1:Xyron。
响应 2:Xandar。
响应 3:Zyrcon。
请注意,当温度为 0 时,所有三个响应都是相同的。请注意,即使温度为 0.0,结果也不会完全确定。但是,与温度为 1 的结果相比,结果有明显差异。每个响应都是一个完全不同的外星球名称。
下面的图表说明了温度对 Claude 输出的影响。使用此提示“选择世界上的任何动物。只用一个单词回答:动物的名字”,我们在温度为 0 的情况下向 Claude 查询了 100 次。然后我们又进行了 100 次,但温度为 1。下图显示了 Claude 提出的每种动物反应的频率。
如您所见,温度为 0 时,Claude 每次都回复“长颈鹿”。请记住,温度为 0 并不能保证确定的结果,但它确实使 Claude 更有可能每次都回复类似的内容。温度为 1 时,Claude 仍然有一半以上的时间选择长颈鹿,但回复中还包括许多其他类型的动物!
系统提示 #
system_prompt 是一个可选参数,您可以在向 Claude 发送消息时包含它。它通过向 Claude 提供高级说明、定义其角色或提供应告知其回复的背景信息来为对话奠定基础。
关于 system_prompt 的要点:
它是可选的,但可用于设置对话的基调和背景。
它应用于对话级别,影响 Claude 在该交流中的所有回复。
它可以帮助引导 Claude 的行为,而无需在每条用户消息中包含说明。
请注意,大多数情况下,系统提示中只应包含语气、上下文和角色内容。详细说明、外部输入内容(如文档)和示例应包含在第一个用户回合中,以获得更好的效果。您无需在后续每个用户回合中重复此操作。
让我们尝试一下:
message = client.messages.create(
model="claude-3-haiku-20240307",
max_tokens=1000,
system="You are a helpful foreign language tutor that always responds in French.",
messages=[
{"role": "user", "content": "Hey there, how are you?!"}
]
)
print(message.content[0].text)
Bonjour ! Je suis ravi de vous rencontrer. Comment allez-vous aujourd'hui ?
练习 #
编写一个名为 generate_questions 的函数,该函数执行以下操作:
采用两个参数:topic 和 num_questions
以编号列表的形式生成有关所提供主题的 num_questions 个发人深省的问题
打印生成的问题
例如,调用 generate_questions(topic=”free will”, num_questions=3) 可能会产生以下输出:
我们的决定和行动在多大程度上真正源于我们自己的自由意志,而不是受到我们无法控制的因素(例如我们的基因、成长经历和社会影响)的影响?
如果我们的决定最终是生物、心理和环境因素复杂相互作用的结果,这是否意味着我们缺乏做出真实、自主选择的能力,或者自由意志与决定论相容?
接受或拒绝自由意志概念的伦理和哲学含义是什么?我们对自由意志的看法会如何影响我们对道德责任、惩罚和人类状况本质的观念?
在您的实施中,请使用以下参数:
max_tokens 将响应限制在 1000 个标记以下
system 提供系统提示,告知模型它是特定主题的专家,并且应该生成编号列表。
stop_sequences 确保模型在生成正确数量的问题后停止。(如果我们要求 3 个问题,我们希望确保模型在生成“4”后立即停止。如果我们要求 5 个问题,我们希望确保模型在生成“6”后立即停止。)
潜在解决方案 #
def generate_questions(topic, num_questions=3):
response = client.messages.create(
model="claude-3-haiku-20240307",
max_tokens=500,
system=f"You are an expert on {topic}. Generate thought-provoking questions about this topic.",
messages=[
{"role": "user", "content": f"Generate {num_questions} questions about {topic} as a numbered list."}
],
stop_sequences=[f"{num_questions+1}."]
)
print(response.content[0].text)
generate_questions(topic="free will", num_questions=3)
Here are three thought-provoking questions about free will:
1. To what extent do our decisions and actions truly originate from our own free will, rather than being shaped by factors beyond our control, such as our genes, upbringing, and societal influences?
2. If our decisions are ultimately the result of a complex interplay of biological, psychological, and environmental factors, does that mean we lack the ability to make authentic, autonomous choices, or is free will compatible with determinism?
3. What are the ethical and philosophical implications of embracing or rejecting the concept of free will? How might our views on free will impact our notions of moral responsibility, punishment, and the nature of the human condition?