본문으로 건너뛰기

© 2026 Molayo

Dev.to헤드라인2026. 06. 07. 11:15

내 고객 지원 봇이 계속 거짓말을 했다 — 해결 방법은 다음과 같다

요약

고객 지원 봇의 환각(hallucination) 문제를 해결하기 위해 프롬프트 엔지니어링과 단순 FAQ 방식의 한계를 분석합니다. 최종적으로 RAG(검색 증강 생성)와 유사도 임계값을 활용하여 정확도를 높이는 실무적인 해결책을 제시합니다.

핵심 포인트

  • 프롬프트 엔지니어링만으로는 LLM의 환각을 완벽히 제어하기 어려움
  • 단순 FAQ 방식은 유지보수가 어렵고 복잡한 질문 대응에 한계가 있음
  • RAG를 통해 관련 컨텍스트를 검색하여 주입하는 방식이 효과적임
  • 유사도 임계값(Similarity threshold)을 설정하여 모르는 질문에 대한 방어 기제 구축

최근 저는 한 달 동안 고객 지원 봇(customer support bot)을 구축하는 데 시간을 보냈습니다. 이론적으로는 간단했습니다. 사용자의 질문을 받고, 약간의 컨텍스트(context)와 함께 LLM(Large Language Model)에 전달한 뒤, 도움이 되는 답변을 반환하는 것이었습니다. 하지만 실제로 제 봇은 자신만만하게 거짓말을 하는 존재였습니다. 우리가 출시한 적도 없는 기능이 제품에 있다고 사용자에게 말하거나, 존재하지 않는 가격 등급을 인용하기도 했습니다. 눈을 가늘게 뜨고 보면 아주 당황스러운 일은 아닐 수도 있지만, 지원 도구로서 모든 환각(hallucination)은 신뢰를 무너뜨리는 폭탄과 같았습니다.

처음에는 "프롬프트 엔지니어링 (prompt engineering)을 더 해야겠다"라고 생각했습니다. 저는 "당신은 친절한 지원 요원입니다. 제공된 컨텍스트 내에서만 답변하세요. 확실하지 않다면 모른다고 말하세요."와 같은 시스템 메시지(system messages)를 추가했습니다. 하지만 봇은 여전히 거짓말을 하면서도, 확신이 없는 듯한 말투를 구사하는 데에만 더 능숙해졌을 뿐입니다. LLM은 그럴듯한 텍스트를 생성하는 데 매우 탁월합니다. 문장을 보기 좋게 완성할 수만 있다면 기꺼이 전체 환불 정책을 지어내기도 합니다.

시도했지만 실패했던 방법들

저는 몇 가지 막다른 길을 거쳤습니다:

  • 단순 FAQ 조회 (Simple FAQ lookup) – Q&A 쌍 목록에 대한 키워드 매칭(Keyword matching) 방식입니다. 명확한 질문("환불 정책이 무엇인가요?")에는 작동하지만, 문장을 재구성하거나 여러 부분이 포함된 질문에는 실패합니다. 또한, 새로운 제품이 추가됨에 따라 목록을 유지 관리하는 것이 악몽이 되었습니다.
  • 전체 지식 베이스를 포함한 LLM 전용 방식 (LLM-only with full knowledge base) – 모든 도움말 문서를 시스템 프롬프트(system prompt)에 쏟아부었습니다. 봇은 무엇이든 대답할 수 있었지만, 컨텍스트(context)가 비대해지고 혼란스러워졌기 때문에 환각(hallucination)도 더 자주 발생했습니다.
  • 온도 조절 (Temperature tuning) – 온도를 0으로 낮추었더니 봇이 로봇처럼 들릴 뿐이었고, 여전히 동일한 빈도로 잘못된 사실을 생성했습니다.

이 중 어느 것도 핵심적인 문제를 해결하지 못했습니다. 즉, LLM은 자신이 무엇을 알고 있는지 '알지' 못한다는 점입니다. LLM은 텍스트 생성기(text generator)이지, 검색 엔진(retrieval engine)이 아닙니다.

결국 효과가 있었던 방법

저는 검색 증강 생성 (RAG, Retrieval-Augmented Generation) 방식으로 전환했습니다. 핵심적인 변화는 다음과 같습니다. LLM에게 우리의 지식 베이스 (knowledge base)를 기억하라고 요구하는 대신, 임베딩 유사도 (embedding similarity)를 사용하여 가장 관련성이 높은 스니펫 (snippets)을 미리 검색한 다음, 그것들이 충분히 관련이 있을 때 주입하는 것입니다. 만약 높은 유사도 임계값 (similarity threshold)을 통과하는 것이 없다면, 봇은 안전한 "모르겠습니다" 응답으로 대체됩니다.

