Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion langchain-crash-course/4_rag/logs/rag_application.log
Original file line number Diff line number Diff line change
Expand Up @@ -139,4 +139,4 @@
2025-08-26 23:24:09,222 - 8_rag_web_scrape_firecrawl.py - INFO - Querying vector store 'chroma_db_web_scrape_firecrawl'...
2025-08-26 23:24:09,222 - 8_rag_web_scrape_firecrawl.py - INFO - Vector store 'chroma_db_web_scrape_firecrawl' already exists. No need to initialize.
2025-08-26 23:24:10,098 - 8_rag_web_scrape_firecrawl.py - INFO - Relevant documents retrieved successfully.
2025-08-26 23:45:35,451 - 8_rag_web_scrape_firecrawl.py - INFO - User exited conversation
2025-08-26 23:45:35,451 - 8_rag_web_scrape_firecrawl.py - INFO - User exited conversation2025-11-04 21:31:41,119 - rag_with_metadata.py - INFO - ==================================================
2 changes: 1 addition & 1 deletion langchain-crash-course/4_rag/utils/logger.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def setup(module_name: str) -> logging.Logger:

# Create formatters and handlers
formatter: logging.Formatter = logging.Formatter(
"%(asctime)s - %(name)s - %(levelname)s - %(message)s"
"%(asctime)s - %(levelname)s - %(module)s - %(message)s"
)

# Rotating file handler
Expand Down
3 changes: 2 additions & 1 deletion langchain-crash-course/5_agents_tools/agent_react_chat.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@


# Module path
module_path: Path = Path(__file__).resolve().parent
module_path: Path = Path(__file__).resolve()

# Set logger
logger: Logger = RAGLogger.get_logger(module_name=module_path.name)
Expand Down Expand Up @@ -178,6 +178,7 @@ async def main() -> None:
input={"input": query},
config={"configurable": {"session_id": session_id}},
)
logger.info(msg=f"Agent: {response['output'][:100]}.....")
print(f"Agent: {response['output']}")

except (KeyboardInterrupt, EOFError):
Expand Down
203 changes: 203 additions & 0 deletions langchain-crash-course/5_agents_tools/agent_react_rag_context.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
# agent_react_rag_context.py

# Import standard libraries
import sys
from logging import Logger
from pathlib import Path
from typing import Any

# Import environment variables
from dotenv import load_dotenv

# Import langchain modules
from langchain.chains import (
create_history_aware_retriever,
create_retrieval_chain,
)
from langchain.chains.combine_documents import create_stuff_documents_chain
from langchain_chroma import Chroma
from langchain_core.messages import AIMessage, HumanMessage
from langchain_core.messages.base import BaseMessage
from langchain_core.prompts.chat import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.runnables.base import Runnable
from langchain_core.vectorstores.base import VectorStoreRetriever
from langchain_ollama import ChatOllama
from langchain_ollama.embeddings import OllamaEmbeddings

# Import custom logger
from utils.logger import RAGLogger

# Load environment variables
load_dotenv()

# Module path
module_path: Path = Path(__file__).resolve()

# Set logger
logger: Logger = RAGLogger.get_logger(module_name=module_path.name)

# Log application startup
logger.info(msg="=" * 50)
logger.info(msg="Starting Agent ReAct RAG Context Application")
logger.info(msg="=" * 50)

# Define directories and paths
rag_dir: Path = Path(__file__).parents[1] / "4_rag"
books_dir: Path = rag_dir / "books"
db_dir: Path = rag_dir / "db"
store_name: str = "chroma_db_with_metadata"
persistent_directory: Path = db_dir / store_name

# Define embeddings models
ollama_embeddings = OllamaEmbeddings(
model="nomic-embed-text:latest",
)

# Define LLM
llm = ChatOllama(model="gemma3:4b")

# Check vector store existence
if not persistent_directory.exists():
logger.error(
msg=f"Vector store '{store_name}' does not exist. Please check the path."
)
sys.exit(1)

# Load vector store and create retriever
try:
logger.info(msg=f"Loading vector store '{store_name}'...")
# Load the Chroma vector store
db: Chroma = Chroma(
persist_directory=str(persistent_directory),
embedding_function=ollama_embeddings,
)
# Create a retriever
retriever: VectorStoreRetriever = db.as_retriever(
search_type="similarity",
search_kwargs={"k": 3},
)
logger.info(msg=f"Created retriever from vector store '{store_name}' successfully.")

