Spaces:
Sleeping
Sleeping
File size: 6,738 Bytes
40e5eae 5fd4bb2 40e5eae 5fd4bb2 40e5eae 5fd4bb2 40e5eae | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 | """
Main RAG Application
Combines all components and provides a Gradio web interface
"""
import os
import gradio as gr
import logging
from typing import Generator
from config import GRADIO_CONFIG, DEFAULT_N_RESULTS, HF_TOKEN
from document_converter import download_test_document, convert_all_documents
from text_splitter import process_all_documents
from vector_store import VectorStore, retrieve_context
from llm_handler import stream_llm_answer, format_response
# Configure logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
class RAGSystem:
"""
Complete RAG (Retrieval-Augmented Generation) System
"""
def __init__(self):
"""
Initialize the RAG system
"""
self.vector_store = None
logger.info("RAG System initialized")
def setup_pipeline(self, force_rebuild: bool = False) -> bool:
"""
Set up the complete RAG pipeline
Args:
force_rebuild: Whether to force rebuild the vector store
Returns:
True if setup successful
"""
try:
# Step 1: Download test document
logger.info("Step 1: Downloading test document...")
test_doc = download_test_document()
if not test_doc:
logger.error("Failed to download test document")
return False
# Step 2: Convert documents to markdown
logger.info("Step 2: Converting documents to markdown...")
converted = convert_all_documents()
if not converted:
logger.error("No documents were converted")
return False
logger.info(f"Converted {len(converted)} documents")
# Step 3: Split documents into chunks
logger.info("Step 3: Splitting documents into chunks...")
chunks = process_all_documents()
if not chunks:
logger.error("No chunks were created")
return False
logger.info(f"Created {len(chunks)} chunks")
# Step 4: Initialize vector store
logger.info("Step 4: Initializing vector store...")
self.vector_store = VectorStore()
# Check if vector store is empty or force rebuild
stats = self.vector_store.get_collection_stats()
if stats["document_count"] == 0 or force_rebuild:
if force_rebuild and stats["document_count"] > 0:
logger.info("Clearing existing vector store...")
self.vector_store.clear_collection()
logger.info("Adding documents to vector store...")
self.vector_store.add_documents(chunks)
else:
logger.info(f"Vector store already contains {stats['document_count']} documents")
logger.info("✅ RAG pipeline setup complete!")
return True
except Exception as e:
logger.error(f"Error setting up pipeline: {e}")
return False
def query(
self,
question: str,
n_results: int = DEFAULT_N_RESULTS
) -> Generator[str, None, None]:
"""
Process a query and stream the response
Args:
question: User's question
n_results: Number of context chunks to retrieve
Yields:
Response text parts
"""
if not question.strip():
yield "❌ Please enter a question."
return
try:
# Retrieve context
logger.info(f"Processing query: {question}")
context, sources = retrieve_context(question, n_results)
if not context:
yield "❌ No relevant information found in the documents."
return
# Start response
response_start = f"**Question:** {question}\n\n**Answer:** "
answer = ""
# Stream the answer
for token in stream_llm_answer(question, context):
answer += token
yield response_start + answer
# Add sources at the end
final_response = format_response(question, answer, sources)
yield final_response
except Exception as e:
logger.error(f"Error processing query: {e}")
yield f"❌ Error: {str(e)}"
# Global RAG system instance
rag_system = RAGSystem()
def rag_interface(question: str) -> Generator[str, None, None]:
"""
Gradio interface function
Args:
question: User's question
Yields:
Response text parts
"""
yield from rag_system.query(question)
def create_gradio_interface() -> gr.Interface:
"""
Create the Gradio web interface
Returns:
Gradio Interface object
"""
interface = gr.Interface(
fn=rag_interface,
inputs=gr.Textbox(
label="Your Question",
placeholder="Ask anything about Python programming...",
lines=3
),
outputs=gr.Markdown(label="Answer"),
title=GRADIO_CONFIG["title"],
description=GRADIO_CONFIG["description"],
examples=GRADIO_CONFIG["examples"],
theme=GRADIO_CONFIG["theme"],
allow_flagging="never"
)
return interface
def main():
"""
Main entry point for the application
"""
logger.info("🚀 Starting RAG System...")
# Validate HF token
if not HF_TOKEN:
logger.warning(
"⚠️ HF_TOKEN not set. Please set the HF_TOKEN environment variable.\n"
"Get your token from: https://huggingface.co/settings/tokens"
)
logger.info("Continuing without HF token validation (may fail during LLM calls)...")
else:
logger.info("✅ HF_TOKEN found")
# Setup the pipeline
logger.info("Setting up RAG pipeline...")
success = rag_system.setup_pipeline(force_rebuild=False)
if not success:
logger.error("Failed to setup RAG pipeline. Please check the logs.")
return
# Create and launch Gradio interface
logger.info("Creating Gradio interface...")
interface = create_gradio_interface()
logger.info("Launching web interface...")
interface.queue().launch(
share=GRADIO_CONFIG["share"],
server_name="0.0.0.0",
server_port=7860,
)
if __name__ == "__main__":
main()
|