PromptBuilder
PromptBuilder
파이프라인에서 Generator 앞에 두고, 프롬프트 템플릿을 렌더링해 변숫값을 채워 넣는 컴포넌트가 PromptBuilder예요.
| 항목 | 내용 |
|---|---|
| 파이프라인에서의 위치 | 질의(querying) 파이프라인에서 Generator 앞 |
| 필수 init 변수 | template: Jinja2 문법을 쓰는 프롬프트 템플릿 문자열 |
| 필수 run 변수 | **kwargs: 프롬프트 템플릿을 렌더링하는 데 쓸 문자열들. Variables 섹션 참고 |
| 출력 변수 | prompt: 렌더링된 프롬프트 템플릿을 나타내는 문자열 |
| API 레퍼런스 | Builders |
| GitHub 링크 | https://github.com/deepset-ai/haystack/blob/main/haystack/components/builders/prompt_builder.py |
| 패키지명 | haystack-ai |
출처: 공식문서
개요 (Overview)
PromptBuilder는 프롬프트 템플릿으로 초기화된 뒤, 키워드 인자(kwargs)로 넘어온 값을 채워 넣어 템플릿을 렌더링해요. kwargs를 쓰면 변수 개수에 제한 없이 전달할 수 있어서, 템플릿에 등장하는 모든 변수에 원하는 값을 지정할 수 있어요. 템플릿 안의 모든 변수에는 kwargs를 통해 값을 반드시 제공해야 하죠.
초기화 시 PromptBuilder에 넘기는 템플릿은 Jinja2 템플릿 언어 규칙을 따라야 해요.
변수 (Variables)
init 템플릿에서 발견되는 템플릿 변수들은 컴포넌트의 입력 타입으로 사용돼요. 기본적으로 required_variables 값이 "*"로 설정돼서 템플릿의 모든 변수가 필수가 돼요. 런타임에 하나라도 빠지면 컴포넌트는 에러를 내고 실행을 멈춰요.
required_variables와 variables로 입력 타입과 필수 변수를 지정할 수 있어요.
-
required_variables- 컴포넌트가 실행될 때 반드시 제공돼야 하는 템플릿 변수를 정의해요.
- 필수 변수가 하나라도 없으면 에러를 내고 실행을 멈춰요.
- 지정 방법은 다양해요:
"*"(기본값)를 쓰면 템플릿의 모든 변수를 필수로, 또는- 필수 변수 이름 목록(예:
["query"])을 넘기면 그 변수들만 필수로 만들고 나머지는 선택으로, 또는 - 빈 목록(
[])이나None을 넘기면 모든 변수를 선택으로 만들어요.None을 명시하면 경고 로그가 찍히는데, 빠진 변수를 조용히 빈 문자열로 대체하면 특히 복잡한 파이프라인에서 예상치 못한 동작이 생길 수 있어서예요.
-
variables- 필수든 선택이든 템플릿에 등장할 수 있는 모든 변수를 나열해요.
- 제공되지 않은 선택 변수는 렌더링된 프롬프트에서 빈 문자열로 대체돼요.
- 덕분에 어떤 변수가 필수로 표시돼 있지 않은 한, 오류 없이 부분 프롬프트를 만들 수 있어요.
from haystack.components.builders import PromptBuilder
# All variables required (the default, equivalent to required_variables="*")
builder = PromptBuilder(
template="Hello {{name}}! {{greeting}}",
)
# Some variables required
builder = PromptBuilder(
template="Hello {{name}}! {{greeting}}",
required_variables=["name"], # 'greeting' becomes optional
)
# All variables optional (missing ones default to empty string)
builder = PromptBuilder(
template="Hello {{name}}! {{greeting}}",
required_variables=[], # explicit None also works but logs a warning
)
컴포넌트는 필수 입력만 갖춰지면 바로 실행돼요.
Jinja2 시간 확장 (Time Extension)
PromptBuilder는 Jinja2 TimeExtension을 지원해서 datetime 형식을 다룰 수 있어요.
시간 확장은 크게 두 가지 기능을 제공해요.
- 현재 시각을 얻을 수 있는
now태그, - Python의 datetime 모듈을 통한 날짜·시간 포맷 기능.
Jinja2 TimeExtension을 쓰려면 의존성을 설치해야 해요.
pip install arrow>=1.3.0
now 태그
now 태그는 현재 시각을 나타내는 datetime 객체를 만든 뒤 변수에 저장할 수 있게 해줘요.
{% now 'utc' as current_time %}
The current UTC time is: {{ current_time }}
다른 시간대도 지정할 수 있어요.
{% now 'America/New_York' as ny_time %}
The time in New York is: {{ ny_time }}
시간대를 지정하지 않으면 시스템의 로컬 시간대가 사용돼요.
{% now as local_time %}
Local time: {{ local_time }}
날짜 포맷 (Date Formatting)
datetime 객체는 Python의 strftime 문법으로 포맷할 수 있어요.
{% now as current_time %}
Formatted date: {{ current_time.strftime('%Y-%m-%d %H:%M:%S') }}
자주 쓰는 포맷 코드는 이러해요.
%Y: 4자리 연도 (예: 2025)%m: 0으로 채운 월 (01-12)%d: 0으로 채운 일 (01-31)%H: 0으로 채운 시(24시간제) (00-23)%M: 0으로 채운 분 (00-59)%S: 0으로 채운 초 (00-59)
예시
from haystack.components.builders import PromptBuilder
# Define template using Jinja-style formatting
template = """
Current date is: {% now 'UTC' %}
Thank you for providing the date
Yesterday was: {% now 'UTC' - 'days=1' %}
"""
builder = PromptBuilder(template=template)
result = builder.run()["prompt"]
사용법 (Usage)
단독으로 쓰기
아래는 PromptBuilder로 프롬프트 템플릿을 렌더링하고 target_language와 snippet을 채워 넣는 예시예요. PromptBuilder는 Translate the following context to spanish. Context: I can't speak spanish.; Translation: 문자열이 담긴 프롬프트를 반환해요.
from haystack.components.builders import PromptBuilder
template = "Translate the following context to {{ target_language }}. Context: {{ snippet }}; Translation:"
builder = PromptBuilder(template=template)
builder.run(target_language="spanish", snippet="I can't speak spanish.")
파이프라인에서 쓰기
아래는 RAG 파이프라인 예시예요. PromptBuilder로 커스텀 프롬프트 템플릿을 렌더링하고, 검색된 문서 내용과 질문으로 채워 넣은 뒤 그 프롬프트를 Generator로 보내요.
from haystack import Pipeline, Document
from haystack.utils import Secret
from haystack.components.generators.chat import OpenAIChatGenerator
from haystack.components.builders.prompt_builder import PromptBuilder
# in a real world use case documents could come from a retriever, web, or any other source
documents = [
Document(content="Joe lives in Berlin"),
Document(content="Joe is a software engineer"),
]
prompt_template = """
Given these documents, answer the question.\nDocuments:
{% for doc in documents %}
{{ doc.content }}
{% endfor %}
\nQuestion: {{query}}
\nAnswer:
"""
p = Pipeline()
p.add_component(instance=PromptBuilder(template=prompt_template), name="prompt_builder")
p.add_component(
instance=OpenAIChatGenerator(api_key=Secret.from_env_var("OPENAI_API_KEY")),
name="llm",
)
p.connect("prompt_builder", "llm")
question = "Where does Joe live?"
result = p.run({"prompt_builder": {"documents": documents, "query": question}})
print(result)
런타임에 템플릿 바꾸기 (프롬프트 엔지니어링)
PromptBuilder는 기존 파이프라인의 프롬프트 템플릿을 바꿔 끼울 수 있게 해줘요. 아래 예시는 앞 섹션의 기존 파이프라인 위에 새 프롬프트 템플릿을 넣어 호출하는 모습이에요.
documents = [
Document(content="Joe lives in Berlin", meta={"name": "doc1"}),
Document(content="Joe is a software engineer", meta={"name": "doc1"}),
]
new_template = """
You are a helpful assistant.
Given these documents, answer the question.
Documents:
{% for doc in documents %}
Document {{ loop.index }}:
Document name: {{ doc.meta['name'] }}
{{ doc.content }}
{% endfor %}
Question: {{ query }}
Answer:
"""
p.run(
{
"prompt_builder": {
"documents": documents,
"query": question,
"template": new_template,
},
},
)
기본 템플릿과 다른 변수를 프롬프트 엔지니어링 때 쓰고 싶다면, PromptBuilder의 variables init 파라미터를 그에 맞게 설정하면 돼요.
런타임에 변수 덮어쓰기
변숫값을 덮어쓰고 싶다면 런타임에 template_variables를 사용할 수 있어요. 아래처럼요.
language_template = """
You are a helpful assistant.
Given these documents, answer the question.
Documents:
{% for doc in documents %}
Document {{ loop.index }}:
Document name: {{ doc.meta['name'] }}
{{ doc.content }}
{% endfor %}
Question: {{ query }}
Please provide your answer in {{ answer_language | default('English') }}
Answer:
"""
p.run(
{
"prompt_builder": {
"documents": documents,
"query": question,
"template": language_template,
"template_variables": {"answer_language": "German"},
},
},
)
여기서 language_template이 도입한 answer_language 변수는 어떤 파이프라인 변수에도 묶여 있지 않아요. 달리 설정하지 않으면 기본값인 "English"가 쓰여요. 이 예시에서는 그 값을 "German"으로 덮어썼죠. template_variables는 documents 같은 파이프라인 변수도 덮어쓸 수 있어요.
YAML에서 쓰기
아래는 앞서 본 RAG 파이프라인의 YAML 표현이에요. 검색된 문서 내용과 질문으로 커스텀 프롬프트 템플릿을 렌더링한 뒤, 그 프롬프트를 생성기로 보내요.
components:
llm:
init_parameters:
api_base_url: null
api_key:
env_vars:
- OPENAI_API_KEY
strict: true
type: env_var
generation_kwargs: {}
http_client_kwargs: null
max_retries: null
model: gpt-5-mini
organization: null
streaming_callback: null
timeout: null
tools: null
tools_strict: false
type: haystack.components.generators.chat.openai.OpenAIChatGenerator
prompt_builder:
init_parameters:
required_variables: '*'
template: "\n Given these documents, answer the question.\nDocuments:\n \
\ {% for doc in documents %}\n {{ doc.content }}\n {% endfor %}\n\
\n \nQuestion: {{query}}\n \nAnswer:\n "
variables: null
type: haystack.components.builders.prompt_builder.PromptBuilder
connection_type_validation: true
connections:
- receiver: llm.messages
sender: prompt_builder.prompt
max_runs_per_component: 100
metadata: {}
더 알아보기 (Learn more)
🧑🍳 쿡북: