mcpField
Q
qdrant-vector-database-integration

qdrant-vector-database-integration

github.com/giuseppe-trisciuoglio数据与数据库36568 次安装7 周前更新
代码仓库

关于 qdrant-vector-database-integration

面向 Java 应用集成 Qdrant 向量搜索的技能指南,提供 Spring Boot 和 LangChain4j 模式,涵盖集合管理、向量操作、过滤搜索与 RAG。

主要功能

  1. 01Java 客户端配置
  2. 02集合管理
  3. 03向量写入与相似度搜索
  4. 04Spring Boot 集成
  5. 05LangChain4j 嵌入存储
  6. 06过滤与多租户搜索

适用场景

  1. 01为 Spring Boot 添加语义搜索
  2. 02构建 Java RAG 流水线
  3. 03创建带过滤条件的向量搜索

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/giuseppe-trisciuoglio/developer-kit --skill qdrant-vector-database-integration

安装后在 Claude Code 中输入/qdrant-vector-database-integration确认已加载。

附带文件references/examples.mdreferences/references.md

详细介绍

Qdrant 向量数据库集成

概述

Qdrant 是一款面向 AI 的向量数据库,适用于语义搜索和相似度检索。本技能提供了将 Qdrant 集成到 Java 应用程序中的模式,重点介绍 Spring Boot 集成和 LangChain4j 框架支持。为 RAG 系统、推荐引擎和语义搜索应用启用高效的向量搜索能力。

适用场景

在以下情况下使用本技能:

  • 在 Spring Boot 应用程序中实现语义搜索或推荐系统
  • 使用 Java 和 LangChain4j 构建检索增强生成(RAG)管道
  • 为 AI 和机器学习应用集成向量数据库
  • 使用筛选查询进行高性能相似度搜索
  • 为具备上下文感知能力的应用存储和检索嵌入

入门:配置 Qdrant

开始集成前,请先部署 Qdrant 实例。

使用 Docker 进行本地开发
# Pull the latest Qdrant image
docker pull qdrant/qdrant

# Run the Qdrant container
docker run -p 6333:6333 -p 6334:6334 \
    -v "$(pwd)/qdrant_storage:/qdrant/storage:z" \
    qdrant/qdrant

通过以下方式访问 Qdrant:

  • REST API:http://localhost:6333
  • gRPC API:http://localhost:6334(Java 客户端使用)

Java 客户端核心集成

将依赖项添加到构建配置中,并初始化客户端以进行程序化访问。

依赖项配置

Maven:

<dependency>
    <groupId>io.qdrant</groupId>
    <artifactId>client</artifactId>
    <version>1.15.0</version>
</dependency>

Gradle:

implementation 'io.qdrant:client:1.15.0'
客户端初始化

创建并配置 Qdrant 客户端,供应用程序使用:

import io.qdrant.client.QdrantClient;
import io.qdrant.client.QdrantGrpcClient;

// Basic local connection
QdrantClient client = new QdrantClient(
    QdrantGrpcClient.newBuilder("localhost").build());

// Secure connection with API key
QdrantClient secureClient = new QdrantClient(
    QdrantGrpcClient.newBuilder("localhost", 6334, false)
        .withApiKey("YOUR_API_KEY")
        .build());

// Managed connection with TLS
QdrantClient tlsClient = new QdrantClient(
    QdrantGrpcClient.newBuilder(channel)
        .withApiKey("YOUR_API_KEY")
        .build());

集合管理

使用适当的距离度量和维度创建并配置向量集合。

创建集合
import io.qdrant.client.grpc.Collections.Distance;
import io.qdrant.client.grpc.Collections.VectorParams;
import java.util.concurrent.ExecutionException;

// Create a collection with cosine distance
client.createCollectionAsync("search-collection",
    VectorParams.newBuilder()
        .setDistance(Distance.Cosine)
        .setSize(384)
        .build()).get();

// Create collection with configuration
client.createCollectionAsync("recommendation-engine",
    VectorParams.newBuilder()
        .setDistance(Distance.Euclidean)
        .setSize(512)
        .build()).get();

向量操作

执行常见的向量操作,包括写入、搜索和筛选。

