Elasticsearch: RAG using Open AI and Langchain – Retrieval Augmented Generation (4)

This blog is a previous article:

  • Elasticsearch: RAG using Open AI and Langchain – Retrieval Augmented Generation (1)
  • Elasticsearch: RAG using Open AI and Langchain – Retrieval Augmented Generation (2)
  • Elasticsearch: RAG using Open AI and Langchain – Retrieval Augmented Generation (3)

’s continuation. In this article, we will learn how to pass search results from Elasticsearch to big data models to get better results.

If you haven’t created your own environment yet, please refer to the first article for detailed installation.

For large text documents, we can use the following architecture:

Create an application and display it

Installation package

#!pip3 install langchain

Import package

from dotenv import load_dotenv
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import ElasticsearchStore
from langchain.text_splitter import CharacterTextSplitter
from langchain.prompts import ChatPromptTemplate
from langchain.prompts import PromptTemplate
from langchain.chat_models import ChatOpenAI
from langchain.schema.output_parser import StrOutputParser
from langchain.schema.runnable import RunnablePassthrough
from langchain.schema.runnable import RunnableLambda
from langchain.schema import HumanMessage
from urllib.request import urlopen
import os, json
 
load_dotenv()
 
openai_api_key=os.getenv('OPENAI_API_KEY')
elastic_user=os.getenv('ES_USER')
elastic_password=os.getenv('ES_PASSWORD')
elastic_endpoint=os.getenv("ES_ENDPOINT")
elastic_index_name='langchain-rag'

Add documents and divide documents into paragraphs

with open('workplace-docs.json') as f:
   workplace_docs = json.load(f)
 
print(f"Successfully loaded {len(workplace_docs)} documents")

metadata = []
content = []
 
for doc in workplace_docs:
  content.append(doc["content"])
  metadata.append({
      "name": doc["name"],
      "summary": doc["summary"],
      "rolePermissions":doc["rolePermissions"]
  })
 
text_splitter = CharacterTextSplitter(chunk_size=50, chunk_overlap=0)
docs = text_splitter.create_documents(content, metadatas=metadata)

Index Documents using ELSER – SparseVectorRetrievalStrategy()

from elasticsearch import Elasticsearch

url = f"https://{elastic_user}:{elastic_password}@{elastic_endpoint}:9200"
connection = Elasticsearch(url, ca_certs = "./http_ca.crt", verify_certs = True)

es = ElasticsearchStore.from_documents(
    docs,
    es_url = url,
    es_connection = connection,
    es_user=elastic_user,
    es_password=elastic_password,
    index_name=elastic_index_name,
    strategy=ElasticsearchStore.SparseVectorRetrievalStrategy()
)

If you have not configured your own ELSER, please refer to the previous article “Elasticsearch: RAG using Open AI and Langchain – Retrieval Augmented Generation (3)”.

After executing the above command, we can view it in Kibana:

Show results

def showResults(output):
  print("Total results: ", len(output))
  for index in range(len(output)):
    print(output[index])
r = es.similarity_search("work from home policy")
showResults(r)

RAG with Elasticsearch – Method 1 (Using Retriever)

retriever = es.as_retriever(search_kwargs={"k": 4})

template = """Answer the question based only on the following context:
{context}

Question: {question}
"""
prompt = ChatPromptTemplate.from_template(template)

chain = (
    {"context": retriever, "question": RunnablePassthrough()}
    | prompt
    | ChatOpenAI()
    | StrOutputParser()
)

chain.invoke("vacation policy")

RAG with Elasticsearch – Method 2 (Without Retriever)

Add Context

def add_context(question: str):
    r = es.similarity_search(question)
    
    context = "\\
".join(x.page_content for x in r)
    
    return context

Chain

template = """Answer the question based only on the following context:
{context}

Question: {question}
"""

prompt = ChatPromptTemplate.from_template(template)

chain = (
    {"context": RunnableLambda(add_context), "question": RunnablePassthrough()}
    | prompt
    | ChatOpenAI()
    | StrOutputParser()
)

chain.invoke("canada employees guidelines")

Compare with RAG and without RAG

q = input("Ask Question: ")

## Question to OpenAI

chat = ChatOpenAI()

messages = [
    HumanMessage(
        content=q
    )
]

gpt_res = chat(messages)

# Question with RAG

gpt_rag_res = chain.invoke(q)


#Responses

s = f"""
ChatGPT Response:

{gpt_res}

ChatGPT with RAG Response:

{gpt_rag_res}
"""

print(s)

The code of the above jupyter notebook can be downloaded at the address https://github.com/liu-xiao-guo/semantic_search_es/blob/main/RAG-langchain-elasticsearch.ipynb.

The knowledge points of the article match the official knowledge files, and you can further learn relevant knowledge. Python entry skill treeHomepageOverview 383353 people are learning the system