LangChain4j의 RetrievalAugmentor 심층 분석

1. 핵심 개념

LangChain4j에서 RetrievalAugmentor는 RAG(Retrieval-Augmented Generation, 검색 증강 생성) 파이프라인의 핵심 진입점 컴포넌트입니다. 이 컴포넌트는 외부 지식 베이스에서 관련 콘텐츠를 동적으로 사용자 쿼리에 주입하여 LLM(대형 언어 모델)에 실시간 컨텍스트 지원을 제공합니다. RetrievalAugmentor의 주요 가치는 LLM의 정적 지식 한계 문제를 해결하며, 검색을 통해 외부 데이터(문서, 데이터베이스 등)를 활용하여 생성 결과의 정확성과 최신성을 향상시킵니다.

2. 주요 기능

2.1 콘텐츠 검색 및 주입

  • 벡터 데이터베이스(Milvus, Redis 등) 또는 외부 지식 소스(Wikipedia, 기업 문서 등)에서 사용자 쿼리와 관련된 콘텐츠 조각을 검색합니다.
  • 검색된 콘텐츠(contents)와 원본 쿼리(userMessage)를 템플릿 엔진을 통해 결합하여 LLM이 이해할 수 있는 프롬프트를 생성합니다.
  • 예제 템플림:
    PromptTemplate.from("""
        당신은 [분야] 전문가로 간결하게 답변합니다.
        다음은 질문입니다: {{userMessage}}
        다음 정보를 사용하여 답변하십시오: {{contents}}
        """)
    

2.2 동적 컨텍스트 관리

  • ContentRetriever 인터페이스를 통해 검색 로직을 커스터마이징할 수 있습니다(키워드 기반, 의미적 유사도 또는 하이브리드 전략).
  • QueryTransformer를 사용하여 사용자 쿼리를 사전 처리할 수 있습니다(대화 기록 압축, 키워드 확장 등)로 검색 정확도를 향상시킵니다.
  • 예제 구성:
    CustomRetrievalAugmentor.builder()
        .queryTransformer(new HistoryCompressorTransformer(aiModel)) // 대화 기록 압축
        .contentRetriever(customRetriever) // 커스텀 검색기
        .build();
    

2.3 메타데이터 지원

  • 문서 메타데이터(파일 이름, 출처, 타임스탬프 등)를 프롬프트에 주입하여 LLM이 콘텐츠 배경을 이해하도록 돕습니다.
  • 예제 시나리오:
    // 검색 시 메타데이터 포함
    DocumentSegment segment = new DocumentSegment("텍스트 내용", Map.of("source_file", "약관.pdf"));
    
    // 프롬프트 템플릿에서 메타데이터 참조
    PromptTemplate.from("{{source_file}}를 기반으로 답변: {{contents}}");
    

3. 일반적인 작업 흐름

3.1 데이터 준비 단계

  • EmbeddingProcessor를 사용하여 문서를 조각(DocumentSegment)으로 분할하고, 임베딩 벡터를 생성하여 벡터 데이터베이스에 저장합니다.
  • 예제 코드:
    Document doc = FileDocumentLoader.loadDocument(Paths.get("약관.pdf"));
    EmbeddingModel embedModel = new MiniLML6V2QuantizedEmbeddingModel();
    EmbeddingStore<DocumentSegment> vectorDB = new PineconeEmbeddingStore();
    
    EmbeddingProcessor processor = EmbeddingProcessor.builder()
        .segmenter(DocumentSplitters.recursive(250, 0)) // 250자 조각, 중복 없음
        .embeddingModel(embedModel)
        .storage(vectorDB)
        .build();
    
    processor.process(doc); // 데이터 처리 실행
    

3.2 쿼리 증강 단계

  • 사용자가 쿼리를 제출하면, RetrievalAugmentorContentRetriever를 호출하여 벡터 데이터베이스에서 관련 조각을 검색합니다.
  • 검색 결과는 ContentInjector를 통해 LLM 프롬프트에 주입되어 최종 응답을 생성합니다.
  • 완전한 예제:
    // 1. 검색 증강기 구성
    ContentRetriever retriever = VectorStoreContentRetriever.builder()
        .embeddingStore(vectorDB)
        .embeddingModel(embedModel)
        .maxResults(4) // 최대 4개 조각 반환
        .build();
    
    KnowledgeAugmentor augmentor = CustomKnowledgeAugmentor.builder()
        .contentInjector(DefaultContentInjector.builder()
            .promptTemplate(PromptTemplate.from("다음 정보를 사용하여 답변: {{contents}}"))
            .build())
        .contentRetriever(retriever)
        .build();
    
    // 2. AI 서비스에 검색 증강기 바인딩
    Advisor advisor = AiServices.builder(Advisor.class)
        .languageModel(aiService) // LLM 모델
        .knowledgeAugmentor(augmentor) // 검색 증강기 주입
        .build();
    
    // 3. 서비스 호출
    String answer = advisor.query("취소 정책은 무엇인가요?");
    

4. 고급 기능

4.1 하이브리드 검색 전략

  • 키워드 검색(BM25)과 의미 검색(벡터 유사도)을 결합한 HybridContentRetriever를 지원합니다.
  • 예제 구성:
    HybridContentRetriever hybridSearch = HybridContentRetriever.builder()
        .keywordSearcher(new BM25ContentSearcher()) // 키워드 검색기
        .semanticSearcher(vectorContentRetriever) // 의미 검색기
        .semanticWeight(0.6) // 의미 가중치
        .build();
    

4.2 다중 소스 데이터 지원

  • 여러 벡터 데이터베이스나 외부 API(Elasticsearch, Confluence 등)를 동시에 검색하고 MultiSourceContentRetriever로 결과를 통합할 수 있습니다.