写入点
import io.qdrant.client.grpc.Points.PointStruct;
import java.util.List;
import java.util.Map;
import static io.qdrant.client.PointIdFactory.id;
import static io.qdrant.client.ValueFactory.value;
import static io.qdrant.client.VectorsFactory.vectors;

// Batch upsert vector points
List<PointStruct> points = List.of(
    PointStruct.newBuilder()
        .setId(id(1))
        .setVectors(vectors(0.05f, 0.61f, 0.76f, 0.74f))
        .putAllPayload(Map.of(
            "title", value("Spring Boot Documentation"),
            "content", value("Spring Boot framework documentation")
        ))
        .build(),
    PointStruct.newBuilder()
        .setId(id(2))
        .setVectors(vectors(0.19f, 0.81f, 0.75f, 0.11f))
        .putAllPayload(Map.of(
            "title", value("Qdrant Vector Database"),
            "content", value("Vector database for AI applications")
        ))
        .build()
);

client.upsertAsync("search-collection", points).get();
向量搜索
import io.qdrant.client.grpc.Points.QueryPoints;
import io.qdrant.client.grpc.Points.ScoredPoint;
import static io.qdrant.client.QueryFactory.nearest;
import java.util.List;

// Basic similarity search
List<ScoredPoint> results = client.queryAsync(
    QueryPoints.newBuilder()
        .setCollectionName("search-collection")
        .setLimit(5)
        .setQuery(nearest(0.2f, 0.1f, 0.9f, 0.7f))
        .build()
).get();

// Search with filters
List<ScoredPoint> filteredResults = client.searchAsync(
    SearchPoints.newBuilder()
        .setCollectionName("search-collection")
        .addAllVector(List.of(0.6235f, 0.123f, 0.532f, 0.123f))
        .setFilter(Filter.newBuilder()
            .addMust(range("rand_number",
                Range.newBuilder().setGte(3).build()))
            .build())
        .setLimit(5)
        .build()).get();

Spring Boot 集成

使用依赖注入和适当的配置将 Qdrant 集成到 Spring Boot 中。

配置类
import io.qdrant.client.QdrantClient;
import io.qdrant.client.QdrantGrpcClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class QdrantConfig {

    @Value("${qdrant.host:localhost}")
    private String host;

    @Value("${qdrant.port:6334}")
    private int port;

    @Value("${qdrant.api-key:}")
    private String apiKey;

    @Bean
    public QdrantClient qdrantClient() {
        QdrantGrpcClient grpcClient = QdrantGrpcClient.newBuilder(host, port, false)
            .withApiKey(apiKey)
            .build();

        return new QdrantClient(grpcClient);
    }
}
服务层实现
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.concurrent.ExecutionException;

@Service
public class VectorSearchService {

    private final QdrantClient qdrantClient;

    public VectorSearchService(QdrantClient qdrantClient) {
        this.qdrantClient = qdrantClient;
    }

    public List<ScoredPoint> search(String collectionName, List<Float> queryVector) {
        try {
            return qdrantClient.queryAsync(
                QueryPoints.newBuilder()
                    .setCollectionName(collectionName)
                    .setLimit(5)
                    .setQuery(nearest(queryVector))
                    .build()
            ).get();
        } catch (InterruptedException | ExecutionException e) {
            throw new RuntimeException("Qdrant search failed", e);
        }
    }

    public void upsertPoints(String collectionName, List<PointStruct> points) {
        try {
            qdrantClient.upsertAsync(collectionName, points).get();
        } catch (InterruptedException | ExecutionException e) {
            throw new RuntimeException("Qdrant upsert failed", e);
        }
    }
}

LangChain4j 集成

利用 LangChain4j 实现高级向量存储抽象和 RAG。

依赖项配置

Maven:

<dependency>
    <groupId>dev.langchain4j</groupId>
    <artifactId>langchain4j-qdrant</artifactId>
    <version>1.7.0</version>