except Exception as e:
logger.error(msg=f"Unexpected error querying vector store '{store_name}': {e}")
sys.exit(1)

# Contextualize question prompt
# System prompt helps the AI understand that it should reformulate the question
# based on the chat history to make it a standalone question
contextualize_q_system_prompt = """
Given a chat history and the latest user question, this prompt helps the AI reformulate
the question to be standalone. The reformulated question should be understandable
without relying on prior chat context. The AI should not answer the question—only
rephrase it if necessary, or return it unchanged if already standalone.
"""

# Create contextualize question prompt template
contextualize_q_prompt_template: ChatPromptTemplate = ChatPromptTemplate.from_messages(
messages=[
("system", contextualize_q_system_prompt),
MessagesPlaceholder(variable_name="chat_history"),
("human", "{input}"),
]
)

# Create a history-aware retriever
# this users the LLM to help reformulate the question based on chat history
history_aware_retriever: VectorStoreRetriever = create_history_aware_retriever(
llm,
retriever,
contextualize_q_prompt_template,
)

# Answer question prompt
# This system prompt helps the AI understand that it should provide concise answers
# based on the retrieved context and indicates what to do if the answer is unknown
qa_system_prompt = """
You are an assistant for question-answering tasks.
Use the following pieces of retrieved context to answer the question.
If you don't know the answer, just say that you don't know.
Limit your response to a maximum of ten sentences and keep the answer concise.
\n\n
{context}
"""

# Create answer question prompt template
qa_prompt_template: ChatPromptTemplate = ChatPromptTemplate.from_messages(
messages=[
("system", qa_system_prompt),
MessagesPlaceholder(variable_name="chat_history"),
("human", "{input}"),
]
)

# Create a chain to combine documents for question answering
# `create_stuff_documents_chain` feeds all retrieved context into the LLM
question_answering_chain: Runnable[dict[str, Any], Any] = create_stuff_documents_chain(
llm=llm, prompt=qa_prompt_template
)

# Create a RAG chain that combines the history-aware retriever and the question answering chain
rag_chain: Runnable[dict[str, Any], Any] = create_retrieval_chain(
history_aware_retriever, question_answering_chain
)


# Run RAG LLM conversation
def main() -> None:
"""
Runs the main conversational loop for the RAG-based chat application.

This function initializes the chat history and enters an infinite loop to
continuously accept user input. It processes the user's query through the
RAG chain, prints the AI's response, and updates the chat history.
The loop can be exited by typing 'exit', or by sending a
KeyboardInterrupt (Ctrl+C) or EOFError (Ctrl+D).
"""
print("\nStart chatting with AI! Type 'exit' to end the conversation.")

# Initialize chat history
chat_history: list[BaseMessage] = []

while True:
try:
# User query
query: str = input("You: ").strip()

if not query:
continue

if query.lower() == "exit":
logger.info(msg="User exited conversation")
print("Exiting...")
break

# Process user query through RAG chain
logger.info(msg="Processing user query through RAG chain...")
result: Any = rag_chain.invoke(
input={"input": query, "chat_history": chat_history}
)

# Display AI response
if result:
logger.info(msg="AI response generated successfully")
print(f"AI: {result['answer']}")

# Update chat history
chat_history.append(HumanMessage(content=query))
chat_history.append(AIMessage(content=result["answer"]))
logger.info(msg="Chat history updated successfully")

except (KeyboardInterrupt, EOFError):
logger.info(msg="Keyboard interrupt or EOF error")
print("Exiting...")
break

except Exception as e:
logger.error(msg=f"Unexpected error: {e}")
print("Exiting...")
break


# Main entry point
if __name__ == "__main__":
main()
4 changes: 2 additions & 2 deletions langchain-crash-course/5_agents_tools/agent_tools_basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@


# Module path
module_path: Path = Path(__file__).resolve().parent
module_path: Path = Path(__file__).resolve()

# Set logger
logger: Logger = RAGLogger.get_logger(module_name=module_path.name)
Expand Down Expand Up @@ -161,7 +161,7 @@ async def main() -> None:

# Run agent executor
response: Any = await agent_executor.ainvoke(input={"input": query})
logger.info(msg="Agent response generated successfully")
logger.info(msg=f"Agent: {response['output']}")
print(f"Agent: {response['output']}")

