LangChain 문서 RAG 챗봇

김동준·2025년 10월 30일

🤖 LangChain 문서 RAG 챗봇

LangChain 공식 문서를 기반으로 하는 지능형 RAG (Retrieval-Augmented Generation) 챗봇 시스템입니다.

📚 목차

🚀 주요 기능

핵심 기능 (7개)

  1. System Prompt 엔지니어링 - LangChain 문서 전문 시스템 구축
  2. 데이터 수집 - 웹 크롤링 및 구조 기반 문서 파싱
  3. VectorDB 통합 - ChromaDB를 통한 임베딩 저장
  4. RAG 검색/응답 - 하이브리드 검색 (벡터 + SQL)
  5. 대화 메모리 관리 - 대화 컨텍스트 유지 및 메모리 저장
  6. Streamlit UI - 웹 기반 사용자 인터페이스
  7. 통합 main.py - 전체 시스템 통합

추가 기능 (3개)

  1. 성능 평가 - 답변 품질 및 속도 평가
  2. Text-to-SQL RAG - 자연어를 SQL로 변환
  3. 구조 기반 청킹 - 코드 블록과 함수 시그니처 보존 청킹

🏗️ 시스템 아키텍처

┌─────────────────────────────────────────────────────────────┐
│                     Streamlit UI (demo.py)                   │
│                 웹 인터페이스 및 시각화                      │
└────────────────────────┬────────────────────────────────────┘
                         │
                         ▼
┌─────────────────────────────────────────────────────────────┐
│                Main Integration (main.py)                    │
│                 모든 컴포넌트 통합 및 오케스트레이션         │
└────────────────────────┬────────────────────────────────────┘
                         │
     ┌───────────────────┼───────────────────┐
     ▼                   ▼                   ▼
┌─────────────┐   ┌─────────────┐   ┌─────────────┐
│ LLM Manager │   │  Retriever  │   │Conversation │
│  (llm.py)   │   │(retriever.py)│  │   Manager   │
└─────────────┘   └─────────────┘   │(conversation│
                                     │    .py)     │
                                     └─────────────┘
     ┌───────────────────┼───────────────────┐
     ▼                   ▼                   ▼
