jdesiree commited on
Commit
7f5d340
ยท
verified ยท
1 Parent(s): bb3a918

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +174 -54
app.py CHANGED
@@ -2,60 +2,98 @@ import gradio as gr
2
  from langchain.prompts import ChatPromptTemplate
3
  from langchain_huggingface import HuggingFaceEndpoint
4
  from langchain.schema import HumanMessage, SystemMessage
 
5
  import os
 
6
 
7
- # Set up the LangChain model (using HuggingFace Zephyr model)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
  llm = HuggingFaceEndpoint(
9
  repo_id="HuggingFaceH4/zephyr-7b-beta",
10
  temperature=0.7,
11
  top_p=0.9,
12
  model_kwargs={
13
- "max_length": 1024
 
 
14
  },
15
  huggingfacehub_api_token=os.getenv("HUGGINGFACEHUB_API_TOKEN")
16
  )
17
 
18
- # Create different prompt templates for different subjects
19
  math_template = ChatPromptTemplate.from_messages([
20
  ("system", """You are an expert math tutor. For every math problem:
21
- 1. Break it down step-by-step
22
- 2. Explain the reasoning behind each step
23
- 3. Show all work clearly
24
- 4. Check your answer
25
- 5. Ask if the student has questions about any step"""),
 
 
 
26
  ("human", "{question}")
27
  ])
28
 
29
  research_template = ChatPromptTemplate.from_messages([
30
  ("system", """You are a research skills mentor. Help students with:
31
- - Finding reliable sources
32
- - Evaluating source credibility
33
- - Proper citation formats
34
- - Research strategies
35
- - Academic writing techniques
36
- Always provide specific, actionable advice."""),
 
 
37
  ("human", "{question}")
38
  ])
39
 
40
  study_template = ChatPromptTemplate.from_messages([
41
  ("system", """You are a study skills coach. Help students with:
42
- - Effective study methods
43
- - Time management
44
- - Memory techniques
45
- - Test preparation strategies
 
46
  - Learning style optimization
47
- Provide personalized, practical advice."""),
 
48
  ("human", "{question}")
49
  ])
50
 
51
  general_template = ChatPromptTemplate.from_messages([
52
- ("system", """You are EduBot, a friendly AI learning assistant. You help students with:
53
- ๐Ÿ“ Math problems (step-by-step solutions)
54
- ๐Ÿ” Research skills (finding sources, citations)
55
- ๐Ÿ“š Study strategies (effective learning techniques)
56
- ๐Ÿ› ๏ธ Educational tools (learning resources)
57
 
58
- Always be encouraging, patient, and thorough in your explanations."""),
59
  ("human", "{question}")
60
  ])
61
 
@@ -63,9 +101,9 @@ def detect_subject(message):
63
  """Determine which prompt template to use based on the message"""
64
  message_lower = message.lower()
65
 
66
- math_keywords = ['math', 'solve', 'calculate', 'equation', 'formula', 'algebra', 'geometry', 'calculus', 'derivative', 'integral']
67
- research_keywords = ['research', 'source', 'citation', 'bibliography', 'reference', 'academic', 'paper', 'essay', 'thesis']
68
- study_keywords = ['study', 'memorize', 'exam', 'test', 'quiz', 'review', 'learn', 'remember']
69
 
70
  if any(keyword in message_lower for keyword in math_keywords):
71
  return math_template, "๐Ÿงฎ Math Mode"
@@ -76,7 +114,7 @@ def detect_subject(message):
76
  else:
77
  return general_template, "๐ŸŽ“ General Mode"
78
 
