1 intro
基础大模型 VS 用指令tune 过的大模型
- 基础大模型 只会对prompt的文本进行续写
- 所以当你向模型发问的时候,它往往会像复读机一样续写几个问题
- 这是因为在它见过的语料库文本(通常大多来自互联网)中,通常会连续列举出N个问题
- 经过指令微调(如RLHF)之后,模型才会像人一样进行有效答复
2 prompt 的原则
2.0 open-ai准备代码
2.0.1 设置& 使用OpenAI的API密钥
import openai
import os
from dotenv import load_dotenv, find_dotenv
_ = load_dotenv(find_dotenv())
'''
首先使用 find_dotenv() 函数查找 .env 文件的路径
然后 load_dotenv() 函数加载该文件中的环境变量。
这样做可以使我们的应用程序读取这些环境变量
'''
openai.api_key = os.getenv('OPENAI_API_KEY')
openai.api_key
'''
'eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJhcHAiLCJzdWIiOiIxODE0MDkyIiwiYXVkIjoiV0VCIiwiaWF0IjoxNzEwMzQyODYwLCJleHAiOjE3MTI5MzQ4NjB9.cxiUyxEBRFvSs0xxnpFTAkHs_neQihbbypAvDF9P2Uw'
'''
#从环境变量中读取 OPENAI_API_KEY 的值,并将其设置为 openai 库中 api_key 的值
当然下面这种方式设置密钥也是可以的
import openai
openai.api_key = "sk-..."
2.0.2 函数:根据用户的输入提示 prompt
生成一个回答,并返回这个回答的文本内容
def get_completion(prompt, model="gpt-3.5-turbo"):
messages = [{"role": "user", "content": prompt}]
'''
创建了一个包含单个字典的列表 messages,字典包含两个键:"role" 和 "content"。
"role" 键的值是 "user",表示这个消息是用户输入的。
"content" 键的值是函数参数 prompt,表示用户的输入内容。
'''
response = openai.ChatCompletion.create(
model=model,
messages=messages,
temperature=0, # this is the degree of randomness of the model's output
)
'''
调用 openai.ChatCompletion.create 方法,使用上面定义的 messages、函数参数 model,
以及一个指定的 temperature 参数来创建一个聊天完成(即模型的回答)
temperature 参数控制输出的随机性程度,这里被设置为 0,意味着模型的输出将是确定性的,
即在给定相同输入和条件的情况下,模型每次都会生成相同的输出。
'''
return response.choices[0].message["content"]
'''
返回从 response 对象中提取的实际生成文本。
通过访问 response 对象的 choices 列表的第一个元素,然后从这个元素中提取 message 字典的 "content" 键的值,即模型生成的回答
'''
2.1 原则1:提供清晰和具体的指令 (Write clear and specific instructions)
2.1.1 策略1:使用分隔符清楚地指示输入的不同部分(Use delimiters to clearly indicate distinct parts of the input)
- 使用分隔符的意义在于避免用户输入的文本可能存在一些误导性的话语对应用功能造成干扰
- 分隔符可以是: ```, """, < >, <tag> </tag>
text = f"""
You should express what you want a model to do by \
providing instructions that are as clear and \
specific as you can possibly make them. \
This will guide the model towards the desired output, \
and reduce the chances of receiving irrelevant \
or incorrect responses. Don't confuse writing a \
clear prompt with writing a short prompt. \
In many cases, longer prompts provide more clarity \
and context for the model, which can lead to \
more detailed and relevant outputs.
"""
prompt = f"""
Summarize the text delimited by triple backticks \
into a single sentence.
```{text}```
"""
response = get_completion(prompt)
print(response)
'''
Providing clear and specific instructions to a model is essential for guiding it towards the desired output and reducing the chances of irrelevant or incorrect responses, with longer prompts often providing more clarity and context for more detailed and relevant outputs.
'''
复习一下,这里prompt 以f开头的用法:python基础:-CSDN博客
2.1.2 策略2 要求结构化的输出(Ask for a structured output)
这样有助于模型输出结果直接用于程序,比如输出的json可以直接被python程序读取并转换为字典格式。
prompt = f"""
Generate a list of three made-up book titles along \
with their authors and genres.
Provide them in JSON format with the following keys:
book_id, title, author, genre.
"""
response = get_completion(prompt)
print(response)
'''
[
{
"book_id": 1,
"title": "The Midnight Garden",
"author": "Elena Nightingale",
"genre": "Fantasy"
},
{
"book_id": 2,
"title": "Echoes of the Past",
"author": "Lucas Blackwood",
"genre": "Mystery"
},
{
"book_id": 3,
"title": "Whispers in the Wind",
"author": "Aria Silvermoon",
"genre": "Romance"
}
]
'''
上面的“provide them in JSON format”就是策略2
2.1.3 策略 3: 让模型检查是否满足条件(Ask the model to check whether conditions are satisfied)
text_1 = f"""
Making a cup of tea is easy! First, you need to get some \
water boiling. While that's happening, \
grab a cup and put a tea bag in it. Once the water is \
hot enough, just pour it over the tea bag. \
Let it sit for a bit so the tea can steep. After a \
few minutes, take out the tea bag. If you \
like, you can add some sugar or milk to taste. \
And that's it! You've got yourself a delicious \
cup of tea to enjoy.
"""
prompt = f"""
You will be provided with text delimited by triple quotes.
If it contains a sequence of instructions, \
re-write those instructions in the following format:
Step 1 - ...
Step 2 - …
…
Step N - …
If the text does not contain a sequence of instructions, \
then simply write \"No steps provided.\"
\"\"\"{text_1}\"\"\"
"""
response = get_completion(prompt)
print("Completion for Text 1:")
print(response)
'''
Completion for Text 1:
Step 1 - Get some water boiling.
Step 2 - Grab a cup and put a tea bag in it.
Step 3 - Once the water is hot enough, pour it over the tea bag.
Step 4 - Let it sit for a bit so the tea can steep.
Step 5 - After a few minutes, take out the tea bag.
Step 6 - Add some sugar or milk to taste.
Step 7 - Enjoy your delicious cup of tea.
'''
这里的“If the text does not contain a sequence of instructions, \
then simply write \"No steps provided.\"就是策略3
反例(无法划分成一个一个step的):
text_2 = f"""
The sun is shining brightly today, and the birds are \
singing. It's a beautiful day to go for a \
walk in the park. The flowers are blooming, and the \
trees are swaying gently in the breeze. People \
are out and about, enjoying the lovely weather. \
Some are having picnics, while others are playing \
games or simply relaxing on the grass. It's a \
perfect day to spend time outdoors and appreciate the \
beauty of nature.
"""
prompt = f"""
You will be provided with text delimited by triple quotes.
If it contains a sequence of instructions, \
re-write those instructions in the following format:
Step 1 - ...
Step 2 - …
…
Step N - …
If the text does not contain a sequence of instructions, \
then simply write \"No steps provided.\"
\"\"\"{text_2}\"\"\"
"""
response = get_completion(prompt)
print("Completion for Text 2:")
print(response)
'''
Completion for Text 2:
No steps provided.
'''
2.1.4 策略4:少样本提示( "Few-shot" prompting)
通过提供给模型一个或多个样本的提示,模型可以更加清楚需要你预期的输出。
prompt = f"""
Your task is to answer in a consistent style.
<child>: Teach me about patience.
<grandparent>: The river that carves the deepest \
valley flows from a modest spring; the \
grandest symphony originates from a single note; \
the most intricate tapestry begins with a solitary thread.
<child>: Teach me about resilience.
"""
response = get_completion(prompt)
print(response)
'''
<grandparent>: The tallest trees weather the strongest storms; the brightest stars shine in the darkest nights; the strongest hearts endure the greatest trials.
'''
2.2 原则2:给模型时间来“思考”(Give the model time to “think” )
利用了思维链的方法,将复杂任务拆成N个顺序的子任务,这样可以让模型一步一步思考,从而给出更精准的输出
2.2.1 策略1:指定完成任务所需的步骤 (Specify the steps required to complete a task)
text = f"""
In a charming village, siblings Jack and Jill set out on \
a quest to fetch water from a hilltop \
well. As they climbed, singing joyfully, misfortune \
struck—Jack tripped on a stone and tumbled \
down the hill, with Jill following suit. \
Though slightly battered, the pair returned home to \
comforting embraces. Despite the mishap, \
their adventurous spirits remained undimmed, and they \
continued exploring with delight.
"""
# example 1
prompt_1 = f"""
Perform the following actions:
1 - Summarize the following text delimited by triple \
backticks with 1 sentence.
2 - Translate the summary into French.
3 - List each name in the French summary.
4 - Output a json object that contains the following \
keys: french_summary, num_names.
Separate your answers with line breaks.
Text:
```{text}```
"""
response = get_completion(prompt_1)
print("Completion for prompt 1:")
print(response)
'''
Completion for prompt 1:
1 - Jack and Jill go on a quest to fetch water from a hilltop well, but misfortune strikes as Jack trips on a stone and tumbles down the hill with Jill following suit, yet they return home slightly battered but with their adventurous spirits undimmed.
2 - Jack et Jill partent en quête d'eau d'un puits au sommet d'une colline, mais la malchance frappe alors que Jack trébuche sur une pierre et dégringole la colline avec Jill qui suit, pourtant ils rentrent chez eux légèrement meurtris mais avec leurs esprits aventureux intacts.
3 - Jack, Jill
4 -
{
"french_summary": "Jack et Jill partent en quête d'eau d'un puits au sommet d'une colline, mais la malchance frappe alors que Jack trébuche sur une pierre et dégringole la colline avec Jill qui suit, pourtant ils rentrent chez eux légèrement meurtris mais avec leurs esprits aventureux intacts.",
"num_names": 2
}
'''
在prompt中,让大模型分成四步,一步一步解决
2.2.2 策略2:在匆忙得出结论之前,让模型自己找出解决方案(Instruct the model to work out its own solution before rushing to a conclusion)
- 反例prompt(模型匆忙地给出了错误的答案)
prompt = f"""
Determine if the student's solution is correct or not.
Question:
I'm building a solar power installation and I need \
help working out the financials.
- Land costs $100 / square foot
- I can buy solar panels for $250 / square foot
- I negotiated a contract for maintenance that will cost \
me a flat $100k per year, and an additional $10 / square \
foot
What is the total cost for the first year of operations
as a function of the number of square feet.
Student's Solution:
Let x be the size of the installation in square feet.
Costs:
1. Land cost: 100x
2. Solar panel cost: 250x
3. Maintenance cost: 100,000 + 100x
Total cost: 100x + 250x + 100,000 + 100x = 450x + 100,000
"""
response = get_completion(prompt)
print(response)
'''
The student's solution is correct. The total cost for the first year of operations as a function of the number of square feet is indeed 450x + 100,000.
'''
- 好的prompt(告诉模型,让模型先找出自己的解决方案)
prompt = f"""
Your task is to determine if the student's solution \
is correct or not.
To solve the problem do the following:
- First, work out your own solution to the problem including the final total.
- Then compare your solution to the student's solution \
and evaluate if the student's solution is correct or not.
Don't decide if the student's solution is correct until
you have done the problem yourself.
Use the following format:
Question:
```
question here
```
Student's solution:
```
student's solution here
```
Actual solution:
```
steps to work out the solution and your solution here
```
Is the student's solution the same as actual solution \
just calculated:
```
yes or no
```
Student grade:
```
correct or incorrect
```
Question:
```
I'm building a solar power installation and I need help \
working out the financials.
- Land costs $100 / square foot
- I can buy solar panels for $250 / square foot
- I negotiated a contract for maintenance that will cost \
me a flat $100k per year, and an additional $10 / square \
foot
What is the total cost for the first year of operations \
as a function of the number of square feet.
```
Student's solution:
```
Let x be the size of the installation in square feet.
Costs:
1. Land cost: 100x
2. Solar panel cost: 250x
3. Maintenance cost: 100,000 + 100x
Total cost: 100x + 250x + 100,000 + 100x = 450x + 100,000
```
Actual solution:
"""
response = get_completion(prompt)
print(response)
'''
Let x be the size of the installation in square feet.
Costs:
1. Land cost: $100 * x
2. Solar panel cost: $250 * x
3. Maintenance cost: $100,000 + $10 * x
Total cost: $100 * x + $250 * x + $100,000 + $10 * x = $360 * x + $100,000
The total cost for the first year of operations as a function of the number of square feet is $360x + $100,000.
```
Is the student's solution the same as actual solution just calculated:
```
No
```
Student grade:
```
incorrect
'''