Alleinzellgaenger commited on
Commit
f1b7f9a
·
1 Parent(s): 8d0b379

Commit working version with chunk state management, sonnet 4 and well made markdown chat

Browse files
backend/app.py CHANGED
@@ -203,7 +203,8 @@ async def chat_endpoint(request: ChatRequest):
203
  * **Language:** The entire conversation must be in English, as indicated by the user's goal.
204
  * **Focus:** Always prioritize intuitive, conceptual, and experimental understanding over formal, mathematical details.
205
  * **Pacing:** The flow is dictated by the user's successful answers. Move from one question to the next smoothly.
206
-
 
207
  Begin the conversation.
208
  """
209
 
@@ -230,13 +231,17 @@ async def chat_endpoint(request: ChatRequest):
230
 
231
  print("🤖 Calling Claude for chat response...")
232
  response = client.messages.create(
233
- model="claude-3-5-sonnet-20241022",
234
- max_tokens=1000,
235
  system=system_prompt, # system prompt here
236
- messages=anthropic_messages
 
 
 
 
237
  )
238
 
239
- response_text = response.content[0].text
240
  print(f"✅ Received response from Claude: {response_text[:100]}...")
241
  return {"role": "assistant", "content": response_text}
242
 
 
203
  * **Language:** The entire conversation must be in English, as indicated by the user's goal.
204
  * **Focus:** Always prioritize intuitive, conceptual, and experimental understanding over formal, mathematical details.
205
  * **Pacing:** The flow is dictated by the user's successful answers. Move from one question to the next smoothly.
206
+ * **Structure:** Importantly, maintain a clear and logical flow in the conversation. Never loose track of the objective.
207
+ * **Markdown:** Output markdown if you think it is useful. Break your response into reasonable sections.
208
  Begin the conversation.
209
  """
210
 
 
231
 
232
  print("🤖 Calling Claude for chat response...")
233
  response = client.messages.create(
234
+ model="claude-sonnet-4-20250514",
235
+ max_tokens=10000,
236
  system=system_prompt, # system prompt here
237
+ messages=anthropic_messages,
238
+ thinking={
239
+ "type": "enabled",
240
+ "budget_tokens": 5000
241
+ },
242
  )
243
 
244
+ response_text = response.content[1].text
245
  print(f"✅ Received response from Claude: {response_text[:100]}...")
246
  return {"role": "assistant", "content": response_text}
247
 
frontend/src/components/ChunkNavigation.jsx CHANGED
@@ -22,10 +22,17 @@ const ChunkNavigation = ({
22
  <div
23
  key={index}
24
  className={`w-3 h-3 rounded-full ${
25
- chunkStates[index] === 'understood' ? 'bg-green-500' :
26
- chunkStates[index] === 'skipped' ? 'bg-red-500' :
27
- chunkStates[index] === 'interactive' ? 'bg-blue-500' :
28
- index === currentChunkIndex ? 'bg-gray-600' : 'bg-gray-300'
 
 
 
 
 
 
 
29
  }`}
30
  />
31
  ))}
 
22
  <div
23
  key={index}
24
  className={`w-3 h-3 rounded-full ${
25
+ index === currentChunkIndex ? (
26
+ chunkStates[index] === 'understood' ? 'bg-green-700' :
27
+ chunkStates[index] === 'skipped' ? 'bg-red-700' :
28
+ chunkStates[index] === 'interactive' ? 'bg-blue-700' :
29
+ 'bg-gray-600'
30
+ ) : (
31
+ chunkStates[index] === 'understood' ? 'bg-green-500' :
32
+ chunkStates[index] === 'skipped' ? 'bg-red-500' :
33
+ chunkStates[index] === 'interactive' ? 'bg-blue-500' :
34
+ 'bg-gray-300'
35
+ )
36
  }`}
37
  />
38
  ))}
