fully working

This commit is contained in:
Madhu 2024-12-05 00:29:12 +05:30
parent 5193d040f1
commit 956cf6d6fa
4 changed files with 92 additions and 35 deletions

View file

@ -1,13 +1,16 @@
# Hybrid RAG Claude Chat 🤖 # LLM Hybrid Search-RAG Assistant - Claude 🤖
A powerful document Q&A application that combines Hybrid Search (RAG) with Claude's general knowledge. This is built on the RAGLite framework and Chainlit for the UI. A powerful document Q&A application that leverages Hybrid Search (RAG) and Claude's advanced language capabilities to provide comprehensive answers. Built with RAGLite for robust document processing and retrieval, and Chainlit for an intuitive chat interface, this system seamlessly combines document-specific knowledge with Claude's general intelligence to deliver accurate and contextual responses.
## Demo
![Demo](rag_tutorials/llm_app_hybrid_RAG_claude/LLM-Hybrid-RagLite-Claude.mp4)
## Features ## Features
- **Hybrid Question Answering** - **Hybrid Search Question Answering**
- RAG-based answers for document-specific queries - RAG-based answers for document-specific queries
- Fallback to Claude for general knowledge questions - Fallback to Claude for general knowledge questions
- Seamless switching between modes
- **Document Processing**: - **Document Processing**:
- PDF document upload and processing - PDF document upload and processing
@ -15,16 +18,10 @@ A powerful document Q&A application that combines Hybrid Search (RAG) with Claud
- Hybrid search combining semantic and keyword matching - Hybrid search combining semantic and keyword matching
- Reranking for better context selection - Reranking for better context selection
- **Interactive Chat Interface**:
- Real-time streaming responses
- Chat history preservation
- Error handling with retry options
- File upload validation
- **Multi-Model Integration**: - **Multi-Model Integration**:
- Claude for text generation - Claude for text generation - tested with Claude 3 Opus
- OpenAI for embeddings - OpenAI for embeddings - tested with text-embedding-3-large
- Cohere for reranking (tried using the new Cohere 3.5 reranker) - Cohere for reranking - tested with Cohere 3.5 reranker
## Prerequisites ## Prerequisites
@ -40,11 +37,11 @@ You'll need the following API keys and database setup:
- [Anthropic API key](https://console.anthropic.com/settings/keys) for Claude - [Anthropic API key](https://console.anthropic.com/settings/keys) for Claude
- [Cohere API key](https://dashboard.cohere.com/api-keys) for reranking - [Cohere API key](https://dashboard.cohere.com/api-keys) for reranking
## Installation ## How to get Started?
1. **Clone the Repository**: 1. **Clone the Repository**:
```bash ```bash
git clone <repository-url> git clone https://github.com/Shubhamsaboo/awesome-llm-apps.git
cd rag_tutorials/llm_app_hybrid_RAG_claude cd rag_tutorials/llm_app_hybrid_RAG_claude
``` ```
@ -66,7 +63,7 @@ You'll need the following API keys and database setup:
## Usage ## Usage
1. Start the application 1. Start the application
2. When prompted, enter your: 2. Enter your important keys in the ChatSettings widget:
- OpenAI API key - OpenAI API key
- Anthropic API key - Anthropic API key
- Cohere API key - Cohere API key

View file

@ -11,8 +11,8 @@ project:
- DB_URL - DB_URL
ui: ui:
name: "LLM App with Hybrid Search and RAG - Claude" name: "🤖 RAG-Powered Document Assistant"
description: "by unwind ai" description: "Upload documents and ask questions using hybrid RAG with Claude"
hide_cot: false hide_cot: false
default_collapse_content: true default_collapse_content: true
default_expand_messages: true default_expand_messages: true
@ -25,6 +25,7 @@ ui:
centered: true centered: true
show_sidebar: true show_sidebar: true
sidebar_position: "left" sidebar_position: "left"
theme: light
# Configure the environment variables UI # Configure the environment variables UI
user_env: user_env:
@ -68,3 +69,29 @@ theme:
primary: "#2563eb" primary: "#2563eb"
background: "#1a1a1a" background: "#1a1a1a"
sidebar: "#1e1e1e" sidebar: "#1e1e1e"
chat_profiles: []
default_expand_messages: false
markdown: true
message_html: true
show_readme_as_default: true
default_collapse_content: true
theme: light
features:
speech_to_text: false
task_list: true
ui:
name: Hybrid RAG Assistant
description: Ask questions about your documents
hide_cot: false
show_docs: false
show_debugger: false
show_file_upload: true
file_upload:
max_size_mb: 20
max_files: 5
accept:
- application/pdf

View file

@ -10,14 +10,13 @@ from chainlit.input_widget import TextInput
from chainlit import AskUserMessage from chainlit import AskUserMessage
import anthropic import anthropic
# Configure logging
logging.basicConfig(level=logging.INFO) logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
# Initialize global config variable
my_config = None my_config = None
# Define RAG system prompt # Defining the RAG system prompt
RAG_SYSTEM_PROMPT = """ RAG_SYSTEM_PROMPT = """
You are a friendly and knowledgeable assistant that provides complete and insightful answers. You are a friendly and knowledgeable assistant that provides complete and insightful answers.
Answer the user's question using only the context below. Answer the user's question using only the context below.
@ -48,7 +47,7 @@ def process_document(file_path: str) -> None:
import time import time
start_time = time.time() start_time = time.time()
# Insert document into PostgreSQL database # Inserting document into PostgreSQL database
insert_document(Path(file_path), config=my_config) insert_document(Path(file_path), config=my_config)
processing_time = time.time() - start_time processing_time = time.time() - start_time
@ -181,7 +180,16 @@ async def start() -> None:
logger.info("Chat session started") logger.info("Chat session started")
cl.user_session.set("chat_history", []) cl.user_session.set("chat_history", [])
# Show settings form first # Add header with markdown formatting
await cl.Message(
content="""# 🤖 LLM-Powered Hybrid Search-RAG Assistant powered by Claude
Welcome! To get started:
Enter your API keys below on the ChatSettings widget
"""
).send()
# Show settings form
await cl.ChatSettings([ await cl.ChatSettings([
TextInput( TextInput(
id="OpenAIApiKey", id="OpenAIApiKey",
@ -280,28 +288,53 @@ async def handle_fallback(query: str, msg: cl.Message) -> None:
"""Handle fallback to Claude when RAG is not available or fails.""" """Handle fallback to Claude when RAG is not available or fails."""
try: try:
user_env = cl.user_session.get("env") user_env = cl.user_session.get("env")
if not user_env or "ANTHROPIC_API_KEY" not in user_env:
raise ValueError("Missing Anthropic API key in session")
client = anthropic.Anthropic(api_key=user_env["ANTHROPIC_API_KEY"]) client = anthropic.Anthropic(api_key=user_env["ANTHROPIC_API_KEY"])
logger.info("Falling back to Claude for response")
# Get response from Claude
response = client.messages.create( response = client.messages.create(
model="claude-3-5-sonnet-20241022", model="claude-3-sonnet-20240229",
max_tokens=1024,
messages=[ messages=[
{"role": "user", "content": query} {
] "role": "system",
"content": """You are a helpful AI assistant. When asked questions, provide informative responses
based on your general knowledge. You don't need to reference any specific documents or context.
Just answer naturally as a knowledgeable assistant."""
},
{
"role": "user",
"content": query
}
],
max_tokens=1024,
temperature=0.7
) )
# Get the complete response
full_response = response.content[0].text full_response = response.content[0].text
await msg.send(content=full_response)
# Create a new message for streaming
msg = cl.Message(content="")
await msg.send()
# Stream the response word by word
for word in full_response.split():
await msg.stream_token(word + " ")
# Update chat history # Update chat history
chat_history = cl.user_session.get("chat_history", []) chat_history = cl.user_session.get("chat_history", [])
chat_history.append((query, full_response)) chat_history.append((query, full_response))
cl.user_session.set("chat_history", chat_history) cl.user_session.set("chat_history", chat_history)
logger.info("Successfully generated fallback response")
except Exception as e: except Exception as e:
error_msg = f"Fallback error: {str(e)}" error_msg = f"Fallback error: {str(e)}"
logger.error(error_msg) logger.error(error_msg)
await msg.send(content=error_msg) await cl.Message(content=f"{error_msg}").send()
if __name__ == "__main__": if __name__ == "__main__":
cl.run() cl.run()