jdesiree commited on
Commit
f5d14de
ยท
verified ยท
1 Parent(s): 3dd3d1c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +216 -19
app.py CHANGED
@@ -12,29 +12,226 @@ import re
12
  logging.basicConfig(level=logging.INFO)
13
  logger = logging.getLogger(__name__)
14
 
15
- # Custom streaming callback with improved behavior
16
- class GradioStreamingCallback(BaseCallbackHandler):
17
- """Enhanced LangChain callback for streaming to Gradio"""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
 
19
- def __init__(self):
20
- self.text = ""
21
- self.tokens = []
22
- self.is_streaming = False
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
 
24
- def on_llm_start(self, serialized, prompts, **kwargs):
25
- """Called when LLM starts generating"""
26
- self.text = ""
27
- self.tokens = []
28
- self.is_streaming = True
29
- logger.info("LLM generation started")
 
 
 
 
 
 
 
 
 
30
 
31
- def on_llm_new_token(self, token: str, **kwargs):
32
- """Called when LLM generates a new token"""
33
- self.tokens.append(token)
34
- self.text += token
35
- return self.text
 
 
 
 
 
 
36
 
37
- def on_llm_end(self, response, **kwargs):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
  """Called when LLM finishes generating"""
39
  self.is_streaming = False
40
  logger.info(f"LLM generation completed. Total tokens: {len(self.tokens)}")
 
12
  logging.basicConfig(level=logging.INFO)
13
  logger = logging.getLogger(__name__)
14
 
15
+ # Set up LangChain model with conservative settings
16
+ llm = HuggingFaceEndpoint(
17
+ repo_id="HuggingFaceH4/zephyr-7b-beta",
18
+ temperature=0.7,
19
+ top_p=0.9,
20
+ repetition_penalty=1.1,
21
+ model_kwargs={"max_length": 1024},
22
+ huggingfacehub_api_token=os.getenv("HUGGINGFACEHUB_API_TOKEN")
23
+ )
24
+
25
+ # Enhanced prompt templates that use system_message parameter
26
+ math_template = ChatPromptTemplate.from_messages([
27
+ ("system", """{system_message}
28
+
29
+ You are an expert math tutor. For every math problem:
30
+ 1. Break it down step-by-step with detailed explanations
31
+ 2. Explain the reasoning behind each step thoroughly
32
+ 3. Show all work clearly with proper mathematical notation
33
+ 4. Check your answer and explain why it's correct
34
+ 5. Provide additional examples if helpful
35
+ 6. Explain the underlying mathematical concepts
36
+
37
+ Be comprehensive and educational. Structure your response clearly."""),
38
+ ("human", "{question}")
39
+ ])
40
+
41
+ research_template = ChatPromptTemplate.from_messages([
42
+ ("system", """{system_message}
43
+
44
+ You are a research skills mentor. Help students with:
45
+ - Finding reliable and credible sources
46
+ - Evaluating source credibility and bias
47
+ - Proper citation formats (APA, MLA, Chicago, etc.)
48
+ - Research strategies and methodologies
49
+ - Academic writing techniques and structure
50
+ - Database navigation and search strategies
51
+
52
+ Provide detailed, actionable advice with specific examples."""),
53
+ ("human", "{question}")
54
+ ])
55
+
56
+ study_template = ChatPromptTemplate.from_messages([
57
+ ("system", """{system_message}
58
+
59
+ You are a study skills coach. Help students with:
60
+ - Effective study methods for different learning styles
61
+ - Time management and scheduling techniques
62
+ - Memory techniques and retention strategies
63
+ - Test preparation and exam strategies
64
+ - Note-taking methods and organization
65
+ - Learning style optimization
66
+
67
+ Provide comprehensive, personalized advice with practical examples."""),
68
+ ("human", "{question}")
69
+ ])
70
+
71
+ general_template = ChatPromptTemplate.from_messages([
72
+ ("system", """{system_message}
73
+
74
+ You are EduBot, a comprehensive AI learning assistant. You help students with:
75
+ ๐Ÿ“ Mathematics (detailed step-by-step solutions and concept explanations)
76
+ ๐Ÿ” Research skills (source finding, evaluation, and citation)
77
+ ๐Ÿ“š Study strategies (effective learning techniques and exam preparation)
78
+ ๐Ÿ› ๏ธ Educational tools (guidance on learning resources and technologies)
79
+
80
+ Always be encouraging, patient, thorough, and comprehensive."""),
81
+ ("human", "{question}")
82
+ ])
83
+
84
+ def detect_subject(message):
85
+ """Determine which prompt template to use based on the message"""
86
+ message_lower = message.lower()
87
 
88
+ math_keywords = ['math', 'solve', 'calculate', 'equation', 'formula', 'algebra', 'geometry', 'calculus', 'derivative', 'integral', 'theorem', 'proof']
89
+ research_keywords = ['research', 'source', 'citation', 'bibliography', 'reference', 'academic', 'paper', 'essay', 'thesis', 'database', 'journal']
90
+ study_keywords = ['study', 'memorize', 'exam', 'test', 'quiz', 'review', 'learn', 'remember', 'focus', 'motivation', 'notes']
91
+
92
+ if any(keyword in message_lower for keyword in math_keywords):
93
+ return math_template, "๐Ÿงฎ Math Mode"
94
+ elif any(keyword in message_lower for keyword in research_keywords):
95
+ return research_template, "๐Ÿ” Research Mode"
96
+ elif any(keyword in message_lower for keyword in study_keywords):
97
+ return study_template, "๐Ÿ“š Study Mode"
98
+ else:
99
+ return general_template, "๐ŸŽ“ General Mode"
100
+
101
+ def smart_truncate(text, max_length=3000):
102
+ """Intelligently truncate text at sentence boundaries"""
103
+ if len(text) <= max_length:
104
+ return text
105
+
106
+ # Try to cut at last complete sentence
107
+ sentences = re.split(r'(?<=[.!?]) +', text[:max_length])
108
+ if len(sentences) > 1:
109
+ # Remove the last incomplete sentence
110
+ return ' '.join(sentences[:-1]) + "... [Response truncated - ask for continuation]"
111
+ else:
112
+ # Fallback to word boundary
113
+ words = text[:max_length].split()
114
+ return ' '.join(words[:-1]) + "... [Response truncated - ask for continuation]"
115
+
116
+ def respond_with_enhanced_streaming(
117
+ message,
118
+ history: list[tuple[str, str]],
119
+ system_message,
120
+ max_tokens,
121
+ temperature,
122
+ top_p,
123
+ ):
124
+ """Enhanced LangChain implementation with proper system message handling"""
125
+
126
+ try:
127
+ # Select template and get mode
128
+ template, mode = detect_subject(message)
129
+
130
+ # Create LangChain chain
131
+ chain = template | llm
132
+
133
+ # Show initial mode
134
+ yield f"*{mode}*\n\nGenerating response..."
135
+
136
+ # Get complete response from LangChain with system message
137
+ logger.info(f"Processing {mode} query: {message[:50]}...")
138
+
139
+ response = chain.invoke({
140
+ "question": message,
141
+ "system_message": system_message or "You are EduBot, an AI learning assistant."
142
+ })
143
+
144
+ # Smart truncation at sentence boundaries
145
+ response = smart_truncate(response, max_length=3000)
146
+
147
+ # Simulate streaming by chunking the response
148
+ words = response.split()
149
+ partial_response = f"*{mode}*\n\n"
150
+
151
+ # Stream word by word for better UX
152
+ for i, word in enumerate(words):
153
+ partial_response += word + " "
154
+
155
+ # Update every 4 words for smooth streaming effect
156
+ if i % 4 == 0:
157
+ yield partial_response
158
+ time.sleep(0.03) # Slightly faster streaming
159
 
160
+ # Final complete response
161
+ final_response = f"*{mode}*\n\n{response}"
162
+ logger.info(f"Response completed. Length: {len(response)} characters")
163
+ yield final_response
164
+
165
+ except Exception as e:
166
+ logger.exception("Error in LangChain response generation")
167
+ yield f"Sorry, I encountered an error: {str(e)[:150]}"
168
+
169
+ # Create enhanced Gradio interface (simplified for compatibility)
170
+ demo = gr.ChatInterface(
171
+ respond_with_enhanced_streaming,
172
+ title="๐ŸŽ“ EduBot | AI Learning Assistant",
173
+ description="""
174
+ **Your comprehensive AI tutor powered by LangChain!**
175
 
176
+ ๐Ÿ”ง **Technical Features:**
177
+ โ€ข Dynamic prompt templates based on question type
178
+ โ€ข LangChain chain composition with `|` operator
179
+ โ€ข Smart response truncation at sentence boundaries
180
+ โ€ข Enhanced error handling and logging
181
+
182
+ ๐Ÿ“š **Educational Modes:**
183
+ โ€ข ๐Ÿงฎ **Math Mode** - Step-by-step problem solving with detailed explanations
184
+ โ€ข ๐Ÿ” **Research Mode** - Source finding, evaluation, and citation guidance
185
+ โ€ข ๐Ÿ“š **Study Mode** - Learning strategies and exam preparation techniques
186
+ โ€ข ๐ŸŽ“ **General Mode** - Comprehensive educational support
187
 
188
+ ๐Ÿ’ก **Tip:** Try asking detailed questions for thorough explanations!
189
+ """,
190
+ examples=[
191
+ ["Solve the quadratic equation xยฒ + 5x + 6 = 0 with complete step-by-step explanations"],
192
+ ["How do I conduct a comprehensive literature review for my psychology research paper?"],
193
+ ["Create a detailed study schedule for my calculus and chemistry final exams"],
194
+ ["Explain derivatives in calculus with real-world applications and examples"],
195
+ ["How do I properly format citations in APA style with detailed guidelines?"]
196
+ ],
197
+ additional_inputs=[
198
+ gr.Textbox(
199
+ value="You are EduBot, an expert AI learning assistant. Provide comprehensive, educational responses that help students truly understand concepts.",
200
+ label="Custom System Message",
201
+ placeholder="Customize how EduBot behaves...",
202
+ lines=2
203
+ ),
204
+ gr.Slider(
205
+ minimum=1,
206
+ maximum=1024,
207
+ value=600,
208
+ step=1,
209
+ label="Max Tokens"
210
+ ),
211
+ gr.Slider(
212
+ minimum=0.1,
213
+ maximum=2.0,
214
+ value=0.7,
215
+ step=0.1,
216
+ label="Temperature"
217
+ ),
218
+ gr.Slider(
219
+ minimum=0.1,
220
+ maximum=1.0,
221
+ value=0.9,
222
+ step=0.05,
223
+ label="Top-p"
224
+ ),
225
+ ],
226
+ theme=gr.themes.Soft(
227
+ primary_hue="blue",
228
+ secondary_hue="green"
229
+ )
230
+ )
231
+
232
+ if __name__ == "__main__":
233
+ logger.info("Starting EduBot application...")
234
+ demo.launch() def on_llm_end(self, response, **kwargs):
235
  """Called when LLM finishes generating"""
236
  self.is_streaming = False
237
  logger.info(f"LLM generation completed. Total tokens: {len(self.tokens)}")