From 511728c7c434e636043545609a66523c5ce8988e Mon Sep 17 00:00:00 2001 From: lakshith Date: Mon, 16 Sep 2024 14:36:24 +0530 Subject: [PATCH 01/11] Fast API server for Adaptive RAG --- .env | 4 + .gitignore | 4 + RAG/agents/answer_grader.py | 31 +++ RAG/agents/extractor.py | 46 ++++ RAG/agents/generate.py | 28 +++ RAG/agents/grader.py | 29 +++ RAG/agents/hallucinate_checker.py | 29 +++ RAG/agents/question_rewriter.py | 23 ++ RAG/edges/decide_to_generate.py | 26 ++ RAG/edges/generation_grader.py | 44 ++++ RAG/graph.py | 48 ++++ RAG/graph_state.py | 24 ++ RAG/nodes/extract_queries.py | 22 ++ RAG/nodes/generate.py | 30 +++ RAG/nodes/grade_documents.py | 31 +++ RAG/nodes/retrieve.py | 21 ++ RAG/nodes/transform.py | 20 ++ RAG/nodes/web_search.py | 23 ++ RAG/tools/vectore_store_retriever.py | 34 +++ RAG/tools/web_search.py | 3 + experiments/adaptive_rag.ipynb | 350 +++++++++++++++++++++++++-- graph_image.png | Bin 0 -> 25398 bytes main.py | 29 +++ 23 files changed, 885 insertions(+), 14 deletions(-) create mode 100644 .env create mode 100644 .gitignore create mode 100644 RAG/agents/answer_grader.py create mode 100644 RAG/agents/extractor.py create mode 100644 RAG/agents/generate.py create mode 100644 RAG/agents/grader.py create mode 100644 RAG/agents/hallucinate_checker.py create mode 100644 RAG/agents/question_rewriter.py create mode 100644 RAG/edges/decide_to_generate.py create mode 100644 RAG/edges/generation_grader.py create mode 100644 RAG/graph.py create mode 100644 RAG/graph_state.py create mode 100644 RAG/nodes/extract_queries.py create mode 100644 RAG/nodes/generate.py create mode 100644 RAG/nodes/grade_documents.py create mode 100644 RAG/nodes/retrieve.py create mode 100644 RAG/nodes/transform.py create mode 100644 RAG/nodes/web_search.py create mode 100644 RAG/tools/vectore_store_retriever.py create mode 100644 RAG/tools/web_search.py create mode 100644 graph_image.png create mode 100644 main.py diff --git a/.env b/.env new file mode 100644 index 0000000..10d39fd --- /dev/null +++ b/.env @@ -0,0 +1,4 @@ +OPENAI_API_KEY=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 +TAVILY_API_KEY=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 +LANGCHAIN_TRACING_V2=true +LANGCHAIN_API_KEY=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 \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..aa5ec2b --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +*.pyc +__pycache__ +vectore_stores +sajith_vectorstore \ No newline at end of file diff --git a/RAG/agents/answer_grader.py b/RAG/agents/answer_grader.py new file mode 100644 index 0000000..e2d80a1 --- /dev/null +++ b/RAG/agents/answer_grader.py @@ -0,0 +1,31 @@ +from langchain_core.output_parsers import StrOutputParser +from langchain_core.prompts import PromptTemplate +from langchain_core.prompts import ChatPromptTemplate +from langchain_core.pydantic_v1 import BaseModel, Field +from langchain_openai import ChatOpenAI + + +# Data model +class GradeAnswer(BaseModel): + """Binary score to assess answer addresses question.""" + + binary_score: str = Field( + description="Answer addresses the question, 'yes' or 'no'" + ) + + +# LLM with function call +llm = ChatOpenAI(model="gpt-4o-mini", temperature=0) +structured_llm_grader = llm.with_structured_output(GradeAnswer) + +# Prompt +system = """You are a grader assessing whether an answer addresses / resolves a question \n + Give a binary score 'yes' or 'no'. Yes' means that the answer resolves the question.""" +answer_prompt = ChatPromptTemplate.from_messages( + [ + ("system", system), + ("human", "User question: \n\n {question} \n\n LLM generation: {generation}"), + ] +) + +answer_grader = answer_prompt | structured_llm_grader \ No newline at end of file diff --git a/RAG/agents/extractor.py b/RAG/agents/extractor.py new file mode 100644 index 0000000..35c8ed5 --- /dev/null +++ b/RAG/agents/extractor.py @@ -0,0 +1,46 @@ +### Router + +from typing import Literal + +from langchain_core.prompts import ChatPromptTemplate +from langchain_core.pydantic_v1 import BaseModel, Field +from langchain_openai import ChatOpenAI + + +# Data model +class ExtractQuery(BaseModel): + """Route a user query to the relevant datasources with subquestions.""" + + vector_search_query: str = Field( + ..., + description="The query to search the vector store.", + ) + web_search_query: str = Field( + ..., + description="The query to search the web.", + ) + +llm = ChatOpenAI(model="gpt-4o-mini") +structured_llm_router = llm.with_structured_output(ExtractQuery) + +# Prompt +system = """You are an expert at routing a user question to a vectorstore or web search. +The vectorstore contains documents related to Manifests of political candidate Sajith Premadasa. +for an example, what this candidate do for education sector, health sector etc is on the vectorstore. +And also their plans for the future of the country is on the vectorstore. + +If the question involves something about sajith's policies in a past year, then you will have to search. +And also if you feel like a web search will be usefull. Do a web search. + +After deciding, +Output the 'vector_search_query': The query that needs to be searched from the vector store. +And the 'web_search_query': The query that needs to be searched from the web. +""" +route_prompt = ChatPromptTemplate.from_messages( + [ + ("system", system), + ("human", "{question}"), + ] +) + +question_extractor = route_prompt | structured_llm_router \ No newline at end of file diff --git a/RAG/agents/generate.py b/RAG/agents/generate.py new file mode 100644 index 0000000..a66ac1f --- /dev/null +++ b/RAG/agents/generate.py @@ -0,0 +1,28 @@ +from langchain_core.output_parsers import StrOutputParser +from langchain_core.prompts import PromptTemplate +from langchain_core.prompts import ChatPromptTemplate +from langchain_core.pydantic_v1 import BaseModel, Field +from langchain_openai import ChatOpenAI + +template = """Use the following pieces of context to answer the question at the end. +If you don't know the answer, just say that you don't know, don't try to make up an answer. +Use three sentences maximum and keep the answer as concise as possible. +Always say "thanks for asking!" at the end of the answer. + +{context} + +Question: {question} + +Helpful Answer:""" +custom_rag_prompt = PromptTemplate.from_template(template) + +# LLM +llm = ChatOpenAI(model="gpt-4o-mini") + + +# Post-processing +def format_docs(docs): + return "\n\n".join(doc.page_content for doc in docs) + + +rag_chain = custom_rag_prompt | llm | StrOutputParser() \ No newline at end of file diff --git a/RAG/agents/grader.py b/RAG/agents/grader.py new file mode 100644 index 0000000..d2c5bb8 --- /dev/null +++ b/RAG/agents/grader.py @@ -0,0 +1,29 @@ +from langchain_core.prompts import ChatPromptTemplate +from langchain_core.pydantic_v1 import BaseModel, Field +from langchain_openai import ChatOpenAI + + +class GradeDocuments(BaseModel): + """Binary score for relevance check on retrieved documents.""" + + binary_score: str = Field( + description="Documents are relevant to the question, 'yes' or 'no'" + ) + + +llm = ChatOpenAI(model="gpt-4o-mini") +structured_llm_grader = llm.with_structured_output(GradeDocuments) + +# Prompt +system = """You are a grader assessing relevance of a retrieved document to a user question. \n + If the document contains keyword(s) or semantic meaning related to the user question, grade it as relevant. \n + It does not need to be a stringent test. The goal is to filter out erroneous retrievals. \n + Give a binary score 'yes' or 'no' score to indicate whether the document is relevant to the question.""" +grade_prompt = ChatPromptTemplate.from_messages( + [ + ("system", system), + ("human", "Retrieved document: \n\n {document} \n\n User question: {question}"), + ] +) + +retrieval_grader = grade_prompt | structured_llm_grader \ No newline at end of file diff --git a/RAG/agents/hallucinate_checker.py b/RAG/agents/hallucinate_checker.py new file mode 100644 index 0000000..3ae53b0 --- /dev/null +++ b/RAG/agents/hallucinate_checker.py @@ -0,0 +1,29 @@ +from langchain_core.output_parsers import StrOutputParser +from langchain_core.prompts import PromptTemplate +from langchain_core.prompts import ChatPromptTemplate +from langchain_core.pydantic_v1 import BaseModel, Field +from langchain_openai import ChatOpenAI + +class GradeHallucinations(BaseModel): + """Binary score for hallucination present in generation answer.""" + + binary_score: str = Field( + description="Answer is grounded in the facts, 'yes' or 'no'" + ) + + +# LLM with function call +llm = ChatOpenAI(model="gpt-4o-mini") +structured_llm_grader = llm.with_structured_output(GradeHallucinations) + +# Prompt +system = """You are a grader assessing whether an LLM generation is grounded in / supported by a set of retrieved facts. \n + Give a binary score 'yes' or 'no'. 'Yes' means that the answer is grounded in / supported by the set of facts.""" +hallucination_prompt = ChatPromptTemplate.from_messages( + [ + ("system", system), + ("human", "Set of facts: \n\n {documents} \n\n LLM generation: {generation}"), + ] +) + +hallucination_grader = hallucination_prompt | structured_llm_grader \ No newline at end of file diff --git a/RAG/agents/question_rewriter.py b/RAG/agents/question_rewriter.py new file mode 100644 index 0000000..50fc988 --- /dev/null +++ b/RAG/agents/question_rewriter.py @@ -0,0 +1,23 @@ +from langchain_core.output_parsers import StrOutputParser +from langchain_core.prompts import PromptTemplate +from langchain_core.prompts import ChatPromptTemplate +from langchain_core.pydantic_v1 import BaseModel, Field +from langchain_openai import ChatOpenAI + +# LLM +llm = ChatOpenAI(model="gpt4-o-mini", temperature=0) + +# Prompt +system = """You a question re-writer that converts an input question to a better version that is optimized \n + for vectorstore retrieval. Look at the input and try to reason about the underlying semantic intent / meaning.""" +re_write_prompt = ChatPromptTemplate.from_messages( + [ + ("system", system), + ( + "human", + "Here is the initial question: \n\n {question} \n Formulate an improved question.", + ), + ] +) + +question_rewriter = re_write_prompt | llm | StrOutputParser() diff --git a/RAG/edges/decide_to_generate.py b/RAG/edges/decide_to_generate.py new file mode 100644 index 0000000..b322d1d --- /dev/null +++ b/RAG/edges/decide_to_generate.py @@ -0,0 +1,26 @@ +def decide_to_generate(state): + """ + Determines whether to generate an answer, or re-generate a question. + + Args: + state (dict): The current graph state + + Returns: + str: Binary decision for next node to call + """ + + print("---ASSESS GRADED DOCUMENTS---") + state["question"] + filtered_documents = state["documents"] + + if not filtered_documents: + # All documents have been filtered check_relevance + # We will re-generate a new query + print( + "---DECISION: ALL DOCUMENTS ARE NOT RELEVANT TO QUESTION, TRANSFORM QUERY---" + ) + return "transform_query" + else: + # We have relevant documents, so generate answer + print("---DECISION: GENERATE---") + return "generate" \ No newline at end of file diff --git a/RAG/edges/generation_grader.py b/RAG/edges/generation_grader.py new file mode 100644 index 0000000..639118d --- /dev/null +++ b/RAG/edges/generation_grader.py @@ -0,0 +1,44 @@ +from RAG.agents.answer_grader import answer_grader +from RAG.agents.hallucinate_checker import hallucination_grader + +def grade_generation_v_documents_and_question(state): + """ + Determines whether the generation is grounded in the document and answers question. + + Args: + state (dict): The current graph state + + Returns: + str: Decision for next node to call + """ + + print("---CHECK HALLUCINATIONS---") + question = state["question"] + documents = state["vector_search_documents"] + state["web_search_documents"] + generation = state["generation"] + + score = hallucination_grader.invoke( + {"documents": documents, "generation": generation} + ) + grade = score.binary_score + + if state.get("generated_count", 0) > 1: + print("---DECISION: AlREADY TRIED AND FAILED. CONTINUING ANYWAYS---") + return "useful" + + # Check hallucination + if grade == "yes": + print("---DECISION: GENERATION IS GROUNDED IN DOCUMENTS---") + # Check question-answering + print("---GRADE GENERATION vs QUESTION---") + score = answer_grader.invoke({"question": question, "generation": generation}) + grade = score.binary_score + if grade == "yes": + print("---DECISION: GENERATION ADDRESSES QUESTION---") + return "useful" + else: + print("---DECISION: GENERATION DOES NOT ADDRESS QUESTION---") + return "not useful" + else: + print("---DECISION: GENERATION IS NOT GROUNDED IN DOCUMENTS, RE-TRY---") + return "not supported" \ No newline at end of file diff --git a/RAG/graph.py b/RAG/graph.py new file mode 100644 index 0000000..4387039 --- /dev/null +++ b/RAG/graph.py @@ -0,0 +1,48 @@ +from langgraph.graph import END, StateGraph, START + +from RAG.graph_state import GraphState + +from RAG.nodes.extract_queries import extract_queries +from RAG.nodes.web_search import web_search +from RAG.nodes.retrieve import retrieve +from RAG.nodes.grade_documents import grade_documents +from RAG.nodes.generate import generate +from RAG.nodes.transform import transform_query + +from RAG.edges.generation_grader import grade_generation_v_documents_and_question + +workflow = StateGraph(GraphState) + +workflow.add_node("web_search", web_search) # web search +workflow.add_node("retrieve", retrieve) # retrieve +workflow.add_node("generate", generate) # generatae +workflow.add_node("transform_query", transform_query) # transform_query +workflow.add_node("extract queries", extract_queries) + +workflow.add_edge(START, "extract queries") +workflow.add_edge("extract queries", "web_search") +workflow.add_edge("extract queries", "retrieve") + +workflow.add_edge(["web_search", "retrieve"], "generate") + +workflow.add_conditional_edges( + "generate", + grade_generation_v_documents_and_question, + { + "not supported": "generate", + "useful": END, + "not useful": "transform_query", + }, +) + +workflow.add_edge("transform_query", "extract queries") + +app = workflow.compile() + +try: + graph_image = app.get_graph(xray=True).draw_mermaid_png() + with open("graph_image.png", "wb") as f: + f.write(graph_image) +except Exception: + # This requires some extra dependencies and is optional + pass diff --git a/RAG/graph_state.py b/RAG/graph_state.py new file mode 100644 index 0000000..c292e34 --- /dev/null +++ b/RAG/graph_state.py @@ -0,0 +1,24 @@ +from typing import List + +from typing_extensions import TypedDict + + +class GraphState(TypedDict): + """ + Represents the state of our graph. + + Attributes: + question: question + generation: LLM generation + documents: list of documents + """ + + question: str + vector_search_query: str + web_search_query: str + generation: str + + vector_search_documents: List[str] + web_search_documents: List[str] + + generated_count: int \ No newline at end of file diff --git a/RAG/nodes/extract_queries.py b/RAG/nodes/extract_queries.py new file mode 100644 index 0000000..221ceac --- /dev/null +++ b/RAG/nodes/extract_queries.py @@ -0,0 +1,22 @@ +from RAG.agents.extractor import question_extractor + +def extract_queries(state): + """ + Extract queries for vector search and web search. + + Args: + state (dict): The current graph state + + Returns: + str: Next node to call + """ + + print("---EXTRACT QUERIES---") + question = state["question"] + source = question_extractor.invoke({"question": question}) + + return { + "vector_search_query": source.vector_search_query, + "web_search_query": source.web_search_query, + "question": question + } diff --git a/RAG/nodes/generate.py b/RAG/nodes/generate.py new file mode 100644 index 0000000..103ed44 --- /dev/null +++ b/RAG/nodes/generate.py @@ -0,0 +1,30 @@ +from RAG.agents.generate import rag_chain + +def generate(state): + """ + Generate answer + + Args: + state (dict): The current graph state + + Returns: + state (dict): New key added to state, generation, that contains LLM generation + """ + print("---GENERATE---") + question = state["question"] + web_documents = state["web_search_documents"] + vector_documents = state["vector_search_documents"] + + documents = web_documents + vector_documents + + # RAG generation + generation = rag_chain.invoke({"context": documents, "question": question}) + + generated_count = state.get("generated_count", 0) + 1 + return { + "web_search_documents": web_documents, + "vector_search_documents": vector_documents, + "question": question, + "generation": generation, + "generated_count": generated_count + } \ No newline at end of file diff --git a/RAG/nodes/grade_documents.py b/RAG/nodes/grade_documents.py new file mode 100644 index 0000000..53f0a9e --- /dev/null +++ b/RAG/nodes/grade_documents.py @@ -0,0 +1,31 @@ +from RAG.agents.grader import retrieval_grader + +def grade_documents(state): + """ + Determines whether the retrieved documents are relevant to the question. + + Args: + state (dict): The current graph state + + Returns: + state (dict): Updates documents key with only filtered relevant documents + """ + + print("---CHECK DOCUMENT RELEVANCE TO QUESTION---") + question = state["question"] + documents = state["documents"] + + # Score each doc + filtered_docs = [] + for d in documents: + score = retrieval_grader.invoke( + {"question": question, "document": d.page_content} + ) + grade = score.binary_score + if grade == "yes": + print("---GRADE: DOCUMENT RELEVANT---") + filtered_docs.append(d) + else: + print("---GRADE: DOCUMENT NOT RELEVANT---") + continue + return {"documents": filtered_docs, "question": question} \ No newline at end of file diff --git a/RAG/nodes/retrieve.py b/RAG/nodes/retrieve.py new file mode 100644 index 0000000..e7707ca --- /dev/null +++ b/RAG/nodes/retrieve.py @@ -0,0 +1,21 @@ +from langchain.schema import Document +from RAG.tools.vectore_store_retriever import retriever + + +def retrieve(state): + """ + Retrieve documents + + Args: + state (dict): The current graph state + + Returns: + state (dict): New key added to state, documents, that contains retrieved documents + """ + print("---RETRIEVE---") + print(state) + search_query = state["vector_search_query"] + + # Retrieval + documents = retriever.invoke(search_query) + return {"vector_search_documents": documents} diff --git a/RAG/nodes/transform.py b/RAG/nodes/transform.py new file mode 100644 index 0000000..c401f21 --- /dev/null +++ b/RAG/nodes/transform.py @@ -0,0 +1,20 @@ +from RAG.agents.question_rewriter import question_rewriter + +def transform_query(state): + """ + Transform the query to produce a better question. + + Args: + state (dict): The current graph state + + Returns: + state (dict): Updates question key with a re-phrased question + """ + + print("---TRANSFORM QUERY---") + question = state["question"] + documents = state["documents"] + + # Re-write question + better_question = question_rewriter.invoke({"question": question}) + return {"documents": documents, "question": better_question} \ No newline at end of file diff --git a/RAG/nodes/web_search.py b/RAG/nodes/web_search.py new file mode 100644 index 0000000..3ae20ad --- /dev/null +++ b/RAG/nodes/web_search.py @@ -0,0 +1,23 @@ +from RAG.tools.web_search import web_search_tool +from langchain_core.documents import Document + +def web_search(state): + """ + Web search based on the re-phrased question. + + Args: + state (dict): The current graph state + + Returns: + state (dict): Updates documents key with appended web results + """ + + print("---WEB SEARCH---") + search_query = state["web_search_query"] + + # Web search + docs = web_search_tool.invoke({"query": search_query}) + web_results = [d["content"] for d in docs] + # web_results = Document(page_content=web_results) + + return {"web_search_documents": web_results} \ No newline at end of file diff --git a/RAG/tools/vectore_store_retriever.py b/RAG/tools/vectore_store_retriever.py new file mode 100644 index 0000000..8d95ec0 --- /dev/null +++ b/RAG/tools/vectore_store_retriever.py @@ -0,0 +1,34 @@ +from langchain_community.document_loaders import TextLoader +import os + +file_names = ["namal.txt", "ranil.txt", "sajith.txt"] +file_name_to_source = { + "namal.txt": "namal", + "ranil.txt": "ranil", + "sajith.txt": "sajith", +} + +docs = [] + +for file_name in file_names: + loader = TextLoader(f"documents/{file_name}") + doc = loader.load() + for d in doc: + d.metadata = {"file_name": file_name} + docs.append(d) + +from langchain_text_splitters import RecursiveCharacterTextSplitter + +text_splitter = RecursiveCharacterTextSplitter( + chunk_size=1000, chunk_overlap=200, add_start_index=True +) +all_splits = text_splitter.split_documents(docs) + +from langchain_chroma import Chroma +from langchain_openai import OpenAIEmbeddings + +vectorstore = Chroma.from_documents( + documents=all_splits, embedding=OpenAIEmbeddings(), persist_directory="./vectore_stores/manifesto_vectorstore", +) + +retriever = vectorstore.as_retriever(search_type="similarity", search_kwargs={"k": 6}) \ No newline at end of file diff --git a/RAG/tools/web_search.py b/RAG/tools/web_search.py new file mode 100644 index 0000000..cc8395e --- /dev/null +++ b/RAG/tools/web_search.py @@ -0,0 +1,3 @@ +from langchain_community.tools.tavily_search import TavilySearchResults + +web_search_tool = TavilySearchResults(k=3) \ No newline at end of file diff --git a/experiments/adaptive_rag.ipynb b/experiments/adaptive_rag.ipynb index 8aadd77..19aec48 100644 --- a/experiments/adaptive_rag.ipynb +++ b/experiments/adaptive_rag.ipynb @@ -686,7 +686,7 @@ }, { "cell_type": "code", - "execution_count": 29, + "execution_count": 33, "metadata": {}, "outputs": [ { @@ -696,20 +696,342 @@ "---ROUTE QUESTION---\n", "---ROUTE QUESTION TO WEB SEARCH---\n", "---WEB SEARCH---\n", - "Node 'web_search':\n", - "\n", - "---\n", - "\n", + "\"Node 'web_search':\"\n", + "{ 'documents': Document(metadata={}, page_content='To return the economy to 2019 levels would take approximately four to five years, he said, adding that his party had an economic plan to overcome the crisis. Inside the palace now full of the people\\n5 of 5\\xa0|\\xa0Sri Lankan opposition leader Sajith Premadasa arrives for an interview with The Associated Press at his office in Colombo, Sri Lanka, Friday, July 15, 2022. COLOMBO, Sri Lanka (AP) — Sri Lanka’s opposition leader, who is seeking the presidency next week, vowed Friday to “listen to the people” who are struggling through the island nation’s worst economic crisis and to hold accountable the president who fled under pressure from protesters. In an interview with The Associated Press from his office in the capital, Sajith Premadasa said that if he wins the election in Parliament, he would ensure that “an elective dictatorship never, ever occurs” in Sri Lanka.\\nNever think you are the freehold owners of the country: Sri Lanka’s opposition leader Premadasa Never think you are the freehold owners of the country: Sri Lanka’s opposition leader Sajith Premadasa Sri Lankan opposition leader Sajith Premadasa speaks during an interview with The Associated Press at his office in Colombo, Sri Lanka, July 15, 2022. COLOMBO: Sri Lanka’s opposition leader, who is seeking the presidency next week, vowed Friday to “listen to the people” who are struggling through the island nation’s worst economic crisis and to hold accountable the president who fled under pressure from protesters. In an interview with The Associated Press from his office in the capital, Sajith Premadasa said that if he wins the election in parliament, he would ensure that “an elective dictatorship never, ever occurs” in Sri Lanka.\\nThe Sunday Times sister paper Irida Lankadeepa sat down with Opposition Leader and Samagi Jana Balawegaya (SJB) presidential candidate Sajith Premadasa this week to talk about his vision for the country and future plans should he emerge victorious. Mr. Premadasa lost the 2019 presidential election to Gotabaya Rajapaksa. Much has happened since ...\\nSajith Premadasa is the presidential nominee for the United National Party (UNP), which is part of the National Democratic Front coalition. ... The UNP, under the Yahapalana government, has performed poorly in the last four-and-half years. The National Unity Government, formed by the UNP and sections of Sri Lanka Freedom Party after ousting ...'),\n", + " 'question': 'What did sajith planned to do for the economy in last election '\n", + " 'in 2019?'}\n", + "'\\n---\\n'\n", "---GENERATE---\n", "---CHECK HALLUCINATIONS---\n", "---DECISION: GENERATION IS GROUNDED IN DOCUMENTS---\n", "---GRADE GENERATION vs QUESTION---\n", - "---DECISION: GENERATION ADDRESSES QUESTION---\n", - "Node 'generate':\n", - "\n", - "---\n", + "---DECISION: GENERATION DOES NOT ADDRESS QUESTION---\n", + "\"Node 'generate':\"\n", + "{ 'documents': Document(metadata={}, page_content='To return the economy to 2019 levels would take approximately four to five years, he said, adding that his party had an economic plan to overcome the crisis. Inside the palace now full of the people\\n5 of 5\\xa0|\\xa0Sri Lankan opposition leader Sajith Premadasa arrives for an interview with The Associated Press at his office in Colombo, Sri Lanka, Friday, July 15, 2022. COLOMBO, Sri Lanka (AP) — Sri Lanka’s opposition leader, who is seeking the presidency next week, vowed Friday to “listen to the people” who are struggling through the island nation’s worst economic crisis and to hold accountable the president who fled under pressure from protesters. In an interview with The Associated Press from his office in the capital, Sajith Premadasa said that if he wins the election in Parliament, he would ensure that “an elective dictatorship never, ever occurs” in Sri Lanka.\\nNever think you are the freehold owners of the country: Sri Lanka’s opposition leader Premadasa Never think you are the freehold owners of the country: Sri Lanka’s opposition leader Sajith Premadasa Sri Lankan opposition leader Sajith Premadasa speaks during an interview with The Associated Press at his office in Colombo, Sri Lanka, July 15, 2022. COLOMBO: Sri Lanka’s opposition leader, who is seeking the presidency next week, vowed Friday to “listen to the people” who are struggling through the island nation’s worst economic crisis and to hold accountable the president who fled under pressure from protesters. In an interview with The Associated Press from his office in the capital, Sajith Premadasa said that if he wins the election in parliament, he would ensure that “an elective dictatorship never, ever occurs” in Sri Lanka.\\nThe Sunday Times sister paper Irida Lankadeepa sat down with Opposition Leader and Samagi Jana Balawegaya (SJB) presidential candidate Sajith Premadasa this week to talk about his vision for the country and future plans should he emerge victorious. Mr. Premadasa lost the 2019 presidential election to Gotabaya Rajapaksa. Much has happened since ...\\nSajith Premadasa is the presidential nominee for the United National Party (UNP), which is part of the National Democratic Front coalition. ... The UNP, under the Yahapalana government, has performed poorly in the last four-and-half years. The National Unity Government, formed by the UNP and sections of Sri Lanka Freedom Party after ousting ...'),\n", + " 'generation': \"The provided context does not specify Sajith Premadasa's \"\n", + " 'specific plans for the economy during the 2019 election. It '\n", + " 'only mentions that he has an economic plan to overcome the '\n", + " 'current crisis as of July 2022. Thanks for asking!',\n", + " 'question': 'What did sajith planned to do for the economy in last election '\n", + " 'in 2019?'}\n", + "'\\n---\\n'\n", + "---TRANSFORM QUERY---\n", + "\"Node 'transform_query':\"\n", + "{ 'documents': Document(metadata={}, page_content='To return the economy to 2019 levels would take approximately four to five years, he said, adding that his party had an economic plan to overcome the crisis. Inside the palace now full of the people\\n5 of 5\\xa0|\\xa0Sri Lankan opposition leader Sajith Premadasa arrives for an interview with The Associated Press at his office in Colombo, Sri Lanka, Friday, July 15, 2022. COLOMBO, Sri Lanka (AP) — Sri Lanka’s opposition leader, who is seeking the presidency next week, vowed Friday to “listen to the people” who are struggling through the island nation’s worst economic crisis and to hold accountable the president who fled under pressure from protesters. In an interview with The Associated Press from his office in the capital, Sajith Premadasa said that if he wins the election in Parliament, he would ensure that “an elective dictatorship never, ever occurs” in Sri Lanka.\\nNever think you are the freehold owners of the country: Sri Lanka’s opposition leader Premadasa Never think you are the freehold owners of the country: Sri Lanka’s opposition leader Sajith Premadasa Sri Lankan opposition leader Sajith Premadasa speaks during an interview with The Associated Press at his office in Colombo, Sri Lanka, July 15, 2022. COLOMBO: Sri Lanka’s opposition leader, who is seeking the presidency next week, vowed Friday to “listen to the people” who are struggling through the island nation’s worst economic crisis and to hold accountable the president who fled under pressure from protesters. In an interview with The Associated Press from his office in the capital, Sajith Premadasa said that if he wins the election in parliament, he would ensure that “an elective dictatorship never, ever occurs” in Sri Lanka.\\nThe Sunday Times sister paper Irida Lankadeepa sat down with Opposition Leader and Samagi Jana Balawegaya (SJB) presidential candidate Sajith Premadasa this week to talk about his vision for the country and future plans should he emerge victorious. Mr. Premadasa lost the 2019 presidential election to Gotabaya Rajapaksa. Much has happened since ...\\nSajith Premadasa is the presidential nominee for the United National Party (UNP), which is part of the National Democratic Front coalition. ... The UNP, under the Yahapalana government, has performed poorly in the last four-and-half years. The National Unity Government, formed by the UNP and sections of Sri Lanka Freedom Party after ousting ...'),\n", + " 'question': 'What economic plans did Sajith have for the 2019 election?'}\n", + "'\\n---\\n'\n", + "---RETRIEVE---\n", + "\"Node 'retrieve':\"\n", + "{ 'documents': [ Document(metadata={'source': '../documents/sajith.txt', 'start_index': 2253}, page_content='Let me end by stating that the SJS is more than just a new alliance; it is a movement for much-needed change, driven by the belief that Sri Lanka can and must finally realize its true potential. I seek your support in this election not just for myself as your candidate but for the vision we all share for a stronger, fairer, and more prosperous nation. Let us come together to, finally, create the Sri Lanka we all deserve.\\nSajith Premadasa\\nLeader\\nSamagi Jana Sandanya (SJS) 29th August 2024\\n \\nA WIN FOR ALL\\nCONTACT :\\nSamagi Jana Balawegaya\\n592, Kotte Road, Sri Jayawardenepura Kotte 10100 Phone: 011 287 0112\\ne-mail : info@sajith.lk\\nWeb : www.sajith.lk\\n \\nCONTENT\\nBUILD A RESILIENT ECONOMY 08\\ny TRANSPARENCY AND ACCOUNTABILITY\\ny MANAGING THE DEBT CRISIS AND THE IMF\\ny MONETARY AND EXCHANGE RATE POLICY\\ny ACHIEVING A REVENUE GROWTH\\ny EXPENDITURE CONTROL\\ny STIMULATING ECONOMIC GROWTH\\ny PUBLIC SECTOR MANAGEMENT AND DIGITALIZATION\\ny ENERGY AND UTILITY REFORMS'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 2253}, page_content='Let me end by stating that the SJS is more than just a new alliance; it is a movement for much-needed change, driven by the belief that Sri Lanka can and must finally realize its true potential. I seek your support in this election not just for myself as your candidate but for the vision we all share for a stronger, fairer, and more prosperous nation. Let us come together to, finally, create the Sri Lanka we all deserve.\\nSajith Premadasa\\nLeader\\nSamagi Jana Sandanya (SJS) 29th August 2024\\n \\nA WIN FOR ALL\\nCONTACT :\\nSamagi Jana Balawegaya\\n592, Kotte Road, Sri Jayawardenepura Kotte 10100 Phone: 011 287 0112\\ne-mail : info@sajith.lk\\nWeb : www.sajith.lk\\n \\nCONTENT\\nBUILD A RESILIENT ECONOMY 08\\ny TRANSPARENCY AND ACCOUNTABILITY\\ny MANAGING THE DEBT CRISIS AND THE IMF\\ny MONETARY AND EXCHANGE RATE POLICY\\ny ACHIEVING A REVENUE GROWTH\\ny EXPENDITURE CONTROL\\ny STIMULATING ECONOMIC GROWTH\\ny PUBLIC SECTOR MANAGEMENT AND DIGITALIZATION\\ny ENERGY AND UTILITY REFORMS'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 2253}, page_content='Let me end by stating that the SJS is more than just a new alliance; it is a movement for much-needed change, driven by the belief that Sri Lanka can and must finally realize its true potential. I seek your support in this election not just for myself as your candidate but for the vision we all share for a stronger, fairer, and more prosperous nation. Let us come together to, finally, create the Sri Lanka we all deserve.\\nSajith Premadasa\\nLeader\\nSamagi Jana Sandanya (SJS) 29th August 2024\\n \\nA WIN FOR ALL\\nCONTACT :\\nSamagi Jana Balawegaya\\n592, Kotte Road, Sri Jayawardenepura Kotte 10100 Phone: 011 287 0112\\ne-mail : info@sajith.lk\\nWeb : www.sajith.lk\\n \\nCONTENT\\nBUILD A RESILIENT ECONOMY 08\\ny TRANSPARENCY AND ACCOUNTABILITY\\ny MANAGING THE DEBT CRISIS AND THE IMF\\ny MONETARY AND EXCHANGE RATE POLICY\\ny ACHIEVING A REVENUE GROWTH\\ny EXPENDITURE CONTROL\\ny STIMULATING ECONOMIC GROWTH\\ny PUBLIC SECTOR MANAGEMENT AND DIGITALIZATION\\ny ENERGY AND UTILITY REFORMS'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 829}, page_content='Therefore, our manifesto & economic vision is not just about statistical growth but about tangible prosperity in every segment of society. We will create a resilient and inclusive economy, combining the strength of free markets with a deep commitment to equality, to ensure no Sri Lankan is left behind.\\nAnother crucial pillar of our vision is the fight against corruption. Corruption has long been a stain on Sri Lanka and has ultimately led us to bankruptcy, undermining trust in government and robbing our citizens. The future SJS government will root out corruption by embedding transparency and accountability in every aspect of governance with the necessary system reforms.'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 829}, page_content='Therefore, our manifesto & economic vision is not just about statistical growth but about tangible prosperity in every segment of society. We will create a resilient and inclusive economy, combining the strength of free markets with a deep commitment to equality, to ensure no Sri Lankan is left behind.\\nAnother crucial pillar of our vision is the fight against corruption. Corruption has long been a stain on Sri Lanka and has ultimately led us to bankruptcy, undermining trust in government and robbing our citizens. The future SJS government will root out corruption by embedding transparency and accountability in every aspect of governance with the necessary system reforms.'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 829}, page_content='Therefore, our manifesto & economic vision is not just about statistical growth but about tangible prosperity in every segment of society. We will create a resilient and inclusive economy, combining the strength of free markets with a deep commitment to equality, to ensure no Sri Lankan is left behind.\\nAnother crucial pillar of our vision is the fight against corruption. Corruption has long been a stain on Sri Lanka and has ultimately led us to bankruptcy, undermining trust in government and robbing our citizens. The future SJS government will root out corruption by embedding transparency and accountability in every aspect of governance with the necessary system reforms.')],\n", + " 'question': 'What economic plans did Sajith have for the 2019 election?'}\n", + "'\\n---\\n'\n", + "---CHECK DOCUMENT RELEVANCE TO QUESTION---\n", + "---GRADE: DOCUMENT RELEVANT---\n", + "---GRADE: DOCUMENT RELEVANT---\n", + "---GRADE: DOCUMENT RELEVANT---\n", + "---GRADE: DOCUMENT RELEVANT---\n", + "---GRADE: DOCUMENT RELEVANT---\n", + "---GRADE: DOCUMENT RELEVANT---\n", + "---ASSESS GRADED DOCUMENTS---\n", + "---DECISION: GENERATE---\n", + "\"Node 'grade_documents':\"\n", + "{ 'documents': [ Document(metadata={'source': '../documents/sajith.txt', 'start_index': 2253}, page_content='Let me end by stating that the SJS is more than just a new alliance; it is a movement for much-needed change, driven by the belief that Sri Lanka can and must finally realize its true potential. I seek your support in this election not just for myself as your candidate but for the vision we all share for a stronger, fairer, and more prosperous nation. Let us come together to, finally, create the Sri Lanka we all deserve.\\nSajith Premadasa\\nLeader\\nSamagi Jana Sandanya (SJS) 29th August 2024\\n \\nA WIN FOR ALL\\nCONTACT :\\nSamagi Jana Balawegaya\\n592, Kotte Road, Sri Jayawardenepura Kotte 10100 Phone: 011 287 0112\\ne-mail : info@sajith.lk\\nWeb : www.sajith.lk\\n \\nCONTENT\\nBUILD A RESILIENT ECONOMY 08\\ny TRANSPARENCY AND ACCOUNTABILITY\\ny MANAGING THE DEBT CRISIS AND THE IMF\\ny MONETARY AND EXCHANGE RATE POLICY\\ny ACHIEVING A REVENUE GROWTH\\ny EXPENDITURE CONTROL\\ny STIMULATING ECONOMIC GROWTH\\ny PUBLIC SECTOR MANAGEMENT AND DIGITALIZATION\\ny ENERGY AND UTILITY REFORMS'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 2253}, page_content='Let me end by stating that the SJS is more than just a new alliance; it is a movement for much-needed change, driven by the belief that Sri Lanka can and must finally realize its true potential. I seek your support in this election not just for myself as your candidate but for the vision we all share for a stronger, fairer, and more prosperous nation. Let us come together to, finally, create the Sri Lanka we all deserve.\\nSajith Premadasa\\nLeader\\nSamagi Jana Sandanya (SJS) 29th August 2024\\n \\nA WIN FOR ALL\\nCONTACT :\\nSamagi Jana Balawegaya\\n592, Kotte Road, Sri Jayawardenepura Kotte 10100 Phone: 011 287 0112\\ne-mail : info@sajith.lk\\nWeb : www.sajith.lk\\n \\nCONTENT\\nBUILD A RESILIENT ECONOMY 08\\ny TRANSPARENCY AND ACCOUNTABILITY\\ny MANAGING THE DEBT CRISIS AND THE IMF\\ny MONETARY AND EXCHANGE RATE POLICY\\ny ACHIEVING A REVENUE GROWTH\\ny EXPENDITURE CONTROL\\ny STIMULATING ECONOMIC GROWTH\\ny PUBLIC SECTOR MANAGEMENT AND DIGITALIZATION\\ny ENERGY AND UTILITY REFORMS'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 2253}, page_content='Let me end by stating that the SJS is more than just a new alliance; it is a movement for much-needed change, driven by the belief that Sri Lanka can and must finally realize its true potential. I seek your support in this election not just for myself as your candidate but for the vision we all share for a stronger, fairer, and more prosperous nation. Let us come together to, finally, create the Sri Lanka we all deserve.\\nSajith Premadasa\\nLeader\\nSamagi Jana Sandanya (SJS) 29th August 2024\\n \\nA WIN FOR ALL\\nCONTACT :\\nSamagi Jana Balawegaya\\n592, Kotte Road, Sri Jayawardenepura Kotte 10100 Phone: 011 287 0112\\ne-mail : info@sajith.lk\\nWeb : www.sajith.lk\\n \\nCONTENT\\nBUILD A RESILIENT ECONOMY 08\\ny TRANSPARENCY AND ACCOUNTABILITY\\ny MANAGING THE DEBT CRISIS AND THE IMF\\ny MONETARY AND EXCHANGE RATE POLICY\\ny ACHIEVING A REVENUE GROWTH\\ny EXPENDITURE CONTROL\\ny STIMULATING ECONOMIC GROWTH\\ny PUBLIC SECTOR MANAGEMENT AND DIGITALIZATION\\ny ENERGY AND UTILITY REFORMS'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 829}, page_content='Therefore, our manifesto & economic vision is not just about statistical growth but about tangible prosperity in every segment of society. We will create a resilient and inclusive economy, combining the strength of free markets with a deep commitment to equality, to ensure no Sri Lankan is left behind.\\nAnother crucial pillar of our vision is the fight against corruption. Corruption has long been a stain on Sri Lanka and has ultimately led us to bankruptcy, undermining trust in government and robbing our citizens. The future SJS government will root out corruption by embedding transparency and accountability in every aspect of governance with the necessary system reforms.'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 829}, page_content='Therefore, our manifesto & economic vision is not just about statistical growth but about tangible prosperity in every segment of society. We will create a resilient and inclusive economy, combining the strength of free markets with a deep commitment to equality, to ensure no Sri Lankan is left behind.\\nAnother crucial pillar of our vision is the fight against corruption. Corruption has long been a stain on Sri Lanka and has ultimately led us to bankruptcy, undermining trust in government and robbing our citizens. The future SJS government will root out corruption by embedding transparency and accountability in every aspect of governance with the necessary system reforms.'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 829}, page_content='Therefore, our manifesto & economic vision is not just about statistical growth but about tangible prosperity in every segment of society. We will create a resilient and inclusive economy, combining the strength of free markets with a deep commitment to equality, to ensure no Sri Lankan is left behind.\\nAnother crucial pillar of our vision is the fight against corruption. Corruption has long been a stain on Sri Lanka and has ultimately led us to bankruptcy, undermining trust in government and robbing our citizens. The future SJS government will root out corruption by embedding transparency and accountability in every aspect of governance with the necessary system reforms.')],\n", + " 'question': 'What economic plans did Sajith have for the 2019 election?'}\n", + "'\\n---\\n'\n", + "---GENERATE---\n", + "---CHECK HALLUCINATIONS---\n", + "---DECISION: GENERATION IS NOT GROUNDED IN DOCUMENTS, RE-TRY---\n", + "\"Node 'generate':\"\n", + "{ 'documents': [ Document(metadata={'source': '../documents/sajith.txt', 'start_index': 2253}, page_content='Let me end by stating that the SJS is more than just a new alliance; it is a movement for much-needed change, driven by the belief that Sri Lanka can and must finally realize its true potential. I seek your support in this election not just for myself as your candidate but for the vision we all share for a stronger, fairer, and more prosperous nation. Let us come together to, finally, create the Sri Lanka we all deserve.\\nSajith Premadasa\\nLeader\\nSamagi Jana Sandanya (SJS) 29th August 2024\\n \\nA WIN FOR ALL\\nCONTACT :\\nSamagi Jana Balawegaya\\n592, Kotte Road, Sri Jayawardenepura Kotte 10100 Phone: 011 287 0112\\ne-mail : info@sajith.lk\\nWeb : www.sajith.lk\\n \\nCONTENT\\nBUILD A RESILIENT ECONOMY 08\\ny TRANSPARENCY AND ACCOUNTABILITY\\ny MANAGING THE DEBT CRISIS AND THE IMF\\ny MONETARY AND EXCHANGE RATE POLICY\\ny ACHIEVING A REVENUE GROWTH\\ny EXPENDITURE CONTROL\\ny STIMULATING ECONOMIC GROWTH\\ny PUBLIC SECTOR MANAGEMENT AND DIGITALIZATION\\ny ENERGY AND UTILITY REFORMS'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 2253}, page_content='Let me end by stating that the SJS is more than just a new alliance; it is a movement for much-needed change, driven by the belief that Sri Lanka can and must finally realize its true potential. I seek your support in this election not just for myself as your candidate but for the vision we all share for a stronger, fairer, and more prosperous nation. Let us come together to, finally, create the Sri Lanka we all deserve.\\nSajith Premadasa\\nLeader\\nSamagi Jana Sandanya (SJS) 29th August 2024\\n \\nA WIN FOR ALL\\nCONTACT :\\nSamagi Jana Balawegaya\\n592, Kotte Road, Sri Jayawardenepura Kotte 10100 Phone: 011 287 0112\\ne-mail : info@sajith.lk\\nWeb : www.sajith.lk\\n \\nCONTENT\\nBUILD A RESILIENT ECONOMY 08\\ny TRANSPARENCY AND ACCOUNTABILITY\\ny MANAGING THE DEBT CRISIS AND THE IMF\\ny MONETARY AND EXCHANGE RATE POLICY\\ny ACHIEVING A REVENUE GROWTH\\ny EXPENDITURE CONTROL\\ny STIMULATING ECONOMIC GROWTH\\ny PUBLIC SECTOR MANAGEMENT AND DIGITALIZATION\\ny ENERGY AND UTILITY REFORMS'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 2253}, page_content='Let me end by stating that the SJS is more than just a new alliance; it is a movement for much-needed change, driven by the belief that Sri Lanka can and must finally realize its true potential. I seek your support in this election not just for myself as your candidate but for the vision we all share for a stronger, fairer, and more prosperous nation. Let us come together to, finally, create the Sri Lanka we all deserve.\\nSajith Premadasa\\nLeader\\nSamagi Jana Sandanya (SJS) 29th August 2024\\n \\nA WIN FOR ALL\\nCONTACT :\\nSamagi Jana Balawegaya\\n592, Kotte Road, Sri Jayawardenepura Kotte 10100 Phone: 011 287 0112\\ne-mail : info@sajith.lk\\nWeb : www.sajith.lk\\n \\nCONTENT\\nBUILD A RESILIENT ECONOMY 08\\ny TRANSPARENCY AND ACCOUNTABILITY\\ny MANAGING THE DEBT CRISIS AND THE IMF\\ny MONETARY AND EXCHANGE RATE POLICY\\ny ACHIEVING A REVENUE GROWTH\\ny EXPENDITURE CONTROL\\ny STIMULATING ECONOMIC GROWTH\\ny PUBLIC SECTOR MANAGEMENT AND DIGITALIZATION\\ny ENERGY AND UTILITY REFORMS'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 829}, page_content='Therefore, our manifesto & economic vision is not just about statistical growth but about tangible prosperity in every segment of society. We will create a resilient and inclusive economy, combining the strength of free markets with a deep commitment to equality, to ensure no Sri Lankan is left behind.\\nAnother crucial pillar of our vision is the fight against corruption. Corruption has long been a stain on Sri Lanka and has ultimately led us to bankruptcy, undermining trust in government and robbing our citizens. The future SJS government will root out corruption by embedding transparency and accountability in every aspect of governance with the necessary system reforms.'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 829}, page_content='Therefore, our manifesto & economic vision is not just about statistical growth but about tangible prosperity in every segment of society. We will create a resilient and inclusive economy, combining the strength of free markets with a deep commitment to equality, to ensure no Sri Lankan is left behind.\\nAnother crucial pillar of our vision is the fight against corruption. Corruption has long been a stain on Sri Lanka and has ultimately led us to bankruptcy, undermining trust in government and robbing our citizens. The future SJS government will root out corruption by embedding transparency and accountability in every aspect of governance with the necessary system reforms.'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 829}, page_content='Therefore, our manifesto & economic vision is not just about statistical growth but about tangible prosperity in every segment of society. We will create a resilient and inclusive economy, combining the strength of free markets with a deep commitment to equality, to ensure no Sri Lankan is left behind.\\nAnother crucial pillar of our vision is the fight against corruption. Corruption has long been a stain on Sri Lanka and has ultimately led us to bankruptcy, undermining trust in government and robbing our citizens. The future SJS government will root out corruption by embedding transparency and accountability in every aspect of governance with the necessary system reforms.')],\n", + " 'generation': \"I don't know. Thanks for asking!\",\n", + " 'question': 'What economic plans did Sajith have for the 2019 election?'}\n", + "'\\n---\\n'\n", + "---GENERATE---\n", + "---CHECK HALLUCINATIONS---\n", + "---DECISION: GENERATION IS NOT GROUNDED IN DOCUMENTS, RE-TRY---\n", + "\"Node 'generate':\"\n", + "{ 'documents': [ Document(metadata={'source': '../documents/sajith.txt', 'start_index': 2253}, page_content='Let me end by stating that the SJS is more than just a new alliance; it is a movement for much-needed change, driven by the belief that Sri Lanka can and must finally realize its true potential. I seek your support in this election not just for myself as your candidate but for the vision we all share for a stronger, fairer, and more prosperous nation. Let us come together to, finally, create the Sri Lanka we all deserve.\\nSajith Premadasa\\nLeader\\nSamagi Jana Sandanya (SJS) 29th August 2024\\n \\nA WIN FOR ALL\\nCONTACT :\\nSamagi Jana Balawegaya\\n592, Kotte Road, Sri Jayawardenepura Kotte 10100 Phone: 011 287 0112\\ne-mail : info@sajith.lk\\nWeb : www.sajith.lk\\n \\nCONTENT\\nBUILD A RESILIENT ECONOMY 08\\ny TRANSPARENCY AND ACCOUNTABILITY\\ny MANAGING THE DEBT CRISIS AND THE IMF\\ny MONETARY AND EXCHANGE RATE POLICY\\ny ACHIEVING A REVENUE GROWTH\\ny EXPENDITURE CONTROL\\ny STIMULATING ECONOMIC GROWTH\\ny PUBLIC SECTOR MANAGEMENT AND DIGITALIZATION\\ny ENERGY AND UTILITY REFORMS'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 2253}, page_content='Let me end by stating that the SJS is more than just a new alliance; it is a movement for much-needed change, driven by the belief that Sri Lanka can and must finally realize its true potential. I seek your support in this election not just for myself as your candidate but for the vision we all share for a stronger, fairer, and more prosperous nation. Let us come together to, finally, create the Sri Lanka we all deserve.\\nSajith Premadasa\\nLeader\\nSamagi Jana Sandanya (SJS) 29th August 2024\\n \\nA WIN FOR ALL\\nCONTACT :\\nSamagi Jana Balawegaya\\n592, Kotte Road, Sri Jayawardenepura Kotte 10100 Phone: 011 287 0112\\ne-mail : info@sajith.lk\\nWeb : www.sajith.lk\\n \\nCONTENT\\nBUILD A RESILIENT ECONOMY 08\\ny TRANSPARENCY AND ACCOUNTABILITY\\ny MANAGING THE DEBT CRISIS AND THE IMF\\ny MONETARY AND EXCHANGE RATE POLICY\\ny ACHIEVING A REVENUE GROWTH\\ny EXPENDITURE CONTROL\\ny STIMULATING ECONOMIC GROWTH\\ny PUBLIC SECTOR MANAGEMENT AND DIGITALIZATION\\ny ENERGY AND UTILITY REFORMS'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 2253}, page_content='Let me end by stating that the SJS is more than just a new alliance; it is a movement for much-needed change, driven by the belief that Sri Lanka can and must finally realize its true potential. I seek your support in this election not just for myself as your candidate but for the vision we all share for a stronger, fairer, and more prosperous nation. Let us come together to, finally, create the Sri Lanka we all deserve.\\nSajith Premadasa\\nLeader\\nSamagi Jana Sandanya (SJS) 29th August 2024\\n \\nA WIN FOR ALL\\nCONTACT :\\nSamagi Jana Balawegaya\\n592, Kotte Road, Sri Jayawardenepura Kotte 10100 Phone: 011 287 0112\\ne-mail : info@sajith.lk\\nWeb : www.sajith.lk\\n \\nCONTENT\\nBUILD A RESILIENT ECONOMY 08\\ny TRANSPARENCY AND ACCOUNTABILITY\\ny MANAGING THE DEBT CRISIS AND THE IMF\\ny MONETARY AND EXCHANGE RATE POLICY\\ny ACHIEVING A REVENUE GROWTH\\ny EXPENDITURE CONTROL\\ny STIMULATING ECONOMIC GROWTH\\ny PUBLIC SECTOR MANAGEMENT AND DIGITALIZATION\\ny ENERGY AND UTILITY REFORMS'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 829}, page_content='Therefore, our manifesto & economic vision is not just about statistical growth but about tangible prosperity in every segment of society. We will create a resilient and inclusive economy, combining the strength of free markets with a deep commitment to equality, to ensure no Sri Lankan is left behind.\\nAnother crucial pillar of our vision is the fight against corruption. Corruption has long been a stain on Sri Lanka and has ultimately led us to bankruptcy, undermining trust in government and robbing our citizens. The future SJS government will root out corruption by embedding transparency and accountability in every aspect of governance with the necessary system reforms.'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 829}, page_content='Therefore, our manifesto & economic vision is not just about statistical growth but about tangible prosperity in every segment of society. We will create a resilient and inclusive economy, combining the strength of free markets with a deep commitment to equality, to ensure no Sri Lankan is left behind.\\nAnother crucial pillar of our vision is the fight against corruption. Corruption has long been a stain on Sri Lanka and has ultimately led us to bankruptcy, undermining trust in government and robbing our citizens. The future SJS government will root out corruption by embedding transparency and accountability in every aspect of governance with the necessary system reforms.'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 829}, page_content='Therefore, our manifesto & economic vision is not just about statistical growth but about tangible prosperity in every segment of society. We will create a resilient and inclusive economy, combining the strength of free markets with a deep commitment to equality, to ensure no Sri Lankan is left behind.\\nAnother crucial pillar of our vision is the fight against corruption. Corruption has long been a stain on Sri Lanka and has ultimately led us to bankruptcy, undermining trust in government and robbing our citizens. The future SJS government will root out corruption by embedding transparency and accountability in every aspect of governance with the necessary system reforms.')],\n", + " 'generation': 'The provided context does not contain specific details about '\n", + " \"Sajith Premadasa's economic plans for the 2019 election. It \"\n", + " 'focuses more on his vision for a resilient economy and '\n", + " 'tackling corruption in a future context. Thanks for asking!',\n", + " 'question': 'What economic plans did Sajith have for the 2019 election?'}\n", + "'\\n---\\n'\n", + "---GENERATE---\n", + "---CHECK HALLUCINATIONS---\n", + "---DECISION: GENERATION IS NOT GROUNDED IN DOCUMENTS, RE-TRY---\n", + "\"Node 'generate':\"\n", + "{ 'documents': [ Document(metadata={'source': '../documents/sajith.txt', 'start_index': 2253}, page_content='Let me end by stating that the SJS is more than just a new alliance; it is a movement for much-needed change, driven by the belief that Sri Lanka can and must finally realize its true potential. I seek your support in this election not just for myself as your candidate but for the vision we all share for a stronger, fairer, and more prosperous nation. Let us come together to, finally, create the Sri Lanka we all deserve.\\nSajith Premadasa\\nLeader\\nSamagi Jana Sandanya (SJS) 29th August 2024\\n \\nA WIN FOR ALL\\nCONTACT :\\nSamagi Jana Balawegaya\\n592, Kotte Road, Sri Jayawardenepura Kotte 10100 Phone: 011 287 0112\\ne-mail : info@sajith.lk\\nWeb : www.sajith.lk\\n \\nCONTENT\\nBUILD A RESILIENT ECONOMY 08\\ny TRANSPARENCY AND ACCOUNTABILITY\\ny MANAGING THE DEBT CRISIS AND THE IMF\\ny MONETARY AND EXCHANGE RATE POLICY\\ny ACHIEVING A REVENUE GROWTH\\ny EXPENDITURE CONTROL\\ny STIMULATING ECONOMIC GROWTH\\ny PUBLIC SECTOR MANAGEMENT AND DIGITALIZATION\\ny ENERGY AND UTILITY REFORMS'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 2253}, page_content='Let me end by stating that the SJS is more than just a new alliance; it is a movement for much-needed change, driven by the belief that Sri Lanka can and must finally realize its true potential. I seek your support in this election not just for myself as your candidate but for the vision we all share for a stronger, fairer, and more prosperous nation. Let us come together to, finally, create the Sri Lanka we all deserve.\\nSajith Premadasa\\nLeader\\nSamagi Jana Sandanya (SJS) 29th August 2024\\n \\nA WIN FOR ALL\\nCONTACT :\\nSamagi Jana Balawegaya\\n592, Kotte Road, Sri Jayawardenepura Kotte 10100 Phone: 011 287 0112\\ne-mail : info@sajith.lk\\nWeb : www.sajith.lk\\n \\nCONTENT\\nBUILD A RESILIENT ECONOMY 08\\ny TRANSPARENCY AND ACCOUNTABILITY\\ny MANAGING THE DEBT CRISIS AND THE IMF\\ny MONETARY AND EXCHANGE RATE POLICY\\ny ACHIEVING A REVENUE GROWTH\\ny EXPENDITURE CONTROL\\ny STIMULATING ECONOMIC GROWTH\\ny PUBLIC SECTOR MANAGEMENT AND DIGITALIZATION\\ny ENERGY AND UTILITY REFORMS'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 2253}, page_content='Let me end by stating that the SJS is more than just a new alliance; it is a movement for much-needed change, driven by the belief that Sri Lanka can and must finally realize its true potential. I seek your support in this election not just for myself as your candidate but for the vision we all share for a stronger, fairer, and more prosperous nation. Let us come together to, finally, create the Sri Lanka we all deserve.\\nSajith Premadasa\\nLeader\\nSamagi Jana Sandanya (SJS) 29th August 2024\\n \\nA WIN FOR ALL\\nCONTACT :\\nSamagi Jana Balawegaya\\n592, Kotte Road, Sri Jayawardenepura Kotte 10100 Phone: 011 287 0112\\ne-mail : info@sajith.lk\\nWeb : www.sajith.lk\\n \\nCONTENT\\nBUILD A RESILIENT ECONOMY 08\\ny TRANSPARENCY AND ACCOUNTABILITY\\ny MANAGING THE DEBT CRISIS AND THE IMF\\ny MONETARY AND EXCHANGE RATE POLICY\\ny ACHIEVING A REVENUE GROWTH\\ny EXPENDITURE CONTROL\\ny STIMULATING ECONOMIC GROWTH\\ny PUBLIC SECTOR MANAGEMENT AND DIGITALIZATION\\ny ENERGY AND UTILITY REFORMS'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 829}, page_content='Therefore, our manifesto & economic vision is not just about statistical growth but about tangible prosperity in every segment of society. We will create a resilient and inclusive economy, combining the strength of free markets with a deep commitment to equality, to ensure no Sri Lankan is left behind.\\nAnother crucial pillar of our vision is the fight against corruption. Corruption has long been a stain on Sri Lanka and has ultimately led us to bankruptcy, undermining trust in government and robbing our citizens. The future SJS government will root out corruption by embedding transparency and accountability in every aspect of governance with the necessary system reforms.'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 829}, page_content='Therefore, our manifesto & economic vision is not just about statistical growth but about tangible prosperity in every segment of society. We will create a resilient and inclusive economy, combining the strength of free markets with a deep commitment to equality, to ensure no Sri Lankan is left behind.\\nAnother crucial pillar of our vision is the fight against corruption. Corruption has long been a stain on Sri Lanka and has ultimately led us to bankruptcy, undermining trust in government and robbing our citizens. The future SJS government will root out corruption by embedding transparency and accountability in every aspect of governance with the necessary system reforms.'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 829}, page_content='Therefore, our manifesto & economic vision is not just about statistical growth but about tangible prosperity in every segment of society. We will create a resilient and inclusive economy, combining the strength of free markets with a deep commitment to equality, to ensure no Sri Lankan is left behind.\\nAnother crucial pillar of our vision is the fight against corruption. Corruption has long been a stain on Sri Lanka and has ultimately led us to bankruptcy, undermining trust in government and robbing our citizens. The future SJS government will root out corruption by embedding transparency and accountability in every aspect of governance with the necessary system reforms.')],\n", + " 'generation': \"I don't know. Thanks for asking!\",\n", + " 'question': 'What economic plans did Sajith have for the 2019 election?'}\n", + "'\\n---\\n'\n", + "---GENERATE---\n", + "---CHECK HALLUCINATIONS---\n", + "---DECISION: GENERATION IS NOT GROUNDED IN DOCUMENTS, RE-TRY---\n", + "\"Node 'generate':\"\n", + "{ 'documents': [ Document(metadata={'source': '../documents/sajith.txt', 'start_index': 2253}, page_content='Let me end by stating that the SJS is more than just a new alliance; it is a movement for much-needed change, driven by the belief that Sri Lanka can and must finally realize its true potential. I seek your support in this election not just for myself as your candidate but for the vision we all share for a stronger, fairer, and more prosperous nation. Let us come together to, finally, create the Sri Lanka we all deserve.\\nSajith Premadasa\\nLeader\\nSamagi Jana Sandanya (SJS) 29th August 2024\\n \\nA WIN FOR ALL\\nCONTACT :\\nSamagi Jana Balawegaya\\n592, Kotte Road, Sri Jayawardenepura Kotte 10100 Phone: 011 287 0112\\ne-mail : info@sajith.lk\\nWeb : www.sajith.lk\\n \\nCONTENT\\nBUILD A RESILIENT ECONOMY 08\\ny TRANSPARENCY AND ACCOUNTABILITY\\ny MANAGING THE DEBT CRISIS AND THE IMF\\ny MONETARY AND EXCHANGE RATE POLICY\\ny ACHIEVING A REVENUE GROWTH\\ny EXPENDITURE CONTROL\\ny STIMULATING ECONOMIC GROWTH\\ny PUBLIC SECTOR MANAGEMENT AND DIGITALIZATION\\ny ENERGY AND UTILITY REFORMS'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 2253}, page_content='Let me end by stating that the SJS is more than just a new alliance; it is a movement for much-needed change, driven by the belief that Sri Lanka can and must finally realize its true potential. I seek your support in this election not just for myself as your candidate but for the vision we all share for a stronger, fairer, and more prosperous nation. Let us come together to, finally, create the Sri Lanka we all deserve.\\nSajith Premadasa\\nLeader\\nSamagi Jana Sandanya (SJS) 29th August 2024\\n \\nA WIN FOR ALL\\nCONTACT :\\nSamagi Jana Balawegaya\\n592, Kotte Road, Sri Jayawardenepura Kotte 10100 Phone: 011 287 0112\\ne-mail : info@sajith.lk\\nWeb : www.sajith.lk\\n \\nCONTENT\\nBUILD A RESILIENT ECONOMY 08\\ny TRANSPARENCY AND ACCOUNTABILITY\\ny MANAGING THE DEBT CRISIS AND THE IMF\\ny MONETARY AND EXCHANGE RATE POLICY\\ny ACHIEVING A REVENUE GROWTH\\ny EXPENDITURE CONTROL\\ny STIMULATING ECONOMIC GROWTH\\ny PUBLIC SECTOR MANAGEMENT AND DIGITALIZATION\\ny ENERGY AND UTILITY REFORMS'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 2253}, page_content='Let me end by stating that the SJS is more than just a new alliance; it is a movement for much-needed change, driven by the belief that Sri Lanka can and must finally realize its true potential. I seek your support in this election not just for myself as your candidate but for the vision we all share for a stronger, fairer, and more prosperous nation. Let us come together to, finally, create the Sri Lanka we all deserve.\\nSajith Premadasa\\nLeader\\nSamagi Jana Sandanya (SJS) 29th August 2024\\n \\nA WIN FOR ALL\\nCONTACT :\\nSamagi Jana Balawegaya\\n592, Kotte Road, Sri Jayawardenepura Kotte 10100 Phone: 011 287 0112\\ne-mail : info@sajith.lk\\nWeb : www.sajith.lk\\n \\nCONTENT\\nBUILD A RESILIENT ECONOMY 08\\ny TRANSPARENCY AND ACCOUNTABILITY\\ny MANAGING THE DEBT CRISIS AND THE IMF\\ny MONETARY AND EXCHANGE RATE POLICY\\ny ACHIEVING A REVENUE GROWTH\\ny EXPENDITURE CONTROL\\ny STIMULATING ECONOMIC GROWTH\\ny PUBLIC SECTOR MANAGEMENT AND DIGITALIZATION\\ny ENERGY AND UTILITY REFORMS'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 829}, page_content='Therefore, our manifesto & economic vision is not just about statistical growth but about tangible prosperity in every segment of society. We will create a resilient and inclusive economy, combining the strength of free markets with a deep commitment to equality, to ensure no Sri Lankan is left behind.\\nAnother crucial pillar of our vision is the fight against corruption. Corruption has long been a stain on Sri Lanka and has ultimately led us to bankruptcy, undermining trust in government and robbing our citizens. The future SJS government will root out corruption by embedding transparency and accountability in every aspect of governance with the necessary system reforms.'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 829}, page_content='Therefore, our manifesto & economic vision is not just about statistical growth but about tangible prosperity in every segment of society. We will create a resilient and inclusive economy, combining the strength of free markets with a deep commitment to equality, to ensure no Sri Lankan is left behind.\\nAnother crucial pillar of our vision is the fight against corruption. Corruption has long been a stain on Sri Lanka and has ultimately led us to bankruptcy, undermining trust in government and robbing our citizens. The future SJS government will root out corruption by embedding transparency and accountability in every aspect of governance with the necessary system reforms.'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 829}, page_content='Therefore, our manifesto & economic vision is not just about statistical growth but about tangible prosperity in every segment of society. We will create a resilient and inclusive economy, combining the strength of free markets with a deep commitment to equality, to ensure no Sri Lankan is left behind.\\nAnother crucial pillar of our vision is the fight against corruption. Corruption has long been a stain on Sri Lanka and has ultimately led us to bankruptcy, undermining trust in government and robbing our citizens. The future SJS government will root out corruption by embedding transparency and accountability in every aspect of governance with the necessary system reforms.')],\n", + " 'generation': \"I don't know. Thanks for asking!\",\n", + " 'question': 'What economic plans did Sajith have for the 2019 election?'}\n", + "'\\n---\\n'\n", + "---GENERATE---\n", + "---CHECK HALLUCINATIONS---\n", + "---DECISION: GENERATION IS NOT GROUNDED IN DOCUMENTS, RE-TRY---\n", + "\"Node 'generate':\"\n", + "{ 'documents': [ Document(metadata={'source': '../documents/sajith.txt', 'start_index': 2253}, page_content='Let me end by stating that the SJS is more than just a new alliance; it is a movement for much-needed change, driven by the belief that Sri Lanka can and must finally realize its true potential. I seek your support in this election not just for myself as your candidate but for the vision we all share for a stronger, fairer, and more prosperous nation. Let us come together to, finally, create the Sri Lanka we all deserve.\\nSajith Premadasa\\nLeader\\nSamagi Jana Sandanya (SJS) 29th August 2024\\n \\nA WIN FOR ALL\\nCONTACT :\\nSamagi Jana Balawegaya\\n592, Kotte Road, Sri Jayawardenepura Kotte 10100 Phone: 011 287 0112\\ne-mail : info@sajith.lk\\nWeb : www.sajith.lk\\n \\nCONTENT\\nBUILD A RESILIENT ECONOMY 08\\ny TRANSPARENCY AND ACCOUNTABILITY\\ny MANAGING THE DEBT CRISIS AND THE IMF\\ny MONETARY AND EXCHANGE RATE POLICY\\ny ACHIEVING A REVENUE GROWTH\\ny EXPENDITURE CONTROL\\ny STIMULATING ECONOMIC GROWTH\\ny PUBLIC SECTOR MANAGEMENT AND DIGITALIZATION\\ny ENERGY AND UTILITY REFORMS'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 2253}, page_content='Let me end by stating that the SJS is more than just a new alliance; it is a movement for much-needed change, driven by the belief that Sri Lanka can and must finally realize its true potential. I seek your support in this election not just for myself as your candidate but for the vision we all share for a stronger, fairer, and more prosperous nation. Let us come together to, finally, create the Sri Lanka we all deserve.\\nSajith Premadasa\\nLeader\\nSamagi Jana Sandanya (SJS) 29th August 2024\\n \\nA WIN FOR ALL\\nCONTACT :\\nSamagi Jana Balawegaya\\n592, Kotte Road, Sri Jayawardenepura Kotte 10100 Phone: 011 287 0112\\ne-mail : info@sajith.lk\\nWeb : www.sajith.lk\\n \\nCONTENT\\nBUILD A RESILIENT ECONOMY 08\\ny TRANSPARENCY AND ACCOUNTABILITY\\ny MANAGING THE DEBT CRISIS AND THE IMF\\ny MONETARY AND EXCHANGE RATE POLICY\\ny ACHIEVING A REVENUE GROWTH\\ny EXPENDITURE CONTROL\\ny STIMULATING ECONOMIC GROWTH\\ny PUBLIC SECTOR MANAGEMENT AND DIGITALIZATION\\ny ENERGY AND UTILITY REFORMS'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 2253}, page_content='Let me end by stating that the SJS is more than just a new alliance; it is a movement for much-needed change, driven by the belief that Sri Lanka can and must finally realize its true potential. I seek your support in this election not just for myself as your candidate but for the vision we all share for a stronger, fairer, and more prosperous nation. Let us come together to, finally, create the Sri Lanka we all deserve.\\nSajith Premadasa\\nLeader\\nSamagi Jana Sandanya (SJS) 29th August 2024\\n \\nA WIN FOR ALL\\nCONTACT :\\nSamagi Jana Balawegaya\\n592, Kotte Road, Sri Jayawardenepura Kotte 10100 Phone: 011 287 0112\\ne-mail : info@sajith.lk\\nWeb : www.sajith.lk\\n \\nCONTENT\\nBUILD A RESILIENT ECONOMY 08\\ny TRANSPARENCY AND ACCOUNTABILITY\\ny MANAGING THE DEBT CRISIS AND THE IMF\\ny MONETARY AND EXCHANGE RATE POLICY\\ny ACHIEVING A REVENUE GROWTH\\ny EXPENDITURE CONTROL\\ny STIMULATING ECONOMIC GROWTH\\ny PUBLIC SECTOR MANAGEMENT AND DIGITALIZATION\\ny ENERGY AND UTILITY REFORMS'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 829}, page_content='Therefore, our manifesto & economic vision is not just about statistical growth but about tangible prosperity in every segment of society. We will create a resilient and inclusive economy, combining the strength of free markets with a deep commitment to equality, to ensure no Sri Lankan is left behind.\\nAnother crucial pillar of our vision is the fight against corruption. Corruption has long been a stain on Sri Lanka and has ultimately led us to bankruptcy, undermining trust in government and robbing our citizens. The future SJS government will root out corruption by embedding transparency and accountability in every aspect of governance with the necessary system reforms.'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 829}, page_content='Therefore, our manifesto & economic vision is not just about statistical growth but about tangible prosperity in every segment of society. We will create a resilient and inclusive economy, combining the strength of free markets with a deep commitment to equality, to ensure no Sri Lankan is left behind.\\nAnother crucial pillar of our vision is the fight against corruption. Corruption has long been a stain on Sri Lanka and has ultimately led us to bankruptcy, undermining trust in government and robbing our citizens. The future SJS government will root out corruption by embedding transparency and accountability in every aspect of governance with the necessary system reforms.'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 829}, page_content='Therefore, our manifesto & economic vision is not just about statistical growth but about tangible prosperity in every segment of society. We will create a resilient and inclusive economy, combining the strength of free markets with a deep commitment to equality, to ensure no Sri Lankan is left behind.\\nAnother crucial pillar of our vision is the fight against corruption. Corruption has long been a stain on Sri Lanka and has ultimately led us to bankruptcy, undermining trust in government and robbing our citizens. The future SJS government will root out corruption by embedding transparency and accountability in every aspect of governance with the necessary system reforms.')],\n", + " 'generation': \"I don't know. Thanks for asking!\",\n", + " 'question': 'What economic plans did Sajith have for the 2019 election?'}\n", + "'\\n---\\n'\n", + "---GENERATE---\n", + "---CHECK HALLUCINATIONS---\n", + "---DECISION: GENERATION IS NOT GROUNDED IN DOCUMENTS, RE-TRY---\n", + "\"Node 'generate':\"\n", + "{ 'documents': [ Document(metadata={'source': '../documents/sajith.txt', 'start_index': 2253}, page_content='Let me end by stating that the SJS is more than just a new alliance; it is a movement for much-needed change, driven by the belief that Sri Lanka can and must finally realize its true potential. I seek your support in this election not just for myself as your candidate but for the vision we all share for a stronger, fairer, and more prosperous nation. Let us come together to, finally, create the Sri Lanka we all deserve.\\nSajith Premadasa\\nLeader\\nSamagi Jana Sandanya (SJS) 29th August 2024\\n \\nA WIN FOR ALL\\nCONTACT :\\nSamagi Jana Balawegaya\\n592, Kotte Road, Sri Jayawardenepura Kotte 10100 Phone: 011 287 0112\\ne-mail : info@sajith.lk\\nWeb : www.sajith.lk\\n \\nCONTENT\\nBUILD A RESILIENT ECONOMY 08\\ny TRANSPARENCY AND ACCOUNTABILITY\\ny MANAGING THE DEBT CRISIS AND THE IMF\\ny MONETARY AND EXCHANGE RATE POLICY\\ny ACHIEVING A REVENUE GROWTH\\ny EXPENDITURE CONTROL\\ny STIMULATING ECONOMIC GROWTH\\ny PUBLIC SECTOR MANAGEMENT AND DIGITALIZATION\\ny ENERGY AND UTILITY REFORMS'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 2253}, page_content='Let me end by stating that the SJS is more than just a new alliance; it is a movement for much-needed change, driven by the belief that Sri Lanka can and must finally realize its true potential. I seek your support in this election not just for myself as your candidate but for the vision we all share for a stronger, fairer, and more prosperous nation. Let us come together to, finally, create the Sri Lanka we all deserve.\\nSajith Premadasa\\nLeader\\nSamagi Jana Sandanya (SJS) 29th August 2024\\n \\nA WIN FOR ALL\\nCONTACT :\\nSamagi Jana Balawegaya\\n592, Kotte Road, Sri Jayawardenepura Kotte 10100 Phone: 011 287 0112\\ne-mail : info@sajith.lk\\nWeb : www.sajith.lk\\n \\nCONTENT\\nBUILD A RESILIENT ECONOMY 08\\ny TRANSPARENCY AND ACCOUNTABILITY\\ny MANAGING THE DEBT CRISIS AND THE IMF\\ny MONETARY AND EXCHANGE RATE POLICY\\ny ACHIEVING A REVENUE GROWTH\\ny EXPENDITURE CONTROL\\ny STIMULATING ECONOMIC GROWTH\\ny PUBLIC SECTOR MANAGEMENT AND DIGITALIZATION\\ny ENERGY AND UTILITY REFORMS'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 2253}, page_content='Let me end by stating that the SJS is more than just a new alliance; it is a movement for much-needed change, driven by the belief that Sri Lanka can and must finally realize its true potential. I seek your support in this election not just for myself as your candidate but for the vision we all share for a stronger, fairer, and more prosperous nation. Let us come together to, finally, create the Sri Lanka we all deserve.\\nSajith Premadasa\\nLeader\\nSamagi Jana Sandanya (SJS) 29th August 2024\\n \\nA WIN FOR ALL\\nCONTACT :\\nSamagi Jana Balawegaya\\n592, Kotte Road, Sri Jayawardenepura Kotte 10100 Phone: 011 287 0112\\ne-mail : info@sajith.lk\\nWeb : www.sajith.lk\\n \\nCONTENT\\nBUILD A RESILIENT ECONOMY 08\\ny TRANSPARENCY AND ACCOUNTABILITY\\ny MANAGING THE DEBT CRISIS AND THE IMF\\ny MONETARY AND EXCHANGE RATE POLICY\\ny ACHIEVING A REVENUE GROWTH\\ny EXPENDITURE CONTROL\\ny STIMULATING ECONOMIC GROWTH\\ny PUBLIC SECTOR MANAGEMENT AND DIGITALIZATION\\ny ENERGY AND UTILITY REFORMS'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 829}, page_content='Therefore, our manifesto & economic vision is not just about statistical growth but about tangible prosperity in every segment of society. We will create a resilient and inclusive economy, combining the strength of free markets with a deep commitment to equality, to ensure no Sri Lankan is left behind.\\nAnother crucial pillar of our vision is the fight against corruption. Corruption has long been a stain on Sri Lanka and has ultimately led us to bankruptcy, undermining trust in government and robbing our citizens. The future SJS government will root out corruption by embedding transparency and accountability in every aspect of governance with the necessary system reforms.'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 829}, page_content='Therefore, our manifesto & economic vision is not just about statistical growth but about tangible prosperity in every segment of society. We will create a resilient and inclusive economy, combining the strength of free markets with a deep commitment to equality, to ensure no Sri Lankan is left behind.\\nAnother crucial pillar of our vision is the fight against corruption. Corruption has long been a stain on Sri Lanka and has ultimately led us to bankruptcy, undermining trust in government and robbing our citizens. The future SJS government will root out corruption by embedding transparency and accountability in every aspect of governance with the necessary system reforms.'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 829}, page_content='Therefore, our manifesto & economic vision is not just about statistical growth but about tangible prosperity in every segment of society. We will create a resilient and inclusive economy, combining the strength of free markets with a deep commitment to equality, to ensure no Sri Lankan is left behind.\\nAnother crucial pillar of our vision is the fight against corruption. Corruption has long been a stain on Sri Lanka and has ultimately led us to bankruptcy, undermining trust in government and robbing our citizens. The future SJS government will root out corruption by embedding transparency and accountability in every aspect of governance with the necessary system reforms.')],\n", + " 'generation': \"I don't know. Thanks for asking!\",\n", + " 'question': 'What economic plans did Sajith have for the 2019 election?'}\n", + "'\\n---\\n'\n", + "---GENERATE---\n", + "---CHECK HALLUCINATIONS---\n", + "---DECISION: GENERATION IS NOT GROUNDED IN DOCUMENTS, RE-TRY---\n", + "\"Node 'generate':\"\n", + "{ 'documents': [ Document(metadata={'source': '../documents/sajith.txt', 'start_index': 2253}, page_content='Let me end by stating that the SJS is more than just a new alliance; it is a movement for much-needed change, driven by the belief that Sri Lanka can and must finally realize its true potential. I seek your support in this election not just for myself as your candidate but for the vision we all share for a stronger, fairer, and more prosperous nation. Let us come together to, finally, create the Sri Lanka we all deserve.\\nSajith Premadasa\\nLeader\\nSamagi Jana Sandanya (SJS) 29th August 2024\\n \\nA WIN FOR ALL\\nCONTACT :\\nSamagi Jana Balawegaya\\n592, Kotte Road, Sri Jayawardenepura Kotte 10100 Phone: 011 287 0112\\ne-mail : info@sajith.lk\\nWeb : www.sajith.lk\\n \\nCONTENT\\nBUILD A RESILIENT ECONOMY 08\\ny TRANSPARENCY AND ACCOUNTABILITY\\ny MANAGING THE DEBT CRISIS AND THE IMF\\ny MONETARY AND EXCHANGE RATE POLICY\\ny ACHIEVING A REVENUE GROWTH\\ny EXPENDITURE CONTROL\\ny STIMULATING ECONOMIC GROWTH\\ny PUBLIC SECTOR MANAGEMENT AND DIGITALIZATION\\ny ENERGY AND UTILITY REFORMS'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 2253}, page_content='Let me end by stating that the SJS is more than just a new alliance; it is a movement for much-needed change, driven by the belief that Sri Lanka can and must finally realize its true potential. I seek your support in this election not just for myself as your candidate but for the vision we all share for a stronger, fairer, and more prosperous nation. Let us come together to, finally, create the Sri Lanka we all deserve.\\nSajith Premadasa\\nLeader\\nSamagi Jana Sandanya (SJS) 29th August 2024\\n \\nA WIN FOR ALL\\nCONTACT :\\nSamagi Jana Balawegaya\\n592, Kotte Road, Sri Jayawardenepura Kotte 10100 Phone: 011 287 0112\\ne-mail : info@sajith.lk\\nWeb : www.sajith.lk\\n \\nCONTENT\\nBUILD A RESILIENT ECONOMY 08\\ny TRANSPARENCY AND ACCOUNTABILITY\\ny MANAGING THE DEBT CRISIS AND THE IMF\\ny MONETARY AND EXCHANGE RATE POLICY\\ny ACHIEVING A REVENUE GROWTH\\ny EXPENDITURE CONTROL\\ny STIMULATING ECONOMIC GROWTH\\ny PUBLIC SECTOR MANAGEMENT AND DIGITALIZATION\\ny ENERGY AND UTILITY REFORMS'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 2253}, page_content='Let me end by stating that the SJS is more than just a new alliance; it is a movement for much-needed change, driven by the belief that Sri Lanka can and must finally realize its true potential. I seek your support in this election not just for myself as your candidate but for the vision we all share for a stronger, fairer, and more prosperous nation. Let us come together to, finally, create the Sri Lanka we all deserve.\\nSajith Premadasa\\nLeader\\nSamagi Jana Sandanya (SJS) 29th August 2024\\n \\nA WIN FOR ALL\\nCONTACT :\\nSamagi Jana Balawegaya\\n592, Kotte Road, Sri Jayawardenepura Kotte 10100 Phone: 011 287 0112\\ne-mail : info@sajith.lk\\nWeb : www.sajith.lk\\n \\nCONTENT\\nBUILD A RESILIENT ECONOMY 08\\ny TRANSPARENCY AND ACCOUNTABILITY\\ny MANAGING THE DEBT CRISIS AND THE IMF\\ny MONETARY AND EXCHANGE RATE POLICY\\ny ACHIEVING A REVENUE GROWTH\\ny EXPENDITURE CONTROL\\ny STIMULATING ECONOMIC GROWTH\\ny PUBLIC SECTOR MANAGEMENT AND DIGITALIZATION\\ny ENERGY AND UTILITY REFORMS'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 829}, page_content='Therefore, our manifesto & economic vision is not just about statistical growth but about tangible prosperity in every segment of society. We will create a resilient and inclusive economy, combining the strength of free markets with a deep commitment to equality, to ensure no Sri Lankan is left behind.\\nAnother crucial pillar of our vision is the fight against corruption. Corruption has long been a stain on Sri Lanka and has ultimately led us to bankruptcy, undermining trust in government and robbing our citizens. The future SJS government will root out corruption by embedding transparency and accountability in every aspect of governance with the necessary system reforms.'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 829}, page_content='Therefore, our manifesto & economic vision is not just about statistical growth but about tangible prosperity in every segment of society. We will create a resilient and inclusive economy, combining the strength of free markets with a deep commitment to equality, to ensure no Sri Lankan is left behind.\\nAnother crucial pillar of our vision is the fight against corruption. Corruption has long been a stain on Sri Lanka and has ultimately led us to bankruptcy, undermining trust in government and robbing our citizens. The future SJS government will root out corruption by embedding transparency and accountability in every aspect of governance with the necessary system reforms.'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 829}, page_content='Therefore, our manifesto & economic vision is not just about statistical growth but about tangible prosperity in every segment of society. We will create a resilient and inclusive economy, combining the strength of free markets with a deep commitment to equality, to ensure no Sri Lankan is left behind.\\nAnother crucial pillar of our vision is the fight against corruption. Corruption has long been a stain on Sri Lanka and has ultimately led us to bankruptcy, undermining trust in government and robbing our citizens. The future SJS government will root out corruption by embedding transparency and accountability in every aspect of governance with the necessary system reforms.')],\n", + " 'generation': \"I don't know. Thanks for asking!\",\n", + " 'question': 'What economic plans did Sajith have for the 2019 election?'}\n", + "'\\n---\\n'\n", + "---GENERATE---\n", + "---CHECK HALLUCINATIONS---\n", + "---DECISION: GENERATION IS NOT GROUNDED IN DOCUMENTS, RE-TRY---\n", + "\"Node 'generate':\"\n", + "{ 'documents': [ Document(metadata={'source': '../documents/sajith.txt', 'start_index': 2253}, page_content='Let me end by stating that the SJS is more than just a new alliance; it is a movement for much-needed change, driven by the belief that Sri Lanka can and must finally realize its true potential. I seek your support in this election not just for myself as your candidate but for the vision we all share for a stronger, fairer, and more prosperous nation. Let us come together to, finally, create the Sri Lanka we all deserve.\\nSajith Premadasa\\nLeader\\nSamagi Jana Sandanya (SJS) 29th August 2024\\n \\nA WIN FOR ALL\\nCONTACT :\\nSamagi Jana Balawegaya\\n592, Kotte Road, Sri Jayawardenepura Kotte 10100 Phone: 011 287 0112\\ne-mail : info@sajith.lk\\nWeb : www.sajith.lk\\n \\nCONTENT\\nBUILD A RESILIENT ECONOMY 08\\ny TRANSPARENCY AND ACCOUNTABILITY\\ny MANAGING THE DEBT CRISIS AND THE IMF\\ny MONETARY AND EXCHANGE RATE POLICY\\ny ACHIEVING A REVENUE GROWTH\\ny EXPENDITURE CONTROL\\ny STIMULATING ECONOMIC GROWTH\\ny PUBLIC SECTOR MANAGEMENT AND DIGITALIZATION\\ny ENERGY AND UTILITY REFORMS'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 2253}, page_content='Let me end by stating that the SJS is more than just a new alliance; it is a movement for much-needed change, driven by the belief that Sri Lanka can and must finally realize its true potential. I seek your support in this election not just for myself as your candidate but for the vision we all share for a stronger, fairer, and more prosperous nation. Let us come together to, finally, create the Sri Lanka we all deserve.\\nSajith Premadasa\\nLeader\\nSamagi Jana Sandanya (SJS) 29th August 2024\\n \\nA WIN FOR ALL\\nCONTACT :\\nSamagi Jana Balawegaya\\n592, Kotte Road, Sri Jayawardenepura Kotte 10100 Phone: 011 287 0112\\ne-mail : info@sajith.lk\\nWeb : www.sajith.lk\\n \\nCONTENT\\nBUILD A RESILIENT ECONOMY 08\\ny TRANSPARENCY AND ACCOUNTABILITY\\ny MANAGING THE DEBT CRISIS AND THE IMF\\ny MONETARY AND EXCHANGE RATE POLICY\\ny ACHIEVING A REVENUE GROWTH\\ny EXPENDITURE CONTROL\\ny STIMULATING ECONOMIC GROWTH\\ny PUBLIC SECTOR MANAGEMENT AND DIGITALIZATION\\ny ENERGY AND UTILITY REFORMS'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 2253}, page_content='Let me end by stating that the SJS is more than just a new alliance; it is a movement for much-needed change, driven by the belief that Sri Lanka can and must finally realize its true potential. I seek your support in this election not just for myself as your candidate but for the vision we all share for a stronger, fairer, and more prosperous nation. Let us come together to, finally, create the Sri Lanka we all deserve.\\nSajith Premadasa\\nLeader\\nSamagi Jana Sandanya (SJS) 29th August 2024\\n \\nA WIN FOR ALL\\nCONTACT :\\nSamagi Jana Balawegaya\\n592, Kotte Road, Sri Jayawardenepura Kotte 10100 Phone: 011 287 0112\\ne-mail : info@sajith.lk\\nWeb : www.sajith.lk\\n \\nCONTENT\\nBUILD A RESILIENT ECONOMY 08\\ny TRANSPARENCY AND ACCOUNTABILITY\\ny MANAGING THE DEBT CRISIS AND THE IMF\\ny MONETARY AND EXCHANGE RATE POLICY\\ny ACHIEVING A REVENUE GROWTH\\ny EXPENDITURE CONTROL\\ny STIMULATING ECONOMIC GROWTH\\ny PUBLIC SECTOR MANAGEMENT AND DIGITALIZATION\\ny ENERGY AND UTILITY REFORMS'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 829}, page_content='Therefore, our manifesto & economic vision is not just about statistical growth but about tangible prosperity in every segment of society. We will create a resilient and inclusive economy, combining the strength of free markets with a deep commitment to equality, to ensure no Sri Lankan is left behind.\\nAnother crucial pillar of our vision is the fight against corruption. Corruption has long been a stain on Sri Lanka and has ultimately led us to bankruptcy, undermining trust in government and robbing our citizens. The future SJS government will root out corruption by embedding transparency and accountability in every aspect of governance with the necessary system reforms.'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 829}, page_content='Therefore, our manifesto & economic vision is not just about statistical growth but about tangible prosperity in every segment of society. We will create a resilient and inclusive economy, combining the strength of free markets with a deep commitment to equality, to ensure no Sri Lankan is left behind.\\nAnother crucial pillar of our vision is the fight against corruption. Corruption has long been a stain on Sri Lanka and has ultimately led us to bankruptcy, undermining trust in government and robbing our citizens. The future SJS government will root out corruption by embedding transparency and accountability in every aspect of governance with the necessary system reforms.'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 829}, page_content='Therefore, our manifesto & economic vision is not just about statistical growth but about tangible prosperity in every segment of society. We will create a resilient and inclusive economy, combining the strength of free markets with a deep commitment to equality, to ensure no Sri Lankan is left behind.\\nAnother crucial pillar of our vision is the fight against corruption. Corruption has long been a stain on Sri Lanka and has ultimately led us to bankruptcy, undermining trust in government and robbing our citizens. The future SJS government will root out corruption by embedding transparency and accountability in every aspect of governance with the necessary system reforms.')],\n", + " 'generation': \"I don't know. Thanks for asking!\",\n", + " 'question': 'What economic plans did Sajith have for the 2019 election?'}\n", + "'\\n---\\n'\n", + "---GENERATE---\n", + "---CHECK HALLUCINATIONS---\n", + "---DECISION: GENERATION IS NOT GROUNDED IN DOCUMENTS, RE-TRY---\n", + "\"Node 'generate':\"\n", + "{ 'documents': [ Document(metadata={'source': '../documents/sajith.txt', 'start_index': 2253}, page_content='Let me end by stating that the SJS is more than just a new alliance; it is a movement for much-needed change, driven by the belief that Sri Lanka can and must finally realize its true potential. I seek your support in this election not just for myself as your candidate but for the vision we all share for a stronger, fairer, and more prosperous nation. Let us come together to, finally, create the Sri Lanka we all deserve.\\nSajith Premadasa\\nLeader\\nSamagi Jana Sandanya (SJS) 29th August 2024\\n \\nA WIN FOR ALL\\nCONTACT :\\nSamagi Jana Balawegaya\\n592, Kotte Road, Sri Jayawardenepura Kotte 10100 Phone: 011 287 0112\\ne-mail : info@sajith.lk\\nWeb : www.sajith.lk\\n \\nCONTENT\\nBUILD A RESILIENT ECONOMY 08\\ny TRANSPARENCY AND ACCOUNTABILITY\\ny MANAGING THE DEBT CRISIS AND THE IMF\\ny MONETARY AND EXCHANGE RATE POLICY\\ny ACHIEVING A REVENUE GROWTH\\ny EXPENDITURE CONTROL\\ny STIMULATING ECONOMIC GROWTH\\ny PUBLIC SECTOR MANAGEMENT AND DIGITALIZATION\\ny ENERGY AND UTILITY REFORMS'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 2253}, page_content='Let me end by stating that the SJS is more than just a new alliance; it is a movement for much-needed change, driven by the belief that Sri Lanka can and must finally realize its true potential. I seek your support in this election not just for myself as your candidate but for the vision we all share for a stronger, fairer, and more prosperous nation. Let us come together to, finally, create the Sri Lanka we all deserve.\\nSajith Premadasa\\nLeader\\nSamagi Jana Sandanya (SJS) 29th August 2024\\n \\nA WIN FOR ALL\\nCONTACT :\\nSamagi Jana Balawegaya\\n592, Kotte Road, Sri Jayawardenepura Kotte 10100 Phone: 011 287 0112\\ne-mail : info@sajith.lk\\nWeb : www.sajith.lk\\n \\nCONTENT\\nBUILD A RESILIENT ECONOMY 08\\ny TRANSPARENCY AND ACCOUNTABILITY\\ny MANAGING THE DEBT CRISIS AND THE IMF\\ny MONETARY AND EXCHANGE RATE POLICY\\ny ACHIEVING A REVENUE GROWTH\\ny EXPENDITURE CONTROL\\ny STIMULATING ECONOMIC GROWTH\\ny PUBLIC SECTOR MANAGEMENT AND DIGITALIZATION\\ny ENERGY AND UTILITY REFORMS'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 2253}, page_content='Let me end by stating that the SJS is more than just a new alliance; it is a movement for much-needed change, driven by the belief that Sri Lanka can and must finally realize its true potential. I seek your support in this election not just for myself as your candidate but for the vision we all share for a stronger, fairer, and more prosperous nation. Let us come together to, finally, create the Sri Lanka we all deserve.\\nSajith Premadasa\\nLeader\\nSamagi Jana Sandanya (SJS) 29th August 2024\\n \\nA WIN FOR ALL\\nCONTACT :\\nSamagi Jana Balawegaya\\n592, Kotte Road, Sri Jayawardenepura Kotte 10100 Phone: 011 287 0112\\ne-mail : info@sajith.lk\\nWeb : www.sajith.lk\\n \\nCONTENT\\nBUILD A RESILIENT ECONOMY 08\\ny TRANSPARENCY AND ACCOUNTABILITY\\ny MANAGING THE DEBT CRISIS AND THE IMF\\ny MONETARY AND EXCHANGE RATE POLICY\\ny ACHIEVING A REVENUE GROWTH\\ny EXPENDITURE CONTROL\\ny STIMULATING ECONOMIC GROWTH\\ny PUBLIC SECTOR MANAGEMENT AND DIGITALIZATION\\ny ENERGY AND UTILITY REFORMS'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 829}, page_content='Therefore, our manifesto & economic vision is not just about statistical growth but about tangible prosperity in every segment of society. We will create a resilient and inclusive economy, combining the strength of free markets with a deep commitment to equality, to ensure no Sri Lankan is left behind.\\nAnother crucial pillar of our vision is the fight against corruption. Corruption has long been a stain on Sri Lanka and has ultimately led us to bankruptcy, undermining trust in government and robbing our citizens. The future SJS government will root out corruption by embedding transparency and accountability in every aspect of governance with the necessary system reforms.'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 829}, page_content='Therefore, our manifesto & economic vision is not just about statistical growth but about tangible prosperity in every segment of society. We will create a resilient and inclusive economy, combining the strength of free markets with a deep commitment to equality, to ensure no Sri Lankan is left behind.\\nAnother crucial pillar of our vision is the fight against corruption. Corruption has long been a stain on Sri Lanka and has ultimately led us to bankruptcy, undermining trust in government and robbing our citizens. The future SJS government will root out corruption by embedding transparency and accountability in every aspect of governance with the necessary system reforms.'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 829}, page_content='Therefore, our manifesto & economic vision is not just about statistical growth but about tangible prosperity in every segment of society. We will create a resilient and inclusive economy, combining the strength of free markets with a deep commitment to equality, to ensure no Sri Lankan is left behind.\\nAnother crucial pillar of our vision is the fight against corruption. Corruption has long been a stain on Sri Lanka and has ultimately led us to bankruptcy, undermining trust in government and robbing our citizens. The future SJS government will root out corruption by embedding transparency and accountability in every aspect of governance with the necessary system reforms.')],\n", + " 'generation': \"I don't know. Thanks for asking!\",\n", + " 'question': 'What economic plans did Sajith have for the 2019 election?'}\n", + "'\\n---\\n'\n", + "---GENERATE---\n", + "---CHECK HALLUCINATIONS---\n", + "---DECISION: GENERATION IS NOT GROUNDED IN DOCUMENTS, RE-TRY---\n", + "\"Node 'generate':\"\n", + "{ 'documents': [ Document(metadata={'source': '../documents/sajith.txt', 'start_index': 2253}, page_content='Let me end by stating that the SJS is more than just a new alliance; it is a movement for much-needed change, driven by the belief that Sri Lanka can and must finally realize its true potential. I seek your support in this election not just for myself as your candidate but for the vision we all share for a stronger, fairer, and more prosperous nation. Let us come together to, finally, create the Sri Lanka we all deserve.\\nSajith Premadasa\\nLeader\\nSamagi Jana Sandanya (SJS) 29th August 2024\\n \\nA WIN FOR ALL\\nCONTACT :\\nSamagi Jana Balawegaya\\n592, Kotte Road, Sri Jayawardenepura Kotte 10100 Phone: 011 287 0112\\ne-mail : info@sajith.lk\\nWeb : www.sajith.lk\\n \\nCONTENT\\nBUILD A RESILIENT ECONOMY 08\\ny TRANSPARENCY AND ACCOUNTABILITY\\ny MANAGING THE DEBT CRISIS AND THE IMF\\ny MONETARY AND EXCHANGE RATE POLICY\\ny ACHIEVING A REVENUE GROWTH\\ny EXPENDITURE CONTROL\\ny STIMULATING ECONOMIC GROWTH\\ny PUBLIC SECTOR MANAGEMENT AND DIGITALIZATION\\ny ENERGY AND UTILITY REFORMS'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 2253}, page_content='Let me end by stating that the SJS is more than just a new alliance; it is a movement for much-needed change, driven by the belief that Sri Lanka can and must finally realize its true potential. I seek your support in this election not just for myself as your candidate but for the vision we all share for a stronger, fairer, and more prosperous nation. Let us come together to, finally, create the Sri Lanka we all deserve.\\nSajith Premadasa\\nLeader\\nSamagi Jana Sandanya (SJS) 29th August 2024\\n \\nA WIN FOR ALL\\nCONTACT :\\nSamagi Jana Balawegaya\\n592, Kotte Road, Sri Jayawardenepura Kotte 10100 Phone: 011 287 0112\\ne-mail : info@sajith.lk\\nWeb : www.sajith.lk\\n \\nCONTENT\\nBUILD A RESILIENT ECONOMY 08\\ny TRANSPARENCY AND ACCOUNTABILITY\\ny MANAGING THE DEBT CRISIS AND THE IMF\\ny MONETARY AND EXCHANGE RATE POLICY\\ny ACHIEVING A REVENUE GROWTH\\ny EXPENDITURE CONTROL\\ny STIMULATING ECONOMIC GROWTH\\ny PUBLIC SECTOR MANAGEMENT AND DIGITALIZATION\\ny ENERGY AND UTILITY REFORMS'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 2253}, page_content='Let me end by stating that the SJS is more than just a new alliance; it is a movement for much-needed change, driven by the belief that Sri Lanka can and must finally realize its true potential. I seek your support in this election not just for myself as your candidate but for the vision we all share for a stronger, fairer, and more prosperous nation. Let us come together to, finally, create the Sri Lanka we all deserve.\\nSajith Premadasa\\nLeader\\nSamagi Jana Sandanya (SJS) 29th August 2024\\n \\nA WIN FOR ALL\\nCONTACT :\\nSamagi Jana Balawegaya\\n592, Kotte Road, Sri Jayawardenepura Kotte 10100 Phone: 011 287 0112\\ne-mail : info@sajith.lk\\nWeb : www.sajith.lk\\n \\nCONTENT\\nBUILD A RESILIENT ECONOMY 08\\ny TRANSPARENCY AND ACCOUNTABILITY\\ny MANAGING THE DEBT CRISIS AND THE IMF\\ny MONETARY AND EXCHANGE RATE POLICY\\ny ACHIEVING A REVENUE GROWTH\\ny EXPENDITURE CONTROL\\ny STIMULATING ECONOMIC GROWTH\\ny PUBLIC SECTOR MANAGEMENT AND DIGITALIZATION\\ny ENERGY AND UTILITY REFORMS'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 829}, page_content='Therefore, our manifesto & economic vision is not just about statistical growth but about tangible prosperity in every segment of society. We will create a resilient and inclusive economy, combining the strength of free markets with a deep commitment to equality, to ensure no Sri Lankan is left behind.\\nAnother crucial pillar of our vision is the fight against corruption. Corruption has long been a stain on Sri Lanka and has ultimately led us to bankruptcy, undermining trust in government and robbing our citizens. The future SJS government will root out corruption by embedding transparency and accountability in every aspect of governance with the necessary system reforms.'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 829}, page_content='Therefore, our manifesto & economic vision is not just about statistical growth but about tangible prosperity in every segment of society. We will create a resilient and inclusive economy, combining the strength of free markets with a deep commitment to equality, to ensure no Sri Lankan is left behind.\\nAnother crucial pillar of our vision is the fight against corruption. Corruption has long been a stain on Sri Lanka and has ultimately led us to bankruptcy, undermining trust in government and robbing our citizens. The future SJS government will root out corruption by embedding transparency and accountability in every aspect of governance with the necessary system reforms.'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 829}, page_content='Therefore, our manifesto & economic vision is not just about statistical growth but about tangible prosperity in every segment of society. We will create a resilient and inclusive economy, combining the strength of free markets with a deep commitment to equality, to ensure no Sri Lankan is left behind.\\nAnother crucial pillar of our vision is the fight against corruption. Corruption has long been a stain on Sri Lanka and has ultimately led us to bankruptcy, undermining trust in government and robbing our citizens. The future SJS government will root out corruption by embedding transparency and accountability in every aspect of governance with the necessary system reforms.')],\n", + " 'generation': 'The provided context does not contain specific details about '\n", + " \"Sajith Premadasa's economic plans for the 2019 election. It \"\n", + " 'primarily discusses the vision and goals of the Samagi Jana '\n", + " 'Sandanya (SJS) movement. Thanks for asking!',\n", + " 'question': 'What economic plans did Sajith have for the 2019 election?'}\n", + "'\\n---\\n'\n", + "---GENERATE---\n", + "---CHECK HALLUCINATIONS---\n", + "---DECISION: GENERATION IS NOT GROUNDED IN DOCUMENTS, RE-TRY---\n", + "\"Node 'generate':\"\n", + "{ 'documents': [ Document(metadata={'source': '../documents/sajith.txt', 'start_index': 2253}, page_content='Let me end by stating that the SJS is more than just a new alliance; it is a movement for much-needed change, driven by the belief that Sri Lanka can and must finally realize its true potential. I seek your support in this election not just for myself as your candidate but for the vision we all share for a stronger, fairer, and more prosperous nation. Let us come together to, finally, create the Sri Lanka we all deserve.\\nSajith Premadasa\\nLeader\\nSamagi Jana Sandanya (SJS) 29th August 2024\\n \\nA WIN FOR ALL\\nCONTACT :\\nSamagi Jana Balawegaya\\n592, Kotte Road, Sri Jayawardenepura Kotte 10100 Phone: 011 287 0112\\ne-mail : info@sajith.lk\\nWeb : www.sajith.lk\\n \\nCONTENT\\nBUILD A RESILIENT ECONOMY 08\\ny TRANSPARENCY AND ACCOUNTABILITY\\ny MANAGING THE DEBT CRISIS AND THE IMF\\ny MONETARY AND EXCHANGE RATE POLICY\\ny ACHIEVING A REVENUE GROWTH\\ny EXPENDITURE CONTROL\\ny STIMULATING ECONOMIC GROWTH\\ny PUBLIC SECTOR MANAGEMENT AND DIGITALIZATION\\ny ENERGY AND UTILITY REFORMS'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 2253}, page_content='Let me end by stating that the SJS is more than just a new alliance; it is a movement for much-needed change, driven by the belief that Sri Lanka can and must finally realize its true potential. I seek your support in this election not just for myself as your candidate but for the vision we all share for a stronger, fairer, and more prosperous nation. Let us come together to, finally, create the Sri Lanka we all deserve.\\nSajith Premadasa\\nLeader\\nSamagi Jana Sandanya (SJS) 29th August 2024\\n \\nA WIN FOR ALL\\nCONTACT :\\nSamagi Jana Balawegaya\\n592, Kotte Road, Sri Jayawardenepura Kotte 10100 Phone: 011 287 0112\\ne-mail : info@sajith.lk\\nWeb : www.sajith.lk\\n \\nCONTENT\\nBUILD A RESILIENT ECONOMY 08\\ny TRANSPARENCY AND ACCOUNTABILITY\\ny MANAGING THE DEBT CRISIS AND THE IMF\\ny MONETARY AND EXCHANGE RATE POLICY\\ny ACHIEVING A REVENUE GROWTH\\ny EXPENDITURE CONTROL\\ny STIMULATING ECONOMIC GROWTH\\ny PUBLIC SECTOR MANAGEMENT AND DIGITALIZATION\\ny ENERGY AND UTILITY REFORMS'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 2253}, page_content='Let me end by stating that the SJS is more than just a new alliance; it is a movement for much-needed change, driven by the belief that Sri Lanka can and must finally realize its true potential. I seek your support in this election not just for myself as your candidate but for the vision we all share for a stronger, fairer, and more prosperous nation. Let us come together to, finally, create the Sri Lanka we all deserve.\\nSajith Premadasa\\nLeader\\nSamagi Jana Sandanya (SJS) 29th August 2024\\n \\nA WIN FOR ALL\\nCONTACT :\\nSamagi Jana Balawegaya\\n592, Kotte Road, Sri Jayawardenepura Kotte 10100 Phone: 011 287 0112\\ne-mail : info@sajith.lk\\nWeb : www.sajith.lk\\n \\nCONTENT\\nBUILD A RESILIENT ECONOMY 08\\ny TRANSPARENCY AND ACCOUNTABILITY\\ny MANAGING THE DEBT CRISIS AND THE IMF\\ny MONETARY AND EXCHANGE RATE POLICY\\ny ACHIEVING A REVENUE GROWTH\\ny EXPENDITURE CONTROL\\ny STIMULATING ECONOMIC GROWTH\\ny PUBLIC SECTOR MANAGEMENT AND DIGITALIZATION\\ny ENERGY AND UTILITY REFORMS'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 829}, page_content='Therefore, our manifesto & economic vision is not just about statistical growth but about tangible prosperity in every segment of society. We will create a resilient and inclusive economy, combining the strength of free markets with a deep commitment to equality, to ensure no Sri Lankan is left behind.\\nAnother crucial pillar of our vision is the fight against corruption. Corruption has long been a stain on Sri Lanka and has ultimately led us to bankruptcy, undermining trust in government and robbing our citizens. The future SJS government will root out corruption by embedding transparency and accountability in every aspect of governance with the necessary system reforms.'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 829}, page_content='Therefore, our manifesto & economic vision is not just about statistical growth but about tangible prosperity in every segment of society. We will create a resilient and inclusive economy, combining the strength of free markets with a deep commitment to equality, to ensure no Sri Lankan is left behind.\\nAnother crucial pillar of our vision is the fight against corruption. Corruption has long been a stain on Sri Lanka and has ultimately led us to bankruptcy, undermining trust in government and robbing our citizens. The future SJS government will root out corruption by embedding transparency and accountability in every aspect of governance with the necessary system reforms.'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 829}, page_content='Therefore, our manifesto & economic vision is not just about statistical growth but about tangible prosperity in every segment of society. We will create a resilient and inclusive economy, combining the strength of free markets with a deep commitment to equality, to ensure no Sri Lankan is left behind.\\nAnother crucial pillar of our vision is the fight against corruption. Corruption has long been a stain on Sri Lanka and has ultimately led us to bankruptcy, undermining trust in government and robbing our citizens. The future SJS government will root out corruption by embedding transparency and accountability in every aspect of governance with the necessary system reforms.')],\n", + " 'generation': 'The provided context does not contain specific details about '\n", + " \"Sajith's economic plans for the 2019 election. Therefore, I \"\n", + " \"don't know. Thanks for asking!\",\n", + " 'question': 'What economic plans did Sajith have for the 2019 election?'}\n", + "'\\n---\\n'\n", + "---GENERATE---\n", + "---CHECK HALLUCINATIONS---\n", + "---DECISION: GENERATION IS NOT GROUNDED IN DOCUMENTS, RE-TRY---\n", + "\"Node 'generate':\"\n", + "{ 'documents': [ Document(metadata={'source': '../documents/sajith.txt', 'start_index': 2253}, page_content='Let me end by stating that the SJS is more than just a new alliance; it is a movement for much-needed change, driven by the belief that Sri Lanka can and must finally realize its true potential. I seek your support in this election not just for myself as your candidate but for the vision we all share for a stronger, fairer, and more prosperous nation. Let us come together to, finally, create the Sri Lanka we all deserve.\\nSajith Premadasa\\nLeader\\nSamagi Jana Sandanya (SJS) 29th August 2024\\n \\nA WIN FOR ALL\\nCONTACT :\\nSamagi Jana Balawegaya\\n592, Kotte Road, Sri Jayawardenepura Kotte 10100 Phone: 011 287 0112\\ne-mail : info@sajith.lk\\nWeb : www.sajith.lk\\n \\nCONTENT\\nBUILD A RESILIENT ECONOMY 08\\ny TRANSPARENCY AND ACCOUNTABILITY\\ny MANAGING THE DEBT CRISIS AND THE IMF\\ny MONETARY AND EXCHANGE RATE POLICY\\ny ACHIEVING A REVENUE GROWTH\\ny EXPENDITURE CONTROL\\ny STIMULATING ECONOMIC GROWTH\\ny PUBLIC SECTOR MANAGEMENT AND DIGITALIZATION\\ny ENERGY AND UTILITY REFORMS'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 2253}, page_content='Let me end by stating that the SJS is more than just a new alliance; it is a movement for much-needed change, driven by the belief that Sri Lanka can and must finally realize its true potential. I seek your support in this election not just for myself as your candidate but for the vision we all share for a stronger, fairer, and more prosperous nation. Let us come together to, finally, create the Sri Lanka we all deserve.\\nSajith Premadasa\\nLeader\\nSamagi Jana Sandanya (SJS) 29th August 2024\\n \\nA WIN FOR ALL\\nCONTACT :\\nSamagi Jana Balawegaya\\n592, Kotte Road, Sri Jayawardenepura Kotte 10100 Phone: 011 287 0112\\ne-mail : info@sajith.lk\\nWeb : www.sajith.lk\\n \\nCONTENT\\nBUILD A RESILIENT ECONOMY 08\\ny TRANSPARENCY AND ACCOUNTABILITY\\ny MANAGING THE DEBT CRISIS AND THE IMF\\ny MONETARY AND EXCHANGE RATE POLICY\\ny ACHIEVING A REVENUE GROWTH\\ny EXPENDITURE CONTROL\\ny STIMULATING ECONOMIC GROWTH\\ny PUBLIC SECTOR MANAGEMENT AND DIGITALIZATION\\ny ENERGY AND UTILITY REFORMS'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 2253}, page_content='Let me end by stating that the SJS is more than just a new alliance; it is a movement for much-needed change, driven by the belief that Sri Lanka can and must finally realize its true potential. I seek your support in this election not just for myself as your candidate but for the vision we all share for a stronger, fairer, and more prosperous nation. Let us come together to, finally, create the Sri Lanka we all deserve.\\nSajith Premadasa\\nLeader\\nSamagi Jana Sandanya (SJS) 29th August 2024\\n \\nA WIN FOR ALL\\nCONTACT :\\nSamagi Jana Balawegaya\\n592, Kotte Road, Sri Jayawardenepura Kotte 10100 Phone: 011 287 0112\\ne-mail : info@sajith.lk\\nWeb : www.sajith.lk\\n \\nCONTENT\\nBUILD A RESILIENT ECONOMY 08\\ny TRANSPARENCY AND ACCOUNTABILITY\\ny MANAGING THE DEBT CRISIS AND THE IMF\\ny MONETARY AND EXCHANGE RATE POLICY\\ny ACHIEVING A REVENUE GROWTH\\ny EXPENDITURE CONTROL\\ny STIMULATING ECONOMIC GROWTH\\ny PUBLIC SECTOR MANAGEMENT AND DIGITALIZATION\\ny ENERGY AND UTILITY REFORMS'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 829}, page_content='Therefore, our manifesto & economic vision is not just about statistical growth but about tangible prosperity in every segment of society. We will create a resilient and inclusive economy, combining the strength of free markets with a deep commitment to equality, to ensure no Sri Lankan is left behind.\\nAnother crucial pillar of our vision is the fight against corruption. Corruption has long been a stain on Sri Lanka and has ultimately led us to bankruptcy, undermining trust in government and robbing our citizens. The future SJS government will root out corruption by embedding transparency and accountability in every aspect of governance with the necessary system reforms.'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 829}, page_content='Therefore, our manifesto & economic vision is not just about statistical growth but about tangible prosperity in every segment of society. We will create a resilient and inclusive economy, combining the strength of free markets with a deep commitment to equality, to ensure no Sri Lankan is left behind.\\nAnother crucial pillar of our vision is the fight against corruption. Corruption has long been a stain on Sri Lanka and has ultimately led us to bankruptcy, undermining trust in government and robbing our citizens. The future SJS government will root out corruption by embedding transparency and accountability in every aspect of governance with the necessary system reforms.'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 829}, page_content='Therefore, our manifesto & economic vision is not just about statistical growth but about tangible prosperity in every segment of society. We will create a resilient and inclusive economy, combining the strength of free markets with a deep commitment to equality, to ensure no Sri Lankan is left behind.\\nAnother crucial pillar of our vision is the fight against corruption. Corruption has long been a stain on Sri Lanka and has ultimately led us to bankruptcy, undermining trust in government and robbing our citizens. The future SJS government will root out corruption by embedding transparency and accountability in every aspect of governance with the necessary system reforms.')],\n", + " 'generation': 'The provided context does not contain specific details about '\n", + " \"Sajith Premadasa's economic plans for the 2019 election. It \"\n", + " 'primarily discusses his vision and goals for the future of '\n", + " 'Sri Lanka. Thanks for asking!',\n", + " 'question': 'What economic plans did Sajith have for the 2019 election?'}\n", + "'\\n---\\n'\n", + "---GENERATE---\n", + "---CHECK HALLUCINATIONS---\n", + "---DECISION: GENERATION IS GROUNDED IN DOCUMENTS---\n", + "---GRADE GENERATION vs QUESTION---\n", + "---DECISION: GENERATION DOES NOT ADDRESS QUESTION---\n", + "\"Node 'generate':\"\n", + "{ 'documents': [ Document(metadata={'source': '../documents/sajith.txt', 'start_index': 2253}, page_content='Let me end by stating that the SJS is more than just a new alliance; it is a movement for much-needed change, driven by the belief that Sri Lanka can and must finally realize its true potential. I seek your support in this election not just for myself as your candidate but for the vision we all share for a stronger, fairer, and more prosperous nation. Let us come together to, finally, create the Sri Lanka we all deserve.\\nSajith Premadasa\\nLeader\\nSamagi Jana Sandanya (SJS) 29th August 2024\\n \\nA WIN FOR ALL\\nCONTACT :\\nSamagi Jana Balawegaya\\n592, Kotte Road, Sri Jayawardenepura Kotte 10100 Phone: 011 287 0112\\ne-mail : info@sajith.lk\\nWeb : www.sajith.lk\\n \\nCONTENT\\nBUILD A RESILIENT ECONOMY 08\\ny TRANSPARENCY AND ACCOUNTABILITY\\ny MANAGING THE DEBT CRISIS AND THE IMF\\ny MONETARY AND EXCHANGE RATE POLICY\\ny ACHIEVING A REVENUE GROWTH\\ny EXPENDITURE CONTROL\\ny STIMULATING ECONOMIC GROWTH\\ny PUBLIC SECTOR MANAGEMENT AND DIGITALIZATION\\ny ENERGY AND UTILITY REFORMS'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 2253}, page_content='Let me end by stating that the SJS is more than just a new alliance; it is a movement for much-needed change, driven by the belief that Sri Lanka can and must finally realize its true potential. I seek your support in this election not just for myself as your candidate but for the vision we all share for a stronger, fairer, and more prosperous nation. Let us come together to, finally, create the Sri Lanka we all deserve.\\nSajith Premadasa\\nLeader\\nSamagi Jana Sandanya (SJS) 29th August 2024\\n \\nA WIN FOR ALL\\nCONTACT :\\nSamagi Jana Balawegaya\\n592, Kotte Road, Sri Jayawardenepura Kotte 10100 Phone: 011 287 0112\\ne-mail : info@sajith.lk\\nWeb : www.sajith.lk\\n \\nCONTENT\\nBUILD A RESILIENT ECONOMY 08\\ny TRANSPARENCY AND ACCOUNTABILITY\\ny MANAGING THE DEBT CRISIS AND THE IMF\\ny MONETARY AND EXCHANGE RATE POLICY\\ny ACHIEVING A REVENUE GROWTH\\ny EXPENDITURE CONTROL\\ny STIMULATING ECONOMIC GROWTH\\ny PUBLIC SECTOR MANAGEMENT AND DIGITALIZATION\\ny ENERGY AND UTILITY REFORMS'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 2253}, page_content='Let me end by stating that the SJS is more than just a new alliance; it is a movement for much-needed change, driven by the belief that Sri Lanka can and must finally realize its true potential. I seek your support in this election not just for myself as your candidate but for the vision we all share for a stronger, fairer, and more prosperous nation. Let us come together to, finally, create the Sri Lanka we all deserve.\\nSajith Premadasa\\nLeader\\nSamagi Jana Sandanya (SJS) 29th August 2024\\n \\nA WIN FOR ALL\\nCONTACT :\\nSamagi Jana Balawegaya\\n592, Kotte Road, Sri Jayawardenepura Kotte 10100 Phone: 011 287 0112\\ne-mail : info@sajith.lk\\nWeb : www.sajith.lk\\n \\nCONTENT\\nBUILD A RESILIENT ECONOMY 08\\ny TRANSPARENCY AND ACCOUNTABILITY\\ny MANAGING THE DEBT CRISIS AND THE IMF\\ny MONETARY AND EXCHANGE RATE POLICY\\ny ACHIEVING A REVENUE GROWTH\\ny EXPENDITURE CONTROL\\ny STIMULATING ECONOMIC GROWTH\\ny PUBLIC SECTOR MANAGEMENT AND DIGITALIZATION\\ny ENERGY AND UTILITY REFORMS'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 829}, page_content='Therefore, our manifesto & economic vision is not just about statistical growth but about tangible prosperity in every segment of society. We will create a resilient and inclusive economy, combining the strength of free markets with a deep commitment to equality, to ensure no Sri Lankan is left behind.\\nAnother crucial pillar of our vision is the fight against corruption. Corruption has long been a stain on Sri Lanka and has ultimately led us to bankruptcy, undermining trust in government and robbing our citizens. The future SJS government will root out corruption by embedding transparency and accountability in every aspect of governance with the necessary system reforms.'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 829}, page_content='Therefore, our manifesto & economic vision is not just about statistical growth but about tangible prosperity in every segment of society. We will create a resilient and inclusive economy, combining the strength of free markets with a deep commitment to equality, to ensure no Sri Lankan is left behind.\\nAnother crucial pillar of our vision is the fight against corruption. Corruption has long been a stain on Sri Lanka and has ultimately led us to bankruptcy, undermining trust in government and robbing our citizens. The future SJS government will root out corruption by embedding transparency and accountability in every aspect of governance with the necessary system reforms.'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 829}, page_content='Therefore, our manifesto & economic vision is not just about statistical growth but about tangible prosperity in every segment of society. We will create a resilient and inclusive economy, combining the strength of free markets with a deep commitment to equality, to ensure no Sri Lankan is left behind.\\nAnother crucial pillar of our vision is the fight against corruption. Corruption has long been a stain on Sri Lanka and has ultimately led us to bankruptcy, undermining trust in government and robbing our citizens. The future SJS government will root out corruption by embedding transparency and accountability in every aspect of governance with the necessary system reforms.')],\n", + " 'generation': 'The provided context does not contain specific details about '\n", + " \"Sajith Premadasa's economic plans for the 2019 election. It \"\n", + " 'focuses more on his current vision and manifesto elements for '\n", + " 'the upcoming election in 2024. Thanks for asking!',\n", + " 'question': 'What economic plans did Sajith have for the 2019 election?'}\n", + "'\\n---\\n'\n", + "---TRANSFORM QUERY---\n", + "\"Node 'transform_query':\"\n", + "{ 'documents': [ Document(metadata={'source': '../documents/sajith.txt', 'start_index': 2253}, page_content='Let me end by stating that the SJS is more than just a new alliance; it is a movement for much-needed change, driven by the belief that Sri Lanka can and must finally realize its true potential. I seek your support in this election not just for myself as your candidate but for the vision we all share for a stronger, fairer, and more prosperous nation. Let us come together to, finally, create the Sri Lanka we all deserve.\\nSajith Premadasa\\nLeader\\nSamagi Jana Sandanya (SJS) 29th August 2024\\n \\nA WIN FOR ALL\\nCONTACT :\\nSamagi Jana Balawegaya\\n592, Kotte Road, Sri Jayawardenepura Kotte 10100 Phone: 011 287 0112\\ne-mail : info@sajith.lk\\nWeb : www.sajith.lk\\n \\nCONTENT\\nBUILD A RESILIENT ECONOMY 08\\ny TRANSPARENCY AND ACCOUNTABILITY\\ny MANAGING THE DEBT CRISIS AND THE IMF\\ny MONETARY AND EXCHANGE RATE POLICY\\ny ACHIEVING A REVENUE GROWTH\\ny EXPENDITURE CONTROL\\ny STIMULATING ECONOMIC GROWTH\\ny PUBLIC SECTOR MANAGEMENT AND DIGITALIZATION\\ny ENERGY AND UTILITY REFORMS'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 2253}, page_content='Let me end by stating that the SJS is more than just a new alliance; it is a movement for much-needed change, driven by the belief that Sri Lanka can and must finally realize its true potential. I seek your support in this election not just for myself as your candidate but for the vision we all share for a stronger, fairer, and more prosperous nation. Let us come together to, finally, create the Sri Lanka we all deserve.\\nSajith Premadasa\\nLeader\\nSamagi Jana Sandanya (SJS) 29th August 2024\\n \\nA WIN FOR ALL\\nCONTACT :\\nSamagi Jana Balawegaya\\n592, Kotte Road, Sri Jayawardenepura Kotte 10100 Phone: 011 287 0112\\ne-mail : info@sajith.lk\\nWeb : www.sajith.lk\\n \\nCONTENT\\nBUILD A RESILIENT ECONOMY 08\\ny TRANSPARENCY AND ACCOUNTABILITY\\ny MANAGING THE DEBT CRISIS AND THE IMF\\ny MONETARY AND EXCHANGE RATE POLICY\\ny ACHIEVING A REVENUE GROWTH\\ny EXPENDITURE CONTROL\\ny STIMULATING ECONOMIC GROWTH\\ny PUBLIC SECTOR MANAGEMENT AND DIGITALIZATION\\ny ENERGY AND UTILITY REFORMS'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 2253}, page_content='Let me end by stating that the SJS is more than just a new alliance; it is a movement for much-needed change, driven by the belief that Sri Lanka can and must finally realize its true potential. I seek your support in this election not just for myself as your candidate but for the vision we all share for a stronger, fairer, and more prosperous nation. Let us come together to, finally, create the Sri Lanka we all deserve.\\nSajith Premadasa\\nLeader\\nSamagi Jana Sandanya (SJS) 29th August 2024\\n \\nA WIN FOR ALL\\nCONTACT :\\nSamagi Jana Balawegaya\\n592, Kotte Road, Sri Jayawardenepura Kotte 10100 Phone: 011 287 0112\\ne-mail : info@sajith.lk\\nWeb : www.sajith.lk\\n \\nCONTENT\\nBUILD A RESILIENT ECONOMY 08\\ny TRANSPARENCY AND ACCOUNTABILITY\\ny MANAGING THE DEBT CRISIS AND THE IMF\\ny MONETARY AND EXCHANGE RATE POLICY\\ny ACHIEVING A REVENUE GROWTH\\ny EXPENDITURE CONTROL\\ny STIMULATING ECONOMIC GROWTH\\ny PUBLIC SECTOR MANAGEMENT AND DIGITALIZATION\\ny ENERGY AND UTILITY REFORMS'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 829}, page_content='Therefore, our manifesto & economic vision is not just about statistical growth but about tangible prosperity in every segment of society. We will create a resilient and inclusive economy, combining the strength of free markets with a deep commitment to equality, to ensure no Sri Lankan is left behind.\\nAnother crucial pillar of our vision is the fight against corruption. Corruption has long been a stain on Sri Lanka and has ultimately led us to bankruptcy, undermining trust in government and robbing our citizens. The future SJS government will root out corruption by embedding transparency and accountability in every aspect of governance with the necessary system reforms.'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 829}, page_content='Therefore, our manifesto & economic vision is not just about statistical growth but about tangible prosperity in every segment of society. We will create a resilient and inclusive economy, combining the strength of free markets with a deep commitment to equality, to ensure no Sri Lankan is left behind.\\nAnother crucial pillar of our vision is the fight against corruption. Corruption has long been a stain on Sri Lanka and has ultimately led us to bankruptcy, undermining trust in government and robbing our citizens. The future SJS government will root out corruption by embedding transparency and accountability in every aspect of governance with the necessary system reforms.'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 829}, page_content='Therefore, our manifesto & economic vision is not just about statistical growth but about tangible prosperity in every segment of society. We will create a resilient and inclusive economy, combining the strength of free markets with a deep commitment to equality, to ensure no Sri Lankan is left behind.\\nAnother crucial pillar of our vision is the fight against corruption. Corruption has long been a stain on Sri Lanka and has ultimately led us to bankruptcy, undermining trust in government and robbing our citizens. The future SJS government will root out corruption by embedding transparency and accountability in every aspect of governance with the necessary system reforms.')],\n", + " 'question': \"What were Sajith's economic strategies for the 2019 election?\"}\n", + "'\\n---\\n'\n", + "---RETRIEVE---\n", + "\"Node 'retrieve':\"\n", + "{ 'documents': [ Document(metadata={'source': '../documents/sajith.txt', 'start_index': 2253}, page_content='Let me end by stating that the SJS is more than just a new alliance; it is a movement for much-needed change, driven by the belief that Sri Lanka can and must finally realize its true potential. I seek your support in this election not just for myself as your candidate but for the vision we all share for a stronger, fairer, and more prosperous nation. Let us come together to, finally, create the Sri Lanka we all deserve.\\nSajith Premadasa\\nLeader\\nSamagi Jana Sandanya (SJS) 29th August 2024\\n \\nA WIN FOR ALL\\nCONTACT :\\nSamagi Jana Balawegaya\\n592, Kotte Road, Sri Jayawardenepura Kotte 10100 Phone: 011 287 0112\\ne-mail : info@sajith.lk\\nWeb : www.sajith.lk\\n \\nCONTENT\\nBUILD A RESILIENT ECONOMY 08\\ny TRANSPARENCY AND ACCOUNTABILITY\\ny MANAGING THE DEBT CRISIS AND THE IMF\\ny MONETARY AND EXCHANGE RATE POLICY\\ny ACHIEVING A REVENUE GROWTH\\ny EXPENDITURE CONTROL\\ny STIMULATING ECONOMIC GROWTH\\ny PUBLIC SECTOR MANAGEMENT AND DIGITALIZATION\\ny ENERGY AND UTILITY REFORMS'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 2253}, page_content='Let me end by stating that the SJS is more than just a new alliance; it is a movement for much-needed change, driven by the belief that Sri Lanka can and must finally realize its true potential. I seek your support in this election not just for myself as your candidate but for the vision we all share for a stronger, fairer, and more prosperous nation. Let us come together to, finally, create the Sri Lanka we all deserve.\\nSajith Premadasa\\nLeader\\nSamagi Jana Sandanya (SJS) 29th August 2024\\n \\nA WIN FOR ALL\\nCONTACT :\\nSamagi Jana Balawegaya\\n592, Kotte Road, Sri Jayawardenepura Kotte 10100 Phone: 011 287 0112\\ne-mail : info@sajith.lk\\nWeb : www.sajith.lk\\n \\nCONTENT\\nBUILD A RESILIENT ECONOMY 08\\ny TRANSPARENCY AND ACCOUNTABILITY\\ny MANAGING THE DEBT CRISIS AND THE IMF\\ny MONETARY AND EXCHANGE RATE POLICY\\ny ACHIEVING A REVENUE GROWTH\\ny EXPENDITURE CONTROL\\ny STIMULATING ECONOMIC GROWTH\\ny PUBLIC SECTOR MANAGEMENT AND DIGITALIZATION\\ny ENERGY AND UTILITY REFORMS'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 2253}, page_content='Let me end by stating that the SJS is more than just a new alliance; it is a movement for much-needed change, driven by the belief that Sri Lanka can and must finally realize its true potential. I seek your support in this election not just for myself as your candidate but for the vision we all share for a stronger, fairer, and more prosperous nation. Let us come together to, finally, create the Sri Lanka we all deserve.\\nSajith Premadasa\\nLeader\\nSamagi Jana Sandanya (SJS) 29th August 2024\\n \\nA WIN FOR ALL\\nCONTACT :\\nSamagi Jana Balawegaya\\n592, Kotte Road, Sri Jayawardenepura Kotte 10100 Phone: 011 287 0112\\ne-mail : info@sajith.lk\\nWeb : www.sajith.lk\\n \\nCONTENT\\nBUILD A RESILIENT ECONOMY 08\\ny TRANSPARENCY AND ACCOUNTABILITY\\ny MANAGING THE DEBT CRISIS AND THE IMF\\ny MONETARY AND EXCHANGE RATE POLICY\\ny ACHIEVING A REVENUE GROWTH\\ny EXPENDITURE CONTROL\\ny STIMULATING ECONOMIC GROWTH\\ny PUBLIC SECTOR MANAGEMENT AND DIGITALIZATION\\ny ENERGY AND UTILITY REFORMS'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 829}, page_content='Therefore, our manifesto & economic vision is not just about statistical growth but about tangible prosperity in every segment of society. We will create a resilient and inclusive economy, combining the strength of free markets with a deep commitment to equality, to ensure no Sri Lankan is left behind.\\nAnother crucial pillar of our vision is the fight against corruption. Corruption has long been a stain on Sri Lanka and has ultimately led us to bankruptcy, undermining trust in government and robbing our citizens. The future SJS government will root out corruption by embedding transparency and accountability in every aspect of governance with the necessary system reforms.'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 829}, page_content='Therefore, our manifesto & economic vision is not just about statistical growth but about tangible prosperity in every segment of society. We will create a resilient and inclusive economy, combining the strength of free markets with a deep commitment to equality, to ensure no Sri Lankan is left behind.\\nAnother crucial pillar of our vision is the fight against corruption. Corruption has long been a stain on Sri Lanka and has ultimately led us to bankruptcy, undermining trust in government and robbing our citizens. The future SJS government will root out corruption by embedding transparency and accountability in every aspect of governance with the necessary system reforms.'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 829}, page_content='Therefore, our manifesto & economic vision is not just about statistical growth but about tangible prosperity in every segment of society. We will create a resilient and inclusive economy, combining the strength of free markets with a deep commitment to equality, to ensure no Sri Lankan is left behind.\\nAnother crucial pillar of our vision is the fight against corruption. Corruption has long been a stain on Sri Lanka and has ultimately led us to bankruptcy, undermining trust in government and robbing our citizens. The future SJS government will root out corruption by embedding transparency and accountability in every aspect of governance with the necessary system reforms.')],\n", + " 'question': \"What were Sajith's economic strategies for the 2019 election?\"}\n", + "'\\n---\\n'\n", + "---CHECK DOCUMENT RELEVANCE TO QUESTION---\n", + "---GRADE: DOCUMENT RELEVANT---\n", + "---GRADE: DOCUMENT RELEVANT---\n", + "---GRADE: DOCUMENT RELEVANT---\n", + "---GRADE: DOCUMENT RELEVANT---\n", + "---GRADE: DOCUMENT RELEVANT---\n", + "---GRADE: DOCUMENT RELEVANT---\n", + "---ASSESS GRADED DOCUMENTS---\n", + "---DECISION: GENERATE---\n", + "\"Node 'grade_documents':\"\n", + "{ 'documents': [ Document(metadata={'source': '../documents/sajith.txt', 'start_index': 2253}, page_content='Let me end by stating that the SJS is more than just a new alliance; it is a movement for much-needed change, driven by the belief that Sri Lanka can and must finally realize its true potential. I seek your support in this election not just for myself as your candidate but for the vision we all share for a stronger, fairer, and more prosperous nation. Let us come together to, finally, create the Sri Lanka we all deserve.\\nSajith Premadasa\\nLeader\\nSamagi Jana Sandanya (SJS) 29th August 2024\\n \\nA WIN FOR ALL\\nCONTACT :\\nSamagi Jana Balawegaya\\n592, Kotte Road, Sri Jayawardenepura Kotte 10100 Phone: 011 287 0112\\ne-mail : info@sajith.lk\\nWeb : www.sajith.lk\\n \\nCONTENT\\nBUILD A RESILIENT ECONOMY 08\\ny TRANSPARENCY AND ACCOUNTABILITY\\ny MANAGING THE DEBT CRISIS AND THE IMF\\ny MONETARY AND EXCHANGE RATE POLICY\\ny ACHIEVING A REVENUE GROWTH\\ny EXPENDITURE CONTROL\\ny STIMULATING ECONOMIC GROWTH\\ny PUBLIC SECTOR MANAGEMENT AND DIGITALIZATION\\ny ENERGY AND UTILITY REFORMS'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 2253}, page_content='Let me end by stating that the SJS is more than just a new alliance; it is a movement for much-needed change, driven by the belief that Sri Lanka can and must finally realize its true potential. I seek your support in this election not just for myself as your candidate but for the vision we all share for a stronger, fairer, and more prosperous nation. Let us come together to, finally, create the Sri Lanka we all deserve.\\nSajith Premadasa\\nLeader\\nSamagi Jana Sandanya (SJS) 29th August 2024\\n \\nA WIN FOR ALL\\nCONTACT :\\nSamagi Jana Balawegaya\\n592, Kotte Road, Sri Jayawardenepura Kotte 10100 Phone: 011 287 0112\\ne-mail : info@sajith.lk\\nWeb : www.sajith.lk\\n \\nCONTENT\\nBUILD A RESILIENT ECONOMY 08\\ny TRANSPARENCY AND ACCOUNTABILITY\\ny MANAGING THE DEBT CRISIS AND THE IMF\\ny MONETARY AND EXCHANGE RATE POLICY\\ny ACHIEVING A REVENUE GROWTH\\ny EXPENDITURE CONTROL\\ny STIMULATING ECONOMIC GROWTH\\ny PUBLIC SECTOR MANAGEMENT AND DIGITALIZATION\\ny ENERGY AND UTILITY REFORMS'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 2253}, page_content='Let me end by stating that the SJS is more than just a new alliance; it is a movement for much-needed change, driven by the belief that Sri Lanka can and must finally realize its true potential. I seek your support in this election not just for myself as your candidate but for the vision we all share for a stronger, fairer, and more prosperous nation. Let us come together to, finally, create the Sri Lanka we all deserve.\\nSajith Premadasa\\nLeader\\nSamagi Jana Sandanya (SJS) 29th August 2024\\n \\nA WIN FOR ALL\\nCONTACT :\\nSamagi Jana Balawegaya\\n592, Kotte Road, Sri Jayawardenepura Kotte 10100 Phone: 011 287 0112\\ne-mail : info@sajith.lk\\nWeb : www.sajith.lk\\n \\nCONTENT\\nBUILD A RESILIENT ECONOMY 08\\ny TRANSPARENCY AND ACCOUNTABILITY\\ny MANAGING THE DEBT CRISIS AND THE IMF\\ny MONETARY AND EXCHANGE RATE POLICY\\ny ACHIEVING A REVENUE GROWTH\\ny EXPENDITURE CONTROL\\ny STIMULATING ECONOMIC GROWTH\\ny PUBLIC SECTOR MANAGEMENT AND DIGITALIZATION\\ny ENERGY AND UTILITY REFORMS'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 829}, page_content='Therefore, our manifesto & economic vision is not just about statistical growth but about tangible prosperity in every segment of society. We will create a resilient and inclusive economy, combining the strength of free markets with a deep commitment to equality, to ensure no Sri Lankan is left behind.\\nAnother crucial pillar of our vision is the fight against corruption. Corruption has long been a stain on Sri Lanka and has ultimately led us to bankruptcy, undermining trust in government and robbing our citizens. The future SJS government will root out corruption by embedding transparency and accountability in every aspect of governance with the necessary system reforms.'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 829}, page_content='Therefore, our manifesto & economic vision is not just about statistical growth but about tangible prosperity in every segment of society. We will create a resilient and inclusive economy, combining the strength of free markets with a deep commitment to equality, to ensure no Sri Lankan is left behind.\\nAnother crucial pillar of our vision is the fight against corruption. Corruption has long been a stain on Sri Lanka and has ultimately led us to bankruptcy, undermining trust in government and robbing our citizens. The future SJS government will root out corruption by embedding transparency and accountability in every aspect of governance with the necessary system reforms.'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 829}, page_content='Therefore, our manifesto & economic vision is not just about statistical growth but about tangible prosperity in every segment of society. We will create a resilient and inclusive economy, combining the strength of free markets with a deep commitment to equality, to ensure no Sri Lankan is left behind.\\nAnother crucial pillar of our vision is the fight against corruption. Corruption has long been a stain on Sri Lanka and has ultimately led us to bankruptcy, undermining trust in government and robbing our citizens. The future SJS government will root out corruption by embedding transparency and accountability in every aspect of governance with the necessary system reforms.')],\n", + " 'question': \"What were Sajith's economic strategies for the 2019 election?\"}\n", + "'\\n---\\n'\n", + "---GENERATE---\n", + "---CHECK HALLUCINATIONS---\n", + "---DECISION: GENERATION IS NOT GROUNDED IN DOCUMENTS, RE-TRY---\n", + "\"Node 'generate':\"\n", + "{ 'documents': [ Document(metadata={'source': '../documents/sajith.txt', 'start_index': 2253}, page_content='Let me end by stating that the SJS is more than just a new alliance; it is a movement for much-needed change, driven by the belief that Sri Lanka can and must finally realize its true potential. I seek your support in this election not just for myself as your candidate but for the vision we all share for a stronger, fairer, and more prosperous nation. Let us come together to, finally, create the Sri Lanka we all deserve.\\nSajith Premadasa\\nLeader\\nSamagi Jana Sandanya (SJS) 29th August 2024\\n \\nA WIN FOR ALL\\nCONTACT :\\nSamagi Jana Balawegaya\\n592, Kotte Road, Sri Jayawardenepura Kotte 10100 Phone: 011 287 0112\\ne-mail : info@sajith.lk\\nWeb : www.sajith.lk\\n \\nCONTENT\\nBUILD A RESILIENT ECONOMY 08\\ny TRANSPARENCY AND ACCOUNTABILITY\\ny MANAGING THE DEBT CRISIS AND THE IMF\\ny MONETARY AND EXCHANGE RATE POLICY\\ny ACHIEVING A REVENUE GROWTH\\ny EXPENDITURE CONTROL\\ny STIMULATING ECONOMIC GROWTH\\ny PUBLIC SECTOR MANAGEMENT AND DIGITALIZATION\\ny ENERGY AND UTILITY REFORMS'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 2253}, page_content='Let me end by stating that the SJS is more than just a new alliance; it is a movement for much-needed change, driven by the belief that Sri Lanka can and must finally realize its true potential. I seek your support in this election not just for myself as your candidate but for the vision we all share for a stronger, fairer, and more prosperous nation. Let us come together to, finally, create the Sri Lanka we all deserve.\\nSajith Premadasa\\nLeader\\nSamagi Jana Sandanya (SJS) 29th August 2024\\n \\nA WIN FOR ALL\\nCONTACT :\\nSamagi Jana Balawegaya\\n592, Kotte Road, Sri Jayawardenepura Kotte 10100 Phone: 011 287 0112\\ne-mail : info@sajith.lk\\nWeb : www.sajith.lk\\n \\nCONTENT\\nBUILD A RESILIENT ECONOMY 08\\ny TRANSPARENCY AND ACCOUNTABILITY\\ny MANAGING THE DEBT CRISIS AND THE IMF\\ny MONETARY AND EXCHANGE RATE POLICY\\ny ACHIEVING A REVENUE GROWTH\\ny EXPENDITURE CONTROL\\ny STIMULATING ECONOMIC GROWTH\\ny PUBLIC SECTOR MANAGEMENT AND DIGITALIZATION\\ny ENERGY AND UTILITY REFORMS'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 2253}, page_content='Let me end by stating that the SJS is more than just a new alliance; it is a movement for much-needed change, driven by the belief that Sri Lanka can and must finally realize its true potential. I seek your support in this election not just for myself as your candidate but for the vision we all share for a stronger, fairer, and more prosperous nation. Let us come together to, finally, create the Sri Lanka we all deserve.\\nSajith Premadasa\\nLeader\\nSamagi Jana Sandanya (SJS) 29th August 2024\\n \\nA WIN FOR ALL\\nCONTACT :\\nSamagi Jana Balawegaya\\n592, Kotte Road, Sri Jayawardenepura Kotte 10100 Phone: 011 287 0112\\ne-mail : info@sajith.lk\\nWeb : www.sajith.lk\\n \\nCONTENT\\nBUILD A RESILIENT ECONOMY 08\\ny TRANSPARENCY AND ACCOUNTABILITY\\ny MANAGING THE DEBT CRISIS AND THE IMF\\ny MONETARY AND EXCHANGE RATE POLICY\\ny ACHIEVING A REVENUE GROWTH\\ny EXPENDITURE CONTROL\\ny STIMULATING ECONOMIC GROWTH\\ny PUBLIC SECTOR MANAGEMENT AND DIGITALIZATION\\ny ENERGY AND UTILITY REFORMS'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 829}, page_content='Therefore, our manifesto & economic vision is not just about statistical growth but about tangible prosperity in every segment of society. We will create a resilient and inclusive economy, combining the strength of free markets with a deep commitment to equality, to ensure no Sri Lankan is left behind.\\nAnother crucial pillar of our vision is the fight against corruption. Corruption has long been a stain on Sri Lanka and has ultimately led us to bankruptcy, undermining trust in government and robbing our citizens. The future SJS government will root out corruption by embedding transparency and accountability in every aspect of governance with the necessary system reforms.'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 829}, page_content='Therefore, our manifesto & economic vision is not just about statistical growth but about tangible prosperity in every segment of society. We will create a resilient and inclusive economy, combining the strength of free markets with a deep commitment to equality, to ensure no Sri Lankan is left behind.\\nAnother crucial pillar of our vision is the fight against corruption. Corruption has long been a stain on Sri Lanka and has ultimately led us to bankruptcy, undermining trust in government and robbing our citizens. The future SJS government will root out corruption by embedding transparency and accountability in every aspect of governance with the necessary system reforms.'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 829}, page_content='Therefore, our manifesto & economic vision is not just about statistical growth but about tangible prosperity in every segment of society. We will create a resilient and inclusive economy, combining the strength of free markets with a deep commitment to equality, to ensure no Sri Lankan is left behind.\\nAnother crucial pillar of our vision is the fight against corruption. Corruption has long been a stain on Sri Lanka and has ultimately led us to bankruptcy, undermining trust in government and robbing our citizens. The future SJS government will root out corruption by embedding transparency and accountability in every aspect of governance with the necessary system reforms.')],\n", + " 'generation': \"I don't know. Thanks for asking!\",\n", + " 'question': \"What were Sajith's economic strategies for the 2019 election?\"}\n", + "'\\n---\\n'\n", + "---GENERATE---\n", + "---CHECK HALLUCINATIONS---\n", + "---DECISION: GENERATION IS NOT GROUNDED IN DOCUMENTS, RE-TRY---\n", + "\"Node 'generate':\"\n", + "{ 'documents': [ Document(metadata={'source': '../documents/sajith.txt', 'start_index': 2253}, page_content='Let me end by stating that the SJS is more than just a new alliance; it is a movement for much-needed change, driven by the belief that Sri Lanka can and must finally realize its true potential. I seek your support in this election not just for myself as your candidate but for the vision we all share for a stronger, fairer, and more prosperous nation. Let us come together to, finally, create the Sri Lanka we all deserve.\\nSajith Premadasa\\nLeader\\nSamagi Jana Sandanya (SJS) 29th August 2024\\n \\nA WIN FOR ALL\\nCONTACT :\\nSamagi Jana Balawegaya\\n592, Kotte Road, Sri Jayawardenepura Kotte 10100 Phone: 011 287 0112\\ne-mail : info@sajith.lk\\nWeb : www.sajith.lk\\n \\nCONTENT\\nBUILD A RESILIENT ECONOMY 08\\ny TRANSPARENCY AND ACCOUNTABILITY\\ny MANAGING THE DEBT CRISIS AND THE IMF\\ny MONETARY AND EXCHANGE RATE POLICY\\ny ACHIEVING A REVENUE GROWTH\\ny EXPENDITURE CONTROL\\ny STIMULATING ECONOMIC GROWTH\\ny PUBLIC SECTOR MANAGEMENT AND DIGITALIZATION\\ny ENERGY AND UTILITY REFORMS'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 2253}, page_content='Let me end by stating that the SJS is more than just a new alliance; it is a movement for much-needed change, driven by the belief that Sri Lanka can and must finally realize its true potential. I seek your support in this election not just for myself as your candidate but for the vision we all share for a stronger, fairer, and more prosperous nation. Let us come together to, finally, create the Sri Lanka we all deserve.\\nSajith Premadasa\\nLeader\\nSamagi Jana Sandanya (SJS) 29th August 2024\\n \\nA WIN FOR ALL\\nCONTACT :\\nSamagi Jana Balawegaya\\n592, Kotte Road, Sri Jayawardenepura Kotte 10100 Phone: 011 287 0112\\ne-mail : info@sajith.lk\\nWeb : www.sajith.lk\\n \\nCONTENT\\nBUILD A RESILIENT ECONOMY 08\\ny TRANSPARENCY AND ACCOUNTABILITY\\ny MANAGING THE DEBT CRISIS AND THE IMF\\ny MONETARY AND EXCHANGE RATE POLICY\\ny ACHIEVING A REVENUE GROWTH\\ny EXPENDITURE CONTROL\\ny STIMULATING ECONOMIC GROWTH\\ny PUBLIC SECTOR MANAGEMENT AND DIGITALIZATION\\ny ENERGY AND UTILITY REFORMS'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 2253}, page_content='Let me end by stating that the SJS is more than just a new alliance; it is a movement for much-needed change, driven by the belief that Sri Lanka can and must finally realize its true potential. I seek your support in this election not just for myself as your candidate but for the vision we all share for a stronger, fairer, and more prosperous nation. Let us come together to, finally, create the Sri Lanka we all deserve.\\nSajith Premadasa\\nLeader\\nSamagi Jana Sandanya (SJS) 29th August 2024\\n \\nA WIN FOR ALL\\nCONTACT :\\nSamagi Jana Balawegaya\\n592, Kotte Road, Sri Jayawardenepura Kotte 10100 Phone: 011 287 0112\\ne-mail : info@sajith.lk\\nWeb : www.sajith.lk\\n \\nCONTENT\\nBUILD A RESILIENT ECONOMY 08\\ny TRANSPARENCY AND ACCOUNTABILITY\\ny MANAGING THE DEBT CRISIS AND THE IMF\\ny MONETARY AND EXCHANGE RATE POLICY\\ny ACHIEVING A REVENUE GROWTH\\ny EXPENDITURE CONTROL\\ny STIMULATING ECONOMIC GROWTH\\ny PUBLIC SECTOR MANAGEMENT AND DIGITALIZATION\\ny ENERGY AND UTILITY REFORMS'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 829}, page_content='Therefore, our manifesto & economic vision is not just about statistical growth but about tangible prosperity in every segment of society. We will create a resilient and inclusive economy, combining the strength of free markets with a deep commitment to equality, to ensure no Sri Lankan is left behind.\\nAnother crucial pillar of our vision is the fight against corruption. Corruption has long been a stain on Sri Lanka and has ultimately led us to bankruptcy, undermining trust in government and robbing our citizens. The future SJS government will root out corruption by embedding transparency and accountability in every aspect of governance with the necessary system reforms.'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 829}, page_content='Therefore, our manifesto & economic vision is not just about statistical growth but about tangible prosperity in every segment of society. We will create a resilient and inclusive economy, combining the strength of free markets with a deep commitment to equality, to ensure no Sri Lankan is left behind.\\nAnother crucial pillar of our vision is the fight against corruption. Corruption has long been a stain on Sri Lanka and has ultimately led us to bankruptcy, undermining trust in government and robbing our citizens. The future SJS government will root out corruption by embedding transparency and accountability in every aspect of governance with the necessary system reforms.'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 829}, page_content='Therefore, our manifesto & economic vision is not just about statistical growth but about tangible prosperity in every segment of society. We will create a resilient and inclusive economy, combining the strength of free markets with a deep commitment to equality, to ensure no Sri Lankan is left behind.\\nAnother crucial pillar of our vision is the fight against corruption. Corruption has long been a stain on Sri Lanka and has ultimately led us to bankruptcy, undermining trust in government and robbing our citizens. The future SJS government will root out corruption by embedding transparency and accountability in every aspect of governance with the necessary system reforms.')],\n", + " 'generation': \"I don't know. Thanks for asking!\",\n", + " 'question': \"What were Sajith's economic strategies for the 2019 election?\"}\n", + "'\\n---\\n'\n", + "---GENERATE---\n", + "---CHECK HALLUCINATIONS---\n", + "---DECISION: GENERATION IS NOT GROUNDED IN DOCUMENTS, RE-TRY---\n", + "\"Node 'generate':\"\n", + "{ 'documents': [ Document(metadata={'source': '../documents/sajith.txt', 'start_index': 2253}, page_content='Let me end by stating that the SJS is more than just a new alliance; it is a movement for much-needed change, driven by the belief that Sri Lanka can and must finally realize its true potential. I seek your support in this election not just for myself as your candidate but for the vision we all share for a stronger, fairer, and more prosperous nation. Let us come together to, finally, create the Sri Lanka we all deserve.\\nSajith Premadasa\\nLeader\\nSamagi Jana Sandanya (SJS) 29th August 2024\\n \\nA WIN FOR ALL\\nCONTACT :\\nSamagi Jana Balawegaya\\n592, Kotte Road, Sri Jayawardenepura Kotte 10100 Phone: 011 287 0112\\ne-mail : info@sajith.lk\\nWeb : www.sajith.lk\\n \\nCONTENT\\nBUILD A RESILIENT ECONOMY 08\\ny TRANSPARENCY AND ACCOUNTABILITY\\ny MANAGING THE DEBT CRISIS AND THE IMF\\ny MONETARY AND EXCHANGE RATE POLICY\\ny ACHIEVING A REVENUE GROWTH\\ny EXPENDITURE CONTROL\\ny STIMULATING ECONOMIC GROWTH\\ny PUBLIC SECTOR MANAGEMENT AND DIGITALIZATION\\ny ENERGY AND UTILITY REFORMS'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 2253}, page_content='Let me end by stating that the SJS is more than just a new alliance; it is a movement for much-needed change, driven by the belief that Sri Lanka can and must finally realize its true potential. I seek your support in this election not just for myself as your candidate but for the vision we all share for a stronger, fairer, and more prosperous nation. Let us come together to, finally, create the Sri Lanka we all deserve.\\nSajith Premadasa\\nLeader\\nSamagi Jana Sandanya (SJS) 29th August 2024\\n \\nA WIN FOR ALL\\nCONTACT :\\nSamagi Jana Balawegaya\\n592, Kotte Road, Sri Jayawardenepura Kotte 10100 Phone: 011 287 0112\\ne-mail : info@sajith.lk\\nWeb : www.sajith.lk\\n \\nCONTENT\\nBUILD A RESILIENT ECONOMY 08\\ny TRANSPARENCY AND ACCOUNTABILITY\\ny MANAGING THE DEBT CRISIS AND THE IMF\\ny MONETARY AND EXCHANGE RATE POLICY\\ny ACHIEVING A REVENUE GROWTH\\ny EXPENDITURE CONTROL\\ny STIMULATING ECONOMIC GROWTH\\ny PUBLIC SECTOR MANAGEMENT AND DIGITALIZATION\\ny ENERGY AND UTILITY REFORMS'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 2253}, page_content='Let me end by stating that the SJS is more than just a new alliance; it is a movement for much-needed change, driven by the belief that Sri Lanka can and must finally realize its true potential. I seek your support in this election not just for myself as your candidate but for the vision we all share for a stronger, fairer, and more prosperous nation. Let us come together to, finally, create the Sri Lanka we all deserve.\\nSajith Premadasa\\nLeader\\nSamagi Jana Sandanya (SJS) 29th August 2024\\n \\nA WIN FOR ALL\\nCONTACT :\\nSamagi Jana Balawegaya\\n592, Kotte Road, Sri Jayawardenepura Kotte 10100 Phone: 011 287 0112\\ne-mail : info@sajith.lk\\nWeb : www.sajith.lk\\n \\nCONTENT\\nBUILD A RESILIENT ECONOMY 08\\ny TRANSPARENCY AND ACCOUNTABILITY\\ny MANAGING THE DEBT CRISIS AND THE IMF\\ny MONETARY AND EXCHANGE RATE POLICY\\ny ACHIEVING A REVENUE GROWTH\\ny EXPENDITURE CONTROL\\ny STIMULATING ECONOMIC GROWTH\\ny PUBLIC SECTOR MANAGEMENT AND DIGITALIZATION\\ny ENERGY AND UTILITY REFORMS'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 829}, page_content='Therefore, our manifesto & economic vision is not just about statistical growth but about tangible prosperity in every segment of society. We will create a resilient and inclusive economy, combining the strength of free markets with a deep commitment to equality, to ensure no Sri Lankan is left behind.\\nAnother crucial pillar of our vision is the fight against corruption. Corruption has long been a stain on Sri Lanka and has ultimately led us to bankruptcy, undermining trust in government and robbing our citizens. The future SJS government will root out corruption by embedding transparency and accountability in every aspect of governance with the necessary system reforms.'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 829}, page_content='Therefore, our manifesto & economic vision is not just about statistical growth but about tangible prosperity in every segment of society. We will create a resilient and inclusive economy, combining the strength of free markets with a deep commitment to equality, to ensure no Sri Lankan is left behind.\\nAnother crucial pillar of our vision is the fight against corruption. Corruption has long been a stain on Sri Lanka and has ultimately led us to bankruptcy, undermining trust in government and robbing our citizens. The future SJS government will root out corruption by embedding transparency and accountability in every aspect of governance with the necessary system reforms.'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 829}, page_content='Therefore, our manifesto & economic vision is not just about statistical growth but about tangible prosperity in every segment of society. We will create a resilient and inclusive economy, combining the strength of free markets with a deep commitment to equality, to ensure no Sri Lankan is left behind.\\nAnother crucial pillar of our vision is the fight against corruption. Corruption has long been a stain on Sri Lanka and has ultimately led us to bankruptcy, undermining trust in government and robbing our citizens. The future SJS government will root out corruption by embedding transparency and accountability in every aspect of governance with the necessary system reforms.')],\n", + " 'generation': \"I don't know. Thanks for asking!\",\n", + " 'question': \"What were Sajith's economic strategies for the 2019 election?\"}\n", + "'\\n---\\n'\n", + "---GENERATE---\n", + "---CHECK HALLUCINATIONS---\n", + "---DECISION: GENERATION IS NOT GROUNDED IN DOCUMENTS, RE-TRY---\n", + "\"Node 'generate':\"\n", + "{ 'documents': [ Document(metadata={'source': '../documents/sajith.txt', 'start_index': 2253}, page_content='Let me end by stating that the SJS is more than just a new alliance; it is a movement for much-needed change, driven by the belief that Sri Lanka can and must finally realize its true potential. I seek your support in this election not just for myself as your candidate but for the vision we all share for a stronger, fairer, and more prosperous nation. Let us come together to, finally, create the Sri Lanka we all deserve.\\nSajith Premadasa\\nLeader\\nSamagi Jana Sandanya (SJS) 29th August 2024\\n \\nA WIN FOR ALL\\nCONTACT :\\nSamagi Jana Balawegaya\\n592, Kotte Road, Sri Jayawardenepura Kotte 10100 Phone: 011 287 0112\\ne-mail : info@sajith.lk\\nWeb : www.sajith.lk\\n \\nCONTENT\\nBUILD A RESILIENT ECONOMY 08\\ny TRANSPARENCY AND ACCOUNTABILITY\\ny MANAGING THE DEBT CRISIS AND THE IMF\\ny MONETARY AND EXCHANGE RATE POLICY\\ny ACHIEVING A REVENUE GROWTH\\ny EXPENDITURE CONTROL\\ny STIMULATING ECONOMIC GROWTH\\ny PUBLIC SECTOR MANAGEMENT AND DIGITALIZATION\\ny ENERGY AND UTILITY REFORMS'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 2253}, page_content='Let me end by stating that the SJS is more than just a new alliance; it is a movement for much-needed change, driven by the belief that Sri Lanka can and must finally realize its true potential. I seek your support in this election not just for myself as your candidate but for the vision we all share for a stronger, fairer, and more prosperous nation. Let us come together to, finally, create the Sri Lanka we all deserve.\\nSajith Premadasa\\nLeader\\nSamagi Jana Sandanya (SJS) 29th August 2024\\n \\nA WIN FOR ALL\\nCONTACT :\\nSamagi Jana Balawegaya\\n592, Kotte Road, Sri Jayawardenepura Kotte 10100 Phone: 011 287 0112\\ne-mail : info@sajith.lk\\nWeb : www.sajith.lk\\n \\nCONTENT\\nBUILD A RESILIENT ECONOMY 08\\ny TRANSPARENCY AND ACCOUNTABILITY\\ny MANAGING THE DEBT CRISIS AND THE IMF\\ny MONETARY AND EXCHANGE RATE POLICY\\ny ACHIEVING A REVENUE GROWTH\\ny EXPENDITURE CONTROL\\ny STIMULATING ECONOMIC GROWTH\\ny PUBLIC SECTOR MANAGEMENT AND DIGITALIZATION\\ny ENERGY AND UTILITY REFORMS'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 2253}, page_content='Let me end by stating that the SJS is more than just a new alliance; it is a movement for much-needed change, driven by the belief that Sri Lanka can and must finally realize its true potential. I seek your support in this election not just for myself as your candidate but for the vision we all share for a stronger, fairer, and more prosperous nation. Let us come together to, finally, create the Sri Lanka we all deserve.\\nSajith Premadasa\\nLeader\\nSamagi Jana Sandanya (SJS) 29th August 2024\\n \\nA WIN FOR ALL\\nCONTACT :\\nSamagi Jana Balawegaya\\n592, Kotte Road, Sri Jayawardenepura Kotte 10100 Phone: 011 287 0112\\ne-mail : info@sajith.lk\\nWeb : www.sajith.lk\\n \\nCONTENT\\nBUILD A RESILIENT ECONOMY 08\\ny TRANSPARENCY AND ACCOUNTABILITY\\ny MANAGING THE DEBT CRISIS AND THE IMF\\ny MONETARY AND EXCHANGE RATE POLICY\\ny ACHIEVING A REVENUE GROWTH\\ny EXPENDITURE CONTROL\\ny STIMULATING ECONOMIC GROWTH\\ny PUBLIC SECTOR MANAGEMENT AND DIGITALIZATION\\ny ENERGY AND UTILITY REFORMS'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 829}, page_content='Therefore, our manifesto & economic vision is not just about statistical growth but about tangible prosperity in every segment of society. We will create a resilient and inclusive economy, combining the strength of free markets with a deep commitment to equality, to ensure no Sri Lankan is left behind.\\nAnother crucial pillar of our vision is the fight against corruption. Corruption has long been a stain on Sri Lanka and has ultimately led us to bankruptcy, undermining trust in government and robbing our citizens. The future SJS government will root out corruption by embedding transparency and accountability in every aspect of governance with the necessary system reforms.'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 829}, page_content='Therefore, our manifesto & economic vision is not just about statistical growth but about tangible prosperity in every segment of society. We will create a resilient and inclusive economy, combining the strength of free markets with a deep commitment to equality, to ensure no Sri Lankan is left behind.\\nAnother crucial pillar of our vision is the fight against corruption. Corruption has long been a stain on Sri Lanka and has ultimately led us to bankruptcy, undermining trust in government and robbing our citizens. The future SJS government will root out corruption by embedding transparency and accountability in every aspect of governance with the necessary system reforms.'),\n", + " Document(metadata={'source': '../documents/sajith.txt', 'start_index': 829}, page_content='Therefore, our manifesto & economic vision is not just about statistical growth but about tangible prosperity in every segment of society. We will create a resilient and inclusive economy, combining the strength of free markets with a deep commitment to equality, to ensure no Sri Lankan is left behind.\\nAnother crucial pillar of our vision is the fight against corruption. Corruption has long been a stain on Sri Lanka and has ultimately led us to bankruptcy, undermining trust in government and robbing our citizens. The future SJS government will root out corruption by embedding transparency and accountability in every aspect of governance with the necessary system reforms.')],\n", + " 'generation': \"I don't know. Thanks for asking!\",\n", + " 'question': \"What were Sajith's economic strategies for the 2019 election?\"}\n", + "'\\n---\\n'\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ "\n", - "In the last election in 2019, Sajith Premadasa planned to revive tourism, boost exports, and attract direct foreign investment to strengthen the economy. His proposals aimed to address the economic challenges facing Sri Lanka. Thanks for asking!\n" + "KeyboardInterrupt\n", + "\n" ] } ], @@ -723,13 +1045,13 @@ "for output in app.stream(inputs):\n", " for key, value in output.items():\n", " # Node\n", - " print(f\"Node '{key}':\")\n", + " pprint(f\"Node '{key}':\")\n", " # Optional: print full state at each node\n", - " # pprint.pprint(value[\"keys\"], indent=2, width=80, depth=None)\n", - " print(\"\\n---\\n\")\n", + " pprint(value, indent=2, width=80, depth=None)\n", + " pprint(\"\\n---\\n\")\n", "\n", "# Final generation\n", - "print(value[\"generation\"])" + "pprint(value[\"generation\"])" ] }, { diff --git a/graph_image.png b/graph_image.png new file mode 100644 index 0000000000000000000000000000000000000000..53b265954b3fa74fa84aaa609991032e71286fd4 GIT binary patch literal 25398 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 Y`KxO8XVLIK694~Q%Ju&Xo?jFH4;70ph5!Hn literal 0 HcmV?d00001 diff --git a/main.py b/main.py new file mode 100644 index 0000000..d0ae69e --- /dev/null +++ b/main.py @@ -0,0 +1,29 @@ +from fastapi import FastAPI +from RAG.graph import app as rag_app + +app = FastAPI() + +from dotenv import load_dotenv + +load_dotenv() + +@app.get("/") +async def test(): + from pprint import pprint + + # Run + inputs = { + "question": "What is the differnce between sajith premadasa's actions for the health sector in this election and previous 2019 election?" + } + + for output in rag_app.stream(inputs): + for key, value in output.items(): + # Node + pprint(f"Node '{key}':") + # Optional: print full state at each node + pprint(value, indent=2, width=80, depth=None) + pprint("\n---\n") + + # Final generation + pprint(value["generation"]) + return value \ No newline at end of file From b0f54a03711345b50f7eb98548553766923f0871 Mon Sep 17 00:00:00 2001 From: lakshith Date: Mon, 16 Sep 2024 21:57:59 +0530 Subject: [PATCH 02/11] handle multiple candidates --- RAG/agents/extractor.py | 23 ++++++++++++++++++----- RAG/agents/generate.py | 24 ++++++++++++++++++++---- RAG/edges/generation_grader.py | 2 +- RAG/graph.py | 1 - RAG/graph_state.py | 8 ++++++-- RAG/nodes/extract_queries.py | 4 +++- RAG/nodes/generate.py | 18 ++++++++++++------ RAG/nodes/retrieve.py | 15 +++++++++++---- RAG/nodes/transform.py | 6 ++---- RAG/nodes/web_search.py | 3 +++ RAG/tools/vectore_store_retriever.py | 7 ++++--- main.py | 4 ++-- 12 files changed, 82 insertions(+), 33 deletions(-) diff --git a/RAG/agents/extractor.py b/RAG/agents/extractor.py index 35c8ed5..a566d71 100644 --- a/RAG/agents/extractor.py +++ b/RAG/agents/extractor.py @@ -11,9 +11,17 @@ class ExtractQuery(BaseModel): """Route a user query to the relevant datasources with subquestions.""" - vector_search_query: str = Field( + namal_vector_search_query: str = Field( ..., - description="The query to search the vector store.", + description="The query to search the vector store of namal.", + ) + ranil_vector_search_query: str = Field( + ..., + description="The query to search the vector store of ranil.", + ) + sajith_vector_search_query: str = Field( + ..., + description="The query to search the vector store of sajith.", ) web_search_query: str = Field( ..., @@ -25,15 +33,20 @@ class ExtractQuery(BaseModel): # Prompt system = """You are an expert at routing a user question to a vectorstore or web search. -The vectorstore contains documents related to Manifests of political candidate Sajith Premadasa. +There are three vectorstores. One contains documents related to Manifests of political candidate Sajith Premadasa. +Another contains documents related to Manifests of political candidate Namal Rajapaksa. +The third contains documents related to Manifests of political candidate Ranil Wickramasinghe. + for an example, what this candidate do for education sector, health sector etc is on the vectorstore. And also their plans for the future of the country is on the vectorstore. -If the question involves something about sajith's policies in a past year, then you will have to search. +If the question involves something about a candidate's policies in a past year, then you will have to do a websearch. And also if you feel like a web search will be usefull. Do a web search. After deciding, -Output the 'vector_search_query': The query that needs to be searched from the vector store. +Output the 'namal_vector_search_query': The query that needs to be searched from the vector store of namal. +And the 'ranil_vector_search_query': The query that needs to be searched from the vector store of ranil. +And the 'sajith_vector_search_query': The query that needs to be searched from the vector store of sajith. And the 'web_search_query': The query that needs to be searched from the web. """ route_prompt = ChatPromptTemplate.from_messages( diff --git a/RAG/agents/generate.py b/RAG/agents/generate.py index a66ac1f..1906baf 100644 --- a/RAG/agents/generate.py +++ b/RAG/agents/generate.py @@ -4,13 +4,29 @@ from langchain_core.pydantic_v1 import BaseModel, Field from langchain_openai import ChatOpenAI -template = """Use the following pieces of context to answer the question at the end. +template = """You are a very vigilant and helpful journalist. Use the following pieces of +context to answer the question at the end. If you don't know the answer, just say that you don't know, don't try to make up an answer. -Use three sentences maximum and keep the answer as concise as possible. -Always say "thanks for asking!" at the end of the answer. +Be concise and helpful. -{context} +________________________________________________________________________________ +Here are the web results regarding the question: +{web_context} +Here are the results from the manifesto of the candidates: +________________________________________________________________________________ +namel rajapakse: +{namal_context} + +________________________________________________________________________________ +ranil wickramasinghe: +{ranil_context} + +________________________________________________________________________________ +sajith premadasa: +{sajith_context} + +________________________________________________________________________________ Question: {question} Helpful Answer:""" diff --git a/RAG/edges/generation_grader.py b/RAG/edges/generation_grader.py index 639118d..a70da12 100644 --- a/RAG/edges/generation_grader.py +++ b/RAG/edges/generation_grader.py @@ -14,7 +14,7 @@ def grade_generation_v_documents_and_question(state): print("---CHECK HALLUCINATIONS---") question = state["question"] - documents = state["vector_search_documents"] + state["web_search_documents"] + documents = state["namal_vector_search_documents"] + state["ranil_vector_search_documents"] + state["sajith_vector_search_documents"] + state["web_search_documents"] generation = state["generation"] score = hallucination_grader.invoke( diff --git a/RAG/graph.py b/RAG/graph.py index 4387039..5dac380 100644 --- a/RAG/graph.py +++ b/RAG/graph.py @@ -5,7 +5,6 @@ from RAG.nodes.extract_queries import extract_queries from RAG.nodes.web_search import web_search from RAG.nodes.retrieve import retrieve -from RAG.nodes.grade_documents import grade_documents from RAG.nodes.generate import generate from RAG.nodes.transform import transform_query diff --git a/RAG/graph_state.py b/RAG/graph_state.py index c292e34..7227060 100644 --- a/RAG/graph_state.py +++ b/RAG/graph_state.py @@ -14,11 +14,15 @@ class GraphState(TypedDict): """ question: str - vector_search_query: str + namal_vector_search_query: str + ranil_vector_search_query: str + sajith_vector_search_query: str web_search_query: str generation: str - vector_search_documents: List[str] + namal_vector_search_documents: List[str] + ranil_vector_search_documents: List[str] + sajith_vector_search_documents: List[str] web_search_documents: List[str] generated_count: int \ No newline at end of file diff --git a/RAG/nodes/extract_queries.py b/RAG/nodes/extract_queries.py index 221ceac..aaae79f 100644 --- a/RAG/nodes/extract_queries.py +++ b/RAG/nodes/extract_queries.py @@ -16,7 +16,9 @@ def extract_queries(state): source = question_extractor.invoke({"question": question}) return { - "vector_search_query": source.vector_search_query, + "namal_vector_search_query": source.namal_vector_search_query, + "ranil_vector_search_query": source.ranil_vector_search_query, + "sajith_vector_search_query": source.sajith_vector_search_query, "web_search_query": source.web_search_query, "question": question } diff --git a/RAG/nodes/generate.py b/RAG/nodes/generate.py index 103ed44..62672d6 100644 --- a/RAG/nodes/generate.py +++ b/RAG/nodes/generate.py @@ -13,17 +13,23 @@ def generate(state): print("---GENERATE---") question = state["question"] web_documents = state["web_search_documents"] - vector_documents = state["vector_search_documents"] - - documents = web_documents + vector_documents + namal_vector_documents = state["namal_vector_search_documents"] + ranil_vector_documents = state["ranil_vector_search_documents"] + sajith_vector_documents = state["sajith_vector_search_documents"] # RAG generation - generation = rag_chain.invoke({"context": documents, "question": question}) + generation = rag_chain.invoke( + { + "web_context": web_documents, + "namal_context": namal_vector_documents, + "ranil_context": ranil_vector_documents, + "sajith_context": sajith_vector_documents, + "question": question + } + ) generated_count = state.get("generated_count", 0) + 1 return { - "web_search_documents": web_documents, - "vector_search_documents": vector_documents, "question": question, "generation": generation, "generated_count": generated_count diff --git a/RAG/nodes/retrieve.py b/RAG/nodes/retrieve.py index e7707ca..bb2feda 100644 --- a/RAG/nodes/retrieve.py +++ b/RAG/nodes/retrieve.py @@ -1,5 +1,5 @@ from langchain.schema import Document -from RAG.tools.vectore_store_retriever import retriever +from RAG.tools.vectore_store_retriever import sajith_retriever, namal_retriever, ranil_retriever def retrieve(state): @@ -14,8 +14,15 @@ def retrieve(state): """ print("---RETRIEVE---") print(state) - search_query = state["vector_search_query"] + namal_vector_search_query = state["namal_vector_search_query"] + ranil_vector_search_query = state["ranil_vector_search_query"] + sajith_vector_search_query = state["sajith_vector_search_query"] # Retrieval - documents = retriever.invoke(search_query) - return {"vector_search_documents": documents} + namal_documents = namal_retriever.get_relevant_documents(namal_vector_search_query) + ranil_documents = ranil_retriever.get_relevant_documents(ranil_vector_search_query) + sajith_documents = sajith_retriever.get_relevant_documents(sajith_vector_search_query) + + return {"namal_vector_search_documents": namal_documents, + "ranil_vector_search_documents": ranil_documents, + "sajith_vector_search_documents": sajith_documents} diff --git a/RAG/nodes/transform.py b/RAG/nodes/transform.py index c401f21..1e49e0d 100644 --- a/RAG/nodes/transform.py +++ b/RAG/nodes/transform.py @@ -13,8 +13,6 @@ def transform_query(state): print("---TRANSFORM QUERY---") question = state["question"] - documents = state["documents"] - - # Re-write question + better_question = question_rewriter.invoke({"question": question}) - return {"documents": documents, "question": better_question} \ No newline at end of file + return {"question": better_question} \ No newline at end of file diff --git a/RAG/nodes/web_search.py b/RAG/nodes/web_search.py index 3ae20ad..159dbdc 100644 --- a/RAG/nodes/web_search.py +++ b/RAG/nodes/web_search.py @@ -14,9 +14,12 @@ def web_search(state): print("---WEB SEARCH---") search_query = state["web_search_query"] + if search_query == "": + return {"web_search_documents": []} # Web search docs = web_search_tool.invoke({"query": search_query}) + print(docs) web_results = [d["content"] for d in docs] # web_results = Document(page_content=web_results) diff --git a/RAG/tools/vectore_store_retriever.py b/RAG/tools/vectore_store_retriever.py index 8d95ec0..a967a02 100644 --- a/RAG/tools/vectore_store_retriever.py +++ b/RAG/tools/vectore_store_retriever.py @@ -7,14 +7,13 @@ "ranil.txt": "ranil", "sajith.txt": "sajith", } - docs = [] for file_name in file_names: loader = TextLoader(f"documents/{file_name}") doc = loader.load() for d in doc: - d.metadata = {"file_name": file_name} + d.metadata = {"file_name": file_name, "source": file_name_to_source[file_name]} docs.append(d) from langchain_text_splitters import RecursiveCharacterTextSplitter @@ -31,4 +30,6 @@ documents=all_splits, embedding=OpenAIEmbeddings(), persist_directory="./vectore_stores/manifesto_vectorstore", ) -retriever = vectorstore.as_retriever(search_type="similarity", search_kwargs={"k": 6}) \ No newline at end of file +sajith_retriever = vectorstore.as_retriever(search_type="similarity", search_kwargs={"k": 6, "filter": {"source": "sajith"}}) +namal_retriever = vectorstore.as_retriever(search_type="similarity", search_kwargs={"k": 6, "filter": {"source": "namal"}}) +ranil_retriever = vectorstore.as_retriever(search_type="similarity", search_kwargs={"k": 6, "filter": {"source": "ranil"}}) \ No newline at end of file diff --git a/main.py b/main.py index d0ae69e..ec836aa 100644 --- a/main.py +++ b/main.py @@ -13,7 +13,7 @@ async def test(): # Run inputs = { - "question": "What is the differnce between sajith premadasa's actions for the health sector in this election and previous 2019 election?" + "question": "What is the differnce between sajith premadasa's actions for the health sector and ranil wickramasinghe's actions for the health sector?" } for output in rag_app.stream(inputs): @@ -26,4 +26,4 @@ async def test(): # Final generation pprint(value["generation"]) - return value \ No newline at end of file + return value["generation"] \ No newline at end of file From 7d31525a22d9a95cb3d749e94cea214b732c7dc7 Mon Sep 17 00:00:00 2001 From: Savith Panamgama Date: Tue, 17 Sep 2024 05:22:30 +0530 Subject: [PATCH 03/11] wip: contextualize query --- .env | 5 +- RAG/agents/answer_grader.py | 9 +-- RAG/agents/contextualize.py | 39 ++++++++++++ RAG/agents/extractor.py | 17 +++-- RAG/agents/generate.py | 9 ++- RAG/agents/grader.py | 8 +-- RAG/agents/hallucinate_checker.py | 9 ++- RAG/agents/question_rewriter.py | 9 ++- RAG/graph.py | 93 ++++++++++++++++------------ RAG/graph_state.py | 12 +++- RAG/nodes/contextualize_query.py | 30 +++++++++ RAG/nodes/extract_queries.py | 2 +- RAG/nodes/generate.py | 18 ++++-- RAG/tools/vectore_store_retriever.py | 17 +++-- RAG/tools/web_search.py | 13 +++- main.py | 41 ++++++++++-- requirements.txt | 10 +++ 17 files changed, 250 insertions(+), 91 deletions(-) create mode 100644 RAG/agents/contextualize.py create mode 100644 RAG/nodes/contextualize_query.py create mode 100644 requirements.txt diff --git a/.env b/.env index 10d39fd..f31682d 100644 --- a/.env +++ b/.env @@ -1,4 +1,3 @@ -OPENAI_API_KEY=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 -TAVILY_API_KEY=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 LANGCHAIN_TRACING_V2=true -LANGCHAIN_API_KEY=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 \ No newline at end of file +LANGCHAIN_API_KEY=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 +MISTRAL_API_KEY=naAG2SIBHoKW5KtKS7B2MN5z49roSnzV \ No newline at end of file diff --git a/RAG/agents/answer_grader.py b/RAG/agents/answer_grader.py index e2d80a1..6dbc7fe 100644 --- a/RAG/agents/answer_grader.py +++ b/RAG/agents/answer_grader.py @@ -1,9 +1,10 @@ from langchain_core.output_parsers import StrOutputParser from langchain_core.prompts import PromptTemplate from langchain_core.prompts import ChatPromptTemplate -from langchain_core.pydantic_v1 import BaseModel, Field -from langchain_openai import ChatOpenAI - +from pydantic import BaseModel , Field +from langchain_mistralai import ChatMistralAI +import os +os.environ["MISTRAL_API_KEY"] = "naAG2SIBHoKW5KtKS7B2MN5z49roSnzV" # Data model class GradeAnswer(BaseModel): @@ -15,7 +16,7 @@ class GradeAnswer(BaseModel): # LLM with function call -llm = ChatOpenAI(model="gpt-4o-mini", temperature=0) +llm = ChatMistralAI(model="mistral-large-latest", api_key=os.getenv("MISTRAL_API_KEY")) structured_llm_grader = llm.with_structured_output(GradeAnswer) # Prompt diff --git a/RAG/agents/contextualize.py b/RAG/agents/contextualize.py new file mode 100644 index 0000000..a5e6791 --- /dev/null +++ b/RAG/agents/contextualize.py @@ -0,0 +1,39 @@ +from langchain.prompts import ChatPromptTemplate +from langchain.schema import MessagesPlaceholder +from pydantic import BaseModel , Field +from langchain_mistralai import ChatMistralAI +from dotenv import load_dotenv +import os + +class ContextualizeQuestion(BaseModel): + """Contextualize the question.""" + + contextualized_question: str = Field( + ..., + description="The contextualized question.", + ) + +contextualize_q_system_prompt = ( + "Given a chat history and the latest user question " + "which might reference context in the chat history, " + "formulate a standalone question which can be understood " + "without the chat history. Do NOT answer the question, " + "just reformulate it if needed and otherwise return it as is." +) + +load_dotenv() +mistral_api_key = os.getenv("MISTRAL_API_KEY") +if not mistral_api_key: + raise ValueError("MISTRAL_API_KEY environment variable not set") +llm = ChatMistralAI(model="mistral-large-latest", api_key=os.getenv("MISTRAL_API_KEY")) + +contextualize_q_prompt = ChatPromptTemplate.from_messages( + [ + ("system", contextualize_q_system_prompt), + MessagesPlaceholder("chat_history"), + ("human", "{input}"), + ] +) +structured_llm_router = llm.with_structured_output(ContextualizeQuestion) + +contextualizer = contextualize_q_prompt | structured_llm_router diff --git a/RAG/agents/extractor.py b/RAG/agents/extractor.py index a566d71..7e820f1 100644 --- a/RAG/agents/extractor.py +++ b/RAG/agents/extractor.py @@ -3,10 +3,10 @@ from typing import Literal from langchain_core.prompts import ChatPromptTemplate -from langchain_core.pydantic_v1 import BaseModel, Field -from langchain_openai import ChatOpenAI - - +from pydantic import BaseModel , Field +from langchain_mistralai import ChatMistralAI +from dotenv import load_dotenv +import os # Data model class ExtractQuery(BaseModel): """Route a user query to the relevant datasources with subquestions.""" @@ -28,7 +28,14 @@ class ExtractQuery(BaseModel): description="The query to search the web.", ) -llm = ChatOpenAI(model="gpt-4o-mini") +load_dotenv() +mistral_api_key = os.getenv("MISTRAL_API_KEY") + +if not mistral_api_key: + raise ValueError("MISTRAL_API_KEY environment variable not set") + +# Initialize the ChatMistralAI client with the API key +llm = ChatMistralAI(model="mistral-large-latest", api_key=mistral_api_key) structured_llm_router = llm.with_structured_output(ExtractQuery) # Prompt diff --git a/RAG/agents/generate.py b/RAG/agents/generate.py index 1906baf..82428f6 100644 --- a/RAG/agents/generate.py +++ b/RAG/agents/generate.py @@ -1,9 +1,9 @@ from langchain_core.output_parsers import StrOutputParser from langchain_core.prompts import PromptTemplate from langchain_core.prompts import ChatPromptTemplate -from langchain_core.pydantic_v1 import BaseModel, Field -from langchain_openai import ChatOpenAI - +from pydantic import BaseModel , Field +from langchain_mistralai import ChatMistralAI +import os template = """You are a very vigilant and helpful journalist. Use the following pieces of context to answer the question at the end. If you don't know the answer, just say that you don't know, don't try to make up an answer. @@ -33,8 +33,7 @@ custom_rag_prompt = PromptTemplate.from_template(template) # LLM -llm = ChatOpenAI(model="gpt-4o-mini") - +llm = ChatMistralAI(model="mistral-large-latest", api_key=os.getenv("MISTRAL_API_KEY")) # Post-processing def format_docs(docs): diff --git a/RAG/agents/grader.py b/RAG/agents/grader.py index d2c5bb8..e97f2ef 100644 --- a/RAG/agents/grader.py +++ b/RAG/agents/grader.py @@ -1,7 +1,7 @@ from langchain_core.prompts import ChatPromptTemplate -from langchain_core.pydantic_v1 import BaseModel, Field -from langchain_openai import ChatOpenAI - +from pydantic import BaseModel , Field +from langchain_mistralai import ChatMistralAI +import os class GradeDocuments(BaseModel): """Binary score for relevance check on retrieved documents.""" @@ -11,7 +11,7 @@ class GradeDocuments(BaseModel): ) -llm = ChatOpenAI(model="gpt-4o-mini") +llm = ChatMistralAI(model="mistral-large-latest", api_key=os.getenv("MISTRAL_API_KEY")) structured_llm_grader = llm.with_structured_output(GradeDocuments) # Prompt diff --git a/RAG/agents/hallucinate_checker.py b/RAG/agents/hallucinate_checker.py index 3ae53b0..7e2be34 100644 --- a/RAG/agents/hallucinate_checker.py +++ b/RAG/agents/hallucinate_checker.py @@ -1,9 +1,8 @@ from langchain_core.output_parsers import StrOutputParser from langchain_core.prompts import PromptTemplate from langchain_core.prompts import ChatPromptTemplate -from langchain_core.pydantic_v1 import BaseModel, Field -from langchain_openai import ChatOpenAI - +from pydantic import BaseModel , Field +from langchain_mistralai import ChatMistralAI class GradeHallucinations(BaseModel): """Binary score for hallucination present in generation answer.""" @@ -11,9 +10,9 @@ class GradeHallucinations(BaseModel): description="Answer is grounded in the facts, 'yes' or 'no'" ) - +import os # LLM with function call -llm = ChatOpenAI(model="gpt-4o-mini") +llm = ChatMistralAI(model="mistral-large-latest", api_key=os.getenv("MISTRAL_API_KEY")) structured_llm_grader = llm.with_structured_output(GradeHallucinations) # Prompt diff --git a/RAG/agents/question_rewriter.py b/RAG/agents/question_rewriter.py index 50fc988..c24edaa 100644 --- a/RAG/agents/question_rewriter.py +++ b/RAG/agents/question_rewriter.py @@ -1,11 +1,10 @@ from langchain_core.output_parsers import StrOutputParser from langchain_core.prompts import PromptTemplate from langchain_core.prompts import ChatPromptTemplate -from langchain_core.pydantic_v1 import BaseModel, Field -from langchain_openai import ChatOpenAI - -# LLM -llm = ChatOpenAI(model="gpt4-o-mini", temperature=0) +from pydantic import BaseModel , Field +from langchain_mistralai import ChatMistralAI +import os +llm = ChatMistralAI(model="mistral-large-latest", api_key=os.getenv("MISTRAL_API_KEY")) # Prompt system = """You a question re-writer that converts an input question to a better version that is optimized \n diff --git a/RAG/graph.py b/RAG/graph.py index 5dac380..3552cc9 100644 --- a/RAG/graph.py +++ b/RAG/graph.py @@ -1,47 +1,62 @@ from langgraph.graph import END, StateGraph, START - from RAG.graph_state import GraphState - from RAG.nodes.extract_queries import extract_queries from RAG.nodes.web_search import web_search from RAG.nodes.retrieve import retrieve from RAG.nodes.generate import generate from RAG.nodes.transform import transform_query - +from RAG.nodes.contextualize_query import contextualize_question as contextualize from RAG.edges.generation_grader import grade_generation_v_documents_and_question - -workflow = StateGraph(GraphState) - -workflow.add_node("web_search", web_search) # web search -workflow.add_node("retrieve", retrieve) # retrieve -workflow.add_node("generate", generate) # generatae -workflow.add_node("transform_query", transform_query) # transform_query -workflow.add_node("extract queries", extract_queries) - -workflow.add_edge(START, "extract queries") -workflow.add_edge("extract queries", "web_search") -workflow.add_edge("extract queries", "retrieve") - -workflow.add_edge(["web_search", "retrieve"], "generate") - -workflow.add_conditional_edges( - "generate", - grade_generation_v_documents_and_question, - { - "not supported": "generate", - "useful": END, - "not useful": "transform_query", - }, -) - -workflow.add_edge("transform_query", "extract queries") - -app = workflow.compile() - -try: - graph_image = app.get_graph(xray=True).draw_mermaid_png() - with open("graph_image.png", "wb") as f: - f.write(graph_image) -except Exception: - # This requires some extra dependencies and is optional - pass +from langchain_core.chat_history import InMemoryChatMessageHistory +import os +import uuid + +def create_workflow(llm): + workflow = StateGraph(GraphState) + + # Initialize the graph state + def init_graph_state(): + return { + "chat_history": InMemoryChatMessageHistory(), + } + + workflow.set_initial_state(init_graph_state) + + workflow.add_node("contextualize", contextualize) + workflow.add_node("extract queries", extract_queries) + # workflow.add_node("web_search", web_search) + # workflow.add_node("retrieve", retrieve) + # workflow.add_node("generate", generate) + # workflow.add_node("transform_query", transform_query) + + workflow.add_edge(START, "contextualize") + workflow.add_edge("contextualize", "extract queries") + workflow.add_edge("extract queries", END) + # workflow.add_edge("extract queries", "web_search") + # workflow.add_edge("extract queries", "retrieve") + # workflow.add_edge(["web_search", "retrieve"], "generate") + + # workflow.add_conditional_edges( + # "generate", + # grade_generation_v_documents_and_question, + # { + # "not supported": "generate", + # "useful": END, + # "not useful": "transform_query", + # }, + # ) + + # workflow.add_edge("transform_query", "extract queries") + + return workflow.compile() + +# Usage +load_dotenv() +mistral_api_key = os.getenv("MISTRAL_API_KEY") + +if not mistral_api_key: + raise ValueError("MISTRAL_API_KEY environment variable not set") + +# Initialize the ChatMistralAI client with the API key +llm = ChatMistralAI(model="mistral-large-latest", api_key=mistral_api_key) +app = create_workflow(llm) # Pass your LLM instance here diff --git a/RAG/graph_state.py b/RAG/graph_state.py index 7227060..360b56b 100644 --- a/RAG/graph_state.py +++ b/RAG/graph_state.py @@ -1,8 +1,12 @@ -from typing import List - +from typing import List, Dict +from langchain_core.messages.base import BaseMessage from typing_extensions import TypedDict +class Message(TypedDict): + role: str + content: str + class GraphState(TypedDict): """ Represents the state of our graph. @@ -14,6 +18,7 @@ class GraphState(TypedDict): """ question: str + contextualized_question: str namal_vector_search_query: str ranil_vector_search_query: str sajith_vector_search_query: str @@ -25,4 +30,5 @@ class GraphState(TypedDict): sajith_vector_search_documents: List[str] web_search_documents: List[str] - generated_count: int \ No newline at end of file + generated_count: int + chat_history: List[BaseMessage] diff --git a/RAG/nodes/contextualize_query.py b/RAG/nodes/contextualize_query.py new file mode 100644 index 0000000..0b73df8 --- /dev/null +++ b/RAG/nodes/contextualize_query.py @@ -0,0 +1,30 @@ +from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder +from dotenv import load_dotenv +from RAG.agents.contextualize import contextualizer +import os + +contextualize_q_system_prompt = ( + "Given a chat history and the latest user question " + "which might reference context in the chat history, " + "formulate a standalone question which can be understood " + "without the chat history. Do NOT answer the question, " + "just reformulate it if needed and otherwise return it as is." +) + +contextualize_q_prompt = ChatPromptTemplate.from_messages( + [ + ("system", contextualize_q_system_prompt), + MessagesPlaceholder("chat_history"), + ("human", "{input}"), + ] +) + +def contextualize_question(state): + question = state["question"] + chat_history = state["chat_history"] + contextualized_question = contextualizer.invoke({"input": question, "chat_history": chat_history}) + return { + "contextualized_question": contextualized_question, + "question": question + } + diff --git a/RAG/nodes/extract_queries.py b/RAG/nodes/extract_queries.py index aaae79f..6756164 100644 --- a/RAG/nodes/extract_queries.py +++ b/RAG/nodes/extract_queries.py @@ -12,7 +12,7 @@ def extract_queries(state): """ print("---EXTRACT QUERIES---") - question = state["question"] + question = state["question_contextualized"] source = question_extractor.invoke({"question": question}) return { diff --git a/RAG/nodes/generate.py b/RAG/nodes/generate.py index 62672d6..5490ba9 100644 --- a/RAG/nodes/generate.py +++ b/RAG/nodes/generate.py @@ -1,4 +1,5 @@ from RAG.agents.generate import rag_chain +from langchain.memory import ChatMessageHistory def generate(state): """ @@ -11,11 +12,12 @@ def generate(state): state (dict): New key added to state, generation, that contains LLM generation """ print("---GENERATE---") - question = state["question"] + question = state["contextualized_question"] web_documents = state["web_search_documents"] namal_vector_documents = state["namal_vector_search_documents"] ranil_vector_documents = state["ranil_vector_search_documents"] sajith_vector_documents = state["sajith_vector_search_documents"] + chat_history = state["chat_history"] # RAG generation generation = rag_chain.invoke( @@ -24,13 +26,19 @@ def generate(state): "namal_context": namal_vector_documents, "ranil_context": ranil_vector_documents, "sajith_context": sajith_vector_documents, - "question": question + "question": question, + "chat_history": chat_history.messages } ) + chat_history.add_user_message(question) + chat_history.add_ai_message(generation) + generated_count = state.get("generated_count", 0) + 1 return { - "question": question, + "question": state["question"], + "contextualized_question": question, "generation": generation, - "generated_count": generated_count - } \ No newline at end of file + "generated_count": generated_count, + "chat_history": chat_history + } \ No newline at end of file diff --git a/RAG/tools/vectore_store_retriever.py b/RAG/tools/vectore_store_retriever.py index a967a02..9fd264e 100644 --- a/RAG/tools/vectore_store_retriever.py +++ b/RAG/tools/vectore_store_retriever.py @@ -1,6 +1,12 @@ from langchain_community.document_loaders import TextLoader +from langchain_community.vectorstores import FAISS +from langchain_huggingface import HuggingFaceEmbeddings +from dotenv import load_dotenv import os +# Load environment variables +load_dotenv() + file_names = ["namal.txt", "ranil.txt", "sajith.txt"] file_name_to_source = { "namal.txt": "namal", @@ -10,7 +16,7 @@ docs = [] for file_name in file_names: - loader = TextLoader(f"documents/{file_name}") + loader = TextLoader(f"documents/{file_name}", encoding="utf-8") doc = loader.load() for d in doc: d.metadata = {"file_name": file_name, "source": file_name_to_source[file_name]} @@ -23,12 +29,11 @@ ) all_splits = text_splitter.split_documents(docs) -from langchain_chroma import Chroma -from langchain_openai import OpenAIEmbeddings +embeddings = HuggingFaceEmbeddings(model_name="all-MiniLM-L6-v2") +vectorstore = FAISS.from_documents(documents=all_splits, embedding=embeddings) -vectorstore = Chroma.from_documents( - documents=all_splits, embedding=OpenAIEmbeddings(), persist_directory="./vectore_stores/manifesto_vectorstore", -) +# Save the FAISS index to disk +vectorstore.save_local("./vectore_stores/manifesto_vectorstore") sajith_retriever = vectorstore.as_retriever(search_type="similarity", search_kwargs={"k": 6, "filter": {"source": "sajith"}}) namal_retriever = vectorstore.as_retriever(search_type="similarity", search_kwargs={"k": 6, "filter": {"source": "namal"}}) diff --git a/RAG/tools/web_search.py b/RAG/tools/web_search.py index cc8395e..5ee87e1 100644 --- a/RAG/tools/web_search.py +++ b/RAG/tools/web_search.py @@ -1,3 +1,12 @@ -from langchain_community.tools.tavily_search import TavilySearchResults +from langchain_community.tools import TavilySearchResults -web_search_tool = TavilySearchResults(k=3) \ No newline at end of file +# Load environment variables +# tavily_api_key = "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" +import os + +if not os.environ.get("TAVILY_API_KEY"): + os.environ["TAVILY_API_KEY"] = "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" +# Initialize the TavilySearchAPIWrapper with the API key +web_search_tool = TavilySearchResults( + max_results=5, +) \ No newline at end of file diff --git a/main.py b/main.py index ec836aa..d735fb8 100644 --- a/main.py +++ b/main.py @@ -1,9 +1,15 @@ -from fastapi import FastAPI +import warnings +warnings.filterwarnings("ignore", category=FutureWarning, module="transformers.tokenization_utils_base") + +from fastapi import FastAPI, Request from RAG.graph import app as rag_app +from dotenv import load_dotenv +import os + + app = FastAPI() -from dotenv import load_dotenv load_dotenv() @@ -25,5 +31,32 @@ async def test(): pprint("\n---\n") # Final generation - pprint(value["generation"]) - return value["generation"] \ No newline at end of file + # pprint(value["generation"]) + # return value["generation"] + return "Hello World" + +@app.post("/process") +async def process(request: Request): + from pprint import pprint + + data = await request.json() + question = data.get("question", "") + + # Run + inputs = { + "question": question + } + + response = [] + for output in rag_app.stream(inputs): + node_output = {} + for key, value in output.items(): + # Node + node_output[key] = value + response.append(node_output) + + return response + +if __name__ == "__main__": + import uvicorn + uvicorn.run(app, host="0.0.0.0", port=8000) \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..1cb937c --- /dev/null +++ b/requirements.txt @@ -0,0 +1,10 @@ +fastapi +python-dotenv +pydantic +langchain +openai +jupyter +faiss-cpu +langchain_community +langchain_core +langchain_openai From 64ee0db8439a4cdabe6551d4c6ac603d534cc5dc Mon Sep 17 00:00:00 2001 From: Savith Panamgama Date: Tue, 17 Sep 2024 06:15:09 +0530 Subject: [PATCH 04/11] wip: work in progress --- RAG/agents/contextualize.py | 3 +-- RAG/graph.py | 12 +++++++----- RAG/graph_state.py | 10 ++++++---- RAG/nodes/contextualize_query.py | 4 +++- RAG/nodes/extract_queries.py | 7 +++++-- RAG/nodes/generate.py | 6 ++++-- main.py | 2 +- 7 files changed, 27 insertions(+), 17 deletions(-) diff --git a/RAG/agents/contextualize.py b/RAG/agents/contextualize.py index a5e6791..2786570 100644 --- a/RAG/agents/contextualize.py +++ b/RAG/agents/contextualize.py @@ -1,5 +1,4 @@ -from langchain.prompts import ChatPromptTemplate -from langchain.schema import MessagesPlaceholder +from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder from pydantic import BaseModel , Field from langchain_mistralai import ChatMistralAI from dotenv import load_dotenv diff --git a/RAG/graph.py b/RAG/graph.py index 3552cc9..6ff4350 100644 --- a/RAG/graph.py +++ b/RAG/graph.py @@ -10,17 +10,19 @@ from langchain_core.chat_history import InMemoryChatMessageHistory import os import uuid +from langchain_mistralai import ChatMistralAI +from dotenv import load_dotenv def create_workflow(llm): workflow = StateGraph(GraphState) # Initialize the graph state - def init_graph_state(): - return { - "chat_history": InMemoryChatMessageHistory(), - } + # def init_graph_state(): + # return { + # "chat_history": InMemoryChatMessageHistory(), + # } - workflow.set_initial_state(init_graph_state) + # workflow.set_initial_state(init_graph_state) workflow.add_node("contextualize", contextualize) workflow.add_node("extract queries", extract_queries) diff --git a/RAG/graph_state.py b/RAG/graph_state.py index 360b56b..4627793 100644 --- a/RAG/graph_state.py +++ b/RAG/graph_state.py @@ -1,7 +1,9 @@ from typing import List, Dict -from langchain_core.messages.base import BaseMessage -from typing_extensions import TypedDict - +# from langchain_core.messages.base import BaseMessage +# from langchain_core.chat_history import InMemoryChatMessageHistory +from typing_extensions import TypedDict, Annotated +from langgraph.graph.message import add_messages +from langchain_core.messages import HumanMessage, AIMessage class Message(TypedDict): role: str @@ -31,4 +33,4 @@ class GraphState(TypedDict): web_search_documents: List[str] generated_count: int - chat_history: List[BaseMessage] + chat_history: Annotated[list[HumanMessage | AIMessage], add_messages] \ No newline at end of file diff --git a/RAG/nodes/contextualize_query.py b/RAG/nodes/contextualize_query.py index 0b73df8..525ef63 100644 --- a/RAG/nodes/contextualize_query.py +++ b/RAG/nodes/contextualize_query.py @@ -1,6 +1,7 @@ from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder from dotenv import load_dotenv from RAG.agents.contextualize import contextualizer +from RAG.graph_state import GraphState import os contextualize_q_system_prompt = ( @@ -25,6 +26,7 @@ def contextualize_question(state): contextualized_question = contextualizer.invoke({"input": question, "chat_history": chat_history}) return { "contextualized_question": contextualized_question, - "question": question + "question": question, + "state": state } diff --git a/RAG/nodes/extract_queries.py b/RAG/nodes/extract_queries.py index 6756164..3364842 100644 --- a/RAG/nodes/extract_queries.py +++ b/RAG/nodes/extract_queries.py @@ -12,7 +12,9 @@ def extract_queries(state): """ print("---EXTRACT QUERIES---") - question = state["question_contextualized"] + question = state["contextualized_question"] + print(state["question"]) + print(question) source = question_extractor.invoke({"question": question}) return { @@ -20,5 +22,6 @@ def extract_queries(state): "ranil_vector_search_query": source.ranil_vector_search_query, "sajith_vector_search_query": source.sajith_vector_search_query, "web_search_query": source.web_search_query, - "question": question + "question": question, + "state": state } diff --git a/RAG/nodes/generate.py b/RAG/nodes/generate.py index 5490ba9..1309133 100644 --- a/RAG/nodes/generate.py +++ b/RAG/nodes/generate.py @@ -1,5 +1,6 @@ from RAG.agents.generate import rag_chain -from langchain.memory import ChatMessageHistory +from langchain_core.chat_history import InMemoryChatMessageHistory + def generate(state): """ @@ -33,6 +34,7 @@ def generate(state): chat_history.add_user_message(question) chat_history.add_ai_message(generation) + state["chat_history"] = chat_history generated_count = state.get("generated_count", 0) + 1 return { @@ -40,5 +42,5 @@ def generate(state): "contextualized_question": question, "generation": generation, "generated_count": generated_count, - "chat_history": chat_history + "state": state } \ No newline at end of file diff --git a/main.py b/main.py index d735fb8..53ff038 100644 --- a/main.py +++ b/main.py @@ -1,6 +1,7 @@ import warnings warnings.filterwarnings("ignore", category=FutureWarning, module="transformers.tokenization_utils_base") + from fastapi import FastAPI, Request from RAG.graph import app as rag_app @@ -41,7 +42,6 @@ async def process(request: Request): data = await request.json() question = data.get("question", "") - # Run inputs = { "question": question From 0b4db996bdfa17c6af5aad0b2dc5c616e9aa09c5 Mon Sep 17 00:00:00 2001 From: Savith Panamgama Date: Tue, 17 Sep 2024 07:13:19 +0530 Subject: [PATCH 05/11] wip: try to add persistance --- RAG/agents/contextualize.py | 1 + RAG/graph.py | 82 +++++++++++++++++--------------- RAG/nodes/contextualize_query.py | 13 +++-- RAG/nodes/generate.py | 12 ++--- main.py | 6 +-- 5 files changed, 62 insertions(+), 52 deletions(-) diff --git a/RAG/agents/contextualize.py b/RAG/agents/contextualize.py index 2786570..b036db6 100644 --- a/RAG/agents/contextualize.py +++ b/RAG/agents/contextualize.py @@ -1,6 +1,7 @@ from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder from pydantic import BaseModel , Field from langchain_mistralai import ChatMistralAI +from langchain_core.output_parsers import StrOutputParser from dotenv import load_dotenv import os diff --git a/RAG/graph.py b/RAG/graph.py index 6ff4350..a9f9184 100644 --- a/RAG/graph.py +++ b/RAG/graph.py @@ -9,56 +9,60 @@ from RAG.edges.generation_grader import grade_generation_v_documents_and_question from langchain_core.chat_history import InMemoryChatMessageHistory import os -import uuid +# import uuid from langchain_mistralai import ChatMistralAI from dotenv import load_dotenv +from langgraph.checkpoint.memory import MemorySaver -def create_workflow(llm): - workflow = StateGraph(GraphState) - # Initialize the graph state - # def init_graph_state(): - # return { - # "chat_history": InMemoryChatMessageHistory(), - # } +workflow = StateGraph(GraphState) - # workflow.set_initial_state(init_graph_state) +# Initialize the graph state +# def init_graph_state(): +# return { +# "chat_history": InMemoryChatMessageHistory(), +# } - workflow.add_node("contextualize", contextualize) - workflow.add_node("extract queries", extract_queries) - # workflow.add_node("web_search", web_search) - # workflow.add_node("retrieve", retrieve) - # workflow.add_node("generate", generate) - # workflow.add_node("transform_query", transform_query) +# workflow.set_initial_state(init_graph_state) - workflow.add_edge(START, "contextualize") - workflow.add_edge("contextualize", "extract queries") - workflow.add_edge("extract queries", END) - # workflow.add_edge("extract queries", "web_search") - # workflow.add_edge("extract queries", "retrieve") - # workflow.add_edge(["web_search", "retrieve"], "generate") +workflow.add_node("contextualize", contextualize) +workflow.add_node("extract queries", extract_queries) +# workflow.add_node("web_search", web_search) +# workflow.add_node("retrieve", retrieve) +# workflow.add_node("generate", generate) +# workflow.add_node("transform_query", transform_query) - # workflow.add_conditional_edges( - # "generate", - # grade_generation_v_documents_and_question, - # { - # "not supported": "generate", - # "useful": END, - # "not useful": "transform_query", - # }, - # ) +workflow.add_edge(START, "contextualize") +workflow.add_edge("contextualize", "extract queries") +workflow.add_edge("extract queries", END) +# workflow.add_edge("extract queries", "web_search") +# workflow.add_edge("extract queries", "retrieve") +# workflow.add_edge(["web_search", "retrieve"], "generate") - # workflow.add_edge("transform_query", "extract queries") +# workflow.add_conditional_edges( +# "generate", +# grade_generation_v_documents_and_question, +# { +# "not supported": "generate", +# "useful": END, +# "not useful": "transform_query", +# }, +# ) - return workflow.compile() +# workflow.add_edge("transform_query", "extract queries") + +checkpointer = MemorySaver() +app = workflow.compile(checkpointer=checkpointer) + +config = {"configurable": {"thread_id": "1"}} # Usage -load_dotenv() -mistral_api_key = os.getenv("MISTRAL_API_KEY") +# load_dotenv() +# mistral_api_key = os.getenv("MISTRAL_API_KEY") -if not mistral_api_key: - raise ValueError("MISTRAL_API_KEY environment variable not set") +# if not mistral_api_key: +# raise ValueError("MISTRAL_API_KEY environment variable not set") -# Initialize the ChatMistralAI client with the API key -llm = ChatMistralAI(model="mistral-large-latest", api_key=mistral_api_key) -app = create_workflow(llm) # Pass your LLM instance here +# # Initialize the ChatMistralAI client with the API key +# llm = ChatMistralAI(model="mistral-large-latest", api_key=mistral_api_key) +# app = create_workflow(llm) # Pass your LLM instance here diff --git a/RAG/nodes/contextualize_query.py b/RAG/nodes/contextualize_query.py index 525ef63..d332a47 100644 --- a/RAG/nodes/contextualize_query.py +++ b/RAG/nodes/contextualize_query.py @@ -1,5 +1,6 @@ from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder from dotenv import load_dotenv +from langchain_core.messages import HumanMessage, AIMessage from RAG.agents.contextualize import contextualizer from RAG.graph_state import GraphState import os @@ -22,10 +23,16 @@ def contextualize_question(state): question = state["question"] - chat_history = state["chat_history"] - contextualized_question = contextualizer.invoke({"input": question, "chat_history": chat_history}) + # chat_history = state["chat_history"] + chat_history = GraphState.get_state({"configurable": {"thread_id": "1"}}).chat_history + print(chat_history) + result = contextualizer.invoke({"input": question, "chat_history": chat_history}) + print("contextualised result", result.contextualized_question) + chat_history.append(HumanMessage(content=result.contextualized_question)) + state["chat_history"] = chat_history + return { - "contextualized_question": contextualized_question, + "contextualized_question": result, "question": question, "state": state } diff --git a/RAG/nodes/generate.py b/RAG/nodes/generate.py index 1309133..f75192c 100644 --- a/RAG/nodes/generate.py +++ b/RAG/nodes/generate.py @@ -1,5 +1,5 @@ from RAG.agents.generate import rag_chain -from langchain_core.chat_history import InMemoryChatMessageHistory +from langchain_core.messages import AIMessage def generate(state): @@ -19,7 +19,7 @@ def generate(state): ranil_vector_documents = state["ranil_vector_search_documents"] sajith_vector_documents = state["sajith_vector_search_documents"] chat_history = state["chat_history"] - + print(chat_history) # RAG generation generation = rag_chain.invoke( { @@ -28,15 +28,13 @@ def generate(state): "ranil_context": ranil_vector_documents, "sajith_context": sajith_vector_documents, "question": question, - "chat_history": chat_history.messages + "chat_history": chat_history } ) - chat_history.add_user_message(question) - chat_history.add_ai_message(generation) - state["chat_history"] = chat_history - + state["chat_history"].append(AIMessage(content=generation)) generated_count = state.get("generated_count", 0) + 1 + return { "question": state["question"], "contextualized_question": question, diff --git a/main.py b/main.py index 53ff038..cf2b3d6 100644 --- a/main.py +++ b/main.py @@ -8,7 +8,7 @@ from dotenv import load_dotenv import os - +config = {"configurable": {"thread_id": "1"}} app = FastAPI() @@ -23,7 +23,7 @@ async def test(): "question": "What is the differnce between sajith premadasa's actions for the health sector and ranil wickramasinghe's actions for the health sector?" } - for output in rag_app.stream(inputs): + for output in rag_app.stream(inputs, config=config): for key, value in output.items(): # Node pprint(f"Node '{key}':") @@ -48,7 +48,7 @@ async def process(request: Request): } response = [] - for output in rag_app.stream(inputs): + for output in rag_app.stream(inputs, config=config): node_output = {} for key, value in output.items(): # Node From 6db861b5aaeed5069ded3756b25cede12552bd3e Mon Sep 17 00:00:00 2001 From: Savith Panamgama Date: Tue, 17 Sep 2024 22:34:10 +0530 Subject: [PATCH 06/11] alert: before state --- RAG/graph.py | 85 ++++++++++++++++++++++++++---------- RAG/nodes/extract_queries.py | 3 +- RAG/nodes/generate.py | 11 ++--- main.py | 82 ++++++++++++++++++++++++++++++++++ 4 files changed, 152 insertions(+), 29 deletions(-) diff --git a/RAG/graph.py b/RAG/graph.py index a9f9184..d9dfc15 100644 --- a/RAG/graph.py +++ b/RAG/graph.py @@ -14,27 +14,66 @@ from dotenv import load_dotenv from langgraph.checkpoint.memory import MemorySaver - workflow = StateGraph(GraphState) -# Initialize the graph state -# def init_graph_state(): -# return { -# "chat_history": InMemoryChatMessageHistory(), -# } +workflow.add_node("web_search", web_search) # web search +workflow.add_node("retrieve", retrieve) # retrieve +workflow.add_node("generate", generate) # generatae +workflow.add_node("transform_query", transform_query) # transform_query +workflow.add_node("extract queries", extract_queries) -# workflow.set_initial_state(init_graph_state) +workflow.add_edge(START, "extract queries") +workflow.add_edge("extract queries", "web_search") +workflow.add_edge("extract queries", "retrieve") -workflow.add_node("contextualize", contextualize) -workflow.add_node("extract queries", extract_queries) +workflow.add_edge(["web_search", "retrieve"], "generate") + +workflow.add_conditional_edges( + "generate", + grade_generation_v_documents_and_question, + { + "not supported": "generate", + "useful": END, + "not useful": "transform_query", + }, +) + +workflow.add_edge("transform_query", "extract queries") + +from langgraph.checkpoint.memory import MemorySaver + +memory = MemorySaver() +app = workflow.compile(checkpointer=memory) + +try: + graph_image = app.get_graph(xray=True).draw_mermaid_png() + with open("graph_image.png", "wb") as f: + f.write(graph_image) +except Exception: + # This requires some extra dependencies and is optional + pass + +# workflow = StateGraph(GraphState) + +# # Initialize the graph state +# # def init_graph_state(): +# # return { +# # "chat_history": InMemoryChatMessageHistory(), +# # } + +# # workflow.set_initial_state(init_graph_state) + +# # workflow.add_node("contextualize", contextualize) +# workflow.add_node("extract queries", extract_queries) # workflow.add_node("web_search", web_search) # workflow.add_node("retrieve", retrieve) # workflow.add_node("generate", generate) # workflow.add_node("transform_query", transform_query) -workflow.add_edge(START, "contextualize") -workflow.add_edge("contextualize", "extract queries") -workflow.add_edge("extract queries", END) +# # workflow.add_edge(START, "contextualize") +# workflow.add_edge(START, "extract_queries") +# # workflow.add_edge("contextualize", "extract queries") +# # workflow.add_edge("extract queries", END) # workflow.add_edge("extract queries", "web_search") # workflow.add_edge("extract queries", "retrieve") # workflow.add_edge(["web_search", "retrieve"], "generate") @@ -51,18 +90,18 @@ # workflow.add_edge("transform_query", "extract queries") -checkpointer = MemorySaver() -app = workflow.compile(checkpointer=checkpointer) +# checkpointer = MemorySaver() +# app = workflow.compile(checkpointer=checkpointer) -config = {"configurable": {"thread_id": "1"}} +# # config = {"configurable": {"thread_id": "1"}} -# Usage -# load_dotenv() -# mistral_api_key = os.getenv("MISTRAL_API_KEY") +# # Usage +# # load_dotenv() +# # mistral_api_key = os.getenv("MISTRAL_API_KEY") -# if not mistral_api_key: -# raise ValueError("MISTRAL_API_KEY environment variable not set") +# # if not mistral_api_key: +# # raise ValueError("MISTRAL_API_KEY environment variable not set") -# # Initialize the ChatMistralAI client with the API key -# llm = ChatMistralAI(model="mistral-large-latest", api_key=mistral_api_key) -# app = create_workflow(llm) # Pass your LLM instance here +# # # Initialize the ChatMistralAI client with the API key +# # llm = ChatMistralAI(model="mistral-large-latest", api_key=mistral_api_key) +# # app = create_workflow(llm) # Pass your LLM instance here diff --git a/RAG/nodes/extract_queries.py b/RAG/nodes/extract_queries.py index 3364842..63dec9f 100644 --- a/RAG/nodes/extract_queries.py +++ b/RAG/nodes/extract_queries.py @@ -12,7 +12,8 @@ def extract_queries(state): """ print("---EXTRACT QUERIES---") - question = state["contextualized_question"] + question = state["question"] + # question = state["contextualized_question"] print(state["question"]) print(question) source = question_extractor.invoke({"question": question}) diff --git a/RAG/nodes/generate.py b/RAG/nodes/generate.py index f75192c..e1b791a 100644 --- a/RAG/nodes/generate.py +++ b/RAG/nodes/generate.py @@ -13,13 +13,14 @@ def generate(state): state (dict): New key added to state, generation, that contains LLM generation """ print("---GENERATE---") - question = state["contextualized_question"] + question = state["question"] + # question = state["contextualized_question"] web_documents = state["web_search_documents"] namal_vector_documents = state["namal_vector_search_documents"] ranil_vector_documents = state["ranil_vector_search_documents"] sajith_vector_documents = state["sajith_vector_search_documents"] - chat_history = state["chat_history"] - print(chat_history) + # chat_history = state["chat_history"] + # print(chat_history) # RAG generation generation = rag_chain.invoke( { @@ -28,11 +29,11 @@ def generate(state): "ranil_context": ranil_vector_documents, "sajith_context": sajith_vector_documents, "question": question, - "chat_history": chat_history + # "chat_history": chat_history } ) - state["chat_history"].append(AIMessage(content=generation)) + # state["chat_history"].append(AIMessage(content=generation)) generated_count = state.get("generated_count", 0) + 1 return { diff --git a/main.py b/main.py index cf2b3d6..3765ffe 100644 --- a/main.py +++ b/main.py @@ -14,6 +14,16 @@ load_dotenv() +from fastapi.middleware.cors import CORSMiddleware + +app.add_middleware( + CORSMiddleware, + allow_origins=["*"], # Allows all origins + allow_credentials=True, + allow_methods=["*"], # Allows all methods + allow_headers=["*"], # Allows all headers +) + @app.get("/") async def test(): from pprint import pprint @@ -36,6 +46,55 @@ async def test(): # return value["generation"] return "Hello World" +@app.post("/compare") +async def compare(request: dict): + from pprint import pprint + + instructions = request.get("instructions") + field = request.get("field") + + compare_2019 = request.get("compare_2019") + + if not instructions and not field: + return {"error": "Either instructions or field must be provided"} + + if not instructions and field == 'misc': + return {"error": "Miscellaneous field requires instructions"} + + candidates = [] + if request.get("namal") is True: + candidates.append("namal rajapakse") + if request.get("sajith") is True: + candidates.append("sajith premadasa") + if request.get("ranil") is True: + candidates.append("ranil wickramasinghe") + + if len(candidates) == 0: + return {"error": "At least one candidate must be provided"} + + field_instructions = f"What are the key differences between candidates on approaching the {field}?" + + question = f"""You need to focus on the following candidates: {' '.join(candidates)}. + You need to answer the question based on the provided instructions and the field. + {"Also compare with the 2019 election manifesto of the candidates" if compare_2019 else ""} + {instructions if instructions else field_instructions}""" + + print(question) + + inputs = { + "question": question + } + + for output in rag_app.stream(inputs): + for key, value in output.items(): + pprint(f"Node '{key}':") + pprint(value, indent=2, width=80, depth=None) + pprint("\n---\n") + + # Final generation + pprint(value["generation"]) + return {"answer": value["generation"]} + @app.post("/process") async def process(request: Request): from pprint import pprint @@ -57,6 +116,29 @@ async def process(request: Request): return response +@app.post("/chat") +async def chat(request: dict): + from pprint import pprint + question = request.get("question") + thread_id = request.get("thread_id") + + print(question) + + inputs = { + "question": question + } + + config = {"configurable": {"thread_id": thread_id}} + for output in rag_app.stream(inputs, config=config): + for key, value in output.items(): + pprint(f"Node '{key}':") + pprint(value, indent=2, width=80, depth=None) + pprint("\n---\n") + + # Final generation + pprint(value["generation"]) + return {"answer": value["generation"]} + if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=8000) \ No newline at end of file From 19c59a47a84b5a173142a669b9848ebf9ed78774 Mon Sep 17 00:00:00 2001 From: Savith Panamgama Date: Wed, 18 Sep 2024 04:10:16 +0530 Subject: [PATCH 07/11] wip: fixing issues --- RAG/graph.py | 43 +++++++++++++++++-------------- RAG/graph_state.py | 5 ++-- RAG/nodes/contextualize_query.py | 28 +++++--------------- RAG/nodes/extract_queries.py | 13 +++++++--- graph_image.png | Bin 25398 -> 9010 bytes main.py | 28 +++++++++++++++----- 6 files changed, 64 insertions(+), 53 deletions(-) diff --git a/RAG/graph.py b/RAG/graph.py index d9dfc15..86c6daf 100644 --- a/RAG/graph.py +++ b/RAG/graph.py @@ -8,6 +8,8 @@ from RAG.nodes.contextualize_query import contextualize_question as contextualize from RAG.edges.generation_grader import grade_generation_v_documents_and_question from langchain_core.chat_history import InMemoryChatMessageHistory + + import os # import uuid from langchain_mistralai import ChatMistralAI @@ -16,29 +18,32 @@ workflow = StateGraph(GraphState) -workflow.add_node("web_search", web_search) # web search -workflow.add_node("retrieve", retrieve) # retrieve -workflow.add_node("generate", generate) # generatae -workflow.add_node("transform_query", transform_query) # transform_query +# workflow.add_node("web_search", web_search) # web search +# workflow.add_node("retrieve", retrieve) # retrieve +# workflow.add_node("generate", generate) # generatae +# workflow.add_node("transform_query", transform_query) # transform_query +workflow.add_node("contextualize", contextualize) workflow.add_node("extract queries", extract_queries) -workflow.add_edge(START, "extract queries") -workflow.add_edge("extract queries", "web_search") -workflow.add_edge("extract queries", "retrieve") +workflow.add_edge(START, "contextualize") +workflow.add_edge("contextualize", "extract queries") +workflow.add_edge("extract queries", END) +# workflow.add_edge("extract queries", "web_search") +# workflow.add_edge("extract queries", "retrieve") -workflow.add_edge(["web_search", "retrieve"], "generate") +# workflow.add_edge(["web_search", "retrieve"], "generate") -workflow.add_conditional_edges( - "generate", - grade_generation_v_documents_and_question, - { - "not supported": "generate", - "useful": END, - "not useful": "transform_query", - }, -) +# workflow.add_conditional_edges( +# "generate", +# grade_generation_v_documents_and_question, +# { +# "not supported": "generate", +# "useful": END, +# "not useful": "transform_query", +# }, +# ) -workflow.add_edge("transform_query", "extract queries") +# workflow.add_edge("transform_query", "extract queries") from langgraph.checkpoint.memory import MemorySaver @@ -50,7 +55,6 @@ with open("graph_image.png", "wb") as f: f.write(graph_image) except Exception: - # This requires some extra dependencies and is optional pass # workflow = StateGraph(GraphState) @@ -63,7 +67,6 @@ # # workflow.set_initial_state(init_graph_state) -# # workflow.add_node("contextualize", contextualize) # workflow.add_node("extract queries", extract_queries) # workflow.add_node("web_search", web_search) # workflow.add_node("retrieve", retrieve) diff --git a/RAG/graph_state.py b/RAG/graph_state.py index 4627793..93a2536 100644 --- a/RAG/graph_state.py +++ b/RAG/graph_state.py @@ -1,9 +1,10 @@ from typing import List, Dict -# from langchain_core.messages.base import BaseMessage +from langchain_core.messages.base import BaseMessage # from langchain_core.chat_history import InMemoryChatMessageHistory from typing_extensions import TypedDict, Annotated from langgraph.graph.message import add_messages from langchain_core.messages import HumanMessage, AIMessage +from langchain.memory import ConversationBufferMemory class Message(TypedDict): role: str @@ -33,4 +34,4 @@ class GraphState(TypedDict): web_search_documents: List[str] generated_count: int - chat_history: Annotated[list[HumanMessage | AIMessage], add_messages] \ No newline at end of file + chat_history: Annotated[List[BaseMessage], add_messages] \ No newline at end of file diff --git a/RAG/nodes/contextualize_query.py b/RAG/nodes/contextualize_query.py index d332a47..42a20e3 100644 --- a/RAG/nodes/contextualize_query.py +++ b/RAG/nodes/contextualize_query.py @@ -5,35 +5,21 @@ from RAG.graph_state import GraphState import os -contextualize_q_system_prompt = ( - "Given a chat history and the latest user question " - "which might reference context in the chat history, " - "formulate a standalone question which can be understood " - "without the chat history. Do NOT answer the question, " - "just reformulate it if needed and otherwise return it as is." -) - -contextualize_q_prompt = ChatPromptTemplate.from_messages( - [ - ("system", contextualize_q_system_prompt), - MessagesPlaceholder("chat_history"), - ("human", "{input}"), - ] -) def contextualize_question(state): + print("---CONTEXTUALIZE QUESTION---") + question = state["question"] - # chat_history = state["chat_history"] - chat_history = GraphState.get_state({"configurable": {"thread_id": "1"}}).chat_history + chat_history = state["chat_history"] + print(chat_history) + result = contextualizer.invoke({"input": question, "chat_history": chat_history}) print("contextualised result", result.contextualized_question) - chat_history.append(HumanMessage(content=result.contextualized_question)) - state["chat_history"] = chat_history return { - "contextualized_question": result, + "contextualized_question": result.contextualized_question, "question": question, - "state": state + # "state": state } diff --git a/RAG/nodes/extract_queries.py b/RAG/nodes/extract_queries.py index 63dec9f..bd25367 100644 --- a/RAG/nodes/extract_queries.py +++ b/RAG/nodes/extract_queries.py @@ -1,6 +1,8 @@ from RAG.agents.extractor import question_extractor +from langchain_core.messages import HumanMessage def extract_queries(state): + from RAG.graph import app """ Extract queries for vector search and web search. @@ -12,10 +14,13 @@ def extract_queries(state): """ print("---EXTRACT QUERIES---") - question = state["question"] + question = state["contextualized_question"] # question = state["contextualized_question"] - print(state["question"]) - print(question) + # state["chat_history"].append(HumanMessage(content=question)) + print("chat_history", state["chat_history"]) + # config = {"configurable": {"thread_id": 1}} + # print(app.get_state(config=config)) + source = question_extractor.invoke({"question": question}) return { @@ -24,5 +29,5 @@ def extract_queries(state): "sajith_vector_search_query": source.sajith_vector_search_query, "web_search_query": source.web_search_query, "question": question, - "state": state + # "state": state } diff --git a/graph_image.png b/graph_image.png index 53b265954b3fa74fa84aaa609991032e71286fd4..79747402b5651462ce1afc65b2d98742cfedce2e 100644 GIT binary patch literal 9010 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 F{{ZVCnS=lU literal 25398 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 Y`KxO8XVLIK694~Q%Ju&Xo?jFH4;70ph5!Hn diff --git a/main.py b/main.py index 3765ffe..1fa7d8e 100644 --- a/main.py +++ b/main.py @@ -4,7 +4,7 @@ from fastapi import FastAPI, Request from RAG.graph import app as rag_app - +from langchain.memory import ConversationBufferMemory from dotenv import load_dotenv import os @@ -13,6 +13,9 @@ load_dotenv() +memory = ConversationBufferMemory() +# Create a dictionary to store ConversationBufferMemory instances for each thread +thread_memories = {} from fastapi.middleware.cors import CORSMiddleware @@ -103,7 +106,8 @@ async def process(request: Request): question = data.get("question", "") # Run inputs = { - "question": question + "question": question, + "chat_history": memory.load_memory_variables({})["history"] } response = [] @@ -122,10 +126,17 @@ async def chat(request: dict): question = request.get("question") thread_id = request.get("thread_id") - print(question) + # Get or create a ConversationBufferMemory instance for this thread + if thread_id not in thread_memories: + thread_memories[thread_id] = ConversationBufferMemory(return_messages=True) + + memory = thread_memories[thread_id] + chat_history = memory.load_memory_variables({})["history"] + # Prepare inputs with chat history inputs = { - "question": question + "question": question, + "chat_history": chat_history } config = {"configurable": {"thread_id": thread_id}} @@ -136,8 +147,13 @@ async def chat(request: dict): pprint("\n---\n") # Final generation - pprint(value["generation"]) - return {"answer": value["generation"]} + # pprint(value["generation"]) + # return {"answer": value["generation"]} + if final_output and "generation" in final_output: + # Add the interaction to memory + memory.chat_memory.add_user_message(question) + memory.chat_memory.add_ai_message(final_output["generation"]) + return value if __name__ == "__main__": import uvicorn From 65ae30cc642dcf262b5f207b2b3511879326afc7 Mon Sep 17 00:00:00 2001 From: Savith Panamgama Date: Wed, 18 Sep 2024 04:32:45 +0530 Subject: [PATCH 08/11] feat: contextualisation done --- RAG/agents/contextualize.py | 12 ++++++++---- main.py | 6 +++--- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/RAG/agents/contextualize.py b/RAG/agents/contextualize.py index b036db6..bf3f61c 100644 --- a/RAG/agents/contextualize.py +++ b/RAG/agents/contextualize.py @@ -14,11 +14,15 @@ class ContextualizeQuestion(BaseModel): ) contextualize_q_system_prompt = ( - "Given a chat history and the latest user question " + "Given a chat history and the latest user question, " "which might reference context in the chat history, " - "formulate a standalone question which can be understood " - "without the chat history. Do NOT answer the question, " - "just reformulate it if needed and otherwise return it as is." + "formulate a standalone question that can be understood " + "without the chat history. Specifically:" + "\n1. Replace pronouns (e.g., 'he', 'she', 'it', 'they') with their specific referents." + "\n2. Expand references like 'that', 'this', 'those' to what they specifically refer to." + "\n3. Include any relevant context from previous messages that's necessary to understand the question." + "\n4. Ensure the reformulated question is clear, specific, and self-contained." + "\nDo NOT answer the question, just reformulate it to be self-explanatory." ) load_dotenv() diff --git a/main.py b/main.py index 1fa7d8e..19e7e16 100644 --- a/main.py +++ b/main.py @@ -149,10 +149,10 @@ async def chat(request: dict): # Final generation # pprint(value["generation"]) # return {"answer": value["generation"]} - if final_output and "generation" in final_output: + # if final_output and "generation" in final_output: # Add the interaction to memory - memory.chat_memory.add_user_message(question) - memory.chat_memory.add_ai_message(final_output["generation"]) + memory.chat_memory.add_user_message(question) + # memory.chat_memory.add_ai_message(final_output["generation"]) return value if __name__ == "__main__": From 149c4d8146fcd8b3edc022d4e8f5673cd8e11e53 Mon Sep 17 00:00:00 2001 From: Savith Panamgama Date: Wed, 18 Sep 2024 04:39:16 +0530 Subject: [PATCH 09/11] uncomment the left out parts --- RAG/graph.py | 41 ++++++++++++++++++++--------------------- graph_image.png | Bin 9010 -> 28065 bytes 2 files changed, 20 insertions(+), 21 deletions(-) diff --git a/RAG/graph.py b/RAG/graph.py index 86c6daf..e11fefa 100644 --- a/RAG/graph.py +++ b/RAG/graph.py @@ -18,32 +18,31 @@ workflow = StateGraph(GraphState) -# workflow.add_node("web_search", web_search) # web search -# workflow.add_node("retrieve", retrieve) # retrieve -# workflow.add_node("generate", generate) # generatae -# workflow.add_node("transform_query", transform_query) # transform_query +workflow.add_node("web_search", web_search) # web search +workflow.add_node("retrieve", retrieve) # retrieve +workflow.add_node("generate", generate) # generatae +workflow.add_node("transform_query", transform_query) # transform_query workflow.add_node("contextualize", contextualize) workflow.add_node("extract queries", extract_queries) workflow.add_edge(START, "contextualize") workflow.add_edge("contextualize", "extract queries") -workflow.add_edge("extract queries", END) -# workflow.add_edge("extract queries", "web_search") -# workflow.add_edge("extract queries", "retrieve") - -# workflow.add_edge(["web_search", "retrieve"], "generate") - -# workflow.add_conditional_edges( -# "generate", -# grade_generation_v_documents_and_question, -# { -# "not supported": "generate", -# "useful": END, -# "not useful": "transform_query", -# }, -# ) - -# workflow.add_edge("transform_query", "extract queries") +workflow.add_edge("extract queries", "web_search") +workflow.add_edge("extract queries", "retrieve") + +workflow.add_edge(["web_search", "retrieve"], "generate") + +workflow.add_conditional_edges( + "generate", + grade_generation_v_documents_and_question, + { + "not supported": "generate", + "useful": END, + "not useful": "transform_query", + }, +) + +workflow.add_edge("transform_query", "extract queries") from langgraph.checkpoint.memory import MemorySaver diff --git a/graph_image.png b/graph_image.png index 79747402b5651462ce1afc65b2d98742cfedce2e..47eabb7def55d809cb8491071fcec048b7c3c73a 100644 GIT binary patch literal 28065 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 literal 9010 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 F{{ZVCnS=lU From 4a5fd3b28f96f497edc049f566a6b9864ee730b8 Mon Sep 17 00:00:00 2001 From: Savith Panamgama Date: Wed, 18 Sep 2024 04:53:19 +0530 Subject: [PATCH 10/11] refactor: clean up code --- RAG/graph.py | 53 +------------------------------- RAG/nodes/contextualize_query.py | 6 ---- RAG/nodes/extract_queries.py | 14 +++------ RAG/nodes/grade_documents.py | 1 + RAG/nodes/retrieve.py | 2 +- 5 files changed, 7 insertions(+), 69 deletions(-) diff --git a/RAG/graph.py b/RAG/graph.py index e11fefa..8cdb7dc 100644 --- a/RAG/graph.py +++ b/RAG/graph.py @@ -55,55 +55,4 @@ f.write(graph_image) except Exception: pass - -# workflow = StateGraph(GraphState) - -# # Initialize the graph state -# # def init_graph_state(): -# # return { -# # "chat_history": InMemoryChatMessageHistory(), -# # } - -# # workflow.set_initial_state(init_graph_state) - -# workflow.add_node("extract queries", extract_queries) -# workflow.add_node("web_search", web_search) -# workflow.add_node("retrieve", retrieve) -# workflow.add_node("generate", generate) -# workflow.add_node("transform_query", transform_query) - -# # workflow.add_edge(START, "contextualize") -# workflow.add_edge(START, "extract_queries") -# # workflow.add_edge("contextualize", "extract queries") -# # workflow.add_edge("extract queries", END) -# workflow.add_edge("extract queries", "web_search") -# workflow.add_edge("extract queries", "retrieve") -# workflow.add_edge(["web_search", "retrieve"], "generate") - -# workflow.add_conditional_edges( -# "generate", -# grade_generation_v_documents_and_question, -# { -# "not supported": "generate", -# "useful": END, -# "not useful": "transform_query", -# }, -# ) - -# workflow.add_edge("transform_query", "extract queries") - -# checkpointer = MemorySaver() -# app = workflow.compile(checkpointer=checkpointer) - -# # config = {"configurable": {"thread_id": "1"}} - -# # Usage -# # load_dotenv() -# # mistral_api_key = os.getenv("MISTRAL_API_KEY") - -# # if not mistral_api_key: -# # raise ValueError("MISTRAL_API_KEY environment variable not set") - -# # # Initialize the ChatMistralAI client with the API key -# # llm = ChatMistralAI(model="mistral-large-latest", api_key=mistral_api_key) -# # app = create_workflow(llm) # Pass your LLM instance here + \ No newline at end of file diff --git a/RAG/nodes/contextualize_query.py b/RAG/nodes/contextualize_query.py index 42a20e3..7dfe97e 100644 --- a/RAG/nodes/contextualize_query.py +++ b/RAG/nodes/contextualize_query.py @@ -11,15 +11,9 @@ def contextualize_question(state): question = state["question"] chat_history = state["chat_history"] - - print(chat_history) - result = contextualizer.invoke({"input": question, "chat_history": chat_history}) - print("contextualised result", result.contextualized_question) return { "contextualized_question": result.contextualized_question, - "question": question, - # "state": state } diff --git a/RAG/nodes/extract_queries.py b/RAG/nodes/extract_queries.py index bd25367..caeb71b 100644 --- a/RAG/nodes/extract_queries.py +++ b/RAG/nodes/extract_queries.py @@ -14,20 +14,14 @@ def extract_queries(state): """ print("---EXTRACT QUERIES---") - question = state["contextualized_question"] - # question = state["contextualized_question"] - # state["chat_history"].append(HumanMessage(content=question)) - print("chat_history", state["chat_history"]) - # config = {"configurable": {"thread_id": 1}} - # print(app.get_state(config=config)) - - source = question_extractor.invoke({"question": question}) + + contextualized_question = state["contextualized_question"] + source = question_extractor.invoke({"question": contextualized_question}) return { "namal_vector_search_query": source.namal_vector_search_query, "ranil_vector_search_query": source.ranil_vector_search_query, "sajith_vector_search_query": source.sajith_vector_search_query, "web_search_query": source.web_search_query, - "question": question, - # "state": state + "question": contextualized_question, } diff --git a/RAG/nodes/grade_documents.py b/RAG/nodes/grade_documents.py index 53f0a9e..2c65afb 100644 --- a/RAG/nodes/grade_documents.py +++ b/RAG/nodes/grade_documents.py @@ -12,6 +12,7 @@ def grade_documents(state): """ print("---CHECK DOCUMENT RELEVANCE TO QUESTION---") + question = state["question"] documents = state["documents"] diff --git a/RAG/nodes/retrieve.py b/RAG/nodes/retrieve.py index bb2feda..4a662c8 100644 --- a/RAG/nodes/retrieve.py +++ b/RAG/nodes/retrieve.py @@ -13,7 +13,7 @@ def retrieve(state): state (dict): New key added to state, documents, that contains retrieved documents """ print("---RETRIEVE---") - print(state) + namal_vector_search_query = state["namal_vector_search_query"] ranil_vector_search_query = state["ranil_vector_search_query"] sajith_vector_search_query = state["sajith_vector_search_query"] From 4a50ab9eaa35b7c265948cd0bc0194d148635d54 Mon Sep 17 00:00:00 2001 From: Savith Panamgama Date: Wed, 18 Sep 2024 22:15:36 +0530 Subject: [PATCH 11/11] Delete .env --- .env | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 .env diff --git a/.env b/.env deleted file mode 100644 index f31682d..0000000 --- a/.env +++ /dev/null @@ -1,3 +0,0 @@ -LANGCHAIN_TRACING_V2=true -LANGCHAIN_API_KEY=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 -MISTRAL_API_KEY=naAG2SIBHoKW5KtKS7B2MN5z49roSnzV \ No newline at end of file