Docs Menu
Docs Home
/ /

LangChain4j 통합 시작하기

MongoDB Vector Search를 LangChain4j 와 통합하여 LLM 애플리케이션을 빌드 할 수 있습니다. 이 튜토리얼에서는 MongoDB Vector Search를 LangChain4j와 함께 사용하여 데이터에 시맨틱 검색을 수행하고 간단한 RAG 구현 빌드 방법을 보여 줍니다. 구체적으로 다음 조치를 수행합니다.

  1. 환경을 설정합니다.

  2. 임베딩 모델을 인스턴스화합니다.

  3. MongoDB 임베딩 저장 로 사용합니다.

  4. 사용자 지정 데이터를 MongoDB cluster 에 저장합니다.

  5. 다음 벡터 검색 쿼리를 실행합니다.

    • 시맨틱 검색.

    • 메타데이터 사전 필터링을 통한 시맨틱 검색.

  6. MongoDB Vector Search를 사용하여 데이터에 대한 질문에 답변 RAG 를 구현합니다.

LangChain4j는 Java에서 LLM 애플리케이션 생성을 간소화하는 프레임워크입니다. LangChain4j는 LangChain, Haystack, LlamaIndex 및 기타 소스의 개념과 기능을 결합합니다. 이 프레임워크는 시맨틱 검색 및 RAG를 비롯한 다양한 사용 사례에 사용할 수 있습니다.

MongoDB Vector Search와 LangChain4j를 통합하면 MongoDB 벡터 데이터베이스 로 사용하고 MongoDB Vector Search를 사용하여 의미적으로 유사한 문서를 사용하여 쿼리에 답변 RAG 를 구현 . RAG에 대해 자세히 학습 MongoDB 사용한 RAG(검색 보강 생성)를 참조하세요.

이 튜토리얼을 완료하려면 다음 조건을 충족해야 합니다.

  • JDK( Java Development Kit) 버전 8 이상.

  • Java 애플리케이션 설정하다 하고 실행 위한 환경입니다. IntelliJ IDEA 또는 Eclipse IDE와 같은 통합 개발 환경(IDE)을 사용하여 프로젝트 빌드 하고 실행 하도록 Maven 또는 Gradle을 구성하는 것이 좋습니다.

먼저 필요한 종속성을 추가하고 환경 변수를 설정하는 등 이 튜토리얼을 위한 환경을 설정해야 합니다.

1
  1. IDE를 열고 새 Java 프로젝트를 생성한 후 다음 구성을 설정합니다.

    • 이름: LangChain4jSampleApp

    • 언어: Java

    • 빌드 시스템: Maven

    • JDK: 다음 이상의 버전 8

    샘플 코드를 포함할 수 있는 옵션이 표시될 수 있습니다. 이 옵션을 선택하면 환경이 제대로 작동하는지 테스트하고, 다음 단계에서 편집할 애플리케이션 파일을 찾는 데 도움이 될 수 있습니다.

2
  1. 프로젝트의 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>
  2. 다음으로, 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 파일 편집을 완료한 후 프로젝트를 다시 로드하여 종속성이 설치되었는지 확인합니다.

3

프로젝트에서 메인 애플리케이션 파일 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.*;

이 튜토리얼의 후반부에서는 이러한 클래스와 메서드를 사용하여 벡터 임베딩을 생성하고 데이터를 쿼리합니다.

4

사용 중인 IDE에 따라 애플리케이션이 조회할 수 있는 환경 변수를 설정하는 방법은 여러 가지가 있을 수 있습니다. IntelliJ에서 환경 변수를 설정하려면 애플리케이션에 대한 실행 구성을 생성해야 합니다. 자세한 내용은 IntelliJ 문서의 실행/디버그 구성: 애플리케이션 페이지에 있는 운영 체제 섹션을 참고하세요.

다음 환경 변수를 설정합니다.

  • MONGODB_URI: MongoDB 연결 문자열 로 설정합니다.

  • VOYAGE_AI_KEY: Voyage AI API 키로 설정합니다.

참고

연결 문자열은 다음 형식을 사용해야 합니다.

mongodb+srv://<db_username>:<db_password>@<clusterName>.<hostname>.mongodb.net/?<settings>

연결 문자열을 검색하는 방법에 대한 자세한 내용은 Atlas 시작하기 튜토리얼을 참조하십시오.

5

애플리케이션의 Main.java 파일의 메인 메서드에 다음 코드를 추가하여 환경 변수를 조회합니다.

String embeddingApiKey = System.getenv("VOYAGE_AI_KEY");
String uri = System.getenv("MONGODB_URI");

이 단계에서는 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 벡터 또는 임베딩 저장 라고도 하는 벡터 데이터베이스로 인스턴스화합니다. 임베딩 저장 인스턴스화하면 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 에 유지합니다.

이 코드는 다음 작업을 수행합니다.

  • textmetadata 필드가 포함된 샘플 문서 목록을 생성합니다.

  • 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);
}

이 섹션에서는 벡터화된 데이터에 대해 쿼리를 실행하는 방법을 보여 줍니다.

1

이 코드는 "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
2

메타데이터 필터링을 사용하여 검색을 수행하려면 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 에 저장된 문서의 정보를 사용하여 질문에 답변 하도록 프롬프트를 표시합니다.

1
  1. 프로젝트의 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 파일 편집을 완료한 후 프로젝트를 다시 로드하여 종속성이 설치되었는지 확인합니다.

  2. 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;
  3. OPENAI_KEY 환경 변수를 OpenAI API 키로 설정합니다. 이 키를 사용하여 쿼리에 대한 응답을 생성하는 채팅 모델을 만듭니다.

2

이 단계에서는 외부 소스에서 Atlas로 데이터를 수집합니다. docs-code-examples GitHub 리포지토리에서 rainforest-docs.json 샘플 데이터 파일을 다운로드하세요. 이 파일의 문서에는 열대 우림의 식물, 동물 및 날씨에 대한 정보가 포함되어 있습니다.

이 파일을 프로젝트의 resources 디렉토리에 업로드하세요. 이 디렉토리는 애플리케이션 파일이 있는 java 디렉토리와 동일한 수준에 있습니다.

데이터를 임베딩 생성이 가능한 형식으로 가공하고, Atlas에 저장해야 합니다. 이 코드는 다음 작업을 수행하는 loadJsonDocuments() 메서드를 정의합니다.

  • ClassLoader 클래스를 사용하여 resources 디렉토리에서 샘플 데이터를 조회합니다.

  • ObjectMapper 클래스를 사용하여 JSON 문서를 MongoDB Document 인스턴스의 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);
3

이 단계에서는 샘플 문서에서 벡터 임베딩을 생성하고 이를 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);
}
4

이 단계에서는 데이터를 기반으로 질문에 답변할 수 있도록 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(을)를 구성하는 방법을 학습하려면 이전 단계의 메타데이터 필터링 예시를 참조하세요.

5

애플리케이션에서 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();
6

마지막으로, 샘플 데이터에 대한 쿼리를 실행합니다. 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는 다음과 같은 개발자 리소스도 제공합니다.

돌아가기

LangChainGo

이 페이지의 내용