Blog
chatbotragai-agentfine-tuningenterprisellmai

엔터프라이즈 AI 챗봇 구축 가이드 - RAG + Agent + Fine-Tuning 통합

RAG, AI Agent, Fine-Tuning을 결합한 엔터프라이즈 AI 챗봇 구축 방법을 정리합니다. 아키텍처 설계, 대화 관리, 도구 연동, 평가, 운영 모니터링까지 실전 가이드를 제공합니다.

Data Dynamics2026년 4월 16일8 min read

엔터프라이즈 AI 챗봇은 단순한 Q&A를 넘어, 사내 문서 검색, 업무 자동화, 시스템 연동까지 수행하는 종합 AI 어시스턴트입니다. 이 글에서는 RAG + Agent + Fine-Tuning을 결합한 프로덕션 수준의 챗봇 구축 방법을 다룹니다.


1. 엔터프라이즈 챗봇의 요구사항

요구사항설명기술
사내 문서 검색위키, Confluence, 기술 문서 검색RAG
시스템 연동Jira, Slack, DB, 모니터링 연동Agent + Tool Use
도메인 특화 응답사내 기술 스택에 맞는 정확한 응답Fine-Tuning
대화 맥락 유지멀티턴 대화에서 문맥 유지메모리 관리
접근 제어사용자 권한에 따른 정보 접근ACL + 메타데이터 필터
안전성할루시네이션 방지, 유해 콘텐츠 차단가드레일

2. 아키텍처

통합 아키텍처

[엔터프라이즈 AI 챗봇 아키텍처]

사용자 (Slack / Web / Teams)
     ↓
┌────────────────────────────────────────────┐
│  API Gateway (인증, 속도 제한)               │
└───────────────┬────────────────────────────┘
                ↓
┌────────────────────────────────────────────┐
│  대화 관리 서비스                             │
│  ├─ 세션 관리 (Redis)                       │
│  ├─ 의도 분류 → 라우팅                       │
│  └─ 대화 이력 관리                           │
└───────────────┬────────────────────────────┘
                ↓
┌────────────────────────────────────────────┐
│  AI 엔진                                    │
│  ┌──────────┐ ┌──────────┐ ┌──────────┐   │
│  │  RAG     │ │  Agent   │ │ Fine-    │   │
│  │  검색    │ │  도구    │ │ Tuned   │   │
│  │  파이프   │ │  실행    │ │ 모델    │   │
│  │  라인    │ │          │ │          │   │
│  └──────────┘ └──────────┘ └──────────┘   │
│       ↓            ↓                       │
│  [벡터 DB]    [Jira, Slack,               │
│               DB, 모니터링]                │
└───────────────┬────────────────────────────┘
                ↓
┌────────────────────────────────────────────┐
│  가드레일 (입력 검증 + 출력 필터링)            │
└───────────────┬────────────────────────────┘
                ↓
              응답 반환

의도 분류 → 라우팅

def route_query(user_message: str, context: dict) -> str:
    """사용자 질의를 적절한 파이프라인으로 라우팅"""
    classification = classify_intent(user_message)
    
    if classification == "document_search":
        return rag_pipeline(user_message, context)
    
    elif classification == "system_action":
        return agent_pipeline(user_message, context)
    
    elif classification == "general_chat":
        return chat_pipeline(user_message, context)
    
    elif classification == "data_query":
        return text_to_sql_pipeline(user_message, context)
    
    else:
        return "죄송합니다. 질문을 이해하지 못했습니다. 다시 질문해주세요."

3. RAG 파이프라인 (문서 검색)

사내 문서 인덱싱

# 다양한 소스에서 문서 수집 및 인덱싱
sources = {
    "confluence": ConfluenceLoader(url="https://wiki.company.com"),
    "github": GitHubLoader(repos=["company/docs", "company/runbook"]),
    "notion": NotionLoader(token="..."),
    "slack_history": SlackLoader(channels=["#engineering", "#incidents"]),
}
 
all_docs = []
for source_name, loader in sources.items():
    docs = loader.load()
    for doc in docs:
        doc.metadata["source"] = source_name
        doc.metadata["access_level"] = get_access_level(doc)
    all_docs.extend(docs)
 
# 청킹 + 임베딩 + 벡터 DB 저장
chunks = text_splitter.split_documents(all_docs)
vectorstore = Chroma.from_documents(chunks, embeddings)

접근 제어 통합 검색

