langchain4j中使用milvus向量数据库做RAG增加索引

安装milvus向量数据库

官方网址 https://milvus.io/zh

使用docker安装milvus

复制代码
mkdir -p /data/docker/milvus
cd /data/docker/milvus
wget https://raw.githubusercontent.com/milvus-io/milvus/master/scripts/standalone_embed.sh

#在docker中启动milvus
sh standalone_embed.sh start
docker ps -a

#停止、删除
sh standalone_embed.sh stop
sh standalone_embed.sh delete

浏览器访问

http://192.168.2.205:9091/webui/


在langchain中使用milvus

  1. pom.xml中引入依赖

    复制代码
     <dependency>
             <groupId>dev.langchain4j</groupId>
             <artifactId>langchain4j-milvus</artifactId>
             <version>${langchain4j.version}</version>
         </dependency>
  2. 设置配置信息

    milvus:
    host: 192.168.1.131
    port: 19530

    langchain4j:
    community:
    dashscope:
    chat-model:
    api-key: {dashscope.key} model-name: qwen-max embedding-model: api-key: {dashscope.key}
    model-name: text-embedding-v3
    streaming-chat-model:
    api-key: ${dashscope.key}
    model-name: qwen-plus

  3. 配置向量库

    @Configuration
    @Slf4j
    public class EmbeddingStoreConfig {
    @Autowired
    private EmbeddingModel embeddingModel;

    复制代码
     @Value("${milvus.host}")
     private String host;
     @Value("${milvus.port}")
     private Integer port;
    
     @Bean
     public EmbeddingStore embeddingStore() {
         log.info("==========开始创建Milvus的Collection");
         MilvusEmbeddingStore store = MilvusEmbeddingStore.builder()
                 .host(host)
                 .port(port)
                 .collectionName("langchain_01")
                 .dimension(1024)
                 .indexType(IndexType.FLAT)
                 .metricType(MetricType.COSINE)

    // .username("username")
    // .password("password")
    .consistencyLevel(ConsistencyLevelEnum.EVENTUALLY)
    .autoFlushOnInsert(true)
    .idFieldName("id")
    .textFieldName("text")
    .metadataFieldName("metadata")
    .vectorFieldName("vector")
    .build();
    log.info("==========创建Milvus的Collection完成");
    return store;
    }

    }

  4. 使用向量库存储数据

    @SpringBootTest
    public class EmbeddingTest {
    @Autowired
    private EmbeddingModel embeddingModel;
    @Autowired
    private EmbeddingStore embeddingStore;

    复制代码
     @Test
     public void testEmbeddingModel() {
         Response<Embedding> embed = embeddingModel.embed("你好");
         System.out.println("向量维度:" + embed.content().vector().length);
         System.out.println("向量输出:" + embed.toString());
     }
    
     /**
      * 将文本转换成向量,然后存储到pinecone中
      * <p>
      * 参考:
      * https://docs.langchain4j.dev/tutorials/embedding-stores
      */
     @Test
     public void testPineconeEmbeded() {
         //将文本转换成向量
         TextSegment segment1 = TextSegment.from("我喜欢羽毛球");
         Embedding embedding1 = embeddingModel.embed(segment1).content();
         //存入向量数据库
         embeddingStore.add(embedding1, segment1);
         TextSegment segment2 = TextSegment.from("今天天气很好");
         Embedding embedding2 = embeddingModel.embed(segment2).content();
         embeddingStore.add(embedding2, segment2);
     }
    
     /**
      * 相似度匹配
      */
     @Test
     public void embeddingSearch() {
         //提问,并将问题转成向量数据
         Embedding queryEmbedding = embeddingModel.embed("你最喜欢的运动是什么?").content();
         //创建搜索请求对象
         EmbeddingSearchRequest searchRequest = EmbeddingSearchRequest.builder()
                 .queryEmbedding(queryEmbedding)
                 .maxResults(1) //匹配最相似的一条记录
                 //.minScore(0.8)
                 .build();
         //根据搜索请求 searchRequest 在向量存储中进行相似度搜索
         EmbeddingSearchResult<TextSegment> searchResult =
                 embeddingStore.search(searchRequest);
         //searchResult.matches():获取搜索结果中的匹配项列表。
         //.get(0):从匹配项列表中获取第一个匹配项
         EmbeddingMatch<TextSegment> embeddingMatch = searchResult.matches().get(0);
         //获取匹配项的相似度得分
         System.out.println(embeddingMatch.score()); // 0.8144288515898701
         //返回文本结果
         System.out.println(embeddingMatch.embedded().text());
     }
    
     @Test
     public void testUploadKnowledgeLibrary() {
         //使用FileSystemDocumentLoader读取指定目录下的知识库文档
         //并使用默认的文档解析器对文档进行解析
         Document document1 = FileSystemDocumentLoader.loadDocument("D:/knowledge/文档1.md");
         Document document2 = FileSystemDocumentLoader.loadDocument("D:/knowledge/文档2.md");
         Document document3 = FileSystemDocumentLoader.loadDocument("D:/knowledge/文档3.md");
         List<Document> documents = Arrays.asList(document1, document2, document3);
         //文本向量化并存入向量数据库:将每个片段进行向量化,得到一个嵌入向量
         EmbeddingStoreIngestor
                 .builder()
                 .embeddingStore(embeddingStore)
                 .embeddingModel(embeddingModel)
                 .build()
                 .ingest(documents);
     }

    }

  5. 配置Agent属性

    @Configuration
    public class AgentConfig {
    @Autowired
    private MongoChatMemoryStore mongoChatMemoryStore;
    @Autowired
    private EmbeddingStore embeddingStore;
    @Autowired
    private EmbeddingModel embeddingModel;

    复制代码
     @Bean
     public ChatMemoryProvider chatMemoryProviderXiaozhi() {
         return memoryId -> MessageWindowChatMemory.builder()
                 .id(memoryId)
                 .maxMessages(20)
                 .chatMemoryStore(mongoChatMemoryStore)
                 .build();
     }
    
     @Bean
     ContentRetriever contentRetriever() {
         // 创建一个 EmbeddingStoreContentRetriever 对象,用于从嵌入存储中检索内容
         return EmbeddingStoreContentRetriever
                 .builder()
                 // 设置用于生成嵌入向量的嵌入模型
                 .embeddingModel(embeddingModel)
                 // 指定要使用的嵌入存储
                 .embeddingStore(embeddingStore)
                 // 设置最大检索结果数量,这里表示最多返回 1 条匹配结果
                 .maxResults(1)
                 // 设置最小得分阈值,只有得分大于等于 0.8 的结果才会被返回
                 .minScore(0.8)
                 // 构建最终的 EmbeddingStoreContentRetriever 实例
                 .build();
     }

    }

  6. 配置AIService

    @AiService(
    wiringMode = EXPLICIT,
    // chatModel = "qwenChatModel",
    streamingChatModel = "qwenStreamingChatModel",
    chatMemoryProvider = "chatMemoryProviderXiaozhi",
    tools = "appointmentTools",
    contentRetriever = "contentRetriever")
    public interface Agent {
    @SystemMessage(fromResource = "zhaozhi-prompt-template.txt")
    Flux<String> chat(@MemoryId Long memoryId, @UserMessage String userMessage);
    }

  7. Controller类

    @RestController
    @RequestMapping("/agent")
    public class AgentController {
    @Autowired
    private Agent agent;

    复制代码
     @Operation(summary = "对话")
     @PostMapping(value = "/chat", produces = "text/stream;charset=utf-8")
     public Flux<String> chat(@RequestBody ChatForm chatForm) {
         return agent.chat(chatForm.getMemoryId(), chatForm.getMessage());
     }

    }