</dependency>
QdrantEmbeddingStore 配置
import dev.langchain4j.data.segment.TextSegment;
import dev.langchain4j.embedding.EmbeddingModel;
import dev.langchain4j.embedding.allminilml6v2.AllMiniLmL6V2EmbeddingModel;
import dev.langchain4j.store.embedding.EmbeddingStore;
import dev.langchain4j.store.embedding.EmbeddingStoreIngestor;
import dev.langchain4j.store.embedding.qdrant.QdrantEmbeddingStore;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class Langchain4jConfig {

    @Bean
    public EmbeddingStore<TextSegment> embeddingStore() {
        return QdrantEmbeddingStore.builder()
            .collectionName("rag-collection")
            .host("localhost")
            .port(6334)
            .apiKey("YOUR_API_KEY")
            .build();
    }

    @Bean
    public EmbeddingModel embeddingModel() {
        return new AllMiniLmL6V2EmbeddingModel();
    }

    @Bean
    public EmbeddingStoreIngestor embeddingStoreIngestor(
            EmbeddingStore<TextSegment> embeddingStore,
            EmbeddingModel embeddingModel) {
        return EmbeddingStoreIngestor.builder()
            .embeddingStore(embeddingStore)
            .embeddingModel(embeddingModel)
            .build();
    }
}
RAG 服务实现
import dev.langchain4j.data.segment.TextSegment;
import dev.langchain4j.embedding.EmbeddingModel;
import dev.langchain4j.store.embedding.EmbeddingStore;
import dev.langchain4j.store.embedding.EmbeddingStoreIngestor;
import org.springframework.stereotype.Service;
import java.util.List;

@Service
public class RagService {

    private final EmbeddingStoreIngestor ingestor;

    public RagService(EmbeddingStoreIngestor ingestor) {
        this.ingestor = ingestor;
    }

    public void ingestDocument(String text) {
        TextSegment segment = TextSegment.from(text);
        ingestor.ingest(segment);
    }

    public List<TextSegment> findRelevant(String query) {
        EmbeddingStore<TextSegment> embeddingStore = ingestor.getEmbeddingStore();
        return embeddingStore.findRelevant(
            ingestor.getEmbeddingModel().embed(query).content(),
            5,
            0.7
        ).stream()
            .map(match -> match.embedded())
            .toList();
    }
}

示例

基本搜索实现
// Create simple search endpoint
@RestController
@RequestMapping("/api/search")
public class SearchController {

    private final VectorSearchService searchService;

    public SearchController(VectorSearchService searchService) {
        this.searchService = searchService;
    }

    @GetMapping
    public List<ScoredPoint> search(@RequestParam String query) {
        // Convert query to embedding (requires embedding model)
        List<Float> queryVector = embeddingModel.embed(query).content().vectorAsList();
        return searchService.search("documents", queryVector);
    }
}

最佳实践

向量数据库配置
  • 使用适当的距离度量:文本使用 Cosine,数值数据使用 Euclidean
  • 根据嵌入模型规范优化向量维度
  • 配置合理的集合命名约定
  • 监控性能并优化搜索参数
Spring Boot 集成
  • 始终使用构造函数注入进行依赖注入
  • 通过适当的异常处理来处理异步操作
  • 配置连接超时和重试策略
  • 为生产环境使用适当的 Bean 配置
安全注意事项
  • 切勿在代码中硬编码 API 密钥
  • 使用环境变量或 Spring 配置属性
  • 实施适当的身份验证和授权
  • 在生产连接中使用 TLS
性能优化
  • 批量执行操作以批量写入
  • 使用适当的限制和筛选条件
  • 监控内存使用情况和连接池
  • 对大型数据集考虑分片

高级模式

多租户向量存储
// Implement collection-based multi-tenancy
public class MultiTenantVectorService {
    private final QdrantClient client;

    public void upsertForTenant(String tenantId, List<PointStruct> points) {
        String collectionName = "tenant_" + tenantId + "_documents";
        client.upsertAsync(collectionName, points).get();
    }
}
带筛选条件的混合搜索
// Combine vector similarity with metadata filtering
public List<ScoredPoint> hybridSearch(String collectionName, List<Float> queryVector,
                                     String category, Date dateRange) {
    Filter filter = Filter.newBuilder()
        .addMust(range("created_at",
            Range.newBuilder().setGte(dateRange.getTime()).build()))
        .addMust(exactMatch("category", category))
        .build();

    return client.searchAsync(
        SearchPoints.newBuilder()
            .setCollectionName(collectionName)
            .addAllVector(queryVector)
            .setFilter(filter)
            .build()
    ).get();
}

参考资料

如需全面的技术细节和高级模式,请参阅:

评论

支持 Markdown