프롬프트 설계에서 종종 “Few-Shot”이라는 개념을 들어봤을 거다. 이는 모델에게 학습 데이터를 직접 제공하지 않고도, 몇 가지 예제를 통해 문제를 이해하고 응답하도록 하는 방식이다. 오늘은 이 Few-Shot 프롬프트를 구현한 경험과 원리를 간단히 정리해보려고 한다
Few-Shot 프롬프트란, 모델이 특정 입력에 대해 올바른 응답을 생성할 수 있도록 몇 가지 예제를 제공하는 방식이다. 모델은 주어진 예제를 기반으로 패턴을 파악하고, 사용자가 입력한 질문에 맞춰 응답을 생성한다. 이 방식은 대규모 데이터셋 없이도 고성능을 낼 수 있는 게 장점이다.
Few-shot 에서는 다음과 같은 형식으로 프롬프트를 작성한다.
1. 몇가지 예제를 "시스템"역할로 입력
2. 사용자의 질문을 "유저"역할로 입력.
3. 모델의 응답을 "ai"역할로 입력.
먼저, 사용자가 어떤 질문을 할지 예상하고 이에 적합한 응답을 작성한다. 이 예제를 모델에게 제공하면, 모델은 예제에서 학습한 맥락을 기반으로 새로운 입력에 응답하게 된다. 예를 들어:
from langchain_core.prompts import ChatPromptTemplate
example_prompt = ChatPromptTemplate.from_messages(
[
("user", "{question}"),
("ai", "{answer}"),
]
)
여기서 "{question}"과 "{answer}"는 사용자가 입력할 질문과 모델이 생성할 응답을 나타낸다.
few_examples = [
{
"question":"타지키스탄 국제협력업무 회장은 누구야?",
"answer" : """
```json
{
"valid": true,
"year_importance": 0,
"person_importance": 8,
"past_importance": 0,
"other_importance": 8,
"which_year": 0,
"related_list_of_people": false,
"other_q": ["타지키스탄 국제협력의 주요 인물은 누구인가요?", "타지키스탄 국제협력의 성과는 무엇인가요?"]
}
```
"""
},
...
]
실제예제들이 담긴 few_examples
from langchain_core.example_selectors import SemanticSimilarityExampleSelector
example_selector = SemanticSimilarityExampleSelector.from_examples(
examples=few_examples,
embeddings=get_embeddings(), # 임베딩
vectorstore_cls=get_fewshot_vectorstore(), # 예제를 저장하고 검색할 벡터 스토어
k=2, # 유사한 예제 2개를 선택
)
주요 매개변수 설명:
작동 원리:
from langchain_core.prompts import FewShotChatMessagePromptTemplate
few_shot_prompt = FewShotChatMessagePromptTemplate(
example_selector=example_selector, # 질문과 유사한 예제를 선택하는 로직
example_prompt=example_prompt # 예제의 형식을 정의한 템플릿
)
작동 원리:
final_prompt에서 few_shot_prompt를 포함하면, 모델이 정해진 패턴에 따라 질문에 응답하는 방식을 학습할 수 있다.
Few-Shot 방식은 전체 데이터셋을 미리 학습시키는 대신, 프롬프트 자체에 중요한 예제를 포함시키는 방법이다.
final_prompt = ChatPromptTemplate.from_messages(
[
("system", "여기 시스템 메시지가 들어간다."),
few_shot_prompt,
("user", "{question}")
]
)
주요 구성:
작동 흐름:
API 요청을 처리하는 함수로, 주로 모델과의 상호작용에 사용된다.
def ollama_request(messages):
"""
Example API 요청 함수
"""
data = {
"model": "gemma2:2b", # LLM 모델 설정
"messages": messages,
"device": "cuda",
"temperature": 0,
"top_p": 0.5,
}
response = requests.post("http://localhost:11434/api/chat", json=data)
if response.status_code != 200:
print(f"Error: API returned status code {response.status_code}")
print(f"Response text: {response.text}")
return None # 오류 발생 시 None 반환
return response.json()
작동 원리:
extract_json_from_text 함수는 모델이 반환한 JSON 형식의 텍스트에서 데이터를 추출한다.
def extract_json_from_text(text):
"""
텍스트에서 JSON 데이터를 추출하는 함수.
"""
try:
print(f"Extracting JSON from text: {text}") # 원본 텍스트 출력 (디버깅용)
# JSON 형태의 텍스트가 있다면, 중괄호를 기준으로 데이터 추출
if "{{" in text and "}}" in text:
text = text.replace("{{", "{").replace("}}", "}") # 중복 중괄호 제거
start = text.find('{')
end = text.rfind('}') + 1
if start != -1 and end != -1:
json_str = text[start:end] # JSON 텍스트 추출
return json.loads(json_str) # JSON 디코딩
else:
print("No JSON format found in text.")
return None # JSON 형식이 없을 경우
except json.JSONDecodeError as e:
print(f"JSON decoding error: {e}")
return None # JSON 디코딩 실패 시
개선할 점:
def get_response_data(question):
extract_json_from_text
# 'final_prompt'를 포맷팅
formatted_prompt = final_prompt.format(question=question)
# 메시지를 API로 전달
response = ollama_request([
{"role": "system", "content": formatted_prompt},
{"role": "user", "content": question}
])
# 응답 텍스트에서 JSON 데이터 추출
parsed_data = extract_json_from_text(response['message']['content'])
return parsed_data
{
"valid": true,
"year_importance": 0,
"person_importance": 0,
"past_importance": 5,
"other_importance": 10,
"which_year": 2024,
"related_list_of_people": false,
"other_q": [
"타지키스탄 협력 사업의 주요 성과는 무엇인가요?",
"2024년 타지키스탄 협력 계획은 어떻게 진행되고 있나요?"
]
}
너무 유익하네요 추가적인 포스팅을 기다립니다 : )