# PAL (프로그램 지원 언어 모델)

import { Callout, FileTree } from "nextra-theme-docs";
import { Screenshot } from "components/screenshot";
import PAL from "../../img/pal.png";

[Gao et al., (2022)](https://arxiv.org/abs/2211.10435)은 프로그램 지원 언어 모델(PAL)이라고 불리며 솔루션을 얻기 위한 자유 형식 텍스트 대신 Python 인터프리터와 같은 프로그램 실행 시 해결 단계를 오프로드합니다.

<Screenshot src={PAL} alt="PAL" />
이미지 출처: [Gao et al., (2022)](https://arxiv.org/abs/2211.10435)

LangChain과 OpenAI GPT-3을 사용한 예를 살펴보겠습니다. 우리는 Python 인터프리터를 활용하여 질문을 해석하고 답변을 제공할 수 있는 간단한 애플리케이션을 개발해야하는 상황이라고 가정해보겠습니다.

특히, 날짜 이해가 필요한 질문에 LLM을 사용하여 답변할 수 있는 기능을 만드는 것에 초점을 맞추겠습니다. 프롬프트에 제공한 몇 가지 예시는 [여기](https://github.com/reasoning-machines/pal/blob/main/pal/prompt/date_understanding_prompt.py)에서 채택했습니다.

다음은 우리가 필요로하는 import 문 입니다:

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

우선 몇 가지 설정을 해보겠습니다:

```python
load_dotenv()

# API 설정
openai.api_key = os.getenv("OPENAI_API_KEY")

# LangChain 설정
os.environ["OPENAI_API_KEY"] = os.getenv("OPENAI_API_KEY")
```

모델 인스턴스를 셋업합니다:

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

설정 프롬프트 + 질문:

```python
question = "오늘은 2023년 2월 27일이야. 나는 정확히 25년전에 태어났어. 내가 태어난 날짜를 MM/DD/YYYY 형식으로 반환해줘"

DATE_UNDERSTANDING_PROMPT = """
# Q: 36시간이 지나면 2015년이야. 오늘로부터 일주일 뒤는 며칠인지 MM/DD/YYYY 형식으로 반환해줘.
# 2015년이 되기까지 36시간이 남았다면 오늘은 36시간 전이다.
today = datetime(2015, 1, 1) - relativedelta(hours=36)
# 오늘부터 일주일 뒤
one_week_from_today = today + relativedelta(weeks=1)
# The answer formatted with %m/%d/%Y is
one_week_from_today.strftime('%m/%d/%Y')
# Q: 2019년의 첫 날은 화요일이고 오늘은 2019년의 첫 번째 월요일이야. 오늘 날짜를 MM/DD/YYY로 반환해줘.
# 2019년의 첫 날이 화요일이고 오늘이 2019년 첫 월요일이라면 오늘은 6일 후입니다.
today = datetime(2019, 1, 1) + relativedelta(days=6)
# %m/%d/%Y 형식으로 포맷팅된 답변은
today.strftime('%m/%d/%Y')
# Q: 콘서트는 1943년 6월 1일에 열리기로 예정되어 있었는데, 하루 연기되어 오늘로 변경됐어. 10일 전 날짜를 MM/DD/YYY 형식으로 반환해줘.
# 콘서트가 1943년 6월 1일로 예정되어 있었으나 오늘로 하루 연기되었다면, 오늘은 하루가 지난 것입니다.
today = datetime(1943, 6, 1) + relativedelta(days=1)
# 열흘 전,
ten_days_ago = today - relativedelta(days=10)
# %m/%d/%Y의 형식으로 반환된 답은
ten_days_ago.strftime('%m/%d/%Y')
# Q: 오늘은 1969년 4월 19일이야. 24시간 후의 날짜를 MM/DD/YYYY 형식으로 반환해줘.
# 오늘의 날짜는 4/19/1969 입니다.
today = datetime(1969, 4, 19)
# 24시간 후,
later = today + relativedelta(hours=24)
# %m/%d/%Y의 형식으로 반환된 답은
today.strftime('%m/%d/%Y')
# Q: Jane은 오늘이 2002년 3월 11일이라고 생각했지만 실제로는 3월 12일이고 하루 뒤야. 24시간 후의 날짜를 MM/DD/YYYY 형식으로 반환해줘.
# 제인은 오늘 날짜를 3/11/2002 라고 생각했고, 사실 오늘은 3월 12일이면 오늘 날짜는 3/1/2002 입니다.
today = datetime(2002, 3, 12)
# 24시간 후,
later = today + relativedelta(hours=24)
# %m/%d/%Y의 형식으로 반환된 답은
later.strftime('%m/%d/%Y')
# Q: Jane은 2001년 2월 마지막 날 태어났어. 오늘은 Jane의 16번째 생일이야. 어제의 날짜를 MM/DD/YYYY 형식으로 반환해줘.
# Jane이 2001년 2월의 마지막 날에 태어났다면 오늘은 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'
```

```python
llm_out = llm(DATE_UNDERSTANDING_PROMPT.format(question=question))
print(llm_out)
```

```python
exec(llm_out)
print(born)
```

다음과 같은 결과를 얻을 수 있습니다: `02/27/1998`