def secure_rag_search(query: str, user: dict) -> str:
    """사용자 권한에 따른 RAG 검색"""
    # 사용자 권한으로 필터 구성
    access_filter = {
        "access_level": {"$in": user["allowed_levels"]},
        "department": {"$in": user["departments"]}
    }
    
    # 필터링된 검색
    docs = vectorstore.similarity_search(
        query, k=5, filter=access_filter
    )
    
    # LLM으로 응답 생성
    context = format_docs_with_sources(docs)
    response = rag_chain.invoke({"context": context, "question": query})
    
    return response

4. Agent 파이프라인 (업무 자동화)

from langchain_core.tools import tool
 
@tool
def search_jira(query: str) -> str:
    """Jira에서 이슈를 검색합니다."""
    issues = jira_client.search_issues(query, maxResults=5)
    return format_issues(issues)
 
@tool
def create_jira_ticket(title: str, description: str, priority: str) -> str:
    """Jira 티켓을 생성합니다. 사용자 확인 후 실행됩니다."""
    issue = jira_client.create_issue(
        project="ENG", summary=title, description=description, priority=priority
    )
    return f"티켓 생성 완료: {issue.key}"
 
@tool
def query_grafana(metric: str, time_range: str) -> str:
    """Grafana에서 메트릭을 조회합니다."""
    data = grafana_client.query(metric, time_range)
    return format_metrics(data)
 
@tool
def send_slack(channel: str, message: str) -> str:
    """Slack 채널에 메시지를 전송합니다."""
    slack_client.chat_postMessage(channel=channel, text=message)
    return f"메시지 전송 완료: {channel}"
 
# Agent 구성
agent = create_react_agent(
    llm=fine_tuned_llm,  # Fine-Tuned 모델 사용
    tools=[search_jira, create_jira_ticket, query_grafana, send_slack, search_docs],
    prompt="당신은 Data Dynamics의 AI 어시스턴트입니다..."
)

5. Fine-Tuned 모델 통합

[Fine-Tuning 효과]

기반 모델 응답: "Spark에서 OOM이 발생하면 메모리를 늘리세요."

Fine-Tuned 모델 응답: "Spark executor OOM 해결 방법:
1. spark.executor.memory를 8g → 16g로 조정 (Airflow DAG: etl_daily.py 수정)
2. 사내 표준 설정: conf/spark-defaults.conf 참고
3. 데이터 스큐 의심 시: #data-team 채널의 '스큐 해결 가이드' 참고
4. 긴급 시: @oncall-data 멘션으로 당직자 호출"

→ 사내 맥락, 도구, 프로세스를 반영한 응답

6. 대화 관리

멀티턴 대화

class ConversationManager:
    def __init__(self, max_history: int = 20):
        self.sessions = {}  # Redis 기반 세션 관리
        self.max_history = max_history
    
    def get_context(self, session_id: str) -> list:
        """대화 이력 조회 (요약 포함)"""
        history = self.sessions.get(session_id, [])
        
        if len(history) > self.max_history:
            # 오래된 대화 요약
            old = history[:-10]
            summary = llm.invoke(f"다음 대화를 3줄로 요약: {old}")
            history = [{"role": "system", "content": f"이전 대화 요약: {summary}"}] + history[-10:]
            self.sessions[session_id] = history
        
        return history
    
    def add_message(self, session_id: str, role: str, content: str):
        if session_id not in self.sessions:
            self.sessions[session_id] = []
        self.sessions[session_id].append({"role": role, "content": content})

7. 운영 및 모니터링

핵심 지표

지표설명목표
응답 정확도정확한 답변 비율> 85%
1차 해결률추가 질문 없이 해결> 70%
응답 시간평균 응답 지연< 5초
사용자 만족도피드백 긍정 비율> 80%
할루시네이션율부정확한 응답 비율< 5%
DAU일 활성 사용자 수증가 추세

피드백 루프

[지속적 개선 사이클]

1. 사용자 피드백 수집 (좋아요/싫어요 + 코멘트)
     ↓
2. 부정 피드백 분석
   ├─ 검색 실패 → 문서 추가, 청킹 조정
   ├─ 잘못된 응답 → 프롬프트 개선, Fine-Tuning 데이터 추가
   └─ 기능 부재 → 새 도구/API 연동
     ↓
3. 개선 적용 (RAG/프롬프트/모델 업데이트)
     ↓
4. A/B 테스트로 효과 검증
     ↓
5. 반복

참고: 엔터프라이즈 챗봇은 "한 번 구축하고 끝"이 아닙니다. 사내 문서가 업데이트되고, 시스템이 변경되며, 사용자의 기대 수준이 높아지므로, 지속적인 개선 체계가 핵심입니다.


References


— Data Dynamics 엔지니어링 팀