Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -2,6 +2,7 @@ import gradio as gr
|
|
| 2 |
import google.generativeai as genai
|
| 3 |
import os
|
| 4 |
import textwrap
|
|
|
|
| 5 |
from dotenv import load_dotenv
|
| 6 |
|
| 7 |
# RAG Specific Imports
|
|
@@ -21,12 +22,12 @@ except (ValueError, AttributeError) as e:
|
|
| 21 |
print(f"⚠️ Configuration Error: {e}")
|
| 22 |
exit()
|
| 23 |
|
| 24 |
-
# --- RAG Setup
|
|
|
|
| 25 |
def setup_rag_pipeline():
|
| 26 |
global retriever
|
| 27 |
print("Setting up RAG pipeline...")
|
| 28 |
try:
|
| 29 |
-
# Make sure your final optimized source file is named this
|
| 30 |
input_file = 'filtered_gardening_kb.txt'
|
| 31 |
with open(input_file, 'r', encoding='utf-8') as f:
|
| 32 |
source_text = f.read()
|
|
@@ -36,10 +37,11 @@ def setup_rag_pipeline():
|
|
| 36 |
documents = text_splitter.create_documents([source_text])
|
| 37 |
|
| 38 |
print(f"Creating embeddings for {len(documents)} chunks...")
|
|
|
|
| 39 |
embeddings = GoogleGenerativeAIEmbeddings(model="models/embedding-001")
|
| 40 |
|
| 41 |
vector_store = FAISS.from_documents(documents, embeddings)
|
| 42 |
-
retriever = vector_store.as_retriever(search_kwargs={"k": 7})
|
| 43 |
|
| 44 |
print("✅ RAG pipeline setup complete!")
|
| 45 |
|
|
@@ -50,35 +52,27 @@ def setup_rag_pipeline():
|
|
| 50 |
print(f"An error occurred during RAG setup: {e}")
|
| 51 |
retriever = None
|
| 52 |
|
| 53 |
-
# --- Gemini Model and
|
| 54 |
MODEL_NAME = 'gemini-1.5-flash-latest'
|
| 55 |
|
| 56 |
-
# UPDATED: This prompt encourages a more natural, expert-like tone.
|
| 57 |
SYSTEM_PROMPT = textwrap.dedent("""
|
| 58 |
You are a knowledgeable and friendly gardening expert from a community chat group. Your entire knowledge base comes from the CONTEXT CHUNKS provided below, which are excerpts from your group's conversations.
|
| 59 |
-
|
| 60 |
Your goal is to answer the user's questions in a helpful, conversational, and natural way, as if you are sharing your collective experience.
|
| 61 |
-
|
| 62 |
**Your Guidelines:**
|
| 63 |
-
1.
|
| 64 |
-
2.
|
| 65 |
-
3.
|
| 66 |
-
4.
|
| 67 |
-
5.
|
| 68 |
""").strip()
|
| 69 |
|
| 70 |
-
|
| 71 |
-
# --- UPDATED: Simplified Response Generation Function ---
|
| 72 |
def generate_gemini_response(message, chat_history):
|
| 73 |
-
"""Generates the chatbot's response using the RAG pipeline."""
|
| 74 |
if not retriever:
|
| 75 |
-
return "The RAG pipeline is not initialized. Please check
|
| 76 |
|
| 77 |
-
# 1. Retrieve relevant documents
|
| 78 |
relevant_docs = retriever.invoke(message)
|
| 79 |
context_chunks = "\n---\n".join([doc.page_content for doc in relevant_docs])
|
| 80 |
|
| 81 |
-
# 2. Construct the prompt with the retrieved context
|
| 82 |
full_prompt = f"""{SYSTEM_PROMPT}
|
| 83 |
|
| 84 |
<CONTEXT CHUNKS>
|
|
@@ -90,15 +84,15 @@ QUERY: {message}
|
|
| 90 |
try:
|
| 91 |
model = genai.GenerativeModel(MODEL_NAME)
|
| 92 |
response = model.generate_content(full_prompt)
|
| 93 |
-
|
| 94 |
-
# The entire citation parsing block is removed. We just return the clean text.
|
| 95 |
return response.text.strip()
|
| 96 |
-
|
| 97 |
except Exception as e:
|
|
|
|
|
|
|
|
|
|
| 98 |
print(f"Error generating response: {e}")
|
| 99 |
-
return "An error occurred while communicating with the AI model.
|
| 100 |
|
| 101 |
-
# --- Gradio UI & Styling
|
| 102 |
CSS = """
|
| 103 |
/* (Your existing CSS code remains unchanged here) */
|
| 104 |
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');
|
|
@@ -120,6 +114,11 @@ body, html { font-family: 'Inter', sans-serif; background-color: #121212; color:
|
|
| 120 |
#send-button:hover { background-color: #0056b3; transform: translateY(-1px); }
|
| 121 |
"""
|
| 122 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 123 |
with gr.Blocks(css=CSS, theme=gr.themes.Base()) as demo:
|
| 124 |
with gr.Column(elem_id="main-container"):
|
| 125 |
with gr.Row(elem_id="header"):
|
|
@@ -157,8 +156,9 @@ with gr.Blocks(css=CSS, theme=gr.themes.Base()) as demo:
|
|
| 157 |
|
| 158 |
btn_submit.click(process_and_clear, [txt_msg, chatbot], [chatbot, txt_msg])
|
| 159 |
txt_msg.submit(process_and_clear, [txt_msg, chatbot], [chatbot, txt_msg])
|
| 160 |
-
|
| 161 |
-
|
| 162 |
|
| 163 |
if __name__ == "__main__":
|
| 164 |
-
|
|
|
|
|
|
| 2 |
import google.generativeai as genai
|
| 3 |
import os
|
| 4 |
import textwrap
|
| 5 |
+
import re
|
| 6 |
from dotenv import load_dotenv
|
| 7 |
|
| 8 |
# RAG Specific Imports
|
|
|
|
| 22 |
print(f"⚠️ Configuration Error: {e}")
|
| 23 |
exit()
|
| 24 |
|
| 25 |
+
# --- RAG Setup Function ---
|
| 26 |
+
# This function will now be called directly, only once.
|
| 27 |
def setup_rag_pipeline():
|
| 28 |
global retriever
|
| 29 |
print("Setting up RAG pipeline...")
|
| 30 |
try:
|
|
|
|
| 31 |
input_file = 'filtered_gardening_kb.txt'
|
| 32 |
with open(input_file, 'r', encoding='utf-8') as f:
|
| 33 |
source_text = f.read()
|
|
|
|
| 37 |
documents = text_splitter.create_documents([source_text])
|
| 38 |
|
| 39 |
print(f"Creating embeddings for {len(documents)} chunks...")
|
| 40 |
+
# Note: Embedding has a different, much higher free quota than generation.
|
| 41 |
embeddings = GoogleGenerativeAIEmbeddings(model="models/embedding-001")
|
| 42 |
|
| 43 |
vector_store = FAISS.from_documents(documents, embeddings)
|
| 44 |
+
retriever = vector_store.as_retriever(search_kwargs={"k": 7})
|
| 45 |
|
| 46 |
print("✅ RAG pipeline setup complete!")
|
| 47 |
|
|
|
|
| 52 |
print(f"An error occurred during RAG setup: {e}")
|
| 53 |
retriever = None
|
| 54 |
|
| 55 |
+
# --- Gemini Model and Prompt ---
|
| 56 |
MODEL_NAME = 'gemini-1.5-flash-latest'
|
| 57 |
|
|
|
|
| 58 |
SYSTEM_PROMPT = textwrap.dedent("""
|
| 59 |
You are a knowledgeable and friendly gardening expert from a community chat group. Your entire knowledge base comes from the CONTEXT CHUNKS provided below, which are excerpts from your group's conversations.
|
|
|
|
| 60 |
Your goal is to answer the user's questions in a helpful, conversational, and natural way, as if you are sharing your collective experience.
|
|
|
|
| 61 |
**Your Guidelines:**
|
| 62 |
+
1. Base all answers on the source: Your responses must be directly inspired by and grounded in the information within the CONTEXT CHUNKS.
|
| 63 |
+
2. Synthesize and Connect: Feel free to connect related ideas from different parts of the context to provide a more complete answer.
|
| 64 |
+
3. Adopt a helpful persona: Sound like an experienced member of a gardening group sharing advice.
|
| 65 |
+
4. Handle missing information gracefully: If the user's question is completely outside the scope of the provided text, state that the chats don't cover that topic. If it's related but not explicit, you can say, "While the chats don't mention that directly, the general advice on [related topic] suggests that..."
|
| 66 |
+
5. Do NOT add citations: Just provide a clean, direct answer.
|
| 67 |
""").strip()
|
| 68 |
|
|
|
|
|
|
|
| 69 |
def generate_gemini_response(message, chat_history):
|
|
|
|
| 70 |
if not retriever:
|
| 71 |
+
return "The RAG pipeline is not initialized. Please check application logs."
|
| 72 |
|
|
|
|
| 73 |
relevant_docs = retriever.invoke(message)
|
| 74 |
context_chunks = "\n---\n".join([doc.page_content for doc in relevant_docs])
|
| 75 |
|
|
|
|
| 76 |
full_prompt = f"""{SYSTEM_PROMPT}
|
| 77 |
|
| 78 |
<CONTEXT CHUNKS>
|
|
|
|
| 84 |
try:
|
| 85 |
model = genai.GenerativeModel(MODEL_NAME)
|
| 86 |
response = model.generate_content(full_prompt)
|
|
|
|
|
|
|
| 87 |
return response.text.strip()
|
|
|
|
| 88 |
except Exception as e:
|
| 89 |
+
# Provide a more user-friendly message for quota errors
|
| 90 |
+
if "quota" in str(e).lower():
|
| 91 |
+
return "The daily free API quota has been reached. Please try again tomorrow or upgrade your Google AI plan by enabling billing."
|
| 92 |
print(f"Error generating response: {e}")
|
| 93 |
+
return "An error occurred while communicating with the AI model."
|
| 94 |
|
| 95 |
+
# --- Gradio UI & Styling ---
|
| 96 |
CSS = """
|
| 97 |
/* (Your existing CSS code remains unchanged here) */
|
| 98 |
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');
|
|
|
|
| 114 |
#send-button:hover { background-color: #0056b3; transform: translateY(-1px); }
|
| 115 |
"""
|
| 116 |
|
| 117 |
+
# --- Main Application Logic ---
|
| 118 |
+
# First, set up the RAG pipeline globally.
|
| 119 |
+
retriever = None
|
| 120 |
+
setup_rag_pipeline()
|
| 121 |
+
|
| 122 |
with gr.Blocks(css=CSS, theme=gr.themes.Base()) as demo:
|
| 123 |
with gr.Column(elem_id="main-container"):
|
| 124 |
with gr.Row(elem_id="header"):
|
|
|
|
| 156 |
|
| 157 |
btn_submit.click(process_and_clear, [txt_msg, chatbot], [chatbot, txt_msg])
|
| 158 |
txt_msg.submit(process_and_clear, [txt_msg, chatbot], [chatbot, txt_msg])
|
| 159 |
+
|
| 160 |
+
# The demo.load() is removed, as setup is now handled before the Blocks are defined.
|
| 161 |
|
| 162 |
if __name__ == "__main__":
|
| 163 |
+
# For deploying on Hugging Face, it's better to set debug=False
|
| 164 |
+
demo.queue().launch(debug=False)
|