4.3 성능 최적화

  • 캐시 메커니즘: 자주 발생하는 쿼리의 검색 결과를 캐싱하여 데이터베이스 부하를 줄입니다.
  • 비동기 검색: @Async 어노테이션을 사용하여 비동기 검색을 구현하고 메인 스레드를 차단하지 않습니다.

5. 적용 시나리오

  • 기업 지식 베이스 Q&A: 내부 문서(계약서, 매뉴얼 등)를 검색하여 직원이나 고객의 질문에 답변하며, 답변이 기업 규정에 부합하도록 보장합니다.
  • 실시간 뉴스 생성: 뉴스 데이터베이스와 결합하여 최신 정보를 포함한 기사나 요약을 생성합니다.
  • 법률 문서 분석: 법률 조항과 사례 데이터베이스를 검색하여 변호사가 문서를 작성하거나 컨설팅할 때 지원합니다.

6. 핵심 구성 요소

6.1 ContentRetriever (콘텐츠 검색기)

  • 기능: 외부 지식 소스(벡터 DB, 검색 엔진, API)에서 사용자 쿼리와 관련된 콘텐츠를 검색합니다.
  • 주요 메서드: retrieve(String query, int limit) - 쿼리에 따라 가장 관련성 높은 DocumentSegment 목록 반환(제한 수량).
  • 일반 구현: VectorStoreContentRetriever(벡터 유사도 기반), KeywordContentRetriever(키워드 일치 기반), HybridContentRetriever(하이브리드 검색).

6.2 ContentInjector (콘텐츠 주입기)

  • 기능: 검색된 DocumentSegment(콘텐츠 및 메타데이터)를 LLM이 이해할 수 있는 프롬프트로 형식화합니다.
  • 주요 메서드: inject(List segments, String userMessage) - 최종 프롬프트 생성.
  • 일반 구현: DefaultContentInjector(메타데이터 필터링 및 템플릿 지원), 커스텀 구현(중복 제거, 정렬, 잘림 로직).

6.3 PromptTemplate (프롬프트 템플릿)

  • 기능: 검색 콘텐츠와 사용자 쿼리를 결합하여 완전한 프롬프트를 정의하는 방법.
  • 주요 메서드: apply(Map variables) - 변수(예: contents, metadata)를 템플릿에 채움.
  • 예제 템플림:
    PromptTemplate.from(
        "다음 문서를 기반으로 답변:\n" +
        "{{contents}}\n" +
        "출처: {{metadata}}"
    );
    

6.4 ChatLanguageModel (LLM 인터페이스)

  • 기능: 대형 언어 모델(GPT, Llama, Claude 등)을 호출하여 답변을 생성합니다.
  • 주요 메서드: generate(String prompt) - 프롬프트에 따라 텍스트 생성.
  • 일반 구현: OpenAiChatModel(OpenAI API 연결), OllamaChatModel(로컬 Ollama 서비스 연결), HuggingFaceChatModel(Hugging Face 모델 연결).

7. 구성 예제

// 1. 임베딩 모델 정의(벡터 검색용)
EmbeddingModel embedModel = new HuggingFaceEmbeddingModel("sentence-transformers/all-MiniLM-L6-v2");

// 2. 텍스트 분할기 정의
TextSplitter splitter = RecursiveCharacterTextSplitter.builder()
    .chunkSize(400) // 각 조각 400자
    .chunkOverlap(40) // 중복 40자
    .build();

// 3. 검색기 정의(벡터 데이터베이스 기반)
ContentRetriever contentSearcher = VectorStoreContentRetriever.builder()
    .embeddingModel(embedModel)
    .textSplitter(splitter)
    .embeddingStore(yourVectorDB) // Chroma, Pinecone 등
    .build();

// 4. 콘텐츠 주입기 정의
ContentInjector contentInjector = DefaultContentInjector.builder()
    .promptTemplate(PromptTemplate.from(
        "다음 문서를 기반으로 답변:\n" +
        "{{contents}}\n" +
        "출처: {{metadata}}"
    ))
    .metadataKeysToInclude(Arrays.asList("file_name", "page"))
    .build();

// 5. 응답 강화기(인용 추가)
ResponseEnhancer answerEnhancer = new CitationResponseEnhancer();

// 6. LLM 정의
ChatLanguageModel languageModel = new OpenAiChatModel("your-api-key");

// 7. RetrievalAugmentor 조립
KnowledgeAugmentor augmentor = CustomKnowledgeAugmentor.builder()
    .contentRetriever(contentSearcher)
    .contentInjector(contentInjector)
    .responseEnhancer(answerEnhancer)
    .languageModel(languageModel)
    .retrievalStrategy(new AlwaysRetrieveStrategy()) // 모든 쿼리에 검색
    .build();

// 사용
String response = augmentor.generate("취소 정책은 무엇인가요?");

8. 주요 요약

구성 요소 기능 필수 여부
ContentRetriever 관련 콘텐츠 검색 필수
ContentInjector 프롬프트 형식화 필수
ChatLanguageModel 답변 생성 필수
PromptTemplate 프롬프트 구조 정의 선택(ContentInjector가 기본 템플릿 포함 가능)
ResponseEnhancer 답변 후 처리 선택
RetrievalStrategy 검색 시기 제어 선택(기본: 항상 검색)
TextSplitter 장문서 분할 선택(검색기 필요 시)
EmbeddingModel 텍스트 벡터화 선택(벡터 검색 필요 시)

이러한 구성 요소를 유연하게 조합하여 고객 서비스, 법률 컨설팅, 의학 진단 등 다양한 시나리오에 적합한 RAG 시스템을 구축할 수 있습니다.

태그: LangChain4j RAG RetrievalAugmentor LLM 검색 증강 생성

6월 5일 21:51에 게시됨