package dev.example;

import static dev.langchain4j.data.document.UrlDocumentLoader.load;
import static dev.langchain4j.model.openai.OpenAiModelName.GPT_3_5_TURBO;

import java.io.IOException;
import java.net.URL;

import jakarta.enterprise.context.ApplicationScoped;

import dev.langchain4j.data.document.Document;
import dev.langchain4j.data.document.DocumentSplitter;
import dev.langchain4j.data.document.splitter.DocumentSplitters;
import dev.langchain4j.data.segment.TextSegment;
import dev.langchain4j.model.embedding.EmbeddingModel;
import dev.langchain4j.model.openai.OpenAiTokenizer;
import dev.langchain4j.retriever.EmbeddingStoreRetriever;
import dev.langchain4j.retriever.Retriever;
import dev.langchain4j.store.embedding.EmbeddingStore;
import dev.langchain4j.store.embedding.EmbeddingStoreIngestor;
import dev.langchain4j.store.embedding.inmemory.InMemoryEmbeddingStore;

public class Beans {

    @ApplicationScoped
    Retriever<TextSegment> retriever(EmbeddingStore<TextSegment> embeddingStore, EmbeddingModel embeddingModel) {

        // You will need to adjust these parameters to find the optimal setting, which will depend on two main factors:
        // - The nature of your data
        // - The embedding model you are using
        int maxResultsRetrieved = 1;
        double minScore = 0.6;

        return EmbeddingStoreRetriever.from(embeddingStore, embeddingModel, maxResultsRetrieved, minScore);
    }

    @ApplicationScoped
    EmbeddingStore<TextSegment> embeddingStore(EmbeddingModel embeddingModel) throws IOException {

        // Normally, you would already have your embedding store filled with your data.
        // However, for the purpose of this demonstration, we will:

        // 1. Create an in-memory embedding store
        EmbeddingStore<TextSegment> embeddingStore = new InMemoryEmbeddingStore<>();

        // 2. Load an example document ("Miles of Smiles" terms of use)
        String documentName = "miles-of-smiles-terms-of-use.txt";
        URL resource = Thread.currentThread().getContextClassLoader().getResource(documentName);
        if (resource == null) {
            throw new IllegalStateException("Unable to locate document: '" + documentName + "' on the classpath");
        }
        Document document = load(resource);

        // 3. Split the document into segments 100 tokens each
        // 4. Convert segments into embeddings
        // 5. Store embeddings into embedding store
        // All this can be done manually, but we will use EmbeddingStoreIngestor to automate this:
        DocumentSplitter documentSplitter = DocumentSplitters.recursive(100, 0, new OpenAiTokenizer(GPT_3_5_TURBO));
        EmbeddingStoreIngestor ingestor = EmbeddingStoreIngestor.builder()
                .documentSplitter(documentSplitter)
                .embeddingModel(embeddingModel)
                .embeddingStore(embeddingStore)
                .build();
        ingestor.ingest(document);

        return embeddingStore;
    }
}

dev.langchain4j.store.embedding.EmbeddingStoreIngestor.builder
[((2707, 2912), 'dev.langchain4j.store.embedding.EmbeddingStoreIngestor.builder'), ((2707, 2887), 'dev.langchain4j.store.embedding.EmbeddingStoreIngestor.builder'), ((2707, 2839), 'dev.langchain4j.store.embedding.EmbeddingStoreIngestor.builder'), ((2707, 2791), 'dev.langchain4j.store.embedding.EmbeddingStoreIngestor.builder')]