package com.rj.embedding;

import dev.langchain4j.data.document.Document;
import dev.langchain4j.data.document.DocumentSplitter;
import dev.langchain4j.data.document.loader.ClassPathDocumentLoader;
import dev.langchain4j.data.document.parser.apache.pdfbox.ApachePdfBoxDocumentParser;
import dev.langchain4j.data.document.splitter.DocumentSplitters;
import dev.langchain4j.data.segment.TextSegment;
import dev.langchain4j.model.embedding.EmbeddingModel;
import dev.langchain4j.rag.content.retriever.ContentRetriever;
import dev.langchain4j.rag.content.retriever.EmbeddingStoreContentRetriever;
import dev.langchain4j.store.embedding.EmbeddingStore;
import dev.langchain4j.store.embedding.EmbeddingStoreIngestor;
import dev.langchain4j.store.embedding.inmemory.InMemoryEmbeddingStore;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import java.io.IOException;
import java.util.List;

/**
 * Author: 李中华  wx: spllzh  email(qq): 28668817@qq.com
 * Date: 2025/8/4 18:21
 **/
@Configuration
public class EnbedingModelConfig {


    @Autowired
    @Lazy
    private EmbeddingModel embeddingModel;

    // 注释掉 RedisEmbeddingStore 的自动注入，避免启动时连接外部网络
    // 如果需要使用 Redis 向量数据库，请在需要时手动创建 Bean，而不是通过 @Autowired 注入
    // @Autowired
    // @Lazy
    // RedisEmbeddingStore redisEmbeddingStore;
    /**
     * 创建向量数据库操作对象
     * @return
     */
    @Bean("myEmbeddingStoreInMemory")
//    @Primary
    public EmbeddingStore<TextSegment> embeddingStoreInMemory() {
        //1 , 加载知识库文档进 内存
        List<Document> documents =ClassPathDocumentLoader.loadDocuments("knowledge"); //暂时去掉 2025-09-20
        //2 ， 构建向量数据库操作对象
        InMemoryEmbeddingStore<TextSegment> embeddingStore = new InMemoryEmbeddingStore<>();
        //3， 构建EmbeddingStoreIngestor ，  完成文本数据的切割， 向量化， 存储
        EmbeddingStoreIngestor ingestor = EmbeddingStoreIngestor.builder()
                .embeddingStore(embeddingStore)
                .build();
        ingestor.ingest( documents);
        return  embeddingStore;
    }

 //   @Bean("myEmbeddingStoreInMemory2")
//    @Primary
    public EmbeddingStore<TextSegment> embeddingStoreInMemory2() throws IOException {
        //1 , 加载知识库文档进 内存
         List<Document> documents1 = ClassPathDocumentLoader.loadDocuments("knowledge\\pdf",new ApachePdfBoxDocumentParser());
//        List<Document> documents2 = ClassPathDocumentLoader.loadDocuments("knowledge");

        //2 ， 构建向量数据库操作对象
        InMemoryEmbeddingStore<TextSegment> embeddingStore = new InMemoryEmbeddingStore<>();

        //构建文档 分割器对象
        DocumentSplitter recursiveSplitter = DocumentSplitters.recursive(300, 50);

        //3， 构建EmbeddingStoreIngestor ，  完成文本数据的切割， 向量化， 存储
        EmbeddingStoreIngestor ingestor = EmbeddingStoreIngestor.builder()
                .embeddingStore(embeddingStore)
                .documentSplitter(recursiveSplitter) //设置文档分割器
//                .embeddingModel(embeddingModel)
                .build();
        ingestor.ingest( documents1);
        return  embeddingStore;
    }


//    @Bean("myEmbeddingStoreInRedis")   不要打开，否则每次都会调用 阿里云的向量化模型 ，消耗token
//    @Primary
    public EmbeddingStore<TextSegment> embeddingStoreInRedis(EmbeddingStore<TextSegment> redisEmbeddingStore) throws IOException {
        //1 , 加载知识库文档进 内存
        List<Document> documents1 = ClassPathDocumentLoader.loadDocuments("knowledge\\pdf",new ApachePdfBoxDocumentParser());
//        List<Document> documents2 = ClassPathDocumentLoader.loadDocuments("knowledge");

        //构建文档 分割器对象
        DocumentSplitter recursiveSplitter = DocumentSplitters.recursive(300, 50);

        //3， 构建EmbeddingStoreIngestor ，  完成文本数据的切割， 向量化， 存储
        EmbeddingStoreIngestor ingestor = EmbeddingStoreIngestor.builder()
                .embeddingStore(redisEmbeddingStore)
                .documentSplitter(recursiveSplitter) //设置文档分割器
                .embeddingModel(embeddingModel)
                .build();
        ingestor.ingest( documents1);
        return  redisEmbeddingStore;
    }

    @Bean
    @Lazy
    public ContentRetriever contentRetriever(@Qualifier("myEmbeddingStoreInMemory") EmbeddingStore<TextSegment> store){
        // 使用 @Lazy 注解延迟初始化，避免启动时连接阿里云
        // embeddingModel 也是 @Lazy 的，只有在实际使用 RAG 功能时才会初始化并连接
        EmbeddingStoreContentRetriever contentRetriever = EmbeddingStoreContentRetriever.builder()
                .embeddingStore(store)
                .embeddingModel(embeddingModel)  // 保持 @Lazy，延迟初始化
                .minScore(0.5)//相似度
                .maxResults(3) //最多返回3条
                .build();
        return  contentRetriever;
    }



}
