deenaik commited on
Commit
d84fcd9
Β·
1 Parent(s): 33bbab3

Deploy: HPMOR Q&A chatbot - 2025-10-15

Browse files
Files changed (5) hide show
  1. .env.example +19 -0
  2. .gitignore +17 -1
  3. README.md +0 -0
  4. app.py +221 -0
  5. requirements.txt +12 -0
.env.example ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Groq API Configuration
2
+ GROQ_API_KEY=your_groq_api_key_here
3
+ GROQ_MODEL=llama-3.3-70b-versatile
4
+
5
+ # Embedding Model
6
+ EMBEDDING_MODEL=sentence-transformers/all-MiniLM-L6-v2
7
+
8
+ # Processing Parameters
9
+ CHUNK_SIZE=1000
10
+ CHUNK_OVERLAP=200
11
+ TOP_K_RETRIEVAL=5
12
+
13
+ # ChromaDB Settings
14
+ CHROMA_PERSIST_DIR=./chroma_db
15
+ COLLECTION_NAME=hpmor_collection
16
+
17
+ # Gradio Settings
18
+ GRADIO_SERVER_PORT=7860
19
+ GRADIO_SHARE=False
.gitignore CHANGED
@@ -9,7 +9,23 @@ wheels/
9
  # Virtual environments
10
  .venv
11
 
12
- # Database
 
 
 
13
  chroma_db/
14
  blobs/
 
 
15
  models/
 
 
 
 
 
 
 
 
 
 
 
 
9
  # Virtual environments
10
  .venv
11
 
12
+ # Environment variables (keep .env.example)
13
+ .env
14
+
15
+ # Database (will be rebuilt on deployment)
16
  chroma_db/
17
  blobs/
18
+
19
+ # Downloaded models (embeddings will be re-downloaded)
20
  models/
21
+
22
+ # Keep data files - they are needed for deployment!
23
+ # data/ is NOT ignored
24
+ # data/raw/hpmor.html is required
25
+ # data/processed/ can be regenerated but it's fine to include
26
+
27
+ # MacOS
28
+ .DS_Store
29
+
30
+ # UV lock file (optional - can be regenerated)
31
+ # uv.lock
README.md CHANGED
Binary files a/README.md and b/README.md differ
 
