# Concept
- LLM과 의사소통 할 수 있는 방법이며, prompt가 좋아야 llm의 성능이 올라간다.
- **LangChain framework의 대부분의 기능도 이 prompt를 만드는 것에 집중되어 있다.**
# Using Template
- Prompt을 만들기 위해서는 Template이 필요하다.
- Template는 크게 `PromptTemplate`, `ChatPromptTemplate`로 나뉜다.
- response를 얻기 위해 `PromptTemplate`는 **predict**을 `ChatPromptTemplate`은 **predict_messages**을 사용하여야 한다.
# Template Type
### PromptTemplate
- PromptTemplate는 string으로부터 template을 만든다.
- 사용자에게 직접적으로 template을 노출시키고 싶지 않고 단어 or 문장만 전달받고 싶을 때 사용한다.
- 각 message 안에는 `{} - placeholder`를 넣을 수 있으며 {}안에 value를 넣어 **변수화** 시킬 수 있다.
- PromptTemplate은 디스크에 save/load가 가능하다.
- 만들어진 Template을 바탕으로 prompt를 만들기 위해 `format` function을 사용한다.
- 변수화된 value는 prompt을 만드는 과정안 format에서 입력할 수 있다.
```python
from langchain.prompts import PromptTemplate
template = PromptTemplate.from_template(
"What is the distance between {country_a} and {country_b}",
)
prompt = template.format(country_a = "Mexico", country_b = "Thailand")
chat.predict(prompt) # prompt is str
```
OR
```python
template = PromptTemplate(
template="What is the capital of {country}",
input_variables={"country"}
)
prompt = template.format(country="France")
```
### ChatPromptTemplate
- ChatPromptTemplate는 message를 통해 template을 만든다.
- `from_messages` function을 사용해 meesage template을 만드는데, parameter는 `system`, `ai`, `human`이 **tuple형태로 들어가있는 List**이다.
- 만들어진 Template을 바탕으로 prompt를 만들기 위해 `format_messages` function을 사용한다.
- 마찬가지로 ChatPromptTemplate에서는 `format_messages`에서 변수화된 value을 넣을 수 있다.
```python
from langchain.prompts import ChatPromptTemplate
template = ChatPromptTemplate.from_messages(
[
("system", "You are a geography expert. And you only reply in {language}"),
("ai", "안녕하세요, 저는 {name}입니다."),
("human","What is the distance between {country_a} and {country_b} Also, what is your name?"),
]
)
prompt = template.format_messages(
language="korea", name="ai", country_a="Mexico", country_b="Thailand"
)
chat.predict_messages(prompt)
```
### FewShotPromptTemplate
- 모델의 response에 대한 예제를 제공하여 예제와 비슷한 방식으로 출력하게 하는 Template
- 예제의 형식을 정하고 형식에 맞는 예제를 토대로 Template을 만든다.
- FewShotPromptTemplate에서 4개의 Parameter가 중요하다.
- example_prompt=example_prompt : 예제의 형식
- examples=examples : 예제
- suffix="Human: What do you about {country}" : User의 답변 형식
- input_variables=`["country"]` : template에 들어가는 value
```python
from langchain.prompts import PromptTemplate
from langchain.prompts.few_shot import FewShotPromptTemplate
examples = [
{
"question": "What do you know about France?",
"answer": """
Here is what I know:
Capital: Paris
Language: French
Food: Wine and Cheese
CurrencyL Euro
""",
},
{
"question": "What do you know about Italy?",
"answer": """
I know this:
Capital: Rome
Language: Italian
Food: Pizza and Pasta
Currency: Euro
""",
},
{
"question": "What do you know about Greece?",
"answer": """
I know this:
Capital: Athens
Language: Greek
Food: Souviaki and Feta Cheese
Currency: Euro
""",
},
]
example_template = """
Human: {question}
AI: {answer}
"""
example_prompt = PromptTemplate.from_template(example_template)
prompt = FewShotPromptTemplate(
example_prompt=example_prompt,
examples=examples,
suffix="Human: What do you about {country}",
input_variables=["country"],
)
chain = prompt | chat
chain.invoke({"country": "Germany"})
```
- example_prompt을 다음과 같이 쓸 수도 있다.
- **template, prompt의 변수명에 헷갈리지 않도록 주의하자.**
```python
example_prompt = PromptTemplate.from_template(example_template)
# OR
example_prompt = PromptTemplate.from_template("Human: {question}\nAI: {answer}")
```
- 예제들이 많은 경우는 비용의 절감과 정확한 response을 위해 **dynamic**하게 예제들을 선별할 필요가 있다.
- example_selector 사용 시, FewShotPromptTemplate Parameter에 exmaple 대신 example_selector을 넣어주어야 한다.
- example_selector은 이미 만들어져 있기도 하지만 필요에 따라 직접 만들 수도 있다.
- `LengthBasedExampleSelector` : exmaple의 개수를 제한하여 가져오는 Selector
- example_prompt=example_prompt : 예제의 형식
- examples=examples : 예제
- max_length=180 : 예제의 총 길이
- `BaseExampleSelector`을 통해 example_selector을 직접 만들 수 있다.
- selector Class가 되기 위해 example_selector Class는 필수적으로 2개의 Function이 필요하다.
- add_example(self, example) : 예제를 추가할 수 있는 함수
- select_examples(self, input_variables) : 예제를 조건에 따라 선택하는 함수
- **LengthBasedExampleSelector**
```python
from langchain.prompts.example_selector import LengthBasedExampleSelector
example_selector = LengthBasedExampleSelector(
example_prompt=example_prompt, examples=examples, max_length=180,
)
prompt = FewShotPromptTemplate(
example_prompt=example_prompt,
example_selector=example_selector,
suffix="Human: What do you about {country}",
input_variables=["country"],
)
```
- **BaseExampleSelector (해당 Code에서는 Random Selector)**
```python
from langchain.prompts.example_selector.base import BaseExampleSelector
class RandomExampleSelector(BaseExampleSelector):
def __init__(self, examples):
self.examples = examples
def add_example(self, example):
self.examples.append(example)
def select_examples(self, input_variables):
from random import choice
return [choice(self.examples)]
example_template = """
Human: {question}
AI: {answer}
"""
example_prompt = PromptTemplate.from_template(example_template)
example_selector = RandomExampleSelector(
examples=examples
)
prompt = FewShotPromptTemplate(
example_prompt=example_prompt,
example_selector=example_selector,
suffix="Human: What do you about {country}",
input_variables=["country"],
)
```
# Load Prompt
- `langchain.prompts import load_prompt`을 통해 `json`이나 `yaml`, `xml`등 여러 파일로 Prompt을 만들어 불러 올 수 있다.
- 당연하게도 해당 파일들은 json형식과 yaml 형식을 만족해야 한다.
- `load_prompt` function을 통해 해당 경로에 있는 파일을 prompt로 만든다.
```python
from langchain.prompts import load_prompt
Json_prompt = load_prompt("./prompt.json")
Yaml_prompt = load_prompt("./prompt.yaml")
```
### Load Json Prompt
- `"_type": "prompt"` : prompt 형식임을 명시해야 한다.
- `"template": "What is the capital of {country}"` : 원하는 형식의 template을 적는다.
- `"input_variables": ["country"]` : tempalte의 value을 명시한다.
```json
{
"_type": "prompt",
"template": "What is the capital of {country}",
"input_variables": [
"country"
]
}
```
### Load Yaml Prompt
- `"_type": "prompt"` : prompt 형식임을 명시해야 한다.
- `"template": "What is the capital of {country}"` : 원하는 형식의 template을 적는다.
- `"input_variables": ["country"]` : tempalte의 value을 명시한다.
```yaml
_type: "prompt"
template: "What is the captial of {country}"
input_variables: ["country"]
```
# Connect Templates
- `from langchain.prompts import PipelinePromptTemplate`을 통해 여러 Templates을 하나로 합칠 수 있다.
- `PipelinePromptTemplate` function안에는 두 개의 Paramemter가 포함되어 있어야 한다.
- `final_prompt=final_Prompt` : Templates을 합칠 최종 Prompt 형식
- `pipeline_prompts=prompts`: 최종 Prompt안에 value **(value)** 들과 template **(key)** 간의 연결정보를 보여주는 prompt 형식
```python
from langchain.prompts import PipelinePromptTemplate
intro = PromptTemplate.from_template(
"""
You are a role playing assistant.
And you are impersonating a {character}
"""
)
example = PromptTemplate.from_template(
"""
This is an example of how you talk:
Human: {example_question}
You: {example_answer}
"""
)
start = PromptTemplate.from_template(
"""
Start now!
Human: {question}
You:
"""
)
final_Prompt = PromptTemplate.from_template(
"""
{intro}
{example}
{start}
"""
)
prompts = [("intro", intro), ("example", example), ("start", start)]
full_Prompt = PipelinePromptTemplate(
final_prompt=final_Prompt, pipeline_prompts=prompts
)
full_Prompt.format(
character="spongebob",
example_question="What is your hobby?",
example_answer="haaaa!, I enjoy catching jellyfish ha haaaa!!!",
question="What do you do on your birthhday?",
)
```