MongoDB Vector Search를 LangChain4j 와 통합하여 LLM 애플리케이션을 빌드 할 수 있습니다. 이 튜토리얼에서는 MongoDB Vector Search를 LangChain4j와 함께 사용하여 데이터에 시맨틱 검색을 수행하고 간단한 RAG 구현 빌드 방법을 보여 줍니다. 구체적으로 다음 조치를 수행합니다.
환경을 설정합니다.
임베딩 모델을 인스턴스화합니다.
MongoDB 임베딩 저장 로 사용합니다.
사용자 지정 데이터를 MongoDB cluster 에 저장합니다.
다음 벡터 검색 쿼리를 실행합니다.
시맨틱 검색.
메타데이터 사전 필터링을 통한 시맨틱 검색.
MongoDB Vector Search를 사용하여 데이터에 대한 질문에 답변 RAG 를 구현합니다.
배경
LangChain4j는 Java에서 LLM 애플리케이션 생성을 간소화하는 프레임워크입니다. LangChain4j는 LangChain, Haystack, LlamaIndex 및 기타 소스의 개념과 기능을 결합합니다. 이 프레임워크는 시맨틱 검색 및 RAG를 비롯한 다양한 사용 사례에 사용할 수 있습니다.
MongoDB Vector Search와 LangChain4j를 통합하면 MongoDB 벡터 데이터베이스 로 사용하고 MongoDB Vector Search를 사용하여 의미적으로 유사한 문서를 사용하여 쿼리에 답변 RAG 를 구현 . RAG에 대해 자세히 학습 MongoDB 사용한 RAG(검색 보강 생성)를 참조하세요.
전제 조건
이 튜토리얼을 완료하려면 다음 조건을 충족해야 합니다.
다음 MongoDB cluster 유형 중 하나입니다.
MongoDB 버전 6.0.11을 실행하는 Atlas 클러스터 7.0.2 또는 그 이상. IP 주소가 Atlas 프로젝트의 액세스 목록에 포함되어 있는지 확인하세요.
Atlas CLI 사용하여 생성된 로컬 Atlas 배포서버 입니다. 자세히 학습 로컬 Atlas 배포 만들기를 참조하세요.
검색 및 벡터 검색이 설치된 MongoDB Community 또는 Enterprise 클러스터.
Voyage AI API 키입니다. API 요청에 사용할 수 있는 토큰이 있는 계정이 있어야 합니다. Voyage AI 계정 등록에 대해 자세히 학습하려면 Voyage AI 웹사이트를 참조하세요.
OpenAI API 키입니다. API 요청에 사용할 수 있는 크레딧이 있는 OpenAI 계정이 있어야 합니다. OpenAI 계정 등록에 대해 자세히 학습하려면 OpenAI API 웹사이트를 참조하세요.
JDK( Java Development Kit) 버전 8 이상.
Java 애플리케이션 설정하다 하고 실행 위한 환경입니다. IntelliJ IDEA 또는 Eclipse IDE와 같은 통합 개발 환경(IDE)을 사용하여 프로젝트 빌드 하고 실행 하도록 Maven 또는 Gradle을 구성하는 것이 좋습니다.
환경 설정
먼저 필요한 종속성을 추가하고 환경 변수를 설정하는 등 이 튜토리얼을 위한 환경을 설정해야 합니다.
종속성을 추가합니다.
프로젝트의
pom.xml
파일에 있는dependencies
배열에 다음 종속성을 추가합니다. 이러한 종속성은 LangChain4j, LangChain4j용 Voyage AI API 및 MongoDB Java Sync Driver 라이브러리를 애플리케이션에 추가합니다.pom.xml<dependency> <groupId>dev.langchain4j</groupId> <artifactId>langchain4j-mongodb-atlas</artifactId> <version>1.1.0</version> </dependency> <dependency> <groupId>dev.langchain4j</groupId> <artifactId>langchain4j-voyage-ai</artifactId> <version>1.1.0-beta7</version> </dependency> <dependency> <groupId>org.mongodb</groupId> <artifactId>mongodb-driver-sync</artifactId> <version>5.4.0</version> </dependency> 다음으로, LangChain4j BOM(Bill of Materials)에 대한 종속성 목록 아래에
dependencyManagement
항목을 추가합니다.pom.xml<dependencyManagement> <dependencies> <dependency> <groupId>dev.langchain4j</groupId> <artifactId>langchain4j-bom</artifactId> <version>1.1.0</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> LangChain4j BOM에 대해 자세히 알아보려면 LangChain4j 문서의 시작하기 페이지를 참조하세요.
pom.xml
파일 편집을 완료한 후 프로젝트를 다시 로드하여 종속성이 설치되었는지 확인합니다.
클래스 및 메서드를 가져옵니다.
프로젝트에서 메인 애플리케이션 파일 Main.java
를 찾으세요. 기존의 import 문이 있다면 아래 목록으로 교체하세요.
import com.mongodb.client.MongoClient; import com.mongodb.client.MongoClients; import dev.langchain4j.data.document.Metadata; import dev.langchain4j.data.embedding.Embedding; import dev.langchain4j.data.segment.TextSegment; import dev.langchain4j.model.embedding.EmbeddingModel; import dev.langchain4j.model.voyageai.VoyageAiEmbeddingModel; import dev.langchain4j.store.embedding.EmbeddingMatch; import dev.langchain4j.store.embedding.EmbeddingSearchRequest; import dev.langchain4j.store.embedding.EmbeddingSearchResult; import dev.langchain4j.store.embedding.filter.comparison.*; import dev.langchain4j.store.embedding.mongodb.IndexMapping; import dev.langchain4j.store.embedding.mongodb.MongoDbEmbeddingStore; import org.bson.Document; import java.io.*; import java.util.*;
이 튜토리얼의 후반부에서는 이러한 클래스와 메서드를 사용하여 벡터 임베딩을 생성하고 데이터를 쿼리합니다.
환경 변수를 설정합니다.
사용 중인 IDE에 따라 애플리케이션이 조회할 수 있는 환경 변수를 설정하는 방법은 여러 가지가 있을 수 있습니다. IntelliJ에서 환경 변수를 설정하려면 애플리케이션에 대한 실행 구성을 생성해야 합니다. 자세한 내용은 IntelliJ 문서의 실행/디버그 구성: 애플리케이션 페이지에 있는 운영 체제 섹션을 참고하세요.
다음 환경 변수를 설정합니다.
MONGODB_URI
: MongoDB 연결 문자열 로 설정합니다.VOYAGE_AI_KEY
: Voyage AI API 키로 설정합니다.
참고
연결 문자열은 다음 형식을 사용해야 합니다.
mongodb+srv://<db_username>:<db_password>@<clusterName>.<hostname>.mongodb.net/?<settings>
연결 문자열을 검색하는 방법에 대한 자세한 내용은 Atlas 시작하기 튜토리얼을 참조하십시오.
임베딩 모델 인스턴스화
이 단계에서는 Voyage AI를 사용하여 샘플 데이터의 텍스트를 벡터 임베딩으로 변환하는 임베딩 모델을 인스턴스화합니다.
다음 코드를 Main.java
파일에 추가하여 Voyage AI API 키를 사용하고 voyage-3-large
을 모델로 선택하여 임베딩 모델을 인스턴스화합니다.
EmbeddingModel embeddingModel = VoyageAiEmbeddingModel.builder() .apiKey(embeddingApiKey) .modelName("voyage-3-large") .build();
voyage-3-large
모델에 대해 자세히 알아보려면 Voyage AI 웹사이트에서 voyage-3 & voyage-3-lite에 대한 블로그 게시물을 참조하세요.
MongoDB 임베딩 스토어로 사용
이 섹션에서는 MongoDB 벡터 또는 임베딩 저장 라고도 하는 벡터 데이터베이스로 인스턴스화합니다. 임베딩 저장 인스턴스화하면 LangChain4j는 데이터에 MongoDB Vector Search 인덱스 자동으로 생성합니다.
참고
필요한 액세스 권한
MongoDB Vector Search 인덱스 만들려면 MongoDB 프로젝트 에 대한 Project Data Access Admin
이상의 액세스 있어야 합니다.
이 코드는 다음 작업을 수행합니다.
Atlas 배포에 연결된
MongoClient
인스턴스를 생성합니다.벡터 검색 인덱스 정의의 차원 수를 AI 모델의 임베딩 차원으로 설정합니다. 결과 벡터 검색 인덱스의 정의는 다음과 같습니다.
{ "fields": [ { "type": "vector", "path": "embedding", "numDimensions": 1024, "similarity": "cosine" } ] } 다음 매개변수를 지정하여 MongoDB 컬렉션 구성합니다.
langchain4j_test.vector_store
문서를 저장 MongoDB 컬렉션 으로 지정합니다.vector_index
임베딩 저장소를 쿼리하는 데 사용할 인덱스입니다.
createIndex
불리언이 true
로 설정되었기 때문에 임베딩 저장소를 인스턴스화하면 벡터 검색 인덱스가 자동으로 생성됩니다. 이 코드에는 인덱스가 성공적으로 생성될 수 있도록 지연이 포함되어 있습니다.
Main.java
파일에 다음 코드를 추가합니다.
MongoClient mongoClient = MongoClients.create(uri); System.out.println("Instantiating the embedding store..."); // Set to false if the vector index already exists Boolean createIndex = true; IndexMapping indexMapping = IndexMapping.builder() .dimension(embeddingModel.dimension()) .metadataFieldNames(new HashSet<>()) .build(); MongoDbEmbeddingStore embeddingStore = MongoDbEmbeddingStore.builder() .databaseName("search") .collectionName("langchaintest") .createIndex(createIndex) .indexName("vector_index") .indexMapping(indexMapping) .fromClient(mongoClient) .build(); if (createIndex) { // Creating a vector search index can take up to a minute, // so this delay allows the index to become queryable try { Thread.sleep(15000); } catch (InterruptedException e) { throw new RuntimeException(e); } }
이전 코드에서 사용된 클래스와 메서드에 대해 자세히 알아보려면 dev.langchain4j.store.embedding.mongodb 패키지 API 문서를 참조하세요.
사용자 지정 데이터 저장
이 섹션에서는 샘플 문서를 만들고, 임베딩 모델을 사용하여 텍스트를 임베딩으로 변환하고, 데이터를 MongoDB 에 유지합니다.
이 코드는 다음 작업을 수행합니다.
text
및metadata
필드가 포함된 샘플 문서 목록을 생성합니다.text
필드 의 내용을 임베딩으로 변환하고 데이터를 MongoDB 에 유지합니다. 이 코드에는 벡터 변환에 필요한 시간을 수용하기 위한 지연이 포함되어 있습니다.
Main.java
파일에 다음 코드를 추가합니다.
ArrayList<Document> docs = new ArrayList<>(); docs.add(new Document() .append("text", "In Zadie Smith's new novel, the true story of a heated nineteenth-century criminal trial connects to the unrest of current times.") .append("metadata", new Metadata(Map.of("author", "A")))); docs.add(new Document() .append("text", "Emperor penguins are the tallest and heaviest of all penguin species, standing up to 4 feet.") .append("metadata", new Metadata(Map.of("author", "D")))); docs.add(new Document() .append("text", "Penguins are flightless seabirds that live almost exclusively below the equator. Some island-dwellers can be found in warmer climates.") .append("metadata", new Metadata(Map.of("author", "C")))); docs.add(new Document() .append("text", "Patagonia is home to five penguin species - Magellanic, Humboldt, Gentoo, Southern Rockhopper and King.") .append("metadata", new Metadata(Map.of("author", "B")))); System.out.println("Persisting document embeddings..."); for (Document doc : docs) { TextSegment segment = TextSegment.from( doc.getString("text"), doc.get("metadata", Metadata.class) ); Embedding embedding = embeddingModel.embed(segment).content(); embeddingStore.add(embedding, segment); } // Delay for persisting data try { Thread.sleep(5000); } catch (InterruptedException e) { throw new RuntimeException(e); }
Vector Search 쿼리 실행
이 섹션에서는 벡터화된 데이터에 대해 쿼리를 실행하는 방법을 보여 줍니다.
시맨틱 검색을 수행합니다.
이 코드는 "Where do penguins live?"
구문에 대한 시맨틱 검색 쿼리를 수행하고 가장 관련성이 높은 결과 세 개를 반환합니다. 또한 각 결과가 쿼리와 얼마나 잘 일치하는지를 나타내는 점수를 출력합니다.
Main.java
파일에 다음 코드를 추가합니다.
String query = "Where do penguins live?"; Embedding queryEmbedding = embeddingModel.embed(query).content(); EmbeddingSearchRequest searchRequest = EmbeddingSearchRequest.builder() .queryEmbedding(queryEmbedding) .maxResults(3) .build(); System.out.println("Performing the query..."); EmbeddingSearchResult<TextSegment> searchResult = embeddingStore.search(searchRequest); List<EmbeddingMatch<TextSegment>> matches = searchResult.matches(); for (EmbeddingMatch<TextSegment> embeddingMatch : matches) { System.out.println("Response: " + embeddingMatch.embedded().text()); System.out.println("Author: " + embeddingMatch.embedded().metadata().getString("author")); System.out.println("Score: " + embeddingMatch.score()); }
Response: Penguins are flightless seabirds that live almost exclusively below the equator. Some island-dwellers can be found in warmer climates. Author: C Score: 0.829620897769928 Response: Patagonia is home to five penguin species - Magellanic, Humboldt, Gentoo, Southern Rockhopper and King. Author: B Score: 0.7459062337875366 Response: Emperor penguins are the tallest and heaviest of all penguin species, standing up to 4 feet. Author: D Score: 0.6908764839172363
(선택 사항) 메타데이터 필터링을 사용하여 시맨틱 검색을 수행합니다.
메타데이터 필터링을 사용하여 검색을 수행하려면 dev.langchain4j.store.embedding.filter.comparison
패키지의 클래스를 사용할 수 있습니다. 이러한 클래스를 사용하면 메타데이터 값을 지정된 값과 비교하는 필터를 생성하여 검색에서 반환되는 결과의 범위를 좁힐 수 있습니다.
이 예시에서는 author
필드의 값이 "B"
또는 "C"
인 문서를 필터링합니다. 그런 다음 "Where do penguins live?"
구문에 대한 시맨틱 검색 쿼리를 수행합니다.
이전 단계에서 EmbeddingSearchRequest
인스턴스를 생성하는 코드를 다음 코드로 바꾸세요.
EmbeddingSearchRequest searchRequest = EmbeddingSearchRequest.builder() .queryEmbedding(queryEmbedding) .filter(new IsIn("author", List.of("B", "C"))) .maxResults(3) .build();
Response: Penguins are flightless seabirds that live almost exclusively below the equator. Some island-dwellers can be found in warmer climates. Author: C Score: 0.8520907163619995 Response: Patagonia is home to five penguin species - Magellanic, Humboldt, Gentoo, Southern Rockhopper and King. Author: B Score: 0.7666836977005005
메타데이터 사전 필터링에 대해 자세히 학습하려면 MongoDB 벡터 검색 사전 필터를 참조하세요.
데이터를 사용하여 질문에 답하기
이 섹션에서는 LangChain j 프레임워크 와 MongoDB Vector Search를 사용하는 RAG 구현 보여 줍니다.4 이제 MongoDB Vector Search를 사용하여 의미적으로 유사한 문서를 조회 했으므로, 다음 코드 예제를 사용하여 LLM이 MongoDB 에 저장된 문서의 정보를 사용하여 질문에 답변 하도록 프롬프트를 표시합니다.
RAG 프로젝트를 설정합니다.
프로젝트의
pom.xml
파일에 있는dependencies
배열에 다음 종속성을 추가하되 이미 추가한 종속성은 제거하지 마세요. 이러한 종속성은 LangChain4j AI 서비스 및 LangChain4j 라이브러리의 OpenAI API를 애플리케이션에 추가합니다.pom.xml<dependency> <groupId>dev.langchain4j</groupId> <artifactId>langchain4j-open-ai</artifactId> <version>1.1.0</version> </dependency> <dependency> <groupId>dev.langchain4j</groupId> <artifactId>langchain4j</artifactId> <version>1.1.0</version> </dependency> pom.xml
파일 편집을 완료한 후 프로젝트를 다시 로드하여 종속성이 설치되었는지 확인합니다.Main.java
파일의 가져오기 목록에 다음 가져오기를 추가합니다.import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import dev.langchain4j.service.AiServices; import dev.langchain4j.model.chat.ChatLanguageModel; import dev.langchain4j.model.openai.OpenAiChatModel; import dev.langchain4j.rag.content.retriever.ContentRetriever; import dev.langchain4j.rag.content.retriever.EmbeddingStoreContentRetriever; OPENAI_KEY
환경 변수를 OpenAI API 키로 설정합니다. 이 키를 사용하여 쿼리에 대한 응답을 생성하는 채팅 모델을 만듭니다.
샘플 데이터를 불러옵니다.
이 단계에서는 외부 소스에서 Atlas로 데이터를 수집합니다. docs-code-examples
GitHub 리포지토리에서 rainforest-docs.json 샘플 데이터 파일을 다운로드하세요. 이 파일의 문서에는 열대 우림의 식물, 동물 및 날씨에 대한 정보가 포함되어 있습니다.
이 파일을 프로젝트의 resources
디렉토리에 업로드하세요. 이 디렉토리는 애플리케이션 파일이 있는 java
디렉토리와 동일한 수준에 있습니다.
데이터를 임베딩 생성이 가능한 형식으로 가공하고, Atlas에 저장해야 합니다. 이 코드는 다음 작업을 수행하는 loadJsonDocuments()
메서드를 정의합니다.
ClassLoader
클래스를 사용하여resources
디렉토리에서 샘플 데이터를 조회합니다.ObjectMapper
클래스를 사용하여 JSON 문서를 MongoDBDocument
인스턴스의List
로 구문 분석합니다.
기본 메서드 외부의 Main.java
파일에 다음 코드를 추가합니다.
private static List<Document> loadJsonDocuments(String resourcePath) throws IOException { // Loads file from resources directory using the ClassLoader InputStream inputStream = Main.class.getClassLoader().getResourceAsStream(resourcePath); if (inputStream == null) { throw new FileNotFoundException("Resource not found: " + resourcePath); } // Parses JSON file to List of MongoDB Documents ObjectMapper objectMapper = new ObjectMapper(); List<Document> documents = objectMapper.readValue(inputStream, new TypeReference<>() {}); return documents; }
그런 다음 메인 메서드 본문에 다음 코드를 추가하여 loadJsonDocuments()
메서드를 호출하고 문서를 로드합니다.
System.out.println("Loading documents from file..."); String resourcePath = "rainforest-docs.json"; List<Document> documents = loadJsonDocuments(resourcePath);
벡터 임베딩을 Atlas에 저장합니다.
이 단계에서는 샘플 문서에서 벡터 임베딩을 생성하고 이를 Atlas에 영구 저장합니다.
이 코드는 샘플 문서의 text
필드 내용을 임베딩으로 변환하고 데이터를 Atlas에 영구 저장합니다. 벡터 변환에 필요한 시간을 고려하여 코드에는 지연 처리가 포함되어 있습니다.
Main.java
파일에 다음 코드를 추가합니다.
System.out.println("Persisting document embeddings..."); for (Document doc : documents) { TextSegment segment = TextSegment.from( doc.getString("text"), new Metadata(doc.get("metadata", Map.class))); Embedding embedding = embeddingModel.embed(segment).content(); embeddingStore.add(embedding, segment); } try { Thread.sleep(5000); } catch (InterruptedException e) { throw new RuntimeException(e); }
채팅 모델을 인스턴스화하고 콘텐츠 검색기를 지정합니다.
이 단계에서는 데이터를 기반으로 질문에 답변할 수 있도록 OpenAI에서 채팅 모델을 인스턴스화합니다. 또한 채팅 모델이 응답을 생성할 때 참조할 수 있도록 관련 문서를 제공하는 콘텐츠 검색기를 지정합니다.
이 코드는 다음 작업을 수행합니다.
OpenAI API 키를 사용하여 채팅 모델을 인스턴스화합니다.
다음 사양에 따라 콘텐츠 검색기를 생성합니다.
최대
3
개의 관련 문서를 조회합니다.관련성 점수가 최소한 다음 값 이상인 문서를 조회합니다.
0.75
메인 메서드 본문의 Main.java
파일에 다음 코드를 추가합니다.
String chatApiKey = System.getenv("OPENAI_KEY"); ChatLanguageModel chatModel = OpenAiChatModel.builder() .apiKey(chatApiKey) .modelName("gpt-4") .build(); ContentRetriever contentRetriever = EmbeddingStoreContentRetriever.builder() .embeddingStore(embeddingStore) .embeddingModel(embeddingModel) .maxResults(3) .minScore(0.75) .build();
팁
메타데이터 필터링
filter()
빌더 메서드를 사용하고 Filter
의 인스턴스를 전달하여 ContentRetriever
에서 메타데이터 필터링을 구현할 수 있습니다. Filter
(을)를 구성하는 방법을 학습하려면 이전 단계의 메타데이터 필터링 예시를 참조하세요.
채팅 어시스턴트를 생성합니다.
애플리케이션에서 AI Services API를 구현하는 간단한 Assistant
인터페이스를 생성합니다. Main.java
파일과 동일한 수준에 Assistant.java
라는 인터페이스 파일을 만드세요.
Assistant
인터페이스를 정의합니다.
package org.example; public interface Assistant { String answer(String question); }
Main.java
파일에서 Assistant
을(를) 인스턴스화합니다.
Assistant assistant = AiServices.builder(Assistant.class) .chatLanguageModel(chatModel) .contentRetriever(contentRetriever) .build();
데이터에 대한 쿼리를 수행합니다.
마지막으로, 샘플 데이터에 대한 쿼리를 실행합니다. Main.java
파일에 다음 코드를 추가하여 쿼리를 실행하고 출력을 인쇄합니다.
String ragQuery = "What types of insects live in the rainforest?"; String output = assistant.answer(ragQuery); System.out.println("Response:\n" + output);
Response: In the rainforest, there are numerous species of insects such as beetles, butterflies, moths, wasps, bees, flies, and ants. Of the many insects that live in the rainforest, ants are particularly important as they play a crucial role in nutrient recycling and aeration of the soil. Moreover, many of these insects are involved in the processes of pollination and decomposition. The adaptations these insects have developed enable their survival in the rainforest's specific conditions, characterized by heavy rainfall.
다음 단계
MongoDB는 다음과 같은 개발자 리소스도 제공합니다.