단순화된 흐름은 다음과 같습니다:

  1. 오프라인 (Offline): 모든 고객 지원 문서를 작은 조각 (200~500자)으로 청킹 (chunking)하고, 각 조각에 대한 임베딩 (embeddings)을 계산하여 벡터 인덱스 (vector index, FAISS)에 저장합니다.
  2. 온라인 (Online): 사용자가 질문을 하면, 질문의 임베딩을 계산하고 인덱스에서 가장 유사한 상위 3개의 청크를 검색합니다.
  3. 유사도 게이트 (Similarity gate): 만약 상위 청크의 유사도 점수가 예를 들어 0.75보다 높다면, 해당 청크들을 컨텍스트 (context)로서 LLM에 전달합니다. 그렇지 않으면 LLM을 건너뛰고 "죄송합니다, 그에 대한 답변을 찾을 수 없습니다. 상담원을 연결해 드리겠습니다."라고 답변합니다.

이 작은 변화가 대부분의 환각 (hallucinations) 현상을 제거했습니다. LLM은 신뢰도가 높은 컨텍스트만을 보게 되며, 게이트는 적절한 컨텍스트가 존재하지 않을 때 LLM이 즉흥적으로 답변하는 것을 방지합니다.

코드: 최소한의 RAG 구현

아래는 단순화된 Python 버전입니다. 청킹은 한 번 실행하여 인덱스를 저장한 다음, 사용자 메시지마다 answer_query를 호출하면 됩니다. 임베딩에는 sentence-transformers를, 검색에는 faiss를 사용했습니다.

import faiss
import numpy as np
from sentence_transformers import SentenceTransformer
...

사용 예시 (모의 LLM 호출):

def mock_llm(prompt):
    # 실제로는 OpenAI, Anthropic 등을 호출하게 됩니다.
    return "제공된 컨텍스트에 기반하면, 답변은 XYZ입니다."
...

교훈 및 트레이드오프 (Lessons Learned & Trade-offs)

  • 임계값 조정 (Threshold tuning)이 매우 중요합니다. 임계값이 너무 낮으면 여전히 환각 (Hallucinations) 현상이 발생합니다. 반대로 너무 높으면 유효한 질문을 놓치고 사용자를 좌절하게 만듭니다 (폴백 (Fallback)이 너무 자주 트리거됨). 저는 오탐 (False positives)을 5% 미만으로 유지하면서 좋은 답변을 최대화하는 임계값을 찾기 위해 200개의 과거 고객 지원 티켓 배치를 실행했습니다.
  • 청크 (Chunk) 품질이 중요합니다. 처음에는 문단 단위로 나누었으나, 임베딩 (Embedding) 과정에서 컨텍스트를 놓쳤습니다. 약 300자의 길이에 50자의 중첩 (Overlap)을 두는 중첩 청크 방식으로 전환하여 검색 (Retrieval) 성능을 개선했습니다.
  • 벡터 검색 (Vector search)은 마법이 아닙니다. 제가 사용한 모델 (all-MiniLM-L6-v2)은 빠르지만, 때때로 도메인 특화 전문 용어 (Domain-specific jargon) 처리에 실패합니다. 튜닝된 모델 (예: 자체 고객 지원 문서를 통한 미세 조정 (Fine-tuning))이 도움이 되겠지만, 이는 더 큰 비용이 드는 작업입니다.
  • 폴백 (Fallback)은 필수적입니다. 훌륭한 검색 파이프라인 (Retrieval pipeline)을 갖추더라도 예외 케이스는 반드시 존재합니다. 상담원에게 연결하는 폴백 기능 덕분에 저희 봇이 골칫덩이가 되는 것을 막을 수 있었습니다. 또한, 시스템 개선을 위한 피드백을 수집하기 위해 "이 답변이 도움이 되었나요?" 버튼을 추가했습니다.

다음에 다시 한다면 다르게 할 점

순수 벡터 검색 (Pure vector search)에 전념하기 전에, 더 단순한 하이브리드 검색 (Hybrid search, BM25 + 임베딩)으로 시작했을 것입니다. BM25는 임베딩이 놓칠 수 있는 정확한 문구 일치 (Exact phrase matches)를 잡아내며, 특히 제품명이나 버전 번호에 효과적입니다. 또한, 첫날부터 자동화된 평가 (Automated evaluations) 체계를 구축하여, 모든 봇 업데이트마다 알려진 정답 Q&A 쌍으로 구성된 테스트 세트를 실행함으로써 성능 저하 (Regressions)를 포착했을 것입니다.

테스트에 사용한 도구 (필수 사항 아님)

참고로, 저는 사용자 상호작용을 시뮬레이션하고 폴백 이벤트를 기록하기 위해 InterWestInfo라는 플랫폼(배경 지식으로 제공해주신 제품 링크)을 사용하여 대화 흐름을 테스트했습니다. 이를 통해 빠르게 반복 (Iterate)할 수 있었지만, 핵심 접근 방식인 유사도 게이트 (Similarity gate)를 활용한 임베딩 검색 (Embedding retrieval)은 도구에 구애받지 않습니다.

여러분의 AI 기능에서는 환각 (Hallucinations) 문제를 어떻게 처리하시나요? 저는 여전히 더 나은 청킹 (Chunking) 전략을 실험 중이며, 곧 하이브리드 검색을 시도해 볼 계획입니다. 여러분의 설정은 어떤 모습인가요?

AI 자동 생성 콘텐츠

본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0