User-Manual-Chatbot / create_rag_agent.py
syildizz's picture
Initial commit.
1ae5927
# rag_gemini_chroma_v1_0_1_fixed.py
import os
from typing import Any
from dotenv import load_dotenv
from langchain.agents import create_agent
from langchain_huggingface import HuggingFaceEmbeddings
from langgraph.graph.state import CompiledStateGraph
from pydantic import SecretStr
from huggingface_hub import snapshot_download
# Core types and prompt
from langchain_core.documents import Document
# Document loaders, text splitters, vectorstore (community / ecosystem packages)
from langchain_chroma import Chroma
# Google Gemini provider and embeddings package
from langchain_google_genai import ChatGoogleGenerativeAI
from langchain.tools import tool
import config
# Instead, LCEL (Runnable components) is used for chain composition.
def get_chroma_store(
chroma_persist_directory: str = config.chroma_persist_directory,
huggingface_embedding_model_repo_path: str = config.huggingface_embedding_model_repo_path,
huggingface_vector_embedding_database_repo_path: str = config.huggingface_vector_embedding_database_repo_path,
) -> Chroma:
"""
Load an existing Chroma store if present, otherwise create from docs and persist.
This version uses lazy loading and batch processing to prevent memory issues.
"""
embedding_model = HuggingFaceEmbeddings(model_name=huggingface_embedding_model_repo_path)
# 3) Check for existing Chroma DB and load it
if os.path.exists(chroma_persist_directory) and os.path.isdir(chroma_persist_directory):
print(f"✅ Loading existing Chroma DB from: {chroma_persist_directory}")
else:
print("📥 No local Chroma DB found. Pulling from Hugging Face dataset...")
# Create local directory
os.makedirs(chroma_persist_directory, exist_ok=True)
# Download all files from the Hugging Face dataset
snapshot_download( # pyright: ignore[reportUnusedCallResult]
repo_id=huggingface_vector_embedding_database_repo_path,
repo_type="dataset",
local_dir=chroma_persist_directory,
ignore_patterns=["*.md", "*.json"], # Optional: skip non-DB files like README,
)
print(f"✅ Pulled and persisted Chroma DB to: {chroma_persist_directory}")
return Chroma(
embedding_function=embedding_model,
persist_directory=chroma_persist_directory
)
def create_rag_agent(
google_llm_model_name: str = config.google_llm_model_name,
temperature: float = 0.3
) -> CompiledStateGraph[Any]:
load_dotenv() # pyright: ignore[reportUnusedCallResult]
gemini_api_key = os.getenv("GEMINI_API_KEY")
if not gemini_api_key:
raise ValueError("Missing GEMINI_API_KEY in environment")
vector_store = get_chroma_store()
# 6) Create Gemini chat model (LLM)
llm = ChatGoogleGenerativeAI(model=google_llm_model_name, temperature=temperature, google_api_key=SecretStr(gemini_api_key))
# 7) Prompt template
# Note: The prompt input variables must match the dict passed to the model
system_prompt = """
You are provided with a list of sample text that comes from various different user manuals.
Your task is to respond to the user using the samples provided to the best of your abilities.
The context text is in the following paragraph.
"""
# Helper to format documents for the prompt
def format_docs(docs: list[Document]) -> str:
"""Formats a list of documents into a single string."""
return "\n".join(doc.page_content for doc in docs)
# 8) Build RAG chain using LCEL (LangChain Expression Language)
# The chain structure is:
# { 'context': retriever | format_docs, 'input': RunnablePassthrough() } | prompt | llm
@tool #fonksiyonun hem cevap (content) hem de kaynak/detay (artifact) döndüreceğini belirtir.
def retrieve_context(query: str) -> str:
'''Sorguyu yanıtlamaya yardımcı olacak bilgileri getir.'''
retrieved_docs = vector_store.similarity_search(query, k=5)
return format_docs(retrieved_docs)
rag_agent = create_agent(llm, [retrieve_context], system_prompt=system_prompt)
return rag_agent
if __name__ == "__main__":
rag_agent = create_rag_agent()
result: dict[str, Any] | Any = rag_agent.invoke(
{"messages": [{"role": "user", "content": "I want to replace the batteries of a sony brand remote. What can I do?"}]}
)