Weaviate 벡터 스토어

Weaviate 벡터 스토어 (Spring AI)

확장성 좋은 벡터 데이터베이스가 필요하다면 Weaviate가 주목할 만한 선택이에요. 이 글은 Weaviate VectorStore를 설정해서 문서 임베딩을 저장하고 유사도 검색을 수행하는 과정을 안내해요.

Weaviate는 오픈소스 벡터 데이터베이스로, 좋아하는 ML 모델의 데이터 객체와 벡터 임베딩을 저장하고 수십억 개의 데이터 객체로 확장할 수 있게 해 줘요. 문서 임베딩, 콘텐츠, 메타데이터를 저장하고, 메타데이터 필터링을 포함한 임베딩 검색 도구를 제공해요.

사전 준비 (Prerequisites)

  • 실행 중인 Weaviate 인스턴스. 다음 옵션이 가능해요.
    • Weaviate Cloud Service (계정 생성과 API 키 필요)
    • Docker container
  • 필요한 경우 WeaviateVectorStore에 저장할 임베딩을 생성하는 EmbeddingModel용 API 키를 준비해요.

의존성 (Dependencies)

중요: Spring AI 자동 설정과 스타터 모듈의 아티팩트 이름에 큰 변화가 있었어요. 자세한 내용은 upgrade notes를 확인해 주세요.

프로젝트에 Weaviate Vector Store 의존성을 추가해요.

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-weaviate-store</artifactId>
</dependency>

또는 Gradle build.gradle 파일에 이렇게 넣어요.

dependencies {
    implementation 'org.springframework.ai:spring-ai-weaviate-store'
}

참고: 스프링 AI BOM을 빌드 파일에 추가하는 방법은 Dependency Management 섹션을 참고해요.

설정 (Configuration)

Weaviate에 연결하고 WeaviateVectorStore를 사용하려면 인스턴스 접근 정보를 제공해야 해요. Spring Boot의 application.properties로 설정할 수 있어요.

spring.ai.vectorstore.weaviate.host=<host_of_your_weaviate_instance>
spring.ai.vectorstore.weaviate.scheme=<http_or_https>
spring.ai.vectorstore.weaviate.api-key=<your_api_key>
# API key if needed, e.g. OpenAI
spring.ai.openai.api-key=<api-key>

API 키 같은 민감 정보에 환경 변수를 쓰고 싶다면 여러 옵션이 있어요.

옵션 1: Spring Expression Language (SpEL) 사용

커스텀 환경 변수 이름을 사용하고 애플리케이션 설정에서 참조할 수 있어요.

# In application.yml
spring:
  ai:
    vectorstore:
      weaviate:
        host: ${WEAVIATE_HOST}
        scheme: ${WEAVIATE_SCHEME}
        api-key: ${WEAV...KEY}
    openai:
      api-key: ***
# In your environment or .env file
export WEAVIATE_HOST=<host_of_your_weaviate_instance>
export WEAVIATE_SCHEME=<http_or_https>
export WEAVIATE_API_KEY=<your_api_key>
export OPENAI_API_KEY=<api-key>

옵션 2: 프로그래밍 방식으로 환경 변수 접근

Java 코드에서 환경 변수에 접근할 수도 있어요.

String weaviateApiKey = System.getenv("WEAVIATE_API_KEY");
String openAiApiKey = System.getenv("OPENAI_API_KEY");

참고: 환경 변수를 관리하는 셸 스크립트를 만든다면, 애플리케이션 시작 전에 파일을 "소싱"해서(source <your_script_name>.sh) 실행해야 해요.

자동 설정 (Auto-configuration)

Spring AI는 Weaviate 벡터 스토어용 Spring Boot 자동 설정을 제공해요. 활성화하려면 Maven pom.xml에 다음 의존성을 추가해요.

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-starter-vector-store-weaviate</artifactId>
</dependency>

또는 Gradle build.gradle 파일에 이렇게 넣어요.

dependencies {
    implementation 'org.springframework.ai:spring-ai-starter-vector-store-weaviate'
}

참고: 스프링 AI BOM은 Dependency Management, Maven Central/Snapshot 저장소 추가는 Artifact Repositories 섹션을 참고해요.

벡터 스토어의 기본값과 설정 옵션은 아래 configuration parameters 목록을 참고해 주세요.

또한 설정된 EmbeddingModel 빈이 필요해요. EmbeddingModel 섹션을 참고하면 되는데, 필요한 빈의 예시는 다음과 같아요.

@Bean
public EmbeddingModel embeddingModel() {
    // Retrieve API key from a secure source or environment variable
    String apiKey = System.getenv("OPENAI_API_KEY");

    // Can be any other EmbeddingModel implementation
    return new OpenAiEmbeddingModel(OpenAiEmbeddingOptions.builder().apiKey(apiKey).build());
}

이제 애플리케이션에서 WeaviateVectorStore를 벡터 스토어로 오토와이어해서 사용할 수 있어요.

수동 설정 (Manual Configuration)