frontend/src/components/ChunkPanel.jsx CHANGED
@@ -154,7 +154,11 @@ const ChunkPanel = ({
154
  <div className="flex items-center justify-center gap-4 mt-4 pt-4 border-gray-200">
155
  <button
156
  onClick={skipChunk}
157
- className="py-2 px-4 bg-white hover:bg-gray-50 border border-gray-300 rounded-lg transition-all text-sm"
 
 
 
 
158
  >
159
  Skip
160
  </button>
@@ -173,7 +177,11 @@ const ChunkPanel = ({
173
  </button>
174
  <button
175
  onClick={markChunkUnderstood}
176
- className="py-2 px-4 bg-white hover:bg-gray-50 border border-gray-300 rounded-lg transition-all text-sm"
 
 
 
 
177
  >
178
  Understood
179
  </button>
@@ -186,7 +194,11 @@ const ChunkPanel = ({
186
  <div className="flex items-center justify-center gap-4 mt-4 pt-4 border-t border-gray-200">
187
  <button
188
  onClick={skipChunk}
189
- className="py-2 px-4 bg-white hover:bg-gray-50 border border-gray-300 rounded-lg transition-all text-sm"
 
 
 
 
190
  >
191
  Skip
192
  </button>
@@ -205,7 +217,11 @@ const ChunkPanel = ({
205
  </button>
206
  <button
207
  onClick={markChunkUnderstood}
208
- className="py-2 px-4 bg-white hover:bg-gray-50 border border-gray-300 rounded-lg transition-all text-sm"
 
 
 
 
209
  >
210
  Understood
211
  </button>
 
154
  <div className="flex items-center justify-center gap-4 mt-4 pt-4 border-gray-200">
155
  <button
156
  onClick={skipChunk}
157
+ className={`py-2 px-4 border rounded-lg transition-all text-sm ${
158
+ chunkStates[currentChunkIndex] === 'skipped'
159
+ ? 'bg-red-500 text-white border-red-500 hover:bg-red-600'
160
+ : 'bg-white hover:bg-gray-50 border-gray-300'
161
+ }`}
162
  >
163
  Skip
164
  </button>
 
177
  </button>
178
  <button
179
  onClick={markChunkUnderstood}
180
+ className={`py-2 px-4 border rounded-lg transition-all text-sm ${
181
+ chunkStates[currentChunkIndex] === 'understood'
182
+ ? 'bg-green-500 text-white border-green-500 hover:bg-green-600'
183
+ : 'bg-white hover:bg-gray-50 border-gray-300'
184
+ }`}
185
  >
186
  Understood
187
  </button>
 
194
  <div className="flex items-center justify-center gap-4 mt-4 pt-4 border-t border-gray-200">
195
  <button
196
  onClick={skipChunk}
197
+ className={`py-2 px-4 border rounded-lg transition-all text-sm ${
198
+ chunkStates[currentChunkIndex] === 'skipped'
199
+ ? 'bg-red-500 text-white border-red-500 hover:bg-red-600'
200
+ : 'bg-white hover:bg-gray-50 border-gray-300'
201
+ }`}
202
  >
203
  Skip
204
  </button>
 
217
  </button>
218
  <button
219
  onClick={markChunkUnderstood}
220
+ className={`py-2 px-4 border rounded-lg transition-all text-sm ${
221
+ chunkStates[currentChunkIndex] === 'understood'
222
+ ? 'bg-green-500 text-white border-green-500 hover:bg-green-600'
223
+ : 'bg-white hover:bg-gray-50 border-gray-300'
224
+ }`}
225
  >
226
  Understood
227
  </button>
frontend/src/components/SimpleChat.jsx CHANGED
@@ -1,4 +1,10 @@
1
  import { useState } from 'react';
 
 
 
 
 
 
2
 
3
  const SimpleChat = ({ messages, onSend, isLoading }) => {
4
  const [input, setInput] = useState('');
@@ -20,13 +26,19 @@ const SimpleChat = ({ messages, onSend, isLoading }) => {
20
  className={`flex ${message.role === 'user' ? 'justify-end' : 'justify-start'}`}
21
  >
22
  <div
23
- className={`max-w-[70%] p-3 rounded-lg ${
24
  message.role === 'user'
25
- ? 'bg-blue-500 text-white'
26
- : 'bg-gray-100 text-gray-900'
27
  }`}
28
  >
29
- {message.content}
 
 
 
 
 
 
30
  </div>
31
  </div>
32
  ))}
 
1
  import { useState } from 'react';
2
+ import ReactMarkdown from 'react-markdown';
3
+ import remarkMath from 'remark-math';
4
+ import rehypeKatex from 'rehype-katex';
5
+ import rehypeRaw from 'rehype-raw';
6
+ import { getChatMarkdownComponents } from '../utils/markdownComponents.jsx';
7
+
8
 
9
  const SimpleChat = ({ messages, onSend, isLoading }) => {
10
  const [input, setInput] = useState('');
 
26
  className={`flex ${message.role === 'user' ? 'justify-end' : 'justify-start'}`}
27
  >
28
  <div
29
+ className={`max-w-[90%] p-3 rounded-lg ${
30
  message.role === 'user'
31
+ ? 'bg-gray-100 text-white'
32
+ : 'bg-white text-gray-900'
33
  }`}
34
  >
35
+ <ReactMarkdown
36
+ remarkPlugins={[remarkMath]}
37
+ rehypePlugins={[rehypeRaw, rehypeKatex]}
38
+ components={getChatMarkdownComponents()}
39
+ >
40
+ {message.content}
41
+ </ReactMarkdown>
42
  </div>
43
  </div>
44
  ))}
frontend/src/hooks/useChunkNavigation.js CHANGED
@@ -30,17 +30,51 @@ export const useChunkNavigation = (documentData, clearTypingAnimation) => {
30
  };
31
 
32
  const skipChunk = () => {
33
- setChunkStates(prev => ({
34
- ...prev,
35
- [currentChunkIndex]: 'skipped'
36
- }));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
  };
38
 
39
  const markChunkUnderstood = () => {
40
- setChunkStates(prev => ({
41
- ...prev,
42
- [currentChunkIndex]: 'understood'
43
- }));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
  };
45
 
46
  const startInteractiveLesson = (startChunkLessonFn) => {
 
30
  };
31
 
32
  const skipChunk = () => {
33
+ setChunkStates(prev => {
34
+ const currentState = prev[currentChunkIndex];
35
+ const newState = currentState === 'skipped' ? undefined : 'skipped';
36
+
37
+ // Auto-advance to next chunk if setting to skipped (not toggling off)
38
+ if (newState === 'skipped' && documentData && currentChunkIndex < documentData.chunks.length - 1) {
39
+ setTimeout(() => {
40
+ if (clearTypingAnimation) {
41
+ clearTypingAnimation();
42
+ }
43
+ setCurrentChunkIndex(currentChunkIndex + 1);
44
+ setChunkExpanded(true);
45
+ setShowChat(false);
46
+ }, 100); // Small delay to allow state update to complete
47
+ }
48
+
49
+ return {
50
+ ...prev,
51
+ [currentChunkIndex]: newState
52
+ };
53
+ });
54
  };
55
 
56
  const markChunkUnderstood = () => {
57
+ setChunkStates(prev => {
58
+ const currentState = prev[currentChunkIndex];
59
+ const newState = currentState === 'understood' ? undefined : 'understood';
60
+
61
+ // Auto-advance to next chunk if setting to understood (not toggling off)
62
+ if (newState === 'understood' && documentData && currentChunkIndex < documentData.chunks.length - 1) {
63
+ setTimeout(() => {
64
+ if (clearTypingAnimation) {
65
+ clearTypingAnimation();
66
+ }
67
+ setCurrentChunkIndex(currentChunkIndex + 1);
68
+ setChunkExpanded(true);
69
+ setShowChat(false);
70
+ }, 100); // Small delay to allow state update to complete
71
+ }
72
+
73
+ return {
74
+ ...prev,
75
+ [currentChunkIndex]: newState
76
+ };
77
+ });
78
  };
79
 
80
  const startInteractiveLesson = (startChunkLessonFn) => {