源码地址:

https://gitee.com/galen.zhang/langchain-ai-demo/java-ai-langchain4j


注意事项

  1. pom.xml文件中的langchain4j-pineconelangchain4j-milvus依赖了不同版本的gRPC,需要注释掉其中一种向量库

  2. milvus 默认有速率限制,写向量库会出现错误

    2025-05-13T14:34:50.404+08:00 ERROR 26656 --- [java-ai-langchain4j] [ main] i.m.client.AbstractMilvusGrpcClient : FlushRequest failed, error code: 8, reason: request is rejected by grpc RateLimiter middleware, please retry later: rate limit exceeded[rate=0.1]
    2025-05-13T14:34:50.405+08:00 ERROR 26656 --- [java-ai-langchain4j] [ main] i.m.client.AbstractMilvusGrpcClient : FlushRequest failed! Exception:{}
    io.milvus.exception.ServerException: request is rejected by grpc RateLimiter middleware, please retry later: rate limit exceeded[rate=0.1]

解决方法:

需要修改配置文件 /milvus/configs/milvus.yaml
quotaAndLimits.flushRate.collection.max 默认值是0.1,需要调高一些

复制代码
quotaAndLimits.flushRate.collection.max = 10

下载配置文件
wget https://raw.githubusercontent.com/milvus-io/milvus/v2.5.11/configs/milvus.yaml