except (KeyboardInterrupt, EOFError):
Expand Down
30 changes: 22 additions & 8 deletions langchain-crash-course/5_agents_tools/logs/agent_tools.log
Original file line number Diff line number Diff line change
@@ -1,8 +1,22 @@
2025-08-31 22:51:29,350 - 5_agents_tools - INFO - Start Agent Tools Basic Application...
2025-08-31 22:52:03,279 - 5_agents_tools - INFO - Agent response generated successfully
2025-08-31 22:52:11,062 - 5_agents_tools - INFO - User exited conversation
2025-09-04 21:00:41,977 - 5_agents_tools - INFO - Start Agent React Chat Application...
2025-09-04 21:01:15,876 - 5_agents_tools - INFO - Getting current time: 2025-09-04 21:01:15
2025-09-04 21:01:56,097 - 5_agents_tools - ERROR - Error getting Wikipedia summary: Page id "michael jacks" does not match any pages. Try another id!
2025-09-04 21:02:05,819 - 5_agents_tools - INFO - Getting Wikipedia summary: Michael Joseph Jackson (August 29, 1958 – June 25, 2009) was an American singer, songwriter, dancer,.....
2025-09-04 21:30:59,868 - 5_agents_tools - INFO - User exited conversation
2025-09-25 15:26:55,633 - agent_tools_basic.py - INFO - Start Agent Tools Basic Application...
2025-09-25 15:27:19,931 - agent_tools_basic.py - INFO - Agent response generated successfully
2025-09-25 15:27:35,672 - agent_tools_basic.py - INFO - User exited conversation
2025-09-25 15:52:42,338 - agent_react_chat.py - INFO - Start Agent React Chat Application...
2025-09-25 15:53:17,567 - agent_react_chat.py - INFO - Getting Wikipedia summary: Microsoft Corporation is an American multinational corporation and technology conglomerate headquart.....
2025-09-25 15:53:29,552 - agent_react_chat.py - INFO - Getting Wikipedia summary: Microsoft Corporation is an American multinational corporation and technology conglomerate headquart.....
2025-09-25 15:53:50,242 - agent_react_chat.py - INFO - Agent: Microsoft is a massive technology company with a rich history. It was founded in 1975 by Bill Gates .....
2025-09-25 15:54:34,323 - agent_react_chat.py - ERROR - Error getting Wikipedia summary: Page id "bill games" does not match any pages. Try another id!
2025-09-25 15:54:45,004 - agent_react_chat.py - INFO - Agent: Bill Gates is a prominent American business magnate, investor, and philanthropist. He co-founded Mic.....
2025-09-25 15:55:00,779 - agent_react_chat.py - INFO - User exited conversation
2025-11-04 22:52:56,368 - INFO - agent_react_rag_context - ==================================================
2025-11-04 22:52:56,368 - INFO - agent_react_rag_context - Starting Agent ReAct RAG Context Application
2025-11-04 22:52:56,368 - INFO - agent_react_rag_context - ==================================================
2025-11-04 22:52:58,444 - INFO - agent_react_rag_context - Loading vector store 'chroma_db_with_metadata'...
2025-11-04 22:52:58,589 - INFO - agent_react_rag_context - Created retriever from vector store 'chroma_db_with_metadata' successfully.
2025-11-04 22:54:46,933 - INFO - agent_react_rag_context - Processing user query through RAG chain...
2025-11-04 22:55:14,195 - INFO - agent_react_rag_context - AI response generated successfully
2025-11-04 22:55:14,198 - INFO - agent_react_rag_context - Chat history updated successfully
2025-11-04 22:57:53,311 - INFO - agent_react_rag_context - Processing user query through RAG chain...
2025-11-04 22:58:41,439 - INFO - agent_react_rag_context - AI response generated successfully
2025-11-04 22:58:41,466 - INFO - agent_react_rag_context - Chat history updated successfully
2025-11-04 22:59:12,397 - INFO - agent_react_rag_context - User exited conversation
2 changes: 1 addition & 1 deletion langchain-crash-course/5_agents_tools/utils/logger.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def setup(module_name: str) -> logging.Logger:

# Create formatters and handlers
formatter: logging.Formatter = logging.Formatter(
"%(asctime)s - %(name)s - %(levelname)s - %(message)s"
"%(asctime)s - %(levelname)s - %(module)s - %(message)s"
)

# Rotating file handler
Expand Down