┌─────────────┐   ┌─────────────┐   ┌─────────────┐
│  Vector DB  │   │Data Collector│  │Text-to-SQL │
│(vector_db.py│   │(data_collector│ │    RAG     │
└─────────────┘   │    .py)      │   │(text_to_sql│
                  └──────────────┘   │    .py)    │
                                     └─────────────┘
     ┌───────────────────┼───────────────────┐
     ▼                   ▼                   ▼
┌─────────────┐   ┌─────────────┐   ┌─────────────┐
│  Evaluator  │   │   Prompts   │   │   Config   │
│(evaluator.py│   │(prompts.py) │   │ Manager    │
└─────────────┘   └─────────────┘   │(config.py) │
                                     └─────────────┘
┌─────────────────────────────────────────────────────────────┐
│                         ▼                                    │
│              Databases & Storage                             │
│                        ▼                                     │
│     ┌──────────────────┴──────────────────┐                │
│     ▼                                      ▼                │
│  ChromaDB                              SQLite               │
│ (Vector Storage)                  (Metadata & Logs)         │
│                                                              │
└─────────────────────────────────────────────────────────────┘

📦 설치 가이드

시스템 요구사항

  • Python 3.10 이상
  • 4GB 이상의 RAM
  • 10GB 이상의 디스크 공간

1. 가상환경 생성 및 활성화

python -m venv venv
source venv/bin/activate  # macOS/Linux
# venv\Scripts\activate  # Windows

2. 의존성 설치

pip install -r requirements.txt

3. 환경 변수 설정

cp .env.example .env
# .env 파일을 열어 API 키 설정

필수 환경변수:

팀작업은 SOLAR_API_KEY

UPSTAGE_API_KEY=your_upstage_api_key_here
DATABASE_URL=sqlite:///./data/langchain.db
CHROMA_PERSIST_DIRECTORY=./data/chroma_db

4. 초기 데이터베이스 설정

python scripts/init_db.py

🎮 사용 방법

웹 UI 실행 (Streamlit)

python main.py
# 또는
streamlit run demo.py

CLI 모드

# 대화 모드
python main.py --mode chat

# 단일 질문
python main.py --mode chat --question "LangChain이 무엇인가요?"

# 데이터 수집
python main.py --mode collect --urls https://python.langchain.com/docs/get_started

# 시스템 평가
python main.py --mode evaluate

# SQL 쿼리
python main.py --mode chat --sql --question "최근 문서 5개를 보여주세요"

Python API 사용

from main import LangChainRAGChatbot

# 챗봇 초기화
chatbot = LangChainRAGChatbot()

# 대화 시작
conversation_id = chatbot.create_new_conversation()

# 질문하기
response = chatbot.chat(
    question="LangChain의 주요 컴포넌트는 무엇인가요?",
    conversation_id=conversation_id
)

print(response['answer'])

💾 데이터베이스 스키마

데이터베이스 개요

  • Database Type: SQLite
  • Location: ./data/langchain.db
  • 총 테이블 수: 7개
  • 현재 데이터: documents 테이블에 63개 LangChain 문서

ER Diagram (Entity Relationship)

documents ─┬─< code_examples (doc_id)
          ├─< api_references (doc_id)
          └─< messages (via conversation)

conversations ─┬─< messages (conversation_id)
              └─< conversation_history (session_id)

evaluations (독립 테이블 - 평가 데이터)

테이블 상세 스키마

1. documents 테이블 (문서 저장)

CREATE TABLE documents (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    doc_id VARCHAR(255) UNIQUE NOT NULL,   -- 문서 고유 ID
    title VARCHAR(500),                    -- 문서 제목
    url TEXT,                              -- 원본 URL
    category VARCHAR(100),                 -- 카테고리 (general, modules, agents 등)
    module_name VARCHAR(200),              -- 모듈 이름
    content TEXT NOT NULL,                 -- 문서 내용 (전체 텍스트)
    summary TEXT,                          -- 문서 요약
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- 인덱스
CREATE INDEX idx_documents_category ON documents(category);
CREATE INDEX idx_documents_created_at ON documents(created_at);

현재 데이터: 63개 레코드 (LangChain 공식 문서)

2. code_examples 테이블 (코드 예제)

CREATE TABLE code_examples (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    doc_id VARCHAR(255),                   -- 관련 문서 ID
    language VARCHAR(50),                  -- 프로그래밍 언어 (python, javascript 등)
    code TEXT NOT NULL,                    -- 코드 내용
    description TEXT,                      -- 코드 설명
    imports TEXT,                          -- import 구문
    FOREIGN KEY (doc_id) REFERENCES documents(doc_id)
);

현재 데이터: 0개 레코드 (추가 예정)

3. api_references 테이블 (API 참조)

CREATE TABLE api_references (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    class_name VARCHAR(200),               -- 클래스 이름
    method_name VARCHAR(200),              -- 메서드 이름
    parameters TEXT,                       -- 파라미터 (JSON 형식)
    return_type VARCHAR(100),              -- 반환 타입
    description TEXT,                      -- 설명
    doc_id VARCHAR(255),                   -- 관련 문서 ID
    FOREIGN KEY (doc_id) REFERENCES documents(doc_id)
);

현재 데이터: 0개 레코드 (추가 예정)

4. conversations 테이블 (대화 세션)

CREATE TABLE conversations (
    id TEXT PRIMARY KEY,                   -- 대화 세션 ID
    title TEXT,                           -- 대화 제목
    summary TEXT,                          -- 대화 요약
    metadata TEXT,                         -- 메타데이터 (JSON)
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

현재 데이터: 0개 레코드

5. messages 테이블 (메시지 기록)

CREATE TABLE messages (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    conversation_id TEXT NOT NULL,         -- 대화 세션 ID
    role TEXT NOT NULL,                    -- 역할 (user, assistant, system)
    content TEXT NOT NULL,                 -- 메시지 내용
    metadata TEXT,                         -- 메타데이터 (JSON)
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (conversation_id) REFERENCES conversations(id)
);

-- 인덱스
CREATE INDEX idx_messages_conversation ON messages(conversation_id);
CREATE INDEX idx_messages_created_at ON messages(created_at);

현재 데이터: 0개 레코드

6. conversation_history 테이블 (대화 이력)

CREATE TABLE conversation_history (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    session_id VARCHAR(255),               -- 세션 ID
    role VARCHAR(50),                      -- 역할 (user, assistant)
    content TEXT,                          -- 대화 내용
    metadata TEXT,                         -- 메타데이터 (JSON)
    timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- 인덱스
CREATE INDEX idx_session_id ON conversation_history(session_id);

현재 데이터: 대화 진행 시 자동 저장

7. evaluations 테이블 (평가 데이터)

CREATE TABLE evaluations (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    question TEXT NOT NULL,                -- 질문
    generated_answer TEXT,                 -- 생성된 답변
    reference_answer TEXT,                 -- 참조 답변
    relevance_score REAL,                  -- 관련성 점수 (0-1)
    accuracy_score REAL,                   -- 정확도 점수 (0-1)
    completeness_score REAL,               -- 완전성 점수 (0-1)
    response_time REAL,                    -- 응답 시간 (초)
    retrieval_precision REAL,              -- 검색 정밀도
    retrieval_recall REAL,                 -- 검색 재현율
    overall_score REAL,                    -- 종합 점수
    metadata TEXT,                         -- 메타데이터 (JSON)
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

현재 데이터: 평가 실행 시 저장

샘플 SQL 쿼리

기본 조회 쿼리

-- 최근 추가된 문서 5개 조회
SELECT title, category, created_at
FROM documents
ORDER BY created_at DESC
LIMIT 5;

-- 특정 카테고리의 문서 개수
SELECT category, COUNT(*) as count
FROM documents
GROUP BY category
ORDER BY count DESC;

-- Agent 관련 문서 검색
SELECT doc_id, title, url
FROM documents
WHERE content LIKE '%Agent%'
  AND category IN ('modules', 'agents');

대화 관련 쿼리

-- 특정 세션의 대화 이력
SELECT role, content, timestamp
FROM conversation_history
WHERE session_id = ?
ORDER BY timestamp ASC;

-- 최근 대화 세션 목록
SELECT id, title, created_at
FROM conversations
ORDER BY created_at DESC
LIMIT 10;

평가 관련 쿼리

-- 평균 성능 지표
SELECT
    AVG(relevance_score) as avg_relevance,
    AVG(accuracy_score) as avg_accuracy,
    AVG(response_time) as avg_response_time
FROM evaluations
WHERE created_at >= datetime('now', '-7 days');

-- 성능이 우수한 질문/답변 쌍
SELECT question, generated_answer, overall_score
FROM evaluations
WHERE overall_score >= 0.8
ORDER BY overall_score DESC
LIMIT 10;

Text-to-SQL 사용 예제

자연어 질문을 SQL로 자동 변환:

from text_to_sql import TextToSQLRAG

sql_rag = TextToSQLRAG()

# 자연어 → SQL
question = "최근 일주일 동안 추가된 문서는 몇 개야?"
sql_query = sql_rag.generate_sql(question)
# 생성된 SQL: SELECT COUNT(*) FROM documents WHERE created_at >= datetime('now', '-7 days')

# SQL 실행
result = sql_rag.execute_sql(sql_query)
print(f"결과: {result.results}")

CREATE TABLE code_examples (
id INTEGER PRIMARY KEY AUTOINCREMENT,
doc_id TEXT NOT NULL, -- documents 테이블 참조
title TEXT, -- 코드 예제 제목
code TEXT NOT NULL, -- 코드 내용
language TEXT DEFAULT 'python', -- 프로그래밍 언어
description TEXT, -- 설명
output TEXT, -- 예상 출력
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (doc_id) REFERENCES documents (doc_id)
);

-- 인덱스
CREATE INDEX idx_code_examples_doc_id ON code_examples(doc_id);
CREATE INDEX idx_code_examples_language ON code_examples(language);


#### 3. api_references 테이블
```sql
CREATE TABLE api_references (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    doc_id TEXT NOT NULL,              -- documents 테이블 참조
    class_name TEXT,                   -- 클래스 이름
    method_name TEXT,                  -- 메서드 이름
    parameters TEXT,                   -- 파라미터 정보 (JSON)
    returns TEXT,                      -- 반환 값
    description TEXT,                  -- 설명
    example_usage TEXT,                -- 사용 예제
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (doc_id) REFERENCES documents (doc_id)
);

-- 인덱스
CREATE INDEX idx_api_references_class ON api_references(class_name);
CREATE INDEX idx_api_references_method ON api_references(method_name);

4. conversations 테이블

CREATE TABLE conversations (
    id TEXT PRIMARY KEY,               -- 대화 세션 ID
    title TEXT,                        -- 대화 제목
    summary TEXT,                      -- 대화 요약
    metadata TEXT,                     -- JSON 형식 메타데이터
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

5. messages 테이블

CREATE TABLE messages (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    conversation_id TEXT NOT NULL,     -- conversations 테이블 참조
    role TEXT NOT NULL,                -- 'user' 또는 'assistant'
    content TEXT NOT NULL,             -- 메시지 내용
    metadata TEXT,                     -- JSON 형식 메타데이터
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (conversation_id) REFERENCES conversations (id)
);

-- 인덱스
CREATE INDEX idx_messages_conversation ON messages(conversation_id);
CREATE INDEX idx_messages_created_at ON messages(created_at);

6. evaluations 테이블

CREATE TABLE evaluations (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    question TEXT NOT NULL,            -- 평가용 질문
    generated_answer TEXT,             -- 생성된 답변
    reference_answer TEXT,             -- 참조 답변
    relevance_score REAL,              -- 관련성 점수 (0-1)
    accuracy_score REAL,               -- 정확도 점수 (0-1)
    completeness_score REAL,           -- 완전성 점수 (0-1)
    response_time REAL,                -- 응답 시간 (초)
    retrieval_precision REAL,          -- 검색 정밀도
    retrieval_recall REAL,             -- 검색 재현율
    overall_score REAL,                -- 종합 점수 (0-1)
    metadata TEXT,                     -- JSON 형식 메타데이터
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- 인덱스
CREATE INDEX idx_evaluations_overall_score ON evaluations(overall_score);
CREATE INDEX idx_evaluations_created_at ON evaluations(created_at);

ChromaDB 컬렉션 구조

langchain_docs 컬렉션

{
    "ids": ["doc_001_chunk_0", "doc_001_chunk_1", ...],
    "embeddings": [[0.1, 0.2, ...], [0.3, 0.4, ...], ...],
    "metadatas": [
        {
            "doc_id": "doc_001",
            "title": "Introduction to LangChain",
            "url": "https://...",
            "category": "tutorials",
            "chunk_index": 0,
            "created_at": "2024-01-01T00:00:00"
        },
        ...
    ],
    "documents": ["LangChain is a framework...", "It provides...", ...]
}

📁 모듈 구조

핵심 모듈 (13개)

  1. llm.py - LLM 및 임베딩 관리

    • Upstage Solar LLM 초기화
    • 임베딩 모델 관리
    • API 키 검증
  2. vector_database.py - 벡터 데이터베이스 관리

    • ChromaDB 초기화 및 관리
    • 문서 추가/검색/삭제
    • 컬렉션 관리
  3. prompts.py - 프롬프트 템플릿 관리

    • 시스템 프롬프트
    • Few-shot 예제
    • 컨텍스트 포맷팅
  4. data_collector.py - 데이터 수집 및 처리

    • 웹 크롤링
    • 문서 파싱
    • 메타데이터 추출
  5. retriever.py - 검색 시스템

    • 하이브리드 검색 (벡터 + SQL)
    • 검색 결과 재순위화
    • LangChain BaseRetriever 구현
  6. conversation.py - 대화 관리

    • 멀티턴 대화 처리
    • 메모리 관리 (Buffer, Summary, Window)
    • 대화 히스토리
  7. text_to_sql.py - Text-to-SQL RAG

    • 자연어를 SQL로 변환
    • 데이터베이스 스키마 인식
    • 쿼리 실행
  8. evaluator.py - 성능 평가

    • 답변 품질 평가
    • 검색 성능 메트릭
    • 배치 평가 지원
  9. demo.py - Streamlit UI

    • 웹 기반 UI 인터페이스
    • 실시간 채팅
    • 설정 관리
  10. main.py - 통합 모듈

    • 전체 시스템 통합
    • CLI/Web 인터페이스
    • 컴포넌트 초기화
  11. utils.py - 유틸리티 함수

    • 텍스트 처리
    • 파일 I/O
    • 시간 관리 도구
  12. config.py - 설정 관리

    • 환경 변수 설정
    • 환경별 구성
    • 설정 검증
  13. requirements.txt - 의존성 목록

📖 API 문서

LangChainRAGChatbot 클래스

초기화

chatbot = LangChainRAGChatbot(config={
    'model_name': 'solar-1-mini-chat',
    'temperature': 0.7,
    'search_mode': 'hybrid',
    'top_k': 5
})

주요 메서드

chat()
response = chatbot.chat(
    question="질문 내용",
    conversation_id="conv_123",  # 선택사항
    use_sql=False,               # SQL 모드
    evaluate=False               # 평가 모드
)
# 반환: {'answer': str, 'sources': list, 'error': str}
collect_documents()
results = chatbot.collect_documents(
    urls=["https://example.com/docs"]
)
# 반환: {'total_documents': int, 'successful_urls': list, 'failed_urls': list}
evaluate_system()
stats = chatbot.evaluate_system(
    test_cases=[
        {'question': '...', 'reference_answer': '...'}
    ]
)
# 반환: {'avg_overall_score': float, 'avg_response_time': float, ...}

🧪 테스트

전체 테스트 실행

python -m pytest tests/ -v

개별 모듈 테스트

# LLM 모듈 테스트
python llm.py

# 벡터 DB 테스트
python vector_database.py

# Retriever 테스트
python retriever.py

# 평가 시스템 테스트
python evaluator.py

통합 테스트

python scripts/test_integration.py

🤝 기여 가이드

브랜치 전략

  • main: 안정화된 버전
  • develop: 개발 버전
  • feature/*: 기능 개발 브랜치
  • hotfix/*: 긴급 수정 브랜치

커밋 메시지 규칙

feat: 새로운 기능 추가
fix: 버그 수정
docs: 문서 수정
style: 코드 포맷팅
refactor: 코드 리팩토링
test: 테스트 추가
chore: 빌드 업무 수정

Pull Request 체크리스트

  • 코드가 스타일 가이드를 준수함
  • 모든 테스트가 통과함
  • 문서가 업데이트됨
  • 성능 영향을 고려함
  • 보안 이슈를 검토함

📋 구조 기반 청킹 전략

개요

LangChain 문서의 특성을 고려한 지능형 텍스트 분할 시스템을 구현했습니다. 코드 블록, 함수 시그니처, Markdown 구조를 보존하면서 효과적으로 문서를 청킹합니다.

핵심 기능

  1. 코드 블록 보존: ``` 코드 블록을 하나의 단위로 유지
  2. 함수/클래스 정의 보존: Python 함수와 클래스를 분할하지 않음
  3. Markdown 구조 인식: 헤더 기반 논리적 섹션 분할
  4. 스마트 오버랩: 코드와 설명 텍스트의 컨텍스트 유지

구현 모듈

  • advanced_text_splitter.py: 구조 기반 텍스트 분할기
    • StructuredTextSplitter: Markdown/코드 구조 인식 분할
    • HTMLStructuredSplitter: HTML 문서 전용 분할
  • data_collector.py: 향상된 크롤러 및 청킹 통합

사용 방법

from advanced_text_splitter import StructuredTextSplitter
from langchain.schema import Document

# 구조 기반 분할기 생성
splitter = StructuredTextSplitter(
    chunk_size=1500,
    chunk_overlap=200,
    preserve_code_blocks=True,
    preserve_functions=True,
    preserve_markdown_structure=True
)

# 문서 분할
doc = Document(page_content=markdown_text, metadata={})
chunks = splitter.split_documents([doc])

# 각 청크는 메타데이터에 구조 정보 포함
for chunk in chunks:
    print(f"타입: {chunk.metadata.get('chunk_type')}")
    print(f"섹션: {chunk.metadata.get('section_title')}")
    print(f"함수들: {chunk.metadata.get('functions', [])}")

청킹 규칙

1. 코드 블록 처리

  • 백틱(```) 코드 블록은 절대 분할하지 않음
  • 코드 블록이 code_block_max_size보다 크면 함수/클래스 단위로 분할
  • 각 코드 청크에 언어 정보와 함수/클래스 이름 메타데이터 추가

2. 계층적 분할

  • Markdown 헤더(#, ##, ###)를 기준으로 섹션 분리
  • 각 섹션을 독립적인 컨텍스트로 처리
  • 섹션 메타데이터: section_title, section_level

3. 메타데이터 강화

청크별 메타데이터:

  • chunk_type: "code", "text", "header", "section"
  • language: 코드 블록의 프로그래밍 언어
  • functions: 포함된 함수 이름 리스트
  • classes: 포함된 클래스 이름 리스트
  • has_code: 코드 포함 여부

성능 비교

항목일반 분할기구조 기반 분할기
코드 블록 보존❌ 분할될 수 있음✅ 완전 보존
함수 정의 유지❌ 중간에 잘림✅ 함수 단위 유지
검색 정확도보통높음
컨텍스트 품질단순 텍스트구조적 컨텍스트

📊 성능 지표

권장 설정

  1. 청크 크기: 1500자 청크, 200자 중복 (구조 기반 청킹)
  2. 검색 설정: Top-5 문서, 하이브리드 검색
  3. 캐싱: 자주 사용되는 쿼리 캐싱
  4. 배치 처리: 임베딩 생성 시 100개 배치
  5. 코드 블록 최대 크기: 3000자 (자동 분할)

벤치마크

  • 응답 시간: 평균 2초 이내
  • 검색 정확도: 85% 이상 (구조 기반 청킹으로 향상)
  • 메모리 사용량: 2GB 이하
  • 코드 예제 정확도: 90% 이상

🔒 보안 고려사항

  1. API 키 관리

    • 환경 변수 사용
    • .env 파일을 .gitignore에 추가
    • 프로덕션에서 시크릿 매니저 사용
  2. 데이터 보호

    • SQLite 데이터베이스 암호화
    • HTTPS 통신 사용
    • 민감정보 마스킹
  3. 접근 제어

    • 인증/인가 구현
    • Rate limiting 적용
    • 입력 검증 강화

🔧 기능 개발 가이드

  1. 이슈 생성 및 논의
  2. 브랜치 생성 (feature/issue-번호)
  3. 코드 작성 및 테스트
  4. 테스트 코드 작성
  5. Pull Request 생성
  6. 코드 리뷰 및 수정
  7. 병합
profile
Story Engineer

0개의 댓글