修改docker启动配置,挂载外部配置文件
vi standalone_embed.sh

增加一行 -v $(pwd)/milvus.yaml:/milvus/configs/milvus.yaml \

复制代码
    sudo docker run -d \
        --name milvus-standalone \
        --security-opt seccomp:unconfined \
        -e ETCD_USE_EMBED=true \
        -e ETCD_DATA_DIR=/var/lib/milvus/etcd \
        -e ETCD_CONFIG_PATH=/milvus/configs/embedEtcd.yaml \
        -e COMMON_STORAGETYPE=local \
	-v $(pwd)/milvus.yaml:/milvus/configs/milvus.yaml \
        -v $(pwd)/volumes/milvus:/var/lib/milvus \
        -v $(pwd)/embedEtcd.yaml:/milvus/configs/embedEtcd.yaml \
        -v $(pwd)/user.yaml:/milvus/configs/user.yaml \
        -p 19530:19530 \
        -p 9091:9091 \
        -p 2379:2379 \
        --health-cmd="curl -f http://localhost:9091/healthz" \
        --health-interval=30s \
        --health-start-period=90s \
        --health-timeout=20s \
        --health-retries=3 \
        milvusdb/milvus:v2.5.11 \
        milvus run standalone  1> /dev/null

删除之前的容器,重新启动

复制代码
sh standalone_embed.sh stop
sh standalone_embed.sh delete

sh standalone_embed.sh start	  
相关推荐
为自己_带盐21 分钟前
浅聊一下数据库的索引优化
开发语言·数据库·php
gb42152871 小时前
mysql数据库中某个数据表的碎片率自己降低了,mysql数据表对碎片率有自动优化机制吗?
数据库·mysql
AI大模型顾潇1 小时前
[特殊字符] 本地大模型编程实战(29):用大语言模型LLM查询图数据库NEO4J(2)
前端·数据库·人工智能·语言模型·自然语言处理·prompt·neo4j
有时间要学习1 小时前
MySQL——数据类型&&表的约束
数据库·mysql
AI改变未来1 小时前
数据库常见故障排查
数据库
bing_1582 小时前
MongoDB 的核心概念(文档、集合、数据库、BSON)是什么?
数据库·mongodb·oracle
feilieren2 小时前
Windows 安装 Milvus
数据库·ai·milvus
kngines2 小时前
【PostgreSQL数据分析实战:从数据清洗到可视化全流程】附录-D. 扩展插件列表(PostGIS/PostgREST等)
数据库·postgresql·数据分析·pgvector·扩展插件·postgrest·向量数据
星星点点洲2 小时前
【Redis】谈谈Redis的设计
数据库·redis·缓存
HelloZheQ2 小时前
MVCC:数据库并发控制的利器
服务器·数据库·oracle