app.py ADDED
@@ -0,0 +1,221 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """HuggingFace Spaces app for HPMOR Q&A System - Cloud deployment version."""
3
+
4
+ import os
5
+ import sys
6
+ import gradio as gr
7
+ from typing import List, Tuple
8
+ from pathlib import Path
9
+
10
+ # Add src to path
11
+ sys.path.insert(0, str(Path(__file__).parent))
12
+
13
+ from src.config import config
14
+ from src.document_processor import HPMORProcessor
15
+ from src.vector_store import VectorStoreManager
16
+ from src.rag_engine import RAGEngine
17
+
18
+ # Force Groq-only mode for cloud deployment
19
+ os.environ["FORCE_GROQ_ONLY"] = "1"
20
+
21
+
22
+ class HFChatInterface:
23
+ """Simplified chat interface for HuggingFace Spaces."""
24
+
25
+ def __init__(self):
26
+ """Initialize the chat interface."""
27
+ print("Initializing HPMOR Q&A Chat Interface for HuggingFace Spaces...")
28
+
29
+ # Check if we need to setup
30
+ processed_docs = config.processed_data_dir / "documents.json"
31
+ if not processed_docs.exists():
32
+ print("Setting up system for first time...")
33
+ self.setup_system()
34
+
35
+ # Initialize RAG engine (Groq-only mode)
36
+ self.engine = RAGEngine(force_recreate=False)
37
+ print("System ready!")
38
+
39
+ def setup_system(self):
40
+ """Set up the HPMOR Q&A system."""
41
+ print("Processing HPMOR document...")
42
+ processor = HPMORProcessor()
43
+ documents = processor.process(force_reprocess=False)
44
+ print(f"Processed {len(documents)} chunks")
45
+
46
+ print("Creating vector index...")
47
+ vector_store = VectorStoreManager()
48
+ vector_store.get_or_create_index(documents, force_recreate=False)
49
+ print("Setup complete!")
50
+
51
+ def format_sources(self, sources: List[dict]) -> str:
52
+ """Format sources for display."""
53
+ if not sources:
54
+ return ""
55
+
56
+ formatted = []
57
+ for i, source in enumerate(sources[:3], 1): # Limit to top 3 sources
58
+ formatted.append(
59
+ f"**Source {i}** - Chapter {source['chapter_number']}: {source['chapter_title']}\n"
60
+ f"Relevance: {source['score']:.2f}\n"
61
+ f"*{source['text_preview'][:100]}...*"
62
+ )
63
+ return "\n\n".join(formatted)
64
+
65
+ def process_message(
66
+ self,
67
+ message: str,
68
+ history: List[List[str]],
69
+ show_sources: bool
70
+ ) -> Tuple[str, str]:
71
+ """Process a chat message and return response."""
72
+ if not message:
73
+ return "", "Please enter a question."
74
+
75
+ # Convert history to messages format
76
+ messages = []
77
+ for user_msg, assistant_msg in history:
78
+ if user_msg:
79
+ messages.append({"role": "user", "content": user_msg})
80
+ if assistant_msg:
81
+ messages.append({"role": "assistant", "content": assistant_msg})
82
+ messages.append({"role": "user", "content": message})
83
+
84
+ try:
85
+ # Get response from engine
86
+ response = self.engine.chat(messages, stream=False)
87
+
88
+ # Extract answer
89
+ if isinstance(response.get("answer"), str):
90
+ answer = response["answer"]
91
+ else:
92
+ answer = str(response.get("answer", "No response generated"))
93
+
94
+ # Format sources if requested
95
+ sources_text = ""
96
+ if show_sources and response.get("sources"):
97
+ sources_text = "\n\n---\n\n**πŸ“š Sources from HPMOR:**\n\n" + self.format_sources(response["sources"])
98
+ answer = answer + sources_text
99
+
100
+ return answer, ""
101
+
102
+ except Exception as e:
103
+ error_msg = f"I apologize, but I encountered an error: {str(e)}\n\nPlease make sure the Groq API key is properly configured."
104
+ return error_msg, ""
105
+
106
+
107
+ def create_interface() -> gr.Blocks:
108
+ """Create the Gradio interface."""
109
+
110
+ # Initialize chat interface
111
+ chat_interface = HFChatInterface()
112
+
113
+ with gr.Blocks(title="Chat with Harry Potter-Evans-Verres", theme=gr.themes.Soft()) as interface:
114
+ gr.Markdown(
115
+ """
116
+ # πŸ§™β€β™‚οΈ Chat with Harry James Potter-Evans-Verres
117
+
118
+ Hello! I'm Harry Potter-Evans-Verres from "Harry Potter and the Methods of Rationality."
119
+ Ask me anything about my adventures, experiments with magic, or my thoughts on rationality and science.
120
+ I'll respond based on my experiences and the scientific method, of course!
121
+
122
+ *Powered by RAG with ChromaDB and Groq API (llama-3.3-70b-versatile)*
123
+ """
124
+ )
125
+
126
+ with gr.Row():
127
+ with gr.Column(scale=3):
128
+ chatbot = gr.Chatbot(
129
+ label="Chat",
130
+ height=500,
131
+ show_copy_button=True,
132
+ avatar_images=(None, "πŸ§™β€β™‚οΈ")
133
+ )
134
+
135
+ with gr.Row():
136
+ msg_input = gr.Textbox(
137
+ label="Your Question",
138
+ placeholder="Ask me anything... For example: 'What do you think about magic?' or 'Tell me about your experiments'",
139
+ lines=2,
140
+ scale=4
141
+ )
142
+ submit_btn = gr.Button("Send πŸ“¨", variant="primary", scale=1)
143
+
144
+ with gr.Column(scale=1):
145
+ gr.Markdown("### βš™οΈ Settings")
146
+
147
+ show_sources = gr.Checkbox(
148
+ value=True,
149
+ label="Show Sources from Book"
150
+ )
151
+
152
+ gr.Markdown(
153
+ """
154
+ ### πŸ’‘ Tips
155
+ - Ask about Harry's experiments
156
+ - Inquire about his views on magic
157
+ - Ask about other characters
158
+ - Request explanations of events
159
+ """
160
+ )
161
+
162
+ # Example questions
163
+ gr.Examples(
164
+ examples=[
165
+ "Harry, how did you first react when you learned magic was real?",
166
+ "What's your opinion on the way Hogwarts teaches magic?",
167
+ "Can you explain your scientific experiments with magic?",
168
+ "What do you think about Hermione?",
169
+ "How do you apply rationality to magical problems?",
170
+ "What's your relationship with Professor Quirrell like?",
171
+ ],
172
+ inputs=msg_input,
173
+ label="πŸ’¬ Example Questions"
174
+ )
175
+
176
+ # Event handlers
177
+ def respond(message, history, sources):
178
+ """Handle message submission."""
179
+ answer, _ = chat_interface.process_message(message, history, sources)
180
+ history.append([message, answer])
181
+ return "", history
182
+
183
+ msg_input.submit(
184
+ respond,
185
+ inputs=[msg_input, chatbot, show_sources],
186
+ outputs=[msg_input, chatbot]
187
+ )
188
+
189
+ submit_btn.click(
190
+ respond,
191
+ inputs=[msg_input, chatbot, show_sources],
192
+ outputs=[msg_input, chatbot]
193
+ )
194
+
195
+ gr.Markdown(
196
+ """
197
+ ---
198
+
199
+ **About:** This chatbot uses Retrieval-Augmented Generation (RAG) to answer questions
200
+ based on "Harry Potter and the Methods of Rationality" by Eliezer Yudkowsky.
201
+
202
+ **Note:** Requires a Groq API key. Get one free at [console.groq.com](https://console.groq.com/)
203
+ """
204
+ )
205
+
206
+ return interface
207
+
208
+
209
+ if __name__ == "__main__":
210
+ # Check for Groq API key
211
+ if not os.getenv("GROQ_API_KEY"):
212
+ print("WARNING: GROQ_API_KEY not found in environment variables!")
213
+ print("Please set it in your HuggingFace Space secrets.")
214
+
215
+ # Launch interface
216
+ interface = create_interface()
217
+ interface.launch(
218
+ server_name="0.0.0.0",
219
+ server_port=7860,
220
+ share=False
221
+ )
requirements.txt ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ chromadb==1.1.1
2
+ gradio==5.49.1
3
+ httpx==0.28.1
4
+ huggingface-hub==0.35.3
5
+ langchain==0.3.27
6
+ langchain-groq==0.3.8
7
+ llama-index==0.14.4
8
+ llama-index-embeddings-huggingface==0.6.1
9
+ llama-index-llms-groq==0.4.1
10
+ llama-index-vector-stores-chroma==0.5.3
11
+ lxml==6.0.2
12
+ sentence-transformers