1010from dotenv import load_dotenv
1111
1212# Import langchain modules
13+ from langchain import hub
14+ from langchain .agents import AgentExecutor , create_react_agent
1315from langchain .chains import (
1416 create_history_aware_retriever ,
1517 create_retrieval_chain ,
2022from langchain_core .messages .base import BaseMessage
2123from langchain_core .prompts .chat import ChatPromptTemplate , MessagesPlaceholder
2224from langchain_core .runnables .base import Runnable
25+ from langchain_core .tools import Tool
2326from langchain_core .vectorstores .base import VectorStoreRetriever
2427from langchain_ollama import ChatOllama
2528from langchain_ollama .embeddings import OllamaEmbeddings
4144logger .info (msg = "Starting Agent ReAct RAG Context Application" )
4245logger .info (msg = "=" * 50 )
4346
47+ # ===== Setup RAG =====
4448# Define directories and paths
4549rag_dir : Path = Path (__file__ ).parents [1 ] / "4_rag"
46- books_dir : Path = rag_dir / "books"
4750db_dir : Path = rag_dir / "db"
4851store_name : str = "chroma_db_with_metadata"
4952persistent_directory : Path = db_dir / store_name
102105)
103106
104107# Create a history-aware retriever
105- # this users the LLM to help reformulate the question based on chat history
108+ # this helps LLM to reformulate the question based on chat history
106109history_aware_retriever : VectorStoreRetriever = create_history_aware_retriever (
107110 llm ,
108111 retriever ,
141144 history_aware_retriever , question_answering_chain
142145)
143146
147+ # ===== Setup ReAct Agent with RAG =====
148+ # load ReAct prompt template from hub
149+ react_prompt_template : Any = hub .pull (owner_repo_commit = "hwchase17/react" )
150+
151+ # create a tool that uses the RAG chain
152+ tools : list [Tool ] = [
153+ Tool (
154+ name = "Answer Question" ,
155+ func = lambda input , ** kwargs : rag_chain .invoke (
156+ input = {"input" : input , "chat_history" : kwargs .get ("chat_history" , [])}
157+ ),
158+ description = "Useful for answering questions based on the provided context." ,
159+ ),
160+ ]
161+
162+ # Create a ReAct agent with the RAG tool
163+ agent : Runnable [Any , Any ] = create_react_agent (
164+ tools = tools ,
165+ llm = llm ,
166+ prompt = react_prompt_template ,
167+ )
168+
169+ # Create agent executor
170+ agent_executor : AgentExecutor = AgentExecutor (
171+ agent = agent , tools = tools , verbose = True , handle_parsing_errors = True
172+ )
144173
145- # Run RAG LLM conversation
174+
175+ # ===== Run ReAct RAG conversation =====
146176def main () -> None :
147177 """
148- Runs the main conversational loop for the RAG-based chat application.
178+ Runs the main conversational loop for the RAG-based ReAct chat application.
149179
150180 This function initializes the chat history and enters an infinite loop to
151181 continuously accept user input. It processes the user's query through the
152182 RAG chain, prints the AI's response, and updates the chat history.
153183 The loop can be exited by typing 'exit', or by sending a
154184 KeyboardInterrupt (Ctrl+C) or EOFError (Ctrl+D).
155185 """
156- print ("\n Start chatting with AI ! Type 'exit' to end the conversation." )
186+ print ("\n Start RAG-based ReAct chatting ! Type 'exit' to end the conversation." )
157187
158188 # Initialize chat history
159189 chat_history : list [BaseMessage ] = []
@@ -164,27 +194,30 @@ def main() -> None:
164194 query : str = input ("You: " ).strip ()
165195
166196 if not query :
197+ print ("Please ask a question!." )
167198 continue
168199
169200 if query .lower () == "exit" :
170201 logger .info (msg = "User exited conversation" )
171202 print ("Exiting..." )
172203 break
173204
174- # Process user query through RAG chain
175- logger .info (msg = "Processing user query through RAG chain..." )
176- result : Any = rag_chain .invoke (
205+ # Process user query through agent executor
206+ logger .info (
207+ msg = "Processing user query through ReAct Agent with RAG chain..."
208+ )
209+ response : Any = agent_executor .invoke (
177210 input = {"input" : query , "chat_history" : chat_history }
178211 )
179212
180213 # Display AI response
181- if result :
214+ if response :
182215 logger .info (msg = "AI response generated successfully" )
183- print (f"AI: { result [ 'answer ' ]} " )
216+ print (f"AI: { response [ 'output ' ]} " )
184217
185218 # Update chat history
186219 chat_history .append (HumanMessage (content = query ))
187- chat_history .append (AIMessage (content = result [ "answer " ]))
220+ chat_history .append (AIMessage (content = response [ "output " ]))
188221 logger .info (msg = "Chat history updated successfully" )
189222
190223 except (KeyboardInterrupt , EOFError ):
0 commit comments