MariaDB 벡터 스토어

MariaDB 벡터 스토어 (MariaDB Vector Store)

이 섹션에서는 MariaDBVectorStore를 설정해서 문서 임베딩을 저장하고 유사도 검색을 수행하는 방법을 안내해요. MariaDB Vector는 MariaDB 11.7의 일부로, 머신러닝 생성 임베딩의 저장과 검색을 가능하게 해요. 벡터 인덱스를 사용한 효율적인 벡터 유사도 검색을 제공하며 코사인 유사도와 유클리드 거리 메트릭을 모두 지원해요.

출처: 문서

본문

MariaDB 벡터 스토어 (MariaDB Vector Store)

이 섹션은 MariaDBVectorStore를 설정해 문서 임베딩을 저장하고 유사도 검색을 수행하는 방법을 안내해요.

MariaDB Vector는 MariaDB 11.7의 일부이며 머신러닝 생성 임베딩의 저장과 검색을 가능하게 해요. 벡터 인덱스를 사용해 효율적인 벡터 유사도 검색 기능을 제공하며, 코사인 유사도와 유클리드 거리 메트릭을 모두 지원해요.

사전 준비 (Prerequisites)

자동 구성 (Auto-Configuration)

참고: Spring AI auto-configuration과 starter 모듈의 아티팩트 이름에 큰 변화가 있었어요. 자세한 내용은 upgrade notes를 참고해 주세요.

Spring AI는 MariaDB Vector Store에 대한 Spring Boot 자동 구성을 제공해요. 활성화하려면 프로젝트의 Maven pom.xml 파일에 다음 의존성을 추가하세요:

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

또는 Gradle build.gradle 빌드 파일에:

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

참고: 빌드 파일에 Spring AI BOM을 추가하려면 Dependency Management 섹션을 참고해 주세요.

벡터 스토어 구현은 필요한 스키마를 초기화할 수 있지만, 적절한 생성자에서 initializeSchema boolean을 지정하거나 application.properties 파일에서 …initialize-schema=true를 설정해 선택해야 해요.

참고: 이것은 호환성을 깨는 변경이에요! 이전 버전의 Spring AI에서는 이 스키마 초기화가 기본으로 일어났어요.

추가로 구성된 EmbeddingModel 빈이 필요해요. 자세한 내용은 EmbeddingModel 섹션을 참고하세요.

예를 들어 OpenAI EmbeddingModel을 사용하려면 다음 의존성을 추가하세요:

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-starter-model-openai</artifactId>
</dependency>

참고: 빌드 파일에 Maven Central 및/또는 Snapshot 저장소를 추가하려면 Artifact Repositories 섹션을 참고해 주세요.

이제 애플리케이션에서 MariaDBVectorStore를 오토와이어할 수 있어요:

@Autowired VectorStore vectorStore;

// ...

List<Document> documents = List.of(
    new Document("Spring AI rocks!! Spring AI rocks!! Spring AI rocks!! Spring AI rocks!! Spring AI rocks!!", Map.of("meta1", "meta1")),
    new Document("The World is Big and Salvation Lurks Around the Corner"),
    new Document("You walk forward facing the past and you turn back toward the future.", Map.of("meta2", "meta2")));

// Add the documents to MariaDB
vectorStore.add(documents);

// Retrieve documents similar to a query
List<Document> results = vectorStore.similaritySearch(SearchRequest.builder().query("Spring").topK(5).build());

구성 프로퍼티 (Configuration Properties)

MariaDB에 연결하고 MariaDBVectorStore를 사용하려면 인스턴스의 접근 세부 정보를 제공해야 해요. 간단한 구성은 Spring Boot의 application.yml로 제공할 수 있어요:

spring:
  datasource:
    url: jdbc:mariadb://localhost/db
    username: myUser
    password: myPassword
  ai:
    vectorstore:
      mariadb:
        initialize-schema: true
        distance-type: COSINE
        dimensions: 1536

참고: Docker Compose나 Testcontainers를 통해 MariaDB Vector를 Spring Boot dev service로 실행한다면, URL·username·password는 Spring Boot가 자동 구성하므로 구성할 필요가 없어요.

spring.ai.vectorstore.mariadb.*로 시작하는 프로퍼티는 MariaDBVectorStore를 구성하는 데 사용돼요:

Property Description Default Value
spring.ai.vectorstore.mariadb.initialize-schema 필요한 스키마를 초기화할지 여부 false
spring.ai.vectorstore.mariadb.distance-type 검색 거리 타입. COSINE(기본값) 또는 EUCLIDEAN 사용. 벡터가 길이 1로 정규화되어 있으면 최고 성능을 위해 EUCLIDEAN을 사용할 수 있어요. COSINE
spring.ai.vectorstore.mariadb.dimensions 임베딩 차원. 명시적으로 지정하지 않으면 제공된 EmbeddingModel에서 차원을 가져와요. 1536
spring.ai.vectorstore.mariadb.remove-existing-vector-store-table 시작 시 기존 벡터 스토어 테이블을 삭제해요. false
spring.ai.vectorstore.mariadb.schema-name 벡터 스토어 스키마 이름 null
spring.ai.vectorstore.mariadb.table-name 벡터 스토어 테이블 이름 vector_store
spring.ai.vectorstore.mariadb.schema-validation 스키마와 테이블 이름이 유효하고 기존 객체인지 확인하는 검증 활성화 false

참고: 커스텀 스키마 및/또는 테이블 이름을 구성한다면 spring.ai.vectorstore.mariadb.schema-validation=true로 설정해 스키마 검증을 활성화하는 것을 고려하세요. 이렇게 하면 이름의 정확성이 보장되고 SQL 주입 공격의 위험이 줄어요.

수동 구성 (Manual Configuration)

