refactor: Update rag_reasoning_agent to use Google Gemini and enhance knowledge management

- Replaced Claude model with Gemini for improved language processing.
- Updated knowledge management by replacing UrlKnowledge with Knowledge class.
- Enhanced session state handling to prevent duplicate URL loading.
- Adjusted README to reflect changes in API key requirements and default knowledge sources.
- Updated requirements.txt to specify a minimum version for the 'agno' package.
This commit is contained in:
Shubhamsaboo
2025-11-09 12:06:51 -08:00
parent 5685c508fc
commit 7c532cd8d6
3 changed files with 90 additions and 64 deletions

View File

@@ -1,13 +1,14 @@
# 🧐 Agentic RAG with Reasoning
A sophisticated RAG system that demonstrates an AI agent's step-by-step reasoning process using Agno, Claude and OpenAI. This implementation allows users to upload documents, add web sources, ask questions, and observe the agent's thought process in real-time.
A sophisticated RAG system that demonstrates an AI agent's step-by-step reasoning process using Agno, Gemini and OpenAI. This implementation allows users to add web sources, ask questions, and observe the agent's thought process in real-time with reasoning capabilities.
## Features
1. Interactive Knowledge Base Management
- Upload documents to expand the knowledge base
- Add URLs dynamically for web content
- Default knowledge source: MCP vs A2A Protocol article
- Persistent vector database storage using LanceDB
- Session state tracking prevents duplicate URL loading
2. Transparent Reasoning Process
@@ -23,24 +24,25 @@ A sophisticated RAG system that demonstrates an AI agent's step-by-step reasonin
## Agent Configuration
- Claude 3.5 Sonnet for language processing
- Gemini 2.5 Flash for language processing
- OpenAI embedding model for vector search
- ReasoningTools for step-by-step analysis
- Customizable agent instructions
- Default knowledge source: MCP vs A2A Protocol article
## Prerequisites
You'll need the following API keys:
1. Anthropic API Key
1. Google API Key
- Sign up at console.anthropic.com
- Sign up at [aistudio.google.com](https://aistudio.google.com/apikey)
- Navigate to API Keys section
- Create a new API key
2. OpenAI API Key
- Sign up at platform.openai.com
- Sign up at [platform.openai.com](https://platform.openai.com/)
- Navigate to API Keys section
- Generate a new API key
@@ -64,35 +66,40 @@ You'll need the following API keys:
4. **Configure API Keys:**
- Enter your Anthropic API key in the first field
- Enter your Google API key in the first field
- Enter your OpenAI API key in the second field
- Both keys are required for the app to function
5. **Use the Application:**
- Default Knowledge Source: The app comes pre-loaded with the MCP vs A2A Protocol article
- Add Knowledge Sources: Use the sidebar to add URLs to your knowledge base
- Suggested Prompts: Click the prompt buttons (What is MCP?, MCP vs A2A, Agent Communication) for quick questions
- Ask Questions: Enter queries in the main input field
- View Reasoning: Watch the agent's thought process unfold in real-time
- Get Answers: Receive comprehensive responses with source citations
- View Reasoning: Watch the agent's thought process unfold in real-time in the left panel
- Get Answers: Receive comprehensive responses with source citations in the right panel
## How It Works
The application uses a sophisticated RAG pipeline:
The application uses a sophisticated RAG pipeline with Agno v2.0:
### Knowledge Base Setup
- Documents are loaded from URLs using WebBaseLoader
- Text is chunked and embedded using OpenAI's embedding model
- Documents are loaded from URLs using Agno's Knowledge class
- Text is automatically chunked and embedded using OpenAI's embedding model
- Vectors are stored in LanceDB for efficient retrieval
- Vector search enables semantic matching for relevant information
- URLs are tracked in session state to prevent duplicate loading
### Agent Processing
- User queries trigger the agent's reasoning process
- ReasoningTools help the agent think step-by-step
- The agent searches the knowledge base for relevant information
- Claude 4 Sonnet generates comprehensive answers with citations
- Gemini 2.5 Flash generates comprehensive answers with citations
- Streaming events provide real-time updates on reasoning and content
### UI Flow
- Enter API keys → Add knowledge sources → Ask questions
- Reasoning process and answer generation displayed side-by-side
- Enter API keys → Knowledge base loads with default MCP vs A2A article → Use suggested prompts or ask custom questions
- Reasoning process displayed in left panel, answer generation in right panel
- Sources cited for transparency and verification
- All events streamed in real-time for better user experience

View File

@@ -1,8 +1,8 @@
import streamlit as st
from agno.agent import Agent, RunEvent
from agno.embedder.openai import OpenAIEmbedder
from agno.knowledge.url import UrlKnowledge
from agno.models.anthropic import Claude
from agno.agent import Agent
from agno.knowledge.embedder.openai import OpenAIEmbedder
from agno.knowledge.knowledge import Knowledge
from agno.models.google import Gemini
from agno.tools.reasoning import ReasoningTools
from agno.vectordb.lancedb import LanceDb, SearchType
from dotenv import load_dotenv
@@ -33,11 +33,11 @@ Enter your API keys below to get started!
st.subheader("🔑 API Keys")
col1, col2 = st.columns(2)
with col1:
anthropic_key = st.text_input(
"Anthropic API Key",
google_key = st.text_input(
"Google API Key",
type="password",
value=os.getenv("ANTHROPIC_API_KEY", ""),
help="Get your key from https://console.anthropic.com/"
value=os.getenv("GOOGLE_API_KEY", ""),
help="Get your key from https://aistudio.google.com/apikey"
)
with col2:
openai_key = st.text_input(
@@ -48,14 +48,19 @@ with col2:
)
# Check if API keys are provided
if anthropic_key and openai_key:
if google_key and openai_key:
# Initialize URLs in session state
if 'knowledge_urls' not in st.session_state:
st.session_state.knowledge_urls = ["https://www.theunwindai.com/p/mcp-vs-a2a-complementing-or-supplementing"] # Default URL
if 'urls_loaded' not in st.session_state:
st.session_state.urls_loaded = set()
# Initialize knowledge base (cached to avoid reloading)
@st.cache_resource(show_spinner="📚 Loading knowledge base...")
def load_knowledge() -> UrlKnowledge:
def load_knowledge() -> Knowledge:
"""Load and initialize the knowledge base with vector database"""
kb = UrlKnowledge(
urls=["https://docs.agno.com/introduction/agents.md"], # Default URL
kb = Knowledge(
vector_db=LanceDb(
uri="tmp/lancedb",
table_name="agno_docs",
@@ -65,17 +70,16 @@ if anthropic_key and openai_key:
),
),
)
kb.load(recreate=True) # Load documents into vector DB
return kb
# Initialize agent (cached to avoid reloading)
@st.cache_resource(show_spinner="🤖 Loading agent...")
def load_agent(_kb: UrlKnowledge) -> Agent:
def load_agent(_kb: Knowledge) -> Agent:
"""Create an agent with reasoning capabilities"""
return Agent(
model=Claude(
id="claude-sonnet-4-20250514",
api_key=anthropic_key
model=Gemini(
id="gemini-2.5-flash",
api_key=google_key
),
knowledge=_kb,
search_knowledge=True, # Enable knowledge search
@@ -89,6 +93,13 @@ if anthropic_key and openai_key:
# Load knowledge and agent
knowledge = load_knowledge()
# Load initial URLs if any (only load once per URL)
for url in st.session_state.knowledge_urls:
if url not in st.session_state.urls_loaded:
knowledge.add_content(url=url)
st.session_state.urls_loaded.add(url)
agent = load_agent(knowledge)
# Sidebar for knowledge management
@@ -98,26 +109,25 @@ if anthropic_key and openai_key:
# Show current URLs
st.write("**Current sources:**")
for i, url in enumerate(knowledge.urls):
for i, url in enumerate(st.session_state.knowledge_urls):
st.text(f"{i+1}. {url}")
# Add new URL
st.divider()
new_url = st.text_input(
"Add new URL",
placeholder="https://example.com/docs",
placeholder="https://www.theunwindai.com/p/mcp-vs-a2a-complementing-or-supplementing",
help="Enter a URL to add to the knowledge base"
)
if st.button(" Add URL", type="primary"):
if new_url:
if new_url not in st.session_state.knowledge_urls:
st.session_state.knowledge_urls.append(new_url)
with st.spinner("📥 Loading new documents..."):
knowledge.urls.append(new_url)
knowledge.load(
recreate=False, # Don't recreate DB
upsert=True, # Update existing docs
skip_existing=True # Skip already loaded docs
)
if new_url not in st.session_state.urls_loaded:
knowledge.add_content(url=new_url)
st.session_state.urls_loaded.add(new_url)
st.success(f"✅ Added: {new_url}")
st.rerun() # Refresh to show new URL
else:
@@ -127,10 +137,23 @@ if anthropic_key and openai_key:
st.divider()
st.subheader("🤔 Ask a Question")
# Suggested prompts
st.markdown("**Try these prompts:**")
col1, col2, col3 = st.columns(3)
with col1:
if st.button("What is MCP?", use_container_width=True):
st.session_state.query = "What is MCP (Model Context Protocol) and how does it work?"
with col2:
if st.button("MCP vs A2A", use_container_width=True):
st.session_state.query = "How do MCP and A2A protocols differ, and are they complementary or competing?"
with col3:
if st.button("Agent Communication", use_container_width=True):
st.session_state.query = "How do MCP and A2A work together in AI agent systems for communication and tool access?"
# Query input
query = st.text_area(
"Your question:",
value="What are Agents?",
value=st.session_state.get("query", "What is the difference between MCP and A2A protocols?"),
height=100,
help="Ask anything about the loaded knowledge sources"
)
@@ -161,11 +184,10 @@ if anthropic_key and openai_key:
for chunk in agent.run(
query,
stream=True, # Enable streaming
show_full_reasoning=True, # Show reasoning steps
stream_intermediate_steps=True, # Stream intermediate updates
stream_events=True, # Stream all events including reasoning
):
# Update reasoning display
if chunk.reasoning_content:
if hasattr(chunk, 'reasoning_content') and chunk.reasoning_content:
reasoning_text = chunk.reasoning_content
reasoning_placeholder.markdown(
reasoning_text,
@@ -173,17 +195,17 @@ if anthropic_key and openai_key:
)
# Update answer display
if chunk.content and chunk.event in {RunEvent.run_response, RunEvent.run_completed}:
if isinstance(chunk.content, str):
answer_text += chunk.content
answer_placeholder.markdown(
answer_text,
unsafe_allow_html=True
)
if hasattr(chunk, 'content') and chunk.content and isinstance(chunk.content, str):
answer_text += chunk.content
answer_placeholder.markdown(
answer_text,
unsafe_allow_html=True
)
# Collect citations
if chunk.citations and chunk.citations.urls:
citations = chunk.citations.urls
if hasattr(chunk, 'citations') and chunk.citations:
if hasattr(chunk.citations, 'urls') and chunk.citations.urls:
citations = chunk.citations.urls
# Show citations if available
if citations:
@@ -200,8 +222,8 @@ else:
st.info("""
👋 **Welcome! To use this app, you need:**
1. **Anthropic API Key** - For Claude AI model
- Sign up at [console.anthropic.com](https://console.anthropic.com/)
1. **Google API Key** - For Gemini AI model
- Sign up at [aistudio.google.com](https://aistudio.google.com/apikey)
2. **OpenAI API Key** - For embeddings
- Sign up at [platform.openai.com](https://platform.openai.com/)
@@ -218,10 +240,10 @@ with st.expander("📖 How This Works"):
1. **Knowledge Loading**: URLs are processed and stored in a vector database (LanceDB)
2. **Vector Search**: Uses OpenAI's embeddings for semantic search to find relevant information
3. **Reasoning Tools**: The agent uses special tools to think through problems step-by-step
4. **Claude AI**: Anthropic's Claude model processes the information and generates answers
4. **Gemini AI**: Google's Gemini model processes the information and generates answers
**Key Components:**
- `UrlKnowledge`: Manages document loading from URLs
- `Knowledge`: Manages document loading from URLs
- `LanceDb`: Vector database for efficient similarity search
- `OpenAIEmbedder`: Converts text to embeddings using OpenAI's embedding model
- `ReasoningTools`: Enables step-by-step reasoning

View File

@@ -1,8 +1,5 @@
streamlit
agno
anthropic
cohere
agno>=2.2.10
lancedb
pandas
numpy
pyarrow
openai
python-dotenv