Langchain4j pgvector implementation as an EmbeddingStore?

186 views Asked by At

I'm building a RAG based AI service using Langchain4j. I have one microservice that is ingesting and saving my documents (pdfs, csv, words...) in my PostgreSQL DB (with vector extension) as embeddings.

From the other hand I'm building another microservice to hold the AI conversation logic.

To do this I'm creating the next beans

    @Bean
public EmbeddingStore<TextSegment> embeddingStore() {
    return new InMemoryEmbeddingStore<>();
}

    @Bean
public ContentRetriever contentRetriever() {
    return EmbeddingStoreContentRetriever.builder()
            .embeddingStore(embeddingStore())
            .embeddingModel(bedrockTitanEmbeddingModel())
            .maxResults(10) // on each interaction we will retrieve the 5 most relevant segments
            .minScore(0.2) // we want to retrieve segments very similar to the user query
            .build();
}
    @Bean
public RetrievalAugmentor retrievalAugmentor() {
    return DefaultRetrievalAugmentor.builder()
            .queryTransformer(queryTransformer())
            .contentRetriever(contentRetriever())
            .build();
}

    @Bean
public AiAgent aiAgent() {
    return AiServices.builder(ErekyAiAgent.class)
            .retrievalAugmentor(retrievalAugmentor())
            .chatLanguageModel(bedrockAnthropicChatModel())
            .contentRetriever(contentRetriever())
            .build();
}

The ContentRetriever is asking me as a mandatory parameter the embeddingStore. Now for testing I'm using the memory one but I saw that Langchain4j has an implementation with pgvector.

In the flow what I'm doing is:

  1. Doing the query to my PostgreSQL database with the user asked question
  2. Returning the document text list found
  3. Transforming the List of Strings containing the document text I got to a list of List<TextSegment> that is a type of langchain4j library.
  4. Then I need to transform the List<TextSegment> to embeddings again and add them along with the List<TextSegment> without embedding them to the embedding store I'm using.

The logic is

List<String> documentTexts = getDocumentTextsFromUserQuestion(promptDto);
        List<TextSegment> textSegments = getTextSegments(documentTexts);
        embeddingStore.addAll(embedComponent.getEmbeddingsFromTextSegments(textSegments), textSegments);
        return new PromptDTO(aiAgent.answer(documentTexts, promptDto.getText()));

I saw that for some reason the logic always need for me to add that data to the embedding store to be able to give a correct answer based on my data. When I used the pgvector implementation of Langchain4j and did the same thing I saw that the implementation is creating a table in my DB with the data I already had saved before inserted in this new table to give the answer. And the data is being duplicated, there is a way to make this work without that?

And since I already have the data saved in the DB, I can't directly do the call to the AI with the data found from the user question + the user question?

I did it like this in Python calling chain.run being documents the data found in the DB and the question being the user question and it works and I don't need this intermmediate embedding store.

chain = load_qa_chain(llm, chain_type="stuff")
    # Call to the model
    # response = st.session_state.conversation({'question': user_question})
    response = chain.run(input_documents=document, question=user_question)
0

There are 0 answers