Spring Boot 자동 설정 대신 MariaDB 벡터 스토어를 수동 구성할 수 있어요. 이를 위해 프로젝트에 다음 의존성을 추가해야 해요:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>

<dependency>
    <groupId>org.mariadb.jdbc</groupId>
    <artifactId>mariadb-java-client</artifactId>
    <scope>runtime</scope>
</dependency>

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

참고: 빌드 파일에 Spring AI BOM을 추가하려면 Dependency Management 섹션을 참고해 주세요.

그런 다음 빌더 패턴으로 MariaDBVectorStore 빈을 만드세요:

@Bean
public VectorStore vectorStore(JdbcTemplate jdbcTemplate, EmbeddingModel embeddingModel) {
    return MariaDBVectorStore.builder(jdbcTemplate, embeddingModel)
        .dimensions(1536)                      // Optional: defaults to 1536
        .distanceType(MariaDBDistanceType.COSINE) // Optional: defaults to COSINE
        .schemaName("mydb")                    // Optional: defaults to null
        .vectorTableName("custom_vectors")     // Optional: defaults to "vector_store"
        .contentFieldName("text")             // Optional: defaults to "content"
        .embeddingFieldName("embedding")      // Optional: defaults to "embedding"
        .idFieldName("doc_id")                // Optional: defaults to "id"
        .metadataFieldName("meta")           // Optional: defaults to "metadata"
        .initializeSchema(true)               // Optional: defaults to false
        .schemaValidation(true)              // Optional: defaults to false
        .removeExistingVectorStoreTable(false) // Optional: defaults to false
        .maxDocumentBatchSize(10000)         // Optional: defaults to 10000
        .build();
}

// This can be any EmbeddingModel implementation
@Bean
public EmbeddingModel embeddingModel() {
    return new OpenAiEmbeddingModel(OpenAiEmbeddingOptions.builder().apiKey(System.getenv("OPENAI_API_KEY")).build());
}

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

MariaDB Vector 스토어에서도 일반적이고 휴대 가능한 메타데이터 필터를 활용할 수 있어요.

예를 들어 텍스트 표현 언어를 사용할 수 있어요:

vectorStore.similaritySearch(
    SearchRequest.builder()
        .query("The World")
        .topK(TOP_K)
        .similarityThreshold(SIMILARITY_THRESHOLD)
        .filterExpression("author in ['john', 'jill'] && article_type == 'blog'").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("author", "john", "jill"),
        b.eq("article_type", "blog")).build()).build());

참고: 이 필터 표현식은 자동으로 동일한 MariaDB JSON 경로 표현식으로 변환돼요.

유사도 점수 (Similarity Scores)

MariaDB Vector Store는 유사도 검색에서 반환된 문서에 대한 유사도 점수를 자동으로 계산해요. 이 점수들은 각 문서가 검색 쿼리와 얼마나 가까운지에 대한 정규화된 측정값을 제공해요.

점수 계산 (Score Calculation)

유사도 점수는 score = 1.0 - distance 공식으로 계산돼요. 여기서:

  • Score: 0.0에서 1.0 사이의 값. 1.0은 완벽한 유사도를, 0.0은 유사도 없음을 나타내요.
  • Distance: 구성된 거리 타입(COSINE 또는 EUCLIDEAN)으로 계산된 원시 거리 값.

이는 거리가 작을수록(더 유사할수록) 점수가 높아진다는 뜻으로, 결과를 더 직관적으로 해석할 수 있게 해 줘요.

점수 접근 (Accessing Scores)

getScore() 메서드로 각 문서의 유사도 점수에 접근할 수 있어요:

List<Document> results = vectorStore.similaritySearch(
    SearchRequest.builder()
        .query("Spring AI")
        .topK(5)
        .build());

for (Document doc : results) {
    double score = doc.getScore();  // Value between 0.0 and 1.0
    System.out.println("Document: " + doc.getText());
    System.out.println("Similarity Score: " + score);
}

검색 결과 정렬 (Search Results Ordering)

검색 결과는 자동으로 유사도 점수 내림차순(가장 높은 점수 먼저)으로 정렬돼요. 이렇게 하면 가장 관련성 높은 문서가 결과 상단에 오게 돼요.

거리 메타데이터 (Distance Metadata)

유사도 점수에 더해 원시 거리 값도 여전히 문서 메타데이터에서 사용할 수 있어요:

for (Document doc : results) {
    double score = doc.getScore();
    float distance = (Float) doc.getMetadata().get("distance");

    System.out.println("Score: " + score + ", Distance: " + distance);
}

유사도 임계값 (Similarity Threshold)

검색 요청에서 유사도 임계값을 사용할 때는 거리가 아니라 점수 값(0.0에서 1.0)으로 지정하세요:

List<Document> results = vectorStore.similaritySearch(
    SearchRequest.builder()
        .query("Spring AI")
        .topK(10)
        .similarityThreshold(0.8)  // Only return documents with score >= 0.8
        .build());

이렇게 하면 임계값이 일관되고 직관적이 되요 - 값이 높을수록 더 제한적인 검색으로, 고도로 유사한 문서만 반환해요.

네이티브 클라이언트 접근 (Accessing the Native Client)

MariaDB Vector Store 구현은 getNativeClient() 메서드를 통해 내부 네이티브 JDBC 클라이언트(JdbcTemplate)에 접근을 제공해요:

MariaDBVectorStore vectorStore = context.getBean(MariaDBVectorStore.class);
Optional<JdbcTemplate> nativeClient = vectorStore.getNativeClient();

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

네이티브 클라이언트는 VectorStore 인터페이스로는 노출되지 않는 MariaDB 특화 기능과 작업에 접근할 수 있게 해 줘요.

더 알아보기 (Learn more)