跳到主要内容

程序辅助的语言模型(PAL)

Gao et al., (2022) 提出了一种利用LLMs来阅读自然语言问题并生成程序作为中间推理步骤的方法。被称为程序辅助语言模型(PAL),它不同于思维链提示,它不是使用自由形式文本来获得解决方案,而是将解决步骤转移到诸如Python解释器之类的程序运行时。

PAL 图片来源:Gao et al., (2022)

让我们通过LangChain和OpenAI GPT-3来看一个示例。我们有兴趣开发一个简单的应用程序,能够解释所提出的问题,并通过利用Python解释器提供答案。

具体来说,我们有兴趣创建一个功能,允许LLM回答需要日期理解的问题。我们将向LLM提供一个提示,其中包含一些示例,这些示例取自这里

这是我们需要导入的内容:

import openai
from datetime import datetime
from dateutil.relativedelta import relativedelta
import os
from langchain.llms import OpenAI
from dotenv import load_dotenv

让我们首先配置一些内容:

load_dotenv()

# API配置
openai.api_key = os.getenv("OPENAI_API_KEY")

# 对于LangChain
os.environ["OPENAI_API_KEY"] = os.getenv("OPENAI_API_KEY")

设置模型实例:

llm = OpenAI(model_name='text-davinci-003', temperature=0)

设置提示 + 问题:

question = "今天是2023年2月27日。我出生在25年前的这一天。我出生的日期是几月几号几年?"

DATE_UNDERSTANDING_PROMPT = """
# Q: 2015年还有36小时就要到来。从今天算起一周后是几月几号几年?
# 如果2015年还有36小时就要到来,那么今天就是36小时之前。
today = datetime(2015, 1, 1) - relativedelta(hours=36)
# 一周后,
one_week_from_today = today + relativedelta(weeks=1)
# 以%m/%d/%Y格式化的答案是
one_week_from_today.strftime('%m/%d/%Y')
# Q: 2019年的第一天是星期二,今天是2019年的第一个星期一。今天是几月几号几年?
# 如果2019年的第一天是星期二,今天是2019年的第一个星期一,那么今天是6天之后。
today = datetime(2019, 1, 1) + relativedelta(days=6)
# 以%m/%d/%Y格式化的答案是
today.strftime('%m/%d/%Y')
# Q: 音乐会原定于1943年06/01举行,但推迟了一天。10天前是几月几号几年?
# 如果音乐会原定于1943年06/01举行,但推迟了一天,那么今天就是推迟一天后。
today = datetime(1943, 6, 1) + relativedelta(days=1)
# 10天前,
ten_days_ago = today - relativedelta(days=10)
# 以%m/%d/%Y格式化的答案是
ten_days_ago.strftime('%m/%d/%Y')
# Q: 今天是1969年4月19日。24小时后是几月几号几年?
# 今天是1969年4月19日。
today = datetime(1969, 4, 19)
# 24小时后,
later = today + relativedelta(hours=24)
# 以%m/%d/%Y格式化的答案是
today.strftime('%m/%d/%Y')
# Q: 简以为今天是2002年3月11日,但实际上是3月12日,比她想的晚了1天。24小时后是几月几号几年?
# 如果简以为今天是2002年3月11日,但实际上是3月12日,那么今天就是2002年3月12日。
today = datetime(2002, 3, 12)
# 24小时后,
later = today + relativedelta(hours=24)
# 以%m/%d/%Y格式化的答案是
later.strftime('%m/%d/%Y')
# Q: 简于2001年2月最后一天出生。今天是她16岁生日。昨天是几月几号几年?
# 如果简于2001年2月最后一天出生,今天是她16岁生日,那么今天就是16年后。
today = datetime(2001, 2, 28) + relativedelta(years=16)
# 昨天,
yesterday = today - relativedelta(days=1)
# 以%m/%d/%Y格式化的答案是
yesterday.strftime('%m/%d/%Y')
# Q: {question}
""".strip() + '\n'
llm_out = llm(DATE_UNDERSTANDING_PROMPT.format(question=question))
print(llm_out)

这将输出以下内容:

# 如果今天是2023年2月27日,我出生在25年前的这一天,那么我出生在25年前。
today = datetime(2023, 2, 27)
# 我出生在25年前,
born = today - relativedelta(years=25)
# 以%m/%d/%Y格式化的答案是
born.strftime('%m/%d/%Y')

llm_out的内容是一个Python代码片段。下面,使用exec命令来执行这个Python代码片段。

exec(llm_out)
print(born)

这将输出以下内容:02/27/1998