RAG 서비스를 위한 프롬프트 엔지니어링
지난 글에서 RAGAS로 RAG 시스템의 답변 품질을 정량적으로 평가하는 방법을 다뤘습니다. 그런데 검색과 평가 체계를 다 갖췄어도, 정작 검색된 문서를 LLM에게 어떻게 전달하는지에 따라 답변 품질이 크게 달라집니다. 이번 글에서는 RAG 서비스에 특화된 프롬프트 엔지니어링 기법을 정리합니다.
1. 일반 프롬프트와 RAG 프롬프트는 무엇이 다른가
일반적인 LLM 프롬프트는 질문만 잘 던지면 되지만, RAG 프롬프트는 검색된 문서를 어떻게 배치하고, 얼마나 강하게 "문서에만 근거하라"고 지시하느냐가 답변 품질을 좌우합니다.
[일반 프롬프트]
"재택근무는 주 몇 회까지 가능해?"
→ 모델이 학습 데이터 기반으로 그럴듯한 답을 생성 (Hallucination 위험)
[RAG 프롬프트]
"다음 문서를 참고해서 질문에 답해줘.
[문서] 재택근무는 팀장 승인 하에 주 2회까지 가능합니다.
[질문] 재택근무는 주 몇 회까지 가능해?"
→ 문서에 근거한 답변 유도RAG 프롬프트의 목적은 모델의 창의성을 억제하고, 주어진 문서 범위 안에서만 답하도록 강하게 제약하는 데 있습니다.
2. 근거 없는 답변을 막는 지침 명시하기
지난 글에서 다룬 Faithfulness(충실도)를 높이는 가장 직접적인 방법은, 문서에 없는 내용은 답하지 말라고 명확하게 지시하는 것입니다.
다음 문서를 참고해서 질문에 답변해줘.
규칙:
1. 반드시 아래 문서 내용에 근거해서만 답변할 것
2. 문서에 없는 내용은 추측하지 말고 "제공된 문서에서 답을 찾을 수 없습니다"라고 답할 것
3. 문서에 있는 내용이라도 질문과 무관한 부분은 답변에 포함하지 말 것
[문서]
{context}
[질문]
{question}이렇게 규칙을 명시적으로 나열하면, 모델이 애매한 상황에서 그럴듯하게 지어내는 대신 "모른다"고 답하는 비율이 눈에 띄게 올라갑니다.
3. 출처를 답변에 포함시키기
사용자가 답변을 신뢰할 수 있으려면, 어떤 문서를 근거로 답했는지 함께 보여주는 것이 좋습니다.
다음 문서들을 참고해서 질문에 답변해줘. 답변 마지막에는 참고한 문서 번호를 표시해줘.
[문서 1] 재택근무는 팀장 승인 하에 주 2회까지 가능합니다.
[문서 2] 재택근무 신청은 인사 시스템을 통해 이루어집니다.
[질문]
재택근무는 어떻게 신청하나요?
[답변 형식]
답변 내용...
(출처: 문서 2)def format_context_with_source(docs):
return "\n\n".join(
f"[문서 {i+1}] {doc.page_content}"
for i, doc in enumerate(docs)
)
각 청크에 번호를 매겨 프롬프트에 넣고, 모델이 답변 끝에 어떤 번호를 참고했는지 표기하도록 요청하면 됩니다. 이 정보는 UI에서 "출처 보기" 같은 기능으로도 바로 연결할 수 있습니다.
4. 검색 결과가 없을 때의 처리
검색된 문서의 유사도 점수가 낮으면, 애초에 관련 문서를 못 찾은 상황일 수 있습니다. 이럴 때는 LLM에게 넘기기 전에 미리 걸러내는 것이 안전합니다.
def build_context(docs, threshold=0.7):
relevant_docs = [doc for doc in docs if doc.similarity_score >= threshold]
if not relevant_docs:
return None
return "\n\n".join(doc.page_content for doc in relevant_docs)
context = build_context(retrieved_docs)
if context is None:
answer = "죄송합니다. 관련된 정보를 찾을 수 없습니다."
else:
answer = rag_chain.invoke({"context": context, "question": question})
유사도 임계값 아래의 문서만 검색됐다면 LLM 호출 자체를 생략하고 정해진 안내 문구를 반환하는 방식입니다. 불필요한 LLM 호출 비용을 줄이면서, 관련 없는 문서를 억지로 근거 삼아 답변하는 상황도 함께 방지할 수 있습니다.
5. Few-shot 예시로 답변 형식 고정하기
답변의 톤이나 형식을 일관되게 유지하고 싶다면, 프롬프트에 예시 몇 개를 미리 넣어두는 Few-shot 방식이 효과적입니다.
아래 예시처럼 간결하고 정중한 톤으로 답변해줘.
예시 1
질문: 연차는 며칠 사용할 수 있나요?
답변: 입사 1년 이상이시면 연 15일의 연차를 사용하실 수 있습니다. (출처: 문서 1)
예시 2
질문: 출장비 정산은 어떻게 하나요?
답변: 출장비는 정산 시스템에 영수증을 첨부해 신청하시면 됩니다. (출처: 문서 3)
이제 아래 질문에 같은 형식으로 답변해줘.
[문서]
{context}
[질문]
{question}예시 2개 정도만 넣어도 답변의 어투와 출처 표기 형식이 훨씬 안정적으로 유지됩니다.
6. 프롬프트 버전 관리의 필요성
지난 글에서 다룬 RAGAS 평가 지표와 프롬프트를 함께 놓고 보면, 프롬프트를 수정할 때마다 지표가 어떻게 변하는지 추적할 필요가 있습니다.
| 프롬프트 버전 | Faithfulness | Answer Relevancy | 비고 |
|---|---|---|---|
| v1 (규칙 없음) | 0.71 | 0.80 | Hallucination 종종 발생 |
| v2 (근거 강제 규칙 추가) | 0.89 | 0.79 | 충실도 개선, 관련성은 유지 |
| v3 (Few-shot 추가) | 0.90 | 0.91 | 형식 일관성까지 개선 |
프롬프트를 감이나 느낌으로 수정하기보다는, 변경 전후로 평가 지표를 비교하면서 실제로 개선되고 있는지 확인하는 습관이 중요합니다.
7. 정리
- RAG 프롬프트의 핵심은 모델이 검색된 문서 범위를 벗어나지 않도록 명확한 규칙으로 제약하는 것입니다.
- 답변에 출처를 함께 표기하고, 검색 결과가 부실하면 LLM 호출 전에 미리 걸러내는 방어 로직을 두면 신뢰도가 올라갑니다.
- Few-shot 예시로 답변 형식을 고정하고, 프롬프트 변경 시마다 RAGAS 지표로 효과를 검증하면 개선 방향을 객관적으로 판단할 수 있습니다.
여기까지 LLM의 한계에서 시작해서 RAG 개념, 임베딩, 벡터 검색, pgvector 실습, 청킹, LangChain 파이프라인, Reranking, 평가, 프롬프트 엔지니어링까지 RAG의 전체 사이클을 한 바퀴 돌아봤습니다. 다음 시리즈에서는 이렇게 만든 RAG 시스템을 실제 Spring Boot 서비스에 연동하는 과정을 다뤄보겠습니다.
'RAG를 활용한 LLM 서비스 구축' 카테고리의 다른 글
| STEP 14 - RAG 챗봇 트래픽 대응하기 (0) | 2026.07.10 |
|---|---|
| STEP 13 - Spring Boot에 RAG 연동하기 (0) | 2026.07.10 |
| STEP 11 - 답변 품질을 측정하는 방법 (0) | 2026.07.09 |
| STEP 10 - 검색 정확도를 높이는 방법 (0) | 2026.07.08 |
| STEP 9 - LangChain으로 RAG 파이프라인 처음부터 구축하기 (0) | 2026.07.08 |