Spring Boot 자동 설정 대신 빌더 패턴으로 WeaviateVectorStore를 수동으로 구성할 수 있어요.

@Bean
public WeaviateClient weaviateClient() {
    return new WeaviateClient(new Config("http", "localhost:8080"));
}

@Bean
public VectorStore vectorStore(WeaviateClient weaviateClient, EmbeddingModel embeddingModel) {
    return WeaviateVectorStore.builder(weaviateClient, embeddingModel)
        .options(options)                              // Optional: use custom options
        .consistencyLevel(ConsistentLevel.QUORUM)      // Optional: defaults to ConsistentLevel.ONE
        .filterMetadataFields(List.of(                 // Optional: fields that can be used in filters
            MetadataField.text("country"),
            MetadataField.number("year")))
        .build();
}

메타데이터 필터링 (Metadata filtering)

Weaviate 스토어에서도 일반적이고 이식 가능한 metadata filters를 활용할 수 있어요.

예를 들어 텍스트 표현 언어로 필터링할 수 있고,

vectorStore.similaritySearch(
    SearchRequest.builder()
        .query("The World")
        .topK(TOP_K)
        .similarityThreshold(SIMILARITY_THRESHOLD)
        .filterExpression("country in ['UK', 'NL'] && year >= 2020").build());

Filter.Expression DSL로 프로그래밍 방식으로도 필터링할 수 있어요.

FilterExpressionBuilder b = new FilterExpressionBuilder();

vectorStore.similaritySearch(SearchRequest.builder()
    .query("The World")
    .topK(TOP_K)
    .similarityThreshold(SIMILARITY_THRESHOLD)
    .filterExpression(b.and(
        b.in("country", "UK", "NL"),
        b.gte("year", 2020)).build()).build());

참고: 이 (이식 가능한) 필터 표현식들은 Weaviate 고유의 where filters로 자동 변환돼요.

예를 들어 이 이식 가능한 필터 표현식:

country in ['UK', 'NL'] && year >= 2020

은 Weaviate 고유 GraphQL 필터 형식으로 이렇게 변환돼요.

operator: And
operands:
    [{
        operator: Or
        operands:
            [{
                path: ["meta_country"]
                operator: Equal
                valueText: "UK"
            },
            {
                path: ["meta_country"]
                operator: Equal
                valueText: "NL"
            }]
    },
    {
        path: ["meta_year"]
        operator: GreaterThanEqual
        valueNumber: 2020
    }]

Weaviate를 Docker로 실행

로컬 Weaviate 인스턴스로 빠르게 시작하려면 Docker에서 실행할 수 있어요.

docker run -it --rm --name weaviate \
    -e AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED=true \
    -e PERSISTENCE_DATA_PATH=/var/lib/weaviate \
    -e QUERY_DEFAULTS_LIMIT=25 \
    -e DEFAULT_VECTORIZER_MODULE=none \
    -e CLUSTER_HOSTNAME=node1 \
    -p 8080:8080 \
    semitechnologies/weaviate:1.31.22

이렇게 하면 http://localhost:8080에서 접근 가능한 Weaviate 인스턴스가 시작돼요.

WeaviateVectorStore 프로퍼티

Spring Boot 설정에서 Weaviate 벡터 스토어를 커스터마이즈할 수 있는 프로퍼티는 다음과 같아요.

Property Description Default value
spring.ai.vectorstore.weaviate.host The host of the Weaviate server localhost:8080
spring.ai.vectorstore.weaviate.scheme Connection schema http
spring.ai.vectorstore.weaviate.api-key The API key for authentication
spring.ai.vectorstore.weaviate.object-class The class name for storing documents. SpringAiWeaviate
spring.ai.vectorstore.weaviate.content-field-name The field name for content content
spring.ai.vectorstore.weaviate.meta-field-prefix The field prefix for metadata meta_
spring.ai.vectorstore.weaviate.consistency-level Desired tradeoff between consistency and speed ConsistentLevel.ONE
spring.ai.vectorstore.weaviate.filter-field Configures metadata fields that can be used in filters. Format: spring.ai.vectorstore.weaviate.filter-field.=

참고: 객체 클래스 이름은 대문자로 시작해야 하고, 필드 이름은 소문자로 시작해야 해요. data-object-concepts 참고.

네이티브 클라이언트 접근

Weaviate 벡터 스토어 구현은 getNativeClient() 메서드를 통해 내부의 네이티브 Weaviate 클라이언트(WeaviateClient)에 접근할 수 있게 해 줘요.

WeaviateVectorStore vectorStore = context.getBean(WeaviateVectorStore.class);
Optional<WeaviateClient> nativeClient = vectorStore.getNativeClient();

if (nativeClient.isPresent()) {
    WeaviateClient client = nativeClient.get();
    // Use the native client for Weaviate-specific operations
}

네이티브 클라이언트는 VectorStore 인터페이스로 노출되지 않는 Weaviate 고유 기능과 연산에 접근할 수 있게 해 줘요.

더 알아보기 (Learn more)