Prompt Registry: 프롬프트 버전 관리·재사용
Prompt Registry: 프롬프트 버전 관리·재사용
LLM 앱을 운영하다 보면 같은 프롬프트를 여러 팀이 조금씩 다른 버전으로 쓰게 되고, 어느 버전이 프로덕션인지 헷갈리기 쉬워요. MLflow Prompt Registry는 프롬프트를 버전 관리하고, 태그로 정리하고, 조직 전역에서 재사용할 수 있게 해주는 도구예요. Git처럼 커밋 기반 버전 관리와 변경 diff 비교를 지원해서, 프롬프트 개발의 일관성과 협업을 크게 높여줘요.
핵심 기능
- 버전 관리: Git 스타일의 커밋 기반 버전 관리와 diff 하이라이팅 포함 나란히 비교. 프롬프트 버전은 **불변(immutable)**이라 재현성을 보장해요.
- 앨리어싱(Aliasing): 메인 앱 코드와 프롬프트 버전을 분리하고, A/B 테스트나 롤백을 손쉽게 할 수 있는 배포 파이프라인을 만들어요.
- 라인리지(Lineage): MLflow의 Tracing, Evaluation, Monitoring과 자연스럽게 이어져 에이전트 관측성과 품질 개선에 연결돼요.
- 협업: 중앙 레지스트리로 조직 전역에서 프롬프트를 공유하고, 팀이 서로의 작업 위에서 발전시킬 수 있어요.
프롬프트 생성과 관리
UI에서는 MLflow UI의 Prompts 탭에서 Create Prompt 버튼으로 등록할 수 있어요. 프롬프트 템플릿은 {{variable}} 형식의 변수를 담을 수 있고, 이 변수는 앱에서 사용할 때 동적 내용으로 채워져요. LangChain이나 LlamaIndex처럼 단일 중괄호 보간을 쓰는 프레임워크에는 to_single_brace_format() API로 변환해줄 수 있어요.
앱에서 프롬프트를 사용하려면 mlflow.genai.load_prompt()로 불러오고, Prompt.format()으로 변수를 채워요.
import mlflow
import openai
target_text = """MLflow is the largest open source AI engineering platform for agents and LLMs.
It enables teams of all sizes to debug, evaluate, monitor, and optimize production-quality
AI applications, while controlling costs and managing access to LLMs and data.
"""
# 프롬프트 로드
prompt = mlflow.genai.load_prompt("prompts:/summarization-prompt/2")
# LLM과 함께 사용
client = openai.OpenAI()
response = client.chat.completions.create(
messages=[
{
"role": "user",
"content": prompt.format(num_sentences=1, sentences=target_text),
}
],
model="gpt-4o-mini",
)
print(response.choices[0].message.content)
이름, 태그, 다른 레지스트리 필드로 프롬프트를 검색할 수도 있어요.
import mlflow
# Fluent API: 일치하는 프롬프트를 평평한 목록으로 반환
prompts = mlflow.genai.search_prompts(filter_string="task='summarization'")
print(f"Found {len(prompts)} prompts")
# 페이지네이션 제어가 필요하면 클라이언트 API 사용
from mlflow.tracking import MlflowClient
client = MlflowClient()
all_prompts = []
token = None
while True:
page = client.search_prompts(
filter_string="task='summarization'",
max_results=50,
page_token=token,
)
all_prompts.extend(page)
token = page.token
if not token:
break
print(f"Total prompts across pages: {len(all_prompts)}")
Prompt 객체
Prompt 객체는 Prompt Registry의 핵심 엔티티로, 동적 내용용 변수를 담을 수 있는 버전 있는 템플릿 텍스트를 나타내요. 주요 속성은 다음과 같아요.
Name: 프롬프트의 고유 식별자Template: 텍스트 문자열({{variable}}형식) 또는 채팅 메시지 딕셔너리 목록('role'/'content' 키)Version: 프롬프트의 개정을 나타내는 순번Commit Message: Git 커밋 메시지처럼 변경 내용 설명Tags: 분류·필터링용 키-값 쌍Alias: 변경 가능한 명명 참조(예:production앨리어스로 프로덕션 버전 가리키기)is_text_prompt: 텍스트 프롬프트인지 여부response_format: LLM 출력의 기대 구조(검증·구조화에 사용)model_config: 모델명, temperature, max_tokens 등 추론 설정 딕셔너리
텍스트 vs 채팅 프롬프트
텍스트 프롬프트는 이중 중괄호 변수를 담은 단순 문자열 템플릿이에요.
text_template = "Hello {{ name }}, how are you today?"
채팅 프롬프트는 'role'과 'content' 키를 가진 메시지 딕셔너리 목록이에요.
chat_template = [
{"role": "system", "content": "You are a helpful {{ style }} assistant."},
{"role": "user", "content": "{{ question }}"},
]
Jinja2 템플릿
더 고급 템플릿이 필요하면 조건문·반복문·필터를 지원하는 Jinja2도 쓸 수 있어요. 템플릿에 제어 흐름 문법({% %})이 있으면 자동으로 Jinja2 프롬프트로 인식해요.
import mlflow
# 조건문과 반복문이 있는 Jinja2 템플릿
jinja_template = """\
Hello {% if name %}{{ name }}{% else %}Guest{% endif %}!
{% if items %}
Here are your items:
{% for item in items %}
- {{ item }}
{% endfor %}
{% endif %}
"""
# Jinja2 프롬프트 등록
prompt = mlflow.genai.register_prompt(
name="greeting-prompt",
template=jinja_template,
)
# 변수로 포맷
result = prompt.format(name="Alice", items=["Book", "Pen", "Notebook"])
Jinja2 렌더링은 보안을 위해 기본적으로 SandboxedEnvironment를 사용해요. 제한 없는 Jinja2 기능이 필요하면 format()에 use_jinja_sandbox=False를 넘기면 돼요.
모델 설정 저장
프롬프트와 함께 모델별 설정을 저장하면 어떤 모델·파라미터로 이 프롬프트 버전을 썼는지 재현 가능하게 남겨요. 프롬프트와 모델 파라미터를 함께 버전 관리하고, 팀에 권장 모델 설정을 공유할 수 있어요.
import mlflow
# 딕셔너리로 모델 설정
model_config = {
"model_name": "gpt-4",
"temperature": 0.7,
"max_tokens": 1000,
"top_p": 0.9,
}
mlflow.genai.register_prompt(
name="qa-prompt",
template="Answer the following question: {{question}}",
model_config=model_config,
commit_message="QA prompt with model config",
)
# 모델 설정 로드·접근
prompt = mlflow.genai.load_prompt("qa-prompt")
print(f"Model: {prompt.model_config['model_name']}")
print(f"Temperature: {prompt.model_config['temperature']}")