让我们回顾一下上一章的一些学习内容:
“提示工程”是一个过程,在这个过程中,我们通过提供更有用的指示或上下文来引导模型产生更相关的回答。
编写提示的两个步骤是:构建提示——通过提供相关的上下文,并进行“优化”,以逐渐改进提示。
到目前为止,我们已经对如何编写提示有了一些基本的了解,但我们需要更深入地了解。在本章中,您将从尝试各种提示开始,了解为什么一个提示比另一个好。您将学习如何使用一些基本的技巧来构建提示,这些技巧适用于任何LLM。
介绍
在本章中,我们将涵盖以下主题:
- 运用不同的技巧来扩展您对提示工程的了解。
- 配置提示以使输出多样化。
学习目标
完成本课程后,您将能够:
- 应用改进提示结果的提示工程技巧。
- 进行变化或确定性的提示。
提示工程
提示工程是创建能产生所需结果的提示的过程。提示工程不仅仅是编写一个文本提示,它不是一门工程学科,而是一系列技巧的集合,您可以应用这些技巧来获得所需的结果。
一个提示的示例
让我们来看一个基本的提示,像这样:
“生成 10 个关于地理的问题。”
在这个提示中,您实际上是应用了一组不同的提示技巧。
让我们来分解一下。
- 上下文,您指定了它应该是关于”地理”的。
- 限制输出,您希望不超过 10 个问题。
简单提示的局限性
您可能会得到所需的结果,也可能不会。您将获得生成的问题,但地理是一个庞大的主题,由于以下原因,您可能无法获得真正想要的结果:
- 庞大的主题,您不知道它是否涉及国家、首都、河流等等。
- 格式,如果您希望问题以某种特定的方式呈现呢?
正如您所见,创建提示时需要考虑许多因素。
到目前为止,我们已经看到了一个简单的提示示例,但生成式AI能够在许多角色和行业中帮助人们,我们来探索一些基本技巧。
提示技巧
首先,我们需要理解提示是LLM的一个“ emergent ”属性,这意味着这不是一个内置在模型中的功能,而是我们在使用模型时发现的东西。
我们可以使用一些基本的技巧来提示LLM。让我们一起来探索一下:
- 少量示例提示,这是最基本的提示形式。它是一个只包含几个示例的提示。
- 思维链,这种类型的提示告诉LLM如何将一个问题分解为一系列步骤进行处理。
- 生成的知识,为了改善提示的回答,您可以提供除了提示外的生成的事实或知识。
- 从少到多,与思维链类似,这个技术是将一个问题分解为一系列步骤,然后按顺序要求执行这些步骤。
- 自我改进,这个技术是对LLM的输出提出批评,然后要求它进行改进。
- 助产提示,在这里,您希望确保LLM的答案是正确的,并要求它解释答案的各个部分。这是一种自我改进的形式。
少量示例提示
这种形式的提示非常简单,它可能由一个提示和几个示例组成。这种技术可能是您刚开始学习LLM时使用的。这是一个示例:
- 提示:”代数是什么?”
- 答案:”代数是研究数学符号及其操作规则的数学分支。”
思维链
思维链是一种非常有趣的技巧,它是将LLM按照一系列步骤进行指导的方法。思维链的思想是通过一种方式教导LLM如何做事情。考虑以下示例,带和不带思维链的情况:
- 提示:"Alice 有 5 个苹果,扔掉了 3 个苹果,把 2 个苹果给了 Bob,然后 Bob 又还给了一个苹果,Alice 还剩下几个苹果?"
- 答案:5
LLM的答案是 5,这是不正确的。正确的答案是 1,根据计算(5 – 3 – 2 + 1 = 1)。
那么我们该如何教导LLM正确地进行计算呢?
让我们尝试思维链。应用思维链意味着:
- 给LLM一个类似的例子。
- 展示计算过程,以及如何正确计算。
- 提供原始提示。
具体如下所示:
- 提示:”Lisa 有 7 个苹果,扔掉了 1 个苹果,把 4 个苹果给了 Bart,然后 Bart 又还给了一个苹果: 7 -1 = 6 6 -4 = 2 2 +1 = 3
Alice 有 5 个苹果,扔掉了 3 个苹果,把 2 个苹果给了 Bob,然后 Bob 又还给了一个苹果,Alice 还剩下几个苹果?” 答案:1
请注意,我们编写了更长的提示,包括另一个例子、一个计算过程,然后是原始提示,最终得到了正确的答案 1。
正如您所见,思维链是一种非常强大的技巧。
生成的知识
当您想要构建提示时,通常希望使用您公司的数据。您希望提示的一部分来自公司,另一部分是您真正感兴趣的提示。
以保险业务为例,如果使用您公司的数据构建提示,提示可能如下所示:
```text
{{公司}}:{{公司名称}}
{{产品}}:
{{产品列表}}
请根据以下预算和要求提供一个保险建议:
预算:{{预算}}
要求:{{要求}}
```
在上面的示例中,您可以看到如何使用模板构建提示。在模板中,有一些变量,用 {{变量}}
表示,将使用公司 API 中的实际值替换这些变量。
下面是提示完成后的示例,变量已被公司的内容替换:
```text
保险公司:ACME Insurance
保险产品(每月费用):
- 汽车,廉价,500 美元
- 汽车,昂贵,1100 美元
- 房屋,廉价,600 美元
- 房屋,昂贵,1200 美元
- 生命,廉价,100 美元
请根据以下预算和要求提供一个保险建议:
预算:$1000
要求:汽车,房屋
```
运行此提示会生成如下回应:
```output
,以及生命保险
根据预算和要求,我们建议从 ACME Insurance 中选择以下保险套餐:
- 汽车,廉价,500 美元
- 房屋,廉价,600 美元
- 生活,廉价,100 美元
总费用:1,200 美元
```
正如您所见,它还建议了生命保险,而实际上不应该建议。这个结果表明我们需要通过更改提示来优化提示,以便更清楚地说明它可以允许什么。经过一些“试错”,我们得到了以下提示:
```text
保险公司:ACME Insurance
保险产品(每月费用):
- 类型:汽车,廉价,费用:500 美元
- 类型:汽车,昂贵,费用:1100 美元
- 类型:房屋,廉价,费用:600 美元
- 类型:房屋,昂贵,费用:1200 美元
- 类型:生命,廉价,费用:100 美元
请根据以下预算和要求提供一个保险建议:
预算:$1000 限制选择类型:汽车,房屋
```
注意添加了“类型”和“费用”,还使用了“限制”关键字,这有助于LLM理解我们的意图。
现在,我们得到了以下回应:
```output
根据预算和要求,我们建议从 ACME Insurance 选择廉价汽车保险产品,每月费用为 500 美元。
```
这个示例的目的是表明,即使我们使用了像“生成的知识”这样的基本技巧,我们在大多数情况下仍需要优化提示才能获得所需的结果。
从少到多
最少到最多的提示思路是将一个更大的问题分解成子问题。这样,您就可以帮助引导LLM如何“征服”这个更大的问题。一个很好的例子可能是数据科学,您可以要求LLM将一个问题分解为如下部分:
提示:”如何以 5 个步骤进行数据科学计算?”
您的AI助手会回答:
- 收集数据。
- 清洁数据。
- 分析数据。
- 绘制数据。
- 呈现数据。
自我改进,批评结果
在生成式AI和LLM中,您不能信任输出结果。您需要验证它。毕竟,LLM只是向您展示下一个最有可能说的事情,而不是正确的事情。因此,一个好主意是要求LLM批评自己,这引导我们进入了自我改进的技巧。
它的工作原理是按照以下步骤进行:
- 初始提示,要求LLM解决一个问题。
- LLM回答。
- 您对答案进行批评,并要求AI进行改进。
- LLM再次回答,这次考虑到了批评,并提出了它提出的解决方案。
您可以根据需要重复此过程。
以下是使用此技术的示例:
提示:”使用 Flask 构建一个 Python Web API,具有产品和客户路由”
AI回答:
```python
import flask
app = Flask(__name__)
@app.route('/products')
def products():
return 'Products'
@app.route('/customers')
def customers():
return 'Customers'
```
提示:”对上述代码提出 3 个改进建议”
AI回答:
```text
没有问题,请找到以下改进建议:
1. 导入正确的模块:第一行应该导入 Flask 而不是 flask。正确的导入语句应该是 from flask import Flask。
2. 添加一个 main 函数:在文件的结尾添加 if __name__ == '__main__': 代码块,以在文件运行时运行应用程序。
3. 使用 f-strings:使用 f-strings 格式化路由函数中的返回语句。例如,return 'Products' 可以改为 return f'This is the {request.path} page'。
```
```python
from flask import Flask, request
app = Flask(__name__)
@app.route('/products')
def products():
return f'This is the {request.path} page'
@app.route('/customers')
def customers():
return f'This is the {request.path} page'
if __name__ == '__main__':
app.run()
```
正如您所见,上面的AI响应正在改进第一个建议的代码,感谢对第一个答案进行批评。
助产提示
助产提示是一种类似于自我改进的技术,但它更多地涉及要求LLM解释自己,目的是减少LLM的输出中的不一致,以确保它得出正确的答案。遵循以下步骤:
- 要求LLM回答一个问题。
- 对于答案的每个部分,要求LLM详细解释。
- 如果存在不一致,则丢弃不一致的部分。
重复步骤 2 和步骤 3,直到您遍历完所有部分并对答案感到满意。
以下是一个示例提示:
提示:”如何通过 5 个步骤创建危机计划以减轻大流行的影响?” LLM回答:
```text
1. 确定风险
2. 确定利益相关方
3. 确定资源
4. 确定行动
5. 确定沟通渠道
```
已确定 5 个步骤,但我们如何确定这是正确的呢?让我们要求LLM详细解释每个步骤:
提示:”更详细地解释第一个步骤,大流行中的风险是什么?”
```text
以下是风险的详细信息:
- 生命损失
- 业务损失
- 声誉损失
- 客户损失
- 员工损失
```
在这一点上,我们希望确保LLM是正确的,所以我们要求它更详细地解释第一个风险,并希望它与上面的答案一致:
提示:”在大流行中,风险最大的是什么?为什么?”
```text
在大流行中,最大的风险是生命损失,因为保护生命是最重要的事情。
```
大流行中的两个最大风险是什么?
```text
两个最大的风险是生命损失和业务损失。
```
在这一点上,LLM是一致的,并将“生命”和“业务”作为最高的两个风险。现在我们可以继续下一个步骤,并且相当自信。但是,我们不应该盲目地相信LLM,我们应该始终验证输出。
改变输出
LLM的特点是非确定性的,这意味着每次运行相同的提示都会得到不同的结果。例如,尝试以下提示:
“生成一个 Python Web API 的代码”
```text
# 导入必要的模块
import flask
from flask import request, jsonify
# 创建一个Flask应用
app = flask.Flask(__name__)
# 为API创建一个路由
@app.route(</api<, methods=[<GET<])
def api():
# 从请求中获取数据
data = request.args
# 处理数据
result = process_data(data)
# 将结果返回为JSON格式
return jsonify(result)
# 处理数据的函数
def process_data(data):
# 对数据进行操作
result = data + 1
# 返回结果
return result
# 运行应用
if __name__ == <__main__<:
app.run()
```
再次运行相同的提示会得到略有不同的结果:
```text
# 导入必要的包
import flask
from flask import request, jsonify
# 创建 Flask 应用
app = flask.Flask(__name__)
app.config["DEBUG"] = True
# 创建书籍列表
books = [
{'id': 0,
'title': '宇宙之炎',
'author': '弗农·芬格',
'first_sentence': '冷冻睡眠本身是无梦的。',
'year_published': '1992'},
{'id': 1,
'title': '离开奥梅拉斯的人们',
'author': '厄舍拉·凯·勒·吉恩',
'first_sentence': '一阵摇铃声使燕子飞翔,夏季节日来到了沿海高塔之城奥梅拉斯。',
'published': '1973'},
{'id': 2,
'title': '达尔格伦',
'author': '塞缪尔·R·德拉尼',
'first_sentence': '伤害秋季之城。',
'published': '1975'}
]
# 创建 API 的端点
@app.route('/', methods=['GET'])
def home():
return '''<h1>图书 API</h1>
<p>用于检索图书的原型 API。</p>'''
# 创建返回所有书籍的端点
@app.route('/api/v1/resources/books/all', methods=['GET'])
def api_all():
return jsonify(books)
# 创建返回单本书籍的端点
@app.route('/api/v1/resources/books', methods=['GET'])
def api_id():
# 检查 URL 中是否提供了 ID
# 如果提供了 ID,则将其赋值给一个变量
# 如果未提供 ID,则显示错误
if 'id' in request.args:
id = int(request.args['id'])
else:
return "错误:未提供 id 字段,请指定一个 id。"
# 创建一个空列表以存储结果
results = []
# 遍历数据并匹配符合请求的 ID 的结果
# ID 是唯一的,但其他字段可能返回多个结果
for book in books:
if book['id'] == id:
results.append(book)
# 使用 Flask 中的 jsonify 函数将我们的 Python 字典列表转换为 JSON 格式
return jsonify(results)
app.run()
```
那么变化的输出是个问题吗?
这要取决于你想做什么。如果你希望得到特定的响应,那么这是个问题。如果你对像”生成任意三个关于地理学的问题”这样的变化输出感到满意,那么这不是个问题。
使用温度来改变输出
好的,我们决定要限制输出,使其更可预测,即更确定性。我们该如何做到呢?
温度是一个介于0和1之间的值,其中0是最确定性的,1是最多变性的。默认值是0.7。让我们看看两次在温度设为0.1的相同提示下运行会发生什么:
“为 Python Web API 生成代码”
```python
# 导入必要的库
import flask
from flask import request, jsonify
# 创建 Flask 类的实例
app = flask.Flask(__name__)
# 创建 API 的端点
@app.route('/api/v1/endpoint', methods=['GET'])
def api_endpoint():
# 获取请求数据
data = request.get_json()
# 处理数据
result = process_data(data)
# 返回结果
return jsonify(result)
# 处理数据的函数
def process_data(data):
# 处理数据
result = {'result': 'success'}
# 返回结果
return result
# 运行 Flask 应用
if __name__ == '__main__':
app.run()
```
再次运行该提示,我们得到了这个结果:
```python
# 导入必要的库
import flask
from flask import request, jsonify
# 创建一个 Flask 应用
app = flask.Flask(__name__)
# 创建一个 API 的路由
@app.route('/api', methods=['GET'])
def api_call():
# 从请求中获取数据
data = request.get_json()
# 处理数据
result = process_data(data)
# 返回结果
return jsonify(result)
# 定义处理数据的函数
def process_data(data):
# 处理数据
result = data + 1
# 返回结果
return result
# 运行应用
if __name__ == '__main__':
app.run()
```
如您所见,这两个输出之间只有微小的差别。让我们进行相反的尝试,将温度设置为 0.9:
```text
# 导入所需的库
import flask
from flask import request, jsonify
# 创建一个 Flask 应用
app = flask.Flask(__name__)
# 创建一个 API 的路由
@app.route('/api', methods=['GET'])
def api_call():
# 从请求中获取数据
data = request.args
# 处理数据
result = process_data(data)
# 返回结果
return jsonify(result)
# 处理数据的函数
def process_data(data):
# 对数据进行处理
result = data + 1
# 返回结果
return result
# 运行应用
if __name__ == '__main__':
app.run()
```
和第二次运行 0.9 作为温度值的尝试:
```text
import flask
from flask import request, jsonify
# 创建 Flask 应用
app = flask.Flask(__name__)
app.config['DEBUG'] = True
# 创建一些测试数据
books = [
{'id': 0, 'title': 'A Fire Upon The Deep', 'author': 'Vernor Vinge', 'first_sentence': 'The coldsleep itself was dreamless.', 'year_published': '1992'},
{'id': 1, 'title': 'The Ones Who Walk Away From Omelas', 'author': 'Ursula K. Le Guin', 'first_sentence': 'With a clamor of bells that set the swallows soaring, the Festival of Summer came to the city Omelas, bright-towered by the sea.', 'published': '1973'},
{'id': 2, 'title': 'Dhalgren', 'author': 'Samuel R. Delany', 'first_sentence': 'to wound the autumnal city.', 'published': '1975'}
]
# 创建一个端点
@app.route('/', methods=['GET'])
def home():
return '''<h1>Welcome to our book API!</h1>'''
@app.route('/api/v1/resources/books
正如您所见,结果变化非常大。
请注意,您可以更改的参数还有很多,如 top-k、top-p、重复惩罚、长度惩罚和多样性惩罚,但这些超出了本课程安排的范围。
良好实践
当提示LLM时,有许多实践方法可供尝试以获得所需的结果。随着您越来越多地使用提示,您将找到自己的风格。
除了我们已经讨论过的技巧之外,还有一些良好的实践方法,可以在提示LLM时考虑。
以下是一些值得考虑的良好实践方法:
- 指定上下文。上下文很重要,您越详细地指定,如领域、主题等,效果就越好。
- 限制输出。如果您希望具有特定数量的项目或特定长度,请指定它。
- 同时指定“什么”和“如何”。请记住同时提及您想要的内容以及您希望以何种方式,例如“使用产品和客户路由创建一个Python Web API,并将其分解成3个文件”。
- 使用模板。您经常会希望使用来自公司的数据丰富提示。使用模板来实现。模板可以有变量,您可以用实际数据替换这些变量。
- 拼写正确。LLM可能提供了正确的答案,但如果拼写正确,您将得到更好的答案。
作业
以下是使用 Flask 构建简单 API 的 Python 代码:
```python
from flask import Flask, request
app = Flask(__name__)
@app.route('/')
def hello():
name = request.args.get('name', 'World')
return f'Hello, {name}!'
if __name__ == '__main__':
app.run()
```
使用 GitHub Copilot 或 ChatGPT 等AI助手,并应用“自我改进”技巧来改进代码。
答案
请尝试通过向代码添加合适的提示来完成作业。
[!TIP] 构建一个提示以要求它进行改进,对于要改进的内容的数量有所限制是个好主意。您还可以要求以特定的方式进行改进,例如架构、性能、安全等方面。
知识检测
我为什么要使用思维链技术?请给出 1 个正确答案和 2 个错误答案。
- 为了教导LLM如何解决一个问题。
- B,为了教导LLM如何找到代码中的错误。
- C,为了教导LLM提出不同的解决方案。
A:1,因为思维链是通过向LLM提供一系列步骤、类似问题及其解决方法来教导LLM如何解决问题的。
🚀 挑战
您刚刚在作业中使用了自我改进技术。选择您构建的任何程序,并考虑要应用的改进。然后使用自我改进技术应用这些改进。您认为结果会更好还是更差?
出色的工作!继续学习
想要了解更多关于创建高级提示的知识吗?转到持续学习页面查找其他关于此主题的资源。
请继续下一课,我们将应用我们对提示工程的了解,通过构建文本生成应用程序来学习。
本文由极客智坊网页翻译服务自动生成:
原文地址:https://microsoft.github.io/generative-ai-for-beginners/#/05-advanced-prompts/README