79
- def respond_with_langchain(
80
  message,
81
  history: list[tuple[str, str]],
82
  system_message,
@@ -84,56 +122,138 @@ def respond_with_langchain(
84
  temperature,
85
  top_p,
86
  ):
 
 
87
  try:
 
88
  template, mode = detect_subject(message)
89
- formatted_prompt = template.format_messages(question=message)
90
- prompt_text = f"{formatted_prompt[0].content}\n\nHuman: {formatted_prompt[1].content}\n\nAssistant:"
91
 
92
- response = llm.invoke(prompt_text)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
93
 
94
- # Ensure response is clean and properly limited
95
- if isinstance(response, str):
96
- response = response.strip()
97
- # Conservative limit to prevent content-length issues
98
- if len(response) > 2500:
99
- response = response[:2500] + "... [Response truncated - ask for continuation]"
100
 
101
- full_response = f"*{mode}*\n\n{response}"
 
 
 
 
 
 
 
102
 
103
- # Return directly instead of yielding (no streaming)
104
- return full_response
105
 
106
  except Exception as e:
107
- return f"Sorry, I encountered an error: {str(e)[:150]}"
108
 
109
- # Create the Gradio interface
110
  demo = gr.ChatInterface(
111
- respond_with_langchain,
112
- title="๐ŸŽ“ EduBot | AI Learning Assistant",
113
- description="Your personal AI tutor",
 
114
  examples=[
115
- ["Solve the equation 3x + 7 = 22 step by step"],
116
- ["How do I find reliable sources for my history paper?"],
117
- ["What's the best way to study for a biology exam?"],
118
- ["Explain the Pythagorean theorem with an example"],
119
- ["How do I cite a website in MLA format?"]
120
  ],
121
  additional_inputs=[
122
  gr.Textbox(
123
- value="You are EduBot, an education assitance. You aid users in studying and understanding new concepts. You show, not tell, how to perform mathematical problem solving, research, study concepts, and utilize study tools.",
124
  label="System message",
125
  visible=False
126
  ),
127
- gr.Slider(minimum=1, maximum=1024, value=512, step=1, label="Max new tokens"),
128
  gr.Slider(minimum=0.1, maximum=2.0, value=0.7, step=0.1, label="Temperature"),
129
  gr.Slider(
130
  minimum=0.1,
131
  maximum=1.0,
132
- value=0.95,
133
  step=0.05,
134
  label="Top-p (nucleus sampling)",
135
  ),
136
  ],
 
 
 
 
137
  )
138
 
139
  if __name__ == "__main__":
 
2
  from langchain.prompts import ChatPromptTemplate
3
  from langchain_huggingface import HuggingFaceEndpoint
4
  from langchain.schema import HumanMessage, SystemMessage
5
+ from langchain.callbacks.base import BaseCallbackHandler
6
  import os
7
+ import time
8
 
9
+ # Custom streaming callback for Gradio
10
+ class GradioStreamingCallback(BaseCallbackHandler):
11
+ """Custom LangChain callback for streaming to Gradio"""
12
+
13
+ def __init__(self):
14
+ self.text = ""
15
+ self.tokens = []
16
+
17
+ def on_llm_start(self, serialized, prompts, **kwargs):
18
+ """Called when LLM starts generating"""
19
+ self.text = ""
20
+ self.tokens = []
21
+
22
+ def on_llm_new_token(self, token: str, **kwargs):
23
+ """Called when LLM generates a new token"""
24
+ self.tokens.append(token)
25
+ self.text += token
26
+ return self.text
27
+
28
+ def on_llm_end(self, response, **kwargs):
29
+ """Called when LLM finishes generating"""
30
+ pass
31
+
32
+ def on_llm_error(self, error, **kwargs):
33
+ """Called when LLM encounters an error"""
34
+ self.text += f"\n[Error: {str(error)[:100]}]"
35
+
36
+ # Set up LangChain model with streaming capabilities
37
  llm = HuggingFaceEndpoint(
38
  repo_id="HuggingFaceH4/zephyr-7b-beta",
39
  temperature=0.7,
40
  top_p=0.9,
41
  model_kwargs={
42
+ "max_length": 1536,
43
+ "return_full_text": False,
44
+ "repetition_penalty": 1.1,
45
  },
46
  huggingfacehub_api_token=os.getenv("HUGGINGFACEHUB_API_TOKEN")
47
  )
48
 
49
+ # Enhanced prompt templates with streaming instructions
50
  math_template = ChatPromptTemplate.from_messages([
51
  ("system", """You are an expert math tutor. For every math problem:
52
+ 1. Break it down step-by-step with detailed explanations
53
+ 2. Explain the reasoning behind each step thoroughly
54
+ 3. Show all work clearly with proper mathematical notation
55
+ 4. Check your answer and explain why it's correct
56
+ 5. Provide additional examples if helpful
57
+ 6. Explain the underlying mathematical concepts
58
+
59
+ Be comprehensive and educational. Structure your response clearly with proper spacing."""),
60
  ("human", "{question}")
61
  ])
62
 
63
  research_template = ChatPromptTemplate.from_messages([
64
  ("system", """You are a research skills mentor. Help students with:
65
+ - Finding reliable and credible sources
66
+ - Evaluating source credibility and bias
67
+ - Proper citation formats (APA, MLA, Chicago, etc.)
68
+ - Research strategies and methodologies
69
+ - Academic writing techniques and structure
70
+ - Database navigation and search strategies
71
+
72
+ Provide detailed, actionable advice with specific examples and clear formatting."""),
73
  ("human", "{question}")
74
  ])
75
 
76
  study_template = ChatPromptTemplate.from_messages([
77
  ("system", """You are a study skills coach. Help students with:
78
+ - Effective study methods for different learning styles
79
+ - Time management and scheduling techniques
80
+ - Memory techniques and retention strategies
81
+ - Test preparation and exam strategies
82
+ - Note-taking methods and organization
83
  - Learning style optimization
84
+
85
+ Provide comprehensive, personalized advice with practical examples and clear structure."""),
86
  ("human", "{question}")
87
  ])
88
 
89
  general_template = ChatPromptTemplate.from_messages([
90
+ ("system", """You are EduBot, a comprehensive AI learning assistant. You help students with:
91
+ ๐Ÿ“ Mathematics (detailed step-by-step solutions and concept explanations)
92
+ ๐Ÿ” Research skills (source finding, evaluation, and citation)
93
+ ๐Ÿ“š Study strategies (effective learning techniques and exam preparation)
94
+ ๐Ÿ› ๏ธ Educational tools (guidance on learning resources and technologies)
95
 
96
+ Always be encouraging, patient, thorough, and comprehensive. Structure responses clearly."""),
97
  ("human", "{question}")
98
  ])
99
 
 
101
  """Determine which prompt template to use based on the message"""
102
  message_lower = message.lower()
103
 
104
+ math_keywords = ['math', 'solve', 'calculate', 'equation', 'formula', 'algebra', 'geometry', 'calculus', 'derivative', 'integral', 'theorem', 'proof']
105
+ research_keywords = ['research', 'source', 'citation', 'bibliography', 'reference', 'academic', 'paper', 'essay', 'thesis', 'database', 'journal']
106
+ study_keywords = ['study', 'memorize', 'exam', 'test', 'quiz', 'review', 'learn', 'remember', 'focus', 'motivation', 'notes']
107
 
108
  if any(keyword in message_lower for keyword in math_keywords):
109
  return math_template, "๐Ÿงฎ Math Mode"
 
114
  else:
115
  return general_template, "๐ŸŽ“ General Mode"
116
 
117
+ def respond_with_langchain_streaming(
118
  message,
119
  history: list[tuple[str, str]],
120
  system_message,
 
122
  temperature,
123
  top_p,
124
  ):
125
+ """Custom LangChain streaming implementation for Gradio"""
126
+
127
  try:
128
+ # Select appropriate template and mode
129
  template, mode = detect_subject(message)
 
 
130
 
131
+ # Create custom streaming callback
132
+ streaming_callback = GradioStreamingCallback()
133
+
134
+ # Create the LangChain chain
135
+ chain = template | llm
136
+
137
+ # Configure streaming with callbacks
138
+ config = {
139
+ "callbacks": [streaming_callback],
140
+ "metadata": {"mode": mode}
141
+ }
142
+
143
+ # Start streaming response
144
+ partial_response = f"*{mode}*\n\n"
145
+ yield partial_response
146
+
147
+ # Invoke LangChain with streaming
148
+ try:
149
+ # Get the response (this triggers the callbacks)
150
+ response = chain.invoke(
151
+ {"question": message},
152
+ config=config
153
+ )
154
+
155
+ # Handle the streaming output
156
+ if hasattr(streaming_callback, 'text') and streaming_callback.text:
157
+ # Use the streamed text from callback
158
+ final_text = streaming_callback.text
159
+ else:
160
+ # Fallback to direct response
161
+ final_text = str(response)
162
+
163
+ # Clean up the response
164
+ if len(final_text) > 4000:
165
+ final_text = final_text[:4000] + "... [Response truncated - ask for continuation]"
166
+
167
+ # Yield the complete response
168
+ full_response = f"*{mode}*\n\n{final_text}"
169
+ yield full_response
170
+
171
+ except Exception as invoke_error:
172
+ yield f"*{mode}*\n\nSorry, I encountered an error while generating the response: {str(invoke_error)[:200]}"
173
+
174
+ except Exception as e:
175
+ yield f"Sorry, I encountered an error: {str(e)[:200]}"
176
+
177
+ # Alternative: Simulated Streaming (More Reliable)
178
+ def respond_with_simulated_streaming(
179
+ message,
180
+ history: list[tuple[str, str]],
181
+ system_message,
182
+ max_tokens,
183
+ temperature,
184
+ top_p,
185
+ ):
186
+ """Simulated streaming that chunks a complete LangChain response"""
187
+
188
+ try:
189
+ # Select template and get mode
190
+ template, mode = detect_subject(message)
191
+
192
+ # Create LangChain chain
193
+ chain = template | llm
194
+
195
+ # Show initial mode
196
+ yield f"*{mode}*\n\nGenerating response..."
197
+
198
+ # Get complete response from LangChain (no streaming)
199
+ response = chain.invoke({"question": message})
200
+
201
+ # Clean the response
202
+ if len(response) > 4000:
203
+ response = response[:4000] + "... [Response truncated - ask for continuation]"
204
 
205
+ # Simulate streaming by chunking the response
206
+ words = response.split()
207
+ partial_response = f"*{mode}*\n\n"
 
 
 
208
 
209
+ # Stream word by word
210
+ for i, word in enumerate(words):
211
+ partial_response += word + " "
212
+
213
+ # Update every few words for smooth streaming effect
214
+ if i % 3 == 0: # Update every 3 words
215
+ yield partial_response
216
+ time.sleep(0.05) # Small delay for streaming effect
217
 
218
+ # Final complete response
219
+ yield f"*{mode}*\n\n{response}"
220
 
221
  except Exception as e:
222
+ yield f"Sorry, I encountered an error: {str(e)[:200]}"
223
 
224
+ # Create Gradio interface with custom streaming
225
  demo = gr.ChatInterface(
226
+ respond_with_simulated_streaming, # Use simulated streaming (more reliable)
227
+ # respond_with_langchain_streaming, # Use this for true LangChain streaming
228
+ title="๐ŸŽ“ EduBot",
229
+ description="Your comprehensive AI tutor",
230
  examples=[
231
+ ["Solve the quadratic equation xยฒ + 5x + 6 = 0 with complete explanations"],
232
+ ["How do I conduct a literature review for my psychology research paper?"],
233
+ ["Create a comprehensive study schedule for my final exams"],
234
+ ["Explain the concept of derivatives in calculus with real-world examples"],
235
+ ["How do I properly format citations in APA style with examples?"]
236
  ],
237
  additional_inputs=[
238
  gr.Textbox(
239
+ value="You are EduBot, powered by advanced LangChain streaming capabilities.",
240
  label="System message",
241
  visible=False
242
  ),
243
+ gr.Slider(minimum=1, maximum=1536, value=800, step=1, label="Max new tokens"),
244
  gr.Slider(minimum=0.1, maximum=2.0, value=0.7, step=0.1, label="Temperature"),
245
  gr.Slider(
246
  minimum=0.1,
247
  maximum=1.0,
248
+ value=0.9,
249
  step=0.05,
250
  label="Top-p (nucleus sampling)",
251
  ),
252
  ],
253
+ theme=gr.themes.Soft(
254
+ primary_hue="blue",
255
+ secondary_hue="green"
256
+ ),
257
  )
258
 
259
  if __name__ == "__main__":