From 64d4052e10b8062d77bb5e0d7531983509ea5c30 Mon Sep 17 00:00:00 2001 From: Madhu Date: Fri, 31 Jan 2025 22:03:09 +0530 Subject: [PATCH 1/8] New project with gemini thinking --- .../ai_gemini_thinking_agent/README.md | 0 .../ai_gemini_thinking_agent/main.py | 20 +++++++++++++++++ .../ai_gemini_thinking_agent/requirements.txt | 0 .../ai_gemini_thinking_agent/test.py | 22 +++++++++++++++++++ 4 files changed, 42 insertions(+) create mode 100644 ai_agent_tutorials/ai_gemini_thinking_agent/README.md create mode 100644 ai_agent_tutorials/ai_gemini_thinking_agent/main.py create mode 100644 ai_agent_tutorials/ai_gemini_thinking_agent/requirements.txt create mode 100644 ai_agent_tutorials/ai_gemini_thinking_agent/test.py diff --git a/ai_agent_tutorials/ai_gemini_thinking_agent/README.md b/ai_agent_tutorials/ai_gemini_thinking_agent/README.md new file mode 100644 index 0000000..e69de29 diff --git a/ai_agent_tutorials/ai_gemini_thinking_agent/main.py b/ai_agent_tutorials/ai_gemini_thinking_agent/main.py new file mode 100644 index 0000000..35995c9 --- /dev/null +++ b/ai_agent_tutorials/ai_gemini_thinking_agent/main.py @@ -0,0 +1,20 @@ +from agno.agent import Agent +from agno.models.openai import OpenAIChat +from agno.models.google import Gemini +from agno.tools.duckduckgo import DuckDuckGoTools +from agno.tools.yfinance import YFinanceTools +import os +from dotenv import load_dotenv +load_dotenv() + +thinking_agent = Agent( + name="Thinking Agent", + role="Think about the problem", + model=Gemini(id="gemini-2.0-flash-thinking-exp-1219", api_key=os.getenv("GOOGLE_API_KEY")), + instructions="Given the problem, think about it and provide a detailed explanation", + show_tool_calls=True, + markdown=True, +) + + +thinking_agent.print_response("Explain Deep Q Networks from first principles", stream=True) \ No newline at end of file diff --git a/ai_agent_tutorials/ai_gemini_thinking_agent/requirements.txt b/ai_agent_tutorials/ai_gemini_thinking_agent/requirements.txt new file mode 100644 index 0000000..e69de29 diff --git a/ai_agent_tutorials/ai_gemini_thinking_agent/test.py b/ai_agent_tutorials/ai_gemini_thinking_agent/test.py new file mode 100644 index 0000000..9149e46 --- /dev/null +++ b/ai_agent_tutorials/ai_gemini_thinking_agent/test.py @@ -0,0 +1,22 @@ +from google import genai +import os +from dotenv import load_dotenv +load_dotenv() + +client = genai.Client(api_key=os.getenv("GOOGLE_API_KEY"), http_options={'api_version':'v1alpha'}) + +import asyncio + +config = {'thinking_config': {'include_thoughts': True}} + +async def main(): + chat = client.aio.chats.create( + model='gemini-2.0-flash-thinking-exp', + config=config + ) + response = await chat.send_message('What is your name?') + print(response.text) + response = await chat.send_message('What did you just say before this?') + print(response.text) + +asyncio.run(main()) \ No newline at end of file From 5f5bebfc9fdb60a2c2a98aed3e68e6f6a5a0c284 Mon Sep 17 00:00:00 2001 From: Madhu Date: Fri, 31 Jan 2025 23:42:48 +0530 Subject: [PATCH 2/8] New project with gemini thinking1 --- .../ai_gemini_thinking_agent/main.py | 62 +++++++++++++++---- .../ai_gemini_thinking_agent/test.py | 4 +- .../ai_gemini_thinking_agent/test2.py | 21 +++++++ 3 files changed, 73 insertions(+), 14 deletions(-) create mode 100644 ai_agent_tutorials/ai_gemini_thinking_agent/test2.py diff --git a/ai_agent_tutorials/ai_gemini_thinking_agent/main.py b/ai_agent_tutorials/ai_gemini_thinking_agent/main.py index 35995c9..661642c 100644 --- a/ai_agent_tutorials/ai_gemini_thinking_agent/main.py +++ b/ai_agent_tutorials/ai_gemini_thinking_agent/main.py @@ -1,20 +1,58 @@ +import streamlit as st from agno.agent import Agent -from agno.models.openai import OpenAIChat from agno.models.google import Gemini from agno.tools.duckduckgo import DuckDuckGoTools from agno.tools.yfinance import YFinanceTools import os -from dotenv import load_dotenv -load_dotenv() -thinking_agent = Agent( - name="Thinking Agent", - role="Think about the problem", - model=Gemini(id="gemini-2.0-flash-thinking-exp-1219", api_key=os.getenv("GOOGLE_API_KEY")), - instructions="Given the problem, think about it and provide a detailed explanation", - show_tool_calls=True, - markdown=True, -) +# Streamlit App Title +st.title("AI Agent with Agno and Gemini Thinking") +# Sidebar for API Key Input +st.sidebar.header("Configuration") +api_key = st.sidebar.text_input("Enter your Google API Key", type="password") +if api_key: + os.environ["GOOGLE_API_KEY"] = api_key -thinking_agent.print_response("Explain Deep Q Networks from first principles", stream=True) \ No newline at end of file +# File/URL Upload Section +st.sidebar.header("Upload Data") +uploaded_file = st.sidebar.file_uploader("Upload a document", type=["txt", "pdf", "jpg", "png"]) +web_url = st.sidebar.text_input("Enter a web URL") + +# Initialize the Agent +if api_key: + thinking_agent = Agent( + name="Thinking Agent", + role="Think about the problem", + model=Gemini(id="gemini-2.0-flash-exp", api_key=api_key), + instructions="Given the problem, think about it and provide a detailed explanation", + show_tool_calls=True, + markdown=True, + ) + + # Chat Interface + st.header("Chat with the Agent") + user_input = st.text_input("Ask a question or describe the problem:") + + if user_input: + # Process the user's input + if uploaded_file: + # Handle file upload + file_content = uploaded_file.read() + st.write("File content:", file_content) + # Add logic to process the file content with the agent + response = thinking_agent.run(f"Given this file content: {file_content}, answer: {user_input}") + elif web_url: + # Handle web URL + st.write("Web URL:", web_url) + # Add logic to process the web URL with the agent + response = thinking_agent.run(f"Given this web URL: {web_url}, answer: {user_input}") + else: + # Handle normal chat + response = thinking_agent.run(user_input) + + # Display the response + st.write("Agent's Response:") + st.write(response.content) +else: + st.warning("Please enter your Google API Key in the sidebar to proceed.") \ No newline at end of file diff --git a/ai_agent_tutorials/ai_gemini_thinking_agent/test.py b/ai_agent_tutorials/ai_gemini_thinking_agent/test.py index 9149e46..c6b2d48 100644 --- a/ai_agent_tutorials/ai_gemini_thinking_agent/test.py +++ b/ai_agent_tutorials/ai_gemini_thinking_agent/test.py @@ -11,10 +11,10 @@ config = {'thinking_config': {'include_thoughts': True}} async def main(): chat = client.aio.chats.create( - model='gemini-2.0-flash-thinking-exp', + model='gemini-2.0-flash-thinking-exp-01-21', config=config ) - response = await chat.send_message('What is your name?') + response = await chat.send_message('Explain Deep Q Networks from first principles') print(response.text) response = await chat.send_message('What did you just say before this?') print(response.text) diff --git a/ai_agent_tutorials/ai_gemini_thinking_agent/test2.py b/ai_agent_tutorials/ai_gemini_thinking_agent/test2.py new file mode 100644 index 0000000..0a04959 --- /dev/null +++ b/ai_agent_tutorials/ai_gemini_thinking_agent/test2.py @@ -0,0 +1,21 @@ +from google import genai +import os +from dotenv import load_dotenv +load_dotenv() + +from google import genai + +client = genai.Client(api_key=os.getenv("GOOGLE_API_KEY"), http_options={'api_version':'v1alpha'}) + +config = {'thinking_config': {'include_thoughts': True}} +response = client.models.generate_content( + model='gemini-2.0-flash-thinking-exp-01-21', + contents='Explain how RLHF works in simple terms.', + config=config +) + +for part in response.candidates[0].content.parts: + if part.thought: + print(f"Model Thought:\n{part.text}\n") + else: + print(f"\nModel Response:\n{part.text}\n") \ No newline at end of file From 38911478ce06037e21d9978a06c8dad98e1caa47 Mon Sep 17 00:00:00 2001 From: Madhu Date: Sat, 1 Feb 2025 00:32:49 +0530 Subject: [PATCH 3/8] New project with gemini thinking --- .../ai_gemini_thinking_agent/main.py | 167 +++++++++++++++--- 1 file changed, 140 insertions(+), 27 deletions(-) diff --git a/ai_agent_tutorials/ai_gemini_thinking_agent/main.py b/ai_agent_tutorials/ai_gemini_thinking_agent/main.py index 661642c..c7f89c4 100644 --- a/ai_agent_tutorials/ai_gemini_thinking_agent/main.py +++ b/ai_agent_tutorials/ai_gemini_thinking_agent/main.py @@ -1,58 +1,171 @@ +import os import streamlit as st from agno.agent import Agent from agno.models.google import Gemini from agno.tools.duckduckgo import DuckDuckGoTools -from agno.tools.yfinance import YFinanceTools -import os +from langchain_community.document_loaders import PyPDFLoader, WebBaseLoader +from langchain.text_splitter import RecursiveCharacterTextSplitter +from langchain_qdrant import QdrantVectorStore +from qdrant_client import QdrantClient +from qdrant_client.models import Distance, VectorParams +from agno.vectordb.pgvector import PgVector +from agno.embedder.google import GeminiEmbedder +import tempfile +import bs4 # Streamlit App Title st.title("AI Agent with Agno and Gemini Thinking") # Sidebar for API Key Input st.sidebar.header("Configuration") -api_key = st.sidebar.text_input("Enter your Google API Key", type="password") -if api_key: - os.environ["GOOGLE_API_KEY"] = api_key +google_api_key = st.sidebar.text_input("Enter your Google API Key", type="password") +qdrant_api_key = st.sidebar.text_input("Enter your Qdrant API Key", type="password") +qdrant_url = st.sidebar.text_input("Enter your Qdrant URL", placeholder="https://your-qdrant-url.com") + +if google_api_key: + os.environ["GOOGLE_API_KEY"] = google_api_key + +# Initialize Qdrant Client +def init_qdrant(): + if not qdrant_api_key or not qdrant_url: + st.warning("Please provide Qdrant API Key and URL in the sidebar.") + return None + try: + client = QdrantClient(url=qdrant_url, api_key=qdrant_api_key, timeout=60) + client.get_collections() # Test connection + return client + except Exception as e: + st.error(f"Failed to initialize Qdrant: {e}") + return None + +qdrant_client = init_qdrant() # File/URL Upload Section st.sidebar.header("Upload Data") uploaded_file = st.sidebar.file_uploader("Upload a document", type=["txt", "pdf", "jpg", "png"]) web_url = st.sidebar.text_input("Enter a web URL") +# Document and Web URL Processing +def process_document(file): + try: + with tempfile.NamedTemporaryFile(delete=False, suffix='.pdf') as tmp_file: + tmp_file.write(file.getvalue()) + tmp_path = tmp_file.name + + loader = PyPDFLoader(tmp_path) + documents = loader.load() + text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200) + texts = text_splitter.split_documents(documents) + + os.unlink(tmp_path) + return texts + except Exception as e: + st.error(f"Error processing document: {e}") + return [] + +def process_web_url(url): + try: + loader = WebBaseLoader( + web_paths=(url,), + bs_kwargs=dict( + parse_only=bs4.SoupStrainer( + class_=("post-content", "post-title", "post-header") + ) + ), + ) + documents = loader.load() + text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200) + texts = text_splitter.split_documents(documents) + return texts + except Exception as e: + st.error(f"Error processing web URL: {e}") + return [] + +# Create and Populate Qdrant Vector Store +COLLECTION_NAME = "agno_rag" + +def create_vector_store(texts): + if not qdrant_client: + return None + try: + # Create collection if it doesn't exist + try: + qdrant_client.create_collection( + collection_name=COLLECTION_NAME, + vectors_config=VectorParams(size=1024, distance=Distance.COSINE) + ) + st.success(f"Created new collection: {COLLECTION_NAME}") + except Exception as e: + if "already exists" not in str(e).lower(): + raise e + + # Initialize QdrantVectorStore + vector_store = QdrantVectorStore( + client=qdrant_client, + collection_name=COLLECTION_NAME, + embedding=GeminiEmbedder(dimensions=1024) # Add embedding model if needed + ) + + # Add documents to the vector store + with st.spinner('Storing documents in Qdrant...'): + vector_store.add_documents(texts) + st.success("Documents successfully stored in Qdrant!") + + return vector_store + except Exception as e: + st.error(f"Error creating vector store: {e}") + return None + +# Process Uploaded File or Web URL +if uploaded_file: + texts = process_document(uploaded_file) + if texts: + vector_store = create_vector_store(texts) +elif web_url: + texts = process_web_url(web_url) + if texts: + vector_store = create_vector_store(texts) + # Initialize the Agent -if api_key: +if google_api_key and qdrant_client: thinking_agent = Agent( name="Thinking Agent", role="Think about the problem", - model=Gemini(id="gemini-2.0-flash-exp", api_key=api_key), + model=Gemini(id="gemini-2.0-flash-exp", api_key=google_api_key), instructions="Given the problem, think about it and provide a detailed explanation", show_tool_calls=True, markdown=True, ) - # Chat Interface - st.header("Chat with the Agent") - user_input = st.text_input("Ask a question or describe the problem:") + + # Display chat history if it exists + if 'chat_history' not in st.session_state: + st.session_state.chat_history = [] + + for message in st.session_state.chat_history: + with st.chat_message(message["role"]): + st.write(message["content"]) + + # Chat input using Streamlit's chat_input for better UX + user_input = st.chat_input("Ask a question or describe a problem you'd like me to think about...") if user_input: - # Process the user's input - if uploaded_file: - # Handle file upload - file_content = uploaded_file.read() - st.write("File content:", file_content) - # Add logic to process the file content with the agent - response = thinking_agent.run(f"Given this file content: {file_content}, answer: {user_input}") - elif web_url: - # Handle web URL - st.write("Web URL:", web_url) - # Add logic to process the web URL with the agent - response = thinking_agent.run(f"Given this web URL: {web_url}, answer: {user_input}") - else: - # Handle normal chat - response = thinking_agent.run(user_input) + # Query the Qdrant vector store for relevant documents + if 'vector_store' in locals(): + retriever = vector_store.as_retriever( + search_type="similarity_score_threshold", + search_kwargs={"k": 5, "score_threshold": 0.7} + ) + relevant_docs = retriever.get_relevant_documents(user_input) - # Display the response + if relevant_docs: + st.write("Relevant Documents:") + for doc in relevant_docs: + st.write(doc.page_content[:200] + "...") + + # Process the user's input with the agent + response = thinking_agent.run(user_input) st.write("Agent's Response:") st.write(response.content) else: - st.warning("Please enter your Google API Key in the sidebar to proceed.") \ No newline at end of file + st.warning("Please enter your Google API Key and Qdrant credentials in the sidebar to proceed.") \ No newline at end of file From 7aa9a761ff4dd928772a0b1ad4d7a20cfa68aee4 Mon Sep 17 00:00:00 2001 From: Madhu Date: Sat, 1 Feb 2025 00:44:05 +0530 Subject: [PATCH 4/8] New project with gemini thinking3 --- .../ai_gemini_thinking_agent/main.py | 251 ++++++++++-------- 1 file changed, 146 insertions(+), 105 deletions(-) diff --git a/ai_agent_tutorials/ai_gemini_thinking_agent/main.py b/ai_agent_tutorials/ai_gemini_thinking_agent/main.py index c7f89c4..639a8c1 100644 --- a/ai_agent_tutorials/ai_gemini_thinking_agent/main.py +++ b/ai_agent_tutorials/ai_gemini_thinking_agent/main.py @@ -1,171 +1,212 @@ import os import streamlit as st +import google.generativeai as genai +import tempfile +import bs4 +from typing import List from agno.agent import Agent from agno.models.google import Gemini -from agno.tools.duckduckgo import DuckDuckGoTools from langchain_community.document_loaders import PyPDFLoader, WebBaseLoader from langchain.text_splitter import RecursiveCharacterTextSplitter from langchain_qdrant import QdrantVectorStore from qdrant_client import QdrantClient from qdrant_client.models import Distance, VectorParams -from agno.vectordb.pgvector import PgVector -from agno.embedder.google import GeminiEmbedder -import tempfile -import bs4 +from langchain_core.embeddings import Embeddings -# Streamlit App Title -st.title("AI Agent with Agno and Gemini Thinking") -# Sidebar for API Key Input -st.sidebar.header("Configuration") -google_api_key = st.sidebar.text_input("Enter your Google API Key", type="password") -qdrant_api_key = st.sidebar.text_input("Enter your Qdrant API Key", type="password") -qdrant_url = st.sidebar.text_input("Enter your Qdrant URL", placeholder="https://your-qdrant-url.com") +# Custom Gemini Embedder Class +class GeminiEmbedder(Embeddings): + def __init__(self, model_name="models/embedding-004"): + genai.configure(api_key=os.environ["GOOGLE_API_KEY"]) + self.model = model_name -if google_api_key: - os.environ["GOOGLE_API_KEY"] = google_api_key + def embed_documents(self, texts: List[str]) -> List[List[float]]: + return [self.embed_query(text) for text in texts] + + def embed_query(self, text: str) -> List[float]: + response = genai.embed_content( + model=self.model, + content=text, + task_type="retrieval_document" + ) + return response['embedding'] + +# Initialize Streamlit App +st.title("🤖 AI Agent with Gemini & Qdrant RAG") + +# Sidebar Configuration +st.sidebar.header("🔑 API Configuration") +google_api_key = st.sidebar.text_input("Google API Key", type="password") +qdrant_api_key = st.sidebar.text_input("Qdrant API Key", type="password") +qdrant_url = st.sidebar.text_input("Qdrant URL", + placeholder="https://your-cluster.cloud.qdrant.io:6333") # Initialize Qdrant Client def init_qdrant(): - if not qdrant_api_key or not qdrant_url: - st.warning("Please provide Qdrant API Key and URL in the sidebar.") + if not all([qdrant_api_key, qdrant_url]): return None try: - client = QdrantClient(url=qdrant_url, api_key=qdrant_api_key, timeout=60) - client.get_collections() # Test connection - return client + return QdrantClient( + url=qdrant_url, + api_key=qdrant_api_key, + timeout=60 + ) except Exception as e: - st.error(f"Failed to initialize Qdrant: {e}") + st.error(f"🔴 Qdrant connection failed: {str(e)}") return None -qdrant_client = init_qdrant() - -# File/URL Upload Section -st.sidebar.header("Upload Data") -uploaded_file = st.sidebar.file_uploader("Upload a document", type=["txt", "pdf", "jpg", "png"]) -web_url = st.sidebar.text_input("Enter a web URL") - -# Document and Web URL Processing -def process_document(file): +# Document Processing Functions +def process_pdf(file): try: with tempfile.NamedTemporaryFile(delete=False, suffix='.pdf') as tmp_file: tmp_file.write(file.getvalue()) - tmp_path = tmp_file.name - - loader = PyPDFLoader(tmp_path) - documents = loader.load() - text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200) - texts = text_splitter.split_documents(documents) - - os.unlink(tmp_path) - return texts + loader = PyPDFLoader(tmp_file.name) + documents = loader.load() + text_splitter = RecursiveCharacterTextSplitter( + chunk_size=1000, + chunk_overlap=200 + ) + return text_splitter.split_documents(documents) except Exception as e: - st.error(f"Error processing document: {e}") + st.error(f"📄 PDF processing error: {str(e)}") return [] -def process_web_url(url): +def process_web(url): try: loader = WebBaseLoader( web_paths=(url,), bs_kwargs=dict( parse_only=bs4.SoupStrainer( - class_=("post-content", "post-title", "post-header") + class_=("post-content", "post-title", "post-header", "content", "main") ) - ), + ) ) documents = loader.load() - text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200) - texts = text_splitter.split_documents(documents) - return texts + text_splitter = RecursiveCharacterTextSplitter( + chunk_size=1000, + chunk_overlap=200 + ) + return text_splitter.split_documents(documents) except Exception as e: - st.error(f"Error processing web URL: {e}") + st.error(f"🌐 Web processing error: {str(e)}") return [] -# Create and Populate Qdrant Vector Store +# Vector Store Management COLLECTION_NAME = "agno_rag" -def create_vector_store(texts): - if not qdrant_client: - return None +def create_vector_store(client, texts): try: - # Create collection if it doesn't exist + # Create collection if needed try: - qdrant_client.create_collection( + client.create_collection( collection_name=COLLECTION_NAME, - vectors_config=VectorParams(size=1024, distance=Distance.COSINE) + vectors_config=VectorParams( + size=768, # Gemini embedding-004 dimension + distance=Distance.COSINE + ) ) - st.success(f"Created new collection: {COLLECTION_NAME}") + st.success(f"📚 Created new collection: {COLLECTION_NAME}") except Exception as e: if "already exists" not in str(e).lower(): raise e - - # Initialize QdrantVectorStore + + # Initialize vector store vector_store = QdrantVectorStore( - client=qdrant_client, + client=client, collection_name=COLLECTION_NAME, - embedding=GeminiEmbedder(dimensions=1024) # Add embedding model if needed + embedding=GeminiEmbedder() ) - - # Add documents to the vector store - with st.spinner('Storing documents in Qdrant...'): + + # Add documents + with st.spinner('📤 Uploading documents to Qdrant...'): vector_store.add_documents(texts) - st.success("Documents successfully stored in Qdrant!") - - return vector_store + st.success("✅ Documents stored successfully!") + return vector_store + except Exception as e: - st.error(f"Error creating vector store: {e}") + st.error(f"🔴 Vector store error: {str(e)}") return None -# Process Uploaded File or Web URL -if uploaded_file: - texts = process_document(uploaded_file) - if texts: - vector_store = create_vector_store(texts) -elif web_url: - texts = process_web_url(web_url) - if texts: - vector_store = create_vector_store(texts) +# Main Application Flow +if google_api_key: + os.environ["GOOGLE_API_KEY"] = google_api_key + genai.configure(api_key=google_api_key) + + qdrant_client = init_qdrant() + + # File/URL Upload Section + st.sidebar.header("📁 Data Upload") + uploaded_file = st.sidebar.file_uploader("Upload PDF", type=["pdf"]) + web_url = st.sidebar.text_input("Or enter URL") + + # Process documents + vector_store = None + if uploaded_file: + texts = process_pdf(uploaded_file) + if texts and qdrant_client: + vector_store = create_vector_store(qdrant_client, texts) + elif web_url: + texts = process_web(web_url) + if texts and qdrant_client: + vector_store = create_vector_store(qdrant_client, texts) -# Initialize the Agent -if google_api_key and qdrant_client: - thinking_agent = Agent( - name="Thinking Agent", - role="Think about the problem", - model=Gemini(id="gemini-2.0-flash-exp", api_key=google_api_key), - instructions="Given the problem, think about it and provide a detailed explanation", + # Initialize Agent + agent = Agent( + name="Gemini RAG Agent", + model=Gemini(id="gemini-2.0-flash-exp"), + instructions="You are AGI. You are elite speicialist in all fields and an expert in all fields. Answer user's questions clearly, if any document is added, Use retrieved documents to answer questions accurately", show_tool_calls=True, markdown=True, ) - - # Display chat history if it exists - if 'chat_history' not in st.session_state: - st.session_state.chat_history = [] + # Initialize chat history + if 'history' not in st.session_state: + st.session_state.history = [] - for message in st.session_state.chat_history: - with st.chat_message(message["role"]): - st.write(message["content"]) + # Display chat messages + for msg in st.session_state.history: + with st.chat_message(msg["role"]): + st.write(msg["content"]) + + # User input + if prompt := st.chat_input("Ask about your documents..."): + # Add user message to history + st.session_state.history.append({"role": "user", "content": prompt}) + with st.chat_message("user"): + st.write(prompt) - # Chat input using Streamlit's chat_input for better UX - user_input = st.chat_input("Ask a question or describe a problem you'd like me to think about...") - - if user_input: - # Query the Qdrant vector store for relevant documents - if 'vector_store' in locals(): + # Retrieve relevant documents + context = "" + if vector_store: retriever = vector_store.as_retriever( search_type="similarity_score_threshold", search_kwargs={"k": 5, "score_threshold": 0.7} ) - relevant_docs = retriever.get_relevant_documents(user_input) + docs = retriever.invoke(prompt) + context = "\n\n".join([d.page_content for d in docs]) + + # Generate response + with st.spinner("🤖 Thinking..."): + try: + full_prompt = f"Context: {context}\n\nQuestion: {prompt}" + response = agent.run(full_prompt) + + # Add assistant response to history + st.session_state.history.append({ + "role": "assistant", + "content": response.content + }) + + with st.chat_message("assistant"): + st.write(response.content) + + if vector_store and docs: + with st.expander("🔍 See sources"): + for i, doc in enumerate(docs, 1): + st.write(f"Source {i}: {doc.page_content[:200]}...") + + except Exception as e: + st.error(f"❌ Error generating response: {str(e)}") - if relevant_docs: - st.write("Relevant Documents:") - for doc in relevant_docs: - st.write(doc.page_content[:200] + "...") - - # Process the user's input with the agent - response = thinking_agent.run(user_input) - st.write("Agent's Response:") - st.write(response.content) else: - st.warning("Please enter your Google API Key and Qdrant credentials in the sidebar to proceed.") \ No newline at end of file + st.warning("âš ī¸ Please enter your Google API Key to continue") \ No newline at end of file From 40ac9f865db719d1951bf014ba2c69346696a91c Mon Sep 17 00:00:00 2001 From: Madhu Date: Sat, 1 Feb 2025 22:46:04 +0530 Subject: [PATCH 5/8] rag document, url working --- .../ai_gemini_thinking_agent/main.py | 147 ++++++++++++++---- .../ai_gemini_thinking_agent/test.py | 22 +-- 2 files changed, 119 insertions(+), 50 deletions(-) diff --git a/ai_agent_tutorials/ai_gemini_thinking_agent/main.py b/ai_agent_tutorials/ai_gemini_thinking_agent/main.py index 639a8c1..e6c9a5d 100644 --- a/ai_agent_tutorials/ai_gemini_thinking_agent/main.py +++ b/ai_agent_tutorials/ai_gemini_thinking_agent/main.py @@ -1,9 +1,11 @@ import os +import tempfile +from datetime import datetime +from typing import List + import streamlit as st import google.generativeai as genai -import tempfile import bs4 -from typing import List from agno.agent import Agent from agno.models.google import Gemini from langchain_community.document_loaders import PyPDFLoader, WebBaseLoader @@ -14,10 +16,10 @@ from qdrant_client.models import Distance, VectorParams from langchain_core.embeddings import Embeddings -# Custom Gemini Embedder Class +# Custom Classes class GeminiEmbedder(Embeddings): - def __init__(self, model_name="models/embedding-004"): - genai.configure(api_key=os.environ["GOOGLE_API_KEY"]) + def __init__(self, model_name="models/text-embedding-004"): + genai.configure(api_key=st.session_state.google_api_key) self.model = model_name def embed_documents(self, texts: List[str]) -> List[List[float]]: @@ -31,37 +33,74 @@ class GeminiEmbedder(Embeddings): ) return response['embedding'] -# Initialize Streamlit App + +# Constants +COLLECTION_NAME = "gemini-rag-agno" + + +# Streamlit App Initialization st.title("🤖 AI Agent with Gemini & Qdrant RAG") +# Session State Initialization +if 'google_api_key' not in st.session_state: + st.session_state.google_api_key = "" +if 'qdrant_api_key' not in st.session_state: + st.session_state.qdrant_api_key = "" +if 'qdrant_url' not in st.session_state: + st.session_state.qdrant_url = "" +if 'vector_store' not in st.session_state: + st.session_state.vector_store = None +if 'processed_documents' not in st.session_state: + st.session_state.processed_documents = [] + + # Sidebar Configuration st.sidebar.header("🔑 API Configuration") -google_api_key = st.sidebar.text_input("Google API Key", type="password") -qdrant_api_key = st.sidebar.text_input("Qdrant API Key", type="password") +google_api_key = st.sidebar.text_input("Google API Key", type="password", value=st.session_state.google_api_key) +qdrant_api_key = st.sidebar.text_input("Qdrant API Key", type="password", value=st.session_state.qdrant_api_key) qdrant_url = st.sidebar.text_input("Qdrant URL", - placeholder="https://your-cluster.cloud.qdrant.io:6333") + placeholder="https://your-cluster.cloud.qdrant.io:6333", + value=st.session_state.qdrant_url) -# Initialize Qdrant Client +# Update session state +st.session_state.google_api_key = google_api_key +st.session_state.qdrant_api_key = qdrant_api_key +st.session_state.qdrant_url = qdrant_url + + +# Utility Functions def init_qdrant(): - if not all([qdrant_api_key, qdrant_url]): + """Initialize Qdrant client with configured settings.""" + if not all([st.session_state.qdrant_api_key, st.session_state.qdrant_url]): return None try: return QdrantClient( - url=qdrant_url, - api_key=qdrant_api_key, + url=st.session_state.qdrant_url, + api_key=st.session_state.qdrant_api_key, timeout=60 ) except Exception as e: st.error(f"🔴 Qdrant connection failed: {str(e)}") return None + # Document Processing Functions -def process_pdf(file): +def process_pdf(file) -> List: + """Process PDF file and add source metadata.""" try: with tempfile.NamedTemporaryFile(delete=False, suffix='.pdf') as tmp_file: tmp_file.write(file.getvalue()) loader = PyPDFLoader(tmp_file.name) documents = loader.load() + + # Add source metadata + for doc in documents: + doc.metadata.update({ + "source_type": "pdf", + "file_name": file.name, + "timestamp": datetime.now().isoformat() + }) + text_splitter = RecursiveCharacterTextSplitter( chunk_size=1000, chunk_overlap=200 @@ -71,7 +110,9 @@ def process_pdf(file): st.error(f"📄 PDF processing error: {str(e)}") return [] -def process_web(url): + +def process_web(url: str) -> List: + """Process web URL and add source metadata.""" try: loader = WebBaseLoader( web_paths=(url,), @@ -82,6 +123,15 @@ def process_web(url): ) ) documents = loader.load() + + # Add source metadata + for doc in documents: + doc.metadata.update({ + "source_type": "url", + "url": url, + "timestamp": datetime.now().isoformat() + }) + text_splitter = RecursiveCharacterTextSplitter( chunk_size=1000, chunk_overlap=200 @@ -91,10 +141,10 @@ def process_web(url): st.error(f"🌐 Web processing error: {str(e)}") return [] -# Vector Store Management -COLLECTION_NAME = "agno_rag" +# Vector Store Management def create_vector_store(client, texts): + """Create and initialize vector store with documents.""" try: # Create collection if needed try: @@ -127,10 +177,11 @@ def create_vector_store(client, texts): st.error(f"🔴 Vector store error: {str(e)}") return None + # Main Application Flow -if google_api_key: - os.environ["GOOGLE_API_KEY"] = google_api_key - genai.configure(api_key=google_api_key) +if st.session_state.google_api_key: + os.environ["GOOGLE_API_KEY"] = st.session_state.google_api_key + genai.configure(api_key=st.session_state.google_api_key) qdrant_client = init_qdrant() @@ -140,15 +191,39 @@ if google_api_key: web_url = st.sidebar.text_input("Or enter URL") # Process documents - vector_store = None if uploaded_file: - texts = process_pdf(uploaded_file) - if texts and qdrant_client: - vector_store = create_vector_store(qdrant_client, texts) - elif web_url: - texts = process_web(web_url) - if texts and qdrant_client: - vector_store = create_vector_store(qdrant_client, texts) + file_name = uploaded_file.name + if file_name not in st.session_state.processed_documents: + with st.spinner('Processing PDF...'): + texts = process_pdf(uploaded_file) + if texts and qdrant_client: + if st.session_state.vector_store: + st.session_state.vector_store.add_documents(texts) + else: + st.session_state.vector_store = create_vector_store(qdrant_client, texts) + st.session_state.processed_documents.append(file_name) + st.success(f"✅ Added PDF: {file_name}") + + if web_url: + if web_url not in st.session_state.processed_documents: + with st.spinner('Processing URL...'): + texts = process_web(web_url) + if texts and qdrant_client: + if st.session_state.vector_store: + st.session_state.vector_store.add_documents(texts) + else: + st.session_state.vector_store = create_vector_store(qdrant_client, texts) + st.session_state.processed_documents.append(web_url) + st.success(f"✅ Added URL: {web_url}") + + # Display sources in sidebar + if st.session_state.processed_documents: + st.sidebar.header("📚 Processed Sources") + for source in st.session_state.processed_documents: + if source.endswith('.pdf'): + st.sidebar.text(f"📄 {source}") + else: + st.sidebar.text(f"🌐 {source}") # Initialize Agent agent = Agent( @@ -159,7 +234,7 @@ if google_api_key: markdown=True, ) - # Initialize chat history + # Chat Interface if 'history' not in st.session_state: st.session_state.history = [] @@ -168,7 +243,7 @@ if google_api_key: with st.chat_message(msg["role"]): st.write(msg["content"]) - # User input + # Handle user input if prompt := st.chat_input("Ask about your documents..."): # Add user message to history st.session_state.history.append({"role": "user", "content": prompt}) @@ -177,8 +252,8 @@ if google_api_key: # Retrieve relevant documents context = "" - if vector_store: - retriever = vector_store.as_retriever( + if st.session_state.vector_store: + retriever = st.session_state.vector_store.as_retriever( search_type="similarity_score_threshold", search_kwargs={"k": 5, "score_threshold": 0.7} ) @@ -200,10 +275,14 @@ if google_api_key: with st.chat_message("assistant"): st.write(response.content) - if vector_store and docs: + if st.session_state.vector_store and docs: with st.expander("🔍 See sources"): for i, doc in enumerate(docs, 1): - st.write(f"Source {i}: {doc.page_content[:200]}...") + source_type = doc.metadata.get("source_type", "unknown") + source_icon = "📄" if source_type == "pdf" else "🌐" + source_name = doc.metadata.get("file_name" if source_type == "pdf" else "url", "unknown") + st.write(f"{source_icon} Source {i} from {source_name}:") + st.write(f"{doc.page_content[:200]}...") except Exception as e: st.error(f"❌ Error generating response: {str(e)}") diff --git a/ai_agent_tutorials/ai_gemini_thinking_agent/test.py b/ai_agent_tutorials/ai_gemini_thinking_agent/test.py index c6b2d48..3c51b38 100644 --- a/ai_agent_tutorials/ai_gemini_thinking_agent/test.py +++ b/ai_agent_tutorials/ai_gemini_thinking_agent/test.py @@ -1,22 +1,12 @@ -from google import genai +import google.generativeai as genai import os from dotenv import load_dotenv load_dotenv() -client = genai.Client(api_key=os.getenv("GOOGLE_API_KEY"), http_options={'api_version':'v1alpha'}) +genai.configure(api_key=os.getenv("GOOGLE_API_KEY")) -import asyncio +result = genai.embed_content( + model="models/text-embedding-004", + content="What is the meaning of life?") -config = {'thinking_config': {'include_thoughts': True}} - -async def main(): - chat = client.aio.chats.create( - model='gemini-2.0-flash-thinking-exp-01-21', - config=config - ) - response = await chat.send_message('Explain Deep Q Networks from first principles') - print(response.text) - response = await chat.send_message('What did you just say before this?') - print(response.text) - -asyncio.run(main()) \ No newline at end of file +print(str(result['embedding'])) \ No newline at end of file From dbb707f81ccea846abdcc075ae922150617bd54e Mon Sep 17 00:00:00 2001 From: Madhu Date: Sat, 1 Feb 2025 23:52:26 +0530 Subject: [PATCH 6/8] added query rewrite --- .../ai_gemini_thinking_agent/main.py | 67 ++++++++++++++++--- .../ai_gemini_thinking_agent/test2.py | 21 ------ 2 files changed, 58 insertions(+), 30 deletions(-) delete mode 100644 ai_agent_tutorials/ai_gemini_thinking_agent/test2.py diff --git a/ai_agent_tutorials/ai_gemini_thinking_agent/main.py b/ai_agent_tutorials/ai_gemini_thinking_agent/main.py index e6c9a5d..9b731bd 100644 --- a/ai_agent_tutorials/ai_gemini_thinking_agent/main.py +++ b/ai_agent_tutorials/ai_gemini_thinking_agent/main.py @@ -52,6 +52,8 @@ if 'vector_store' not in st.session_state: st.session_state.vector_store = None if 'processed_documents' not in st.session_state: st.session_state.processed_documents = [] +if 'history' not in st.session_state: + st.session_state.history = [] # Sidebar Configuration @@ -62,6 +64,11 @@ qdrant_url = st.sidebar.text_input("Qdrant URL", placeholder="https://your-cluster.cloud.qdrant.io:6333", value=st.session_state.qdrant_url) +# Clear Chat Button +if st.sidebar.button("đŸ—‘ī¸ Clear Chat History"): + st.session_state.history = [] + st.rerun() + # Update session state st.session_state.google_api_key = google_api_key st.session_state.qdrant_api_key = qdrant_api_key @@ -178,6 +185,38 @@ def create_vector_store(client, texts): return None +# Add this after the GeminiEmbedder class +def get_query_rewriter_agent() -> Agent: + """Initialize a query rewriting agent.""" + return Agent( + name="Query Rewriter", + model=Gemini(id="gemini-exp-1206"), + instructions="""You are an expert at reformulating questions to be more precise and detailed. + Your task is to: + 1. Analyze the user's question + 2. Judge the query first, if you think it is clear enough, just return the same query + 3. Take the user's question and rewrite it to be more specific and search-friendly + 3. Rewrite it to be more specific and search-friendly (RAG and Web Search) + 4. Expand any acronyms or technical terms + 5. Return ONLY the rewritten query without explanations + + Example: + User: "What is DQN?" + Rewritten: "Explain Deep Q-Networks (DQN), including their architecture, how they combine Q-learning with neural networks, their key innovations like experience replay and target networks, and their applications in reinforcement learning for complex environments" + + Example 2: + User: "What's the price?" + Rewritten: "What is the current market price of the product we discussed in our previous conversation about electric vehicles, specifically the Tesla Model 3?" + + Example 3: + User: "AWS costs too much" + Rewritten: "What are the effective strategies and best practices for optimizing and reducing AWS cloud infrastructure costs, including resource management and cost-saving features?" + """, + show_tool_calls=False, + markdown=True, + ) + + # Main Application Flow if st.session_state.google_api_key: os.environ["GOOGLE_API_KEY"] = st.session_state.google_api_key @@ -228,16 +267,13 @@ if st.session_state.google_api_key: # Initialize Agent agent = Agent( name="Gemini RAG Agent", - model=Gemini(id="gemini-2.0-flash-exp"), - instructions="You are AGI. You are elite speicialist in all fields and an expert in all fields. Answer user's questions clearly, if any document is added, Use retrieved documents to answer questions accurately", + model=Gemini(id="gemini-2.0-flash-thinking-exp-01-21"), + instructions="You are AGI. You are an elite specialist in all fields and an expert in all fields. Answer user's questions clearly, if any document is added, Use retrieved documents to answer questions accurately", show_tool_calls=True, markdown=True, ) # Chat Interface - if 'history' not in st.session_state: - st.session_state.history = [] - # Display chat messages for msg in st.session_state.history: with st.chat_message(msg["role"]): @@ -250,20 +286,33 @@ if st.session_state.google_api_key: with st.chat_message("user"): st.write(prompt) - # Retrieve relevant documents + # Rewrite query for better retrieval + with st.spinner("🤔 Reformulating query..."): + try: + query_rewriter = get_query_rewriter_agent() + rewritten_query = query_rewriter.run(f"Rewrite this query: {prompt}").content + + with st.expander("🔄 See rewritten query"): + st.write(f"Original: {prompt}") + st.write(f"Rewritten: {rewritten_query}") + except Exception as e: + st.error(f"❌ Error rewriting query: {str(e)}") + rewritten_query = prompt # Fallback to original query + + # Retrieve relevant documents using rewritten query context = "" if st.session_state.vector_store: retriever = st.session_state.vector_store.as_retriever( search_type="similarity_score_threshold", search_kwargs={"k": 5, "score_threshold": 0.7} ) - docs = retriever.invoke(prompt) + docs = retriever.invoke(rewritten_query) # Use rewritten query context = "\n\n".join([d.page_content for d in docs]) - + # Generate response with st.spinner("🤖 Thinking..."): try: - full_prompt = f"Context: {context}\n\nQuestion: {prompt}" + full_prompt = f"Context: {context}\n\nOriginal Question: {prompt}\nRewritten Question: {rewritten_query}" response = agent.run(full_prompt) # Add assistant response to history diff --git a/ai_agent_tutorials/ai_gemini_thinking_agent/test2.py b/ai_agent_tutorials/ai_gemini_thinking_agent/test2.py deleted file mode 100644 index 0a04959..0000000 --- a/ai_agent_tutorials/ai_gemini_thinking_agent/test2.py +++ /dev/null @@ -1,21 +0,0 @@ -from google import genai -import os -from dotenv import load_dotenv -load_dotenv() - -from google import genai - -client = genai.Client(api_key=os.getenv("GOOGLE_API_KEY"), http_options={'api_version':'v1alpha'}) - -config = {'thinking_config': {'include_thoughts': True}} -response = client.models.generate_content( - model='gemini-2.0-flash-thinking-exp-01-21', - contents='Explain how RLHF works in simple terms.', - config=config -) - -for part in response.candidates[0].content.parts: - if part.thought: - print(f"Model Thought:\n{part.text}\n") - else: - print(f"\nModel Response:\n{part.text}\n") \ No newline at end of file From 5cbe84a31c7891f18e676700df3172b7045e9837 Mon Sep 17 00:00:00 2001 From: Madhu Date: Sun, 2 Feb 2025 00:50:35 +0530 Subject: [PATCH 7/8] full agentic rag code done with gemini --- .../ai_gemini_thinking_agent/main.py | 75 ++++++++++++++++++- .../ai_gemini_thinking_agent/test.py | 12 --- 2 files changed, 71 insertions(+), 16 deletions(-) delete mode 100644 ai_agent_tutorials/ai_gemini_thinking_agent/test.py diff --git a/ai_agent_tutorials/ai_gemini_thinking_agent/main.py b/ai_agent_tutorials/ai_gemini_thinking_agent/main.py index 9b731bd..22583a3 100644 --- a/ai_agent_tutorials/ai_gemini_thinking_agent/main.py +++ b/ai_agent_tutorials/ai_gemini_thinking_agent/main.py @@ -14,6 +14,7 @@ from langchain_qdrant import QdrantVectorStore from qdrant_client import QdrantClient from qdrant_client.models import Distance, VectorParams from langchain_core.embeddings import Embeddings +from agno.tools.exa import ExaTools # Custom Classes @@ -35,7 +36,7 @@ class GeminiEmbedder(Embeddings): # Constants -COLLECTION_NAME = "gemini-rag-agno" +COLLECTION_NAME = "indecisive" # Streamlit App Initialization @@ -54,6 +55,10 @@ if 'processed_documents' not in st.session_state: st.session_state.processed_documents = [] if 'history' not in st.session_state: st.session_state.history = [] +if 'exa_api_key' not in st.session_state: + st.session_state.exa_api_key = "" +if 'use_web_search' not in st.session_state: + st.session_state.use_web_search = False # Sidebar Configuration @@ -74,6 +79,28 @@ st.session_state.google_api_key = google_api_key st.session_state.qdrant_api_key = qdrant_api_key st.session_state.qdrant_url = qdrant_url +# Add in the sidebar configuration section, after the existing API inputs +st.sidebar.header("🌐 Web Search Configuration") +st.session_state.use_web_search = st.sidebar.checkbox("Enable Web Search Fallback", value=st.session_state.use_web_search) + +if st.session_state.use_web_search: + exa_api_key = st.sidebar.text_input( + "Exa AI API Key", + type="password", + value=st.session_state.exa_api_key, + help="Required for web search fallback when no relevant documents are found" + ) + st.session_state.exa_api_key = exa_api_key + + # Optional domain filtering + default_domains = ["arxiv.org", "wikipedia.org", "github.com", "medium.com"] + custom_domains = st.sidebar.text_input( + "Custom domains (comma-separated)", + value=",".join(default_domains), + help="Enter domains to search from, e.g.: arxiv.org,wikipedia.org" + ) + search_domains = [d.strip() for d in custom_domains.split(",") if d.strip()] + # Utility Functions def init_qdrant(): @@ -91,6 +118,24 @@ def init_qdrant(): return None +def get_web_search_results(query: str) -> str: + """Perform web search using Exa AI and return formatted results.""" + try: + exa_agent = Agent( + name="Web Search Agent", + tools=[ExaTools( + api_key=st.session_state.exa_api_key, + include_domains=search_domains + )], + show_tool_calls=True + ) + response = exa_agent.run(f"Search for the query: {query}") + return response.content + except Exception as e: + st.error(f"🌐 Web search error: {str(e)}") + return "" + + # Document Processing Functions def process_pdf(file) -> List: """Process PDF file and add source metadata.""" @@ -268,7 +313,7 @@ if st.session_state.google_api_key: agent = Agent( name="Gemini RAG Agent", model=Gemini(id="gemini-2.0-flash-thinking-exp-01-21"), - instructions="You are AGI. You are an elite specialist in all fields and an expert in all fields. Answer user's questions clearly, if any document is added, Use retrieved documents to answer questions accurately", + instructions="You are AGI. You are an elite specialist in all fields and an expert in all fields. Answer user's questions clearly, if any document is added, Use retrieved documents to answer questions accurately.", show_tool_calls=True, markdown=True, ) @@ -312,7 +357,23 @@ if st.session_state.google_api_key: # Generate response with st.spinner("🤖 Thinking..."): try: - full_prompt = f"Context: {context}\n\nOriginal Question: {prompt}\nRewritten Question: {rewritten_query}" + # Check if we have relevant documents + if context: + full_prompt = f"Context: {context}\n\nOriginal Question: {prompt}\nRewritten Question: {rewritten_query}" + # If no relevant documents and web search is enabled + elif st.session_state.use_web_search and st.session_state.exa_api_key: + with st.spinner("🔍 Searching the web..."): + web_results = get_web_search_results(rewritten_query) + if web_results: + full_prompt = f"Web Search Results: {web_results}\n\nOriginal Question: {prompt}\nRewritten Question: {rewritten_query}" + st.info("â„šī¸ No relevant documents found in the database. Using web search results.") + else: + full_prompt = f"Original Question: {prompt}\nRewritten Question: {rewritten_query}" + else: + full_prompt = f"Original Question: {prompt}\nRewritten Question: {rewritten_query}" + if not context: + st.info("â„šī¸ No relevant documents found in the database.") + response = agent.run(full_prompt) # Add assistant response to history @@ -324,14 +385,20 @@ if st.session_state.google_api_key: with st.chat_message("assistant"): st.write(response.content) + # Show sources if available if st.session_state.vector_store and docs: - with st.expander("🔍 See sources"): + with st.expander("🔍 See document sources"): for i, doc in enumerate(docs, 1): source_type = doc.metadata.get("source_type", "unknown") source_icon = "📄" if source_type == "pdf" else "🌐" source_name = doc.metadata.get("file_name" if source_type == "pdf" else "url", "unknown") st.write(f"{source_icon} Source {i} from {source_name}:") st.write(f"{doc.page_content[:200]}...") + + # Show web search results if used + elif 'web_results' in locals() and web_results: + with st.expander("🌐 See web search results"): + st.write(web_results) except Exception as e: st.error(f"❌ Error generating response: {str(e)}") diff --git a/ai_agent_tutorials/ai_gemini_thinking_agent/test.py b/ai_agent_tutorials/ai_gemini_thinking_agent/test.py deleted file mode 100644 index 3c51b38..0000000 --- a/ai_agent_tutorials/ai_gemini_thinking_agent/test.py +++ /dev/null @@ -1,12 +0,0 @@ -import google.generativeai as genai -import os -from dotenv import load_dotenv -load_dotenv() - -genai.configure(api_key=os.getenv("GOOGLE_API_KEY")) - -result = genai.embed_content( - model="models/text-embedding-004", - content="What is the meaning of life?") - -print(str(result['embedding'])) \ No newline at end of file From e2c2813ce0070d70e161c86a55f9cc203baa9456 Mon Sep 17 00:00:00 2001 From: Madhu Date: Sun, 2 Feb 2025 01:05:57 +0530 Subject: [PATCH 8/8] full agentic rag code done with gemini --- .../ai_gemini_thinking_agent/README.md | 0 .../ai_gemini_thinking_agent/requirements.txt | 0 rag_tutorials/gemini_agentic_rag/README.md | 90 +++++++++++++++++++ .../gemini_agentic_rag/agentic_rag_gemini.py | 6 +- .../gemini_agentic_rag/requirements.txt | 6 ++ 5 files changed, 99 insertions(+), 3 deletions(-) delete mode 100644 ai_agent_tutorials/ai_gemini_thinking_agent/README.md delete mode 100644 ai_agent_tutorials/ai_gemini_thinking_agent/requirements.txt create mode 100644 rag_tutorials/gemini_agentic_rag/README.md rename ai_agent_tutorials/ai_gemini_thinking_agent/main.py => rag_tutorials/gemini_agentic_rag/agentic_rag_gemini.py (97%) create mode 100644 rag_tutorials/gemini_agentic_rag/requirements.txt diff --git a/ai_agent_tutorials/ai_gemini_thinking_agent/README.md b/ai_agent_tutorials/ai_gemini_thinking_agent/README.md deleted file mode 100644 index e69de29..0000000 diff --git a/ai_agent_tutorials/ai_gemini_thinking_agent/requirements.txt b/ai_agent_tutorials/ai_gemini_thinking_agent/requirements.txt deleted file mode 100644 index e69de29..0000000 diff --git a/rag_tutorials/gemini_agentic_rag/README.md b/rag_tutorials/gemini_agentic_rag/README.md new file mode 100644 index 0000000..0042f11 --- /dev/null +++ b/rag_tutorials/gemini_agentic_rag/README.md @@ -0,0 +1,90 @@ +# Agentic RAG with Gemini Thinking ⌘G + +A RAG Agentic system built with the new Gemini 2.0 Flash Thinking model and gemini-exp-1206, Qdrant for vector storage, and Agno (phidata prev) for agent orchestration. This application features intelligent query rewriting, document processing, and web search fallback capabilities to provide comprehensive AI-powered responses. + +## Features + +- **Document Processing** + - PDF document upload and processing + - Web page content extraction + - Automatic text chunking and embedding + - Vector storage in Qdrant cloud + +- **Intelligent Querying** + - Query rewriting for better retrieval + - RAG-based document retrieval + - Similarity search with threshold filtering + - Automatic fallback to web search + - Source attribution for answers + +- **Advanced Capabilities** + - Exa AI web search integration + - Custom domain filtering for web search + - Context-aware response generation + - Chat history management + - Query reformulation agent + +- **Model Specific Features** + - Gemini Thinking 2.0 Flash for chat and reasoning + - Gemini Embedding model for vector embeddings + - Agno Agent framework for orchestration + - Streamlit-based interactive interface + +## Prerequisites + +### 1. Google API Key +1. Go to [Google AI Studio](https://aistudio.google.com/apikey) +2. Sign up or log in to your account +3. Create a new API key + +### 2. Qdrant Cloud Setup +1. Visit [Qdrant Cloud](https://cloud.qdrant.io/) +2. Create an account or sign in +3. Create a new cluster +4. Get your credentials: + - Qdrant API Key: Found in API Keys section + - Qdrant URL: Your cluster URL (format: `https://xxx-xxx.cloud.qdrant.io`) + +### 3. Exa AI API Key (Optional) +1. Visit [Exa AI](https://exa.ai) +2. Sign up for an account +3. Generate an API key for web search capabilities + +## How to Run + +1. Clone the repository: +```bash +git clone https://github.com/Shubhamsaboo/awesome-llm-apps.git +cd rag_tutorials/gemini_agentic_rag +``` + +2. Install dependencies: +```bash +pip install -r requirements.txt +``` + +3. Run the application: +```bash +streamlit run agentic_rag_gemini.py +``` + +## Usage + +1. Configure API keys in the sidebar: + - Enter your Google API key + - Add Qdrant credentials + - (Optional) Add Exa AI key for web search + +2. Upload documents: + - Use the file uploader for PDFs + - Enter URLs for web content + +3. Ask questions: + - Type your query in the chat interface + - View rewritten queries and sources + - See web search results when relevant + +4. Manage your session: + - Clear chat history as needed + - Configure web search domains + - Monitor processed documents diff --git a/ai_agent_tutorials/ai_gemini_thinking_agent/main.py b/rag_tutorials/gemini_agentic_rag/agentic_rag_gemini.py similarity index 97% rename from ai_agent_tutorials/ai_gemini_thinking_agent/main.py rename to rag_tutorials/gemini_agentic_rag/agentic_rag_gemini.py index 22583a3..dac188f 100644 --- a/ai_agent_tutorials/ai_gemini_thinking_agent/main.py +++ b/rag_tutorials/gemini_agentic_rag/agentic_rag_gemini.py @@ -36,11 +36,11 @@ class GeminiEmbedder(Embeddings): # Constants -COLLECTION_NAME = "indecisive" +COLLECTION_NAME = "gemini-thinking-agent-agno" # Streamlit App Initialization -st.title("🤖 AI Agent with Gemini & Qdrant RAG") +st.title("🤖 Agentic RAG with Gemini Thinking and Agno") # Session State Initialization if 'google_api_key' not in st.session_state: @@ -313,7 +313,7 @@ if st.session_state.google_api_key: agent = Agent( name="Gemini RAG Agent", model=Gemini(id="gemini-2.0-flash-thinking-exp-01-21"), - instructions="You are AGI. You are an elite specialist in all fields and an expert in all fields. Answer user's questions clearly, if any document is added, Use retrieved documents to answer questions accurately.", + instructions="You are an Intelligent Agent. You are an elite specialist and an expert in all fields. Answer user's questions clearly, if any document is added, Use retrieved documents to answer questions accurately.", show_tool_calls=True, markdown=True, ) diff --git a/rag_tutorials/gemini_agentic_rag/requirements.txt b/rag_tutorials/gemini_agentic_rag/requirements.txt new file mode 100644 index 0000000..1ac2d62 --- /dev/null +++ b/rag_tutorials/gemini_agentic_rag/requirements.txt @@ -0,0 +1,6 @@ +agno +exa==0.5.26 +qdrant-client==1.12.1 +langchain-qdrant==0.2.0 +langchain-community==0.3.13 +streamlit==1.41.1 \ No newline at end of file