Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
math_tutor_dev
public_math_tutor
Commits
867bda9d
Commit
867bda9d
authored
May 04, 2026
by
Kantz
Browse files
tip und Lösungsbutton zum Feedbackmode hinzugefügt
parent
6c2341ba
Changes
5
Hide whitespace changes
Inline
Side-by-side
math-tutor/backend/app/api/context.py
View file @
867bda9d
...
...
@@ -20,6 +20,10 @@ class ContextRequest(BaseModel):
draft
:
Optional
[
str
]
=
None
class
DraftRequest
(
BaseModel
):
draft
:
str
=
Field
(...,
min_length
=
1
)
@
router
.
post
(
"/api/context/retrieval"
)
def
get_retrieval_context
(
request
:
ContextRequest
)
->
List
[
dict
]:
if
not
request
or
not
request
.
messages
:
...
...
@@ -35,3 +39,14 @@ def get_retrieval_context(request: ContextRequest) -> List[dict]:
if
not
sources
:
return
[]
return
[
source
.
model_dump
()
for
source
in
sources
]
@
router
.
post
(
"/api/context/solution"
)
def
get_context_solution
(
request
:
DraftRequest
)
->
dict
[
str
,
str
]:
sheet
=
context_store
.
load_sheet
(
request
.
draft
)
if
not
sheet
:
raise
HTTPException
(
status_code
=
404
,
detail
=
"context sheet not found"
)
return
{
"solution"
:
context_store
.
context_store_new
.
get_solution
(
sheet
),
}
math-tutor/frontend/src/components/Chat/ChatWindow.tsx
View file @
867bda9d
...
...
@@ -9,6 +9,8 @@ type ChatWindowProps = {
draft
:
string
;
onDraftChange
:
(
value
:
string
)
=>
void
;
onSend
:
()
=>
void
;
onTip
?:
()
=>
void
;
onRevealSolution
?:
()
=>
void
;
isSending
?:
boolean
;
onHistoryNavigate
?:
(
direction
:
"
older
"
|
"
newer
"
)
=>
boolean
;
onToggleCanvas
?:
()
=>
void
;
...
...
@@ -23,6 +25,8 @@ export default function ChatWindow({
draft
,
onDraftChange
,
onSend
,
onTip
,
onRevealSolution
,
isSending
=
false
,
onHistoryNavigate
,
onToggleCanvas
,
...
...
@@ -44,6 +48,8 @@ export default function ChatWindow({
value
=
{
draft
}
onChange
=
{
onDraftChange
}
onSend
=
{
onSend
}
onTip
=
{
onTip
}
onRevealSolution
=
{
onRevealSolution
}
isSending
=
{
isSending
}
onHistoryNavigate
=
{
onHistoryNavigate
}
onToggleCanvas
=
{
onToggleCanvas
}
...
...
math-tutor/frontend/src/components/Chat/MessageInput.tsx
View file @
867bda9d
...
...
@@ -6,6 +6,8 @@ type MessageInputProps = {
value
:
string
;
onChange
:
(
value
:
string
)
=>
void
;
onSend
:
()
=>
void
;
onTip
?:
()
=>
void
;
onRevealSolution
?:
()
=>
void
;
isSending
?:
boolean
;
onHistoryNavigate
?:
(
direction
:
"
older
"
|
"
newer
"
)
=>
boolean
;
onToggleCanvas
?:
()
=>
void
;
...
...
@@ -16,6 +18,8 @@ export default function MessageInput({
value
,
onChange
,
onSend
,
onTip
,
onRevealSolution
,
isSending
=
false
,
onHistoryNavigate
,
onToggleCanvas
,
...
...
@@ -89,6 +93,30 @@ export default function MessageInput({
className
=
"canvas-upload-input"
onChange
=
{
handleUploadChange
}
/>
{
onTip
?
(
<
button
className
=
"btn"
type
=
"button"
onClick
=
{
onTip
}
disabled
=
{
isSending
}
aria-label
=
{
t
(
"
tip
"
)
}
title
=
{
t
(
"
tip
"
)
}
>
{
t
(
"
tip
"
)
}
</
button
>
)
:
null
}
{
onRevealSolution
?
(
<
button
className
=
"btn"
type
=
"button"
onClick
=
{
onRevealSolution
}
disabled
=
{
isSending
}
aria-label
=
{
t
(
"
revealSolution
"
)
}
title
=
{
t
(
"
revealSolution
"
)
}
>
{
t
(
"
revealSolution
"
)
}
</
button
>
)
:
null
}
<
button
className
=
"btn primary"
type
=
"button"
...
...
math-tutor/frontend/src/i18n.ts
View file @
867bda9d
...
...
@@ -39,6 +39,8 @@
inspect
:
"
Inspect
"
,
cite
:
"
Cite
"
,
draw
:
"
Draw
"
,
tip
:
"
Tip
"
,
revealSolution
:
"
Solution
"
,
send
:
"
Send
"
,
roleUser
:
"
user
"
,
roleAssistant
:
"
assistant
"
,
...
...
@@ -57,6 +59,7 @@
failedLoadTasks
:
"
Could not load tasks.
"
,
failedLoadOrchestratorConfig
:
"
Could not load orchestrator config. Fallback mode active.
"
,
chatRequestFailed
:
"
The chat request failed. Please check backend logs.
"
,
noStoredSolution
:
"
No stored solution is available for this task yet.
"
,
retrievalFailed
:
"
Source retrieval failed. Please check backend logs.
"
,
failedLoadSavedChats
:
"
Could not load saved chats.
"
,
failedLoadSelectedChat
:
"
Could not load the selected chat.
"
,
...
...
@@ -137,6 +140,8 @@
inspect
:
"
Ansehen
"
,
cite
:
"
Zitieren
"
,
draw
:
"
Zeichnen
"
,
tip
:
"
Tip
"
,
revealSolution
:
"
Lösung
"
,
send
:
"
Senden
"
,
roleUser
:
"
nutzer
"
,
roleAssistant
:
"
assistent
"
,
...
...
@@ -157,6 +162,8 @@
"
Orchestrator-Konfiguration konnte nicht geladen werden. Fallback-Modus aktiv.
"
,
chatRequestFailed
:
"
Da ist wohl die Chat-Anfrage fehlgeschlagen. Gib gerne deinem Dozenten bescheid. In vielen Fällen hilft es die Seite neu zu laden.
"
,
noStoredSolution
:
"
Für diese Aufgabe ist aktuell keine gespeicherte Lösung verfügbar.
"
,
retrievalFailed
:
"
Da ist wohl der Quellenabruf fehlgeschlagen. Gib gerne deinem Dozenten bescheid. In vielen Fällen hilft es die Seite neu zu laden.
"
,
failedLoadSavedChats
:
"
Gespeicherte Chats konnten nicht geladen werden.
"
,
...
...
math-tutor/frontend/src/pages/ChatPage.tsx
View file @
867bda9d
...
...
@@ -619,12 +619,29 @@ export default function ChatPage() {
return
true
;
};
const
handleSend
=
async
()
=>
{
const
appendAssistantMessage
=
(
text
:
string
)
=>
{
setMessages
((
prev
)
=>
[
...
prev
,
{
id
:
`m-
${
Date
.
now
()}
-assistant`
,
role
:
"
assistant
"
,
text
,
},
]);
};
const
sendMessage
=
async
({
text
,
clearDraft
,
}:
{
text
:
string
;
clearDraft
:
boolean
;
})
=>
{
if
(
isSending
)
{
return
;
}
const
trimmed
=
draf
t
.
trim
();
const
trimmed
=
tex
t
.
trim
();
if
(
!
trimmed
)
{
return
;
}
...
...
@@ -636,8 +653,10 @@ export default function ChatPage() {
};
setMessages
((
prev
)
=>
[...
prev
,
userMessage
]);
setDraft
(
""
);
resetDraftHistoryNavigation
();
if
(
clearDraft
)
{
setDraft
(
""
);
resetDraftHistoryNavigation
();
}
setIsSending
(
true
);
setRetrievalLoading
(
true
);
...
...
@@ -685,25 +704,11 @@ export default function ChatPage() {
const
payload
:
{
reply
?:
string
}
=
await
response
.
json
();
const
reply
=
payload
.
reply
;
if
(
typeof
reply
===
"
string
"
&&
reply
.
length
>
0
)
{
setMessages
((
prev
)
=>
[
...
prev
,
{
id
:
`m-
${
Date
.
now
()}
-assistant`
,
role
:
"
assistant
"
,
text
:
reply
,
},
]);
appendAssistantMessage
(
reply
);
}
chatRequestSucceeded
=
true
;
}
catch
(
error
)
{
setMessages
((
prev
)
=>
[
...
prev
,
{
id
:
`m-
${
Date
.
now
()}
-assistant`
,
role
:
"
assistant
"
,
text
:
t
(
"
chatRequestFailed
"
),
},
]);
appendAssistantMessage
(
t
(
"
chatRequestFailed
"
));
setRetrievalError
(
t
(
"
retrievalFailed
"
));
void
error
;
}
finally
{
...
...
@@ -747,6 +752,57 @@ export default function ChatPage() {
setRetrievalLoading
(
false
);
};
const
handleSend
=
async
()
=>
{
await
sendMessage
({
text
:
draft
,
clearDraft
:
true
,
});
};
const
handleFeedbackTip
=
async
()
=>
{
if
(
selectedOrchestrator
!==
"
feedback
"
)
{
return
;
}
await
sendMessage
({
text
:
"
Gib mir einen Hinweis zum nächsten Schritt
"
,
clearDraft
:
false
,
});
};
const
handleRevealSolution
=
async
()
=>
{
if
(
selectedOrchestrator
!==
"
feedback
"
||
isSending
)
{
return
;
}
setIsSending
(
true
);
try
{
const
response
=
await
fetch
(
`/api/context/solution`
,
{
method
:
"
POST
"
,
headers
:
{
"
Content-Type
"
:
"
application/json
"
},
body
:
JSON
.
stringify
({
draft
:
chatSessionId
}),
});
if
(
response
.
status
===
404
)
{
appendAssistantMessage
(
t
(
"
noStoredSolution
"
));
return
;
}
if
(
!
response
.
ok
)
{
throw
new
Error
(
`Solution failed:
${
response
.
status
}
`
);
}
const
payload
:
{
solution
?:
string
}
=
await
response
.
json
();
const
solution
=
typeof
payload
.
solution
===
"
string
"
?
payload
.
solution
.
trim
()
:
""
;
appendAssistantMessage
(
solution
||
t
(
"
noStoredSolution
"
));
}
catch
(
error
)
{
appendAssistantMessage
(
t
(
"
chatRequestFailed
"
));
void
error
;
}
finally
{
setIsSending
(
false
);
}
};
const
handleToggleCanvas
=
()
=>
{
setIsCanvasVisible
((
prev
)
=>
!
prev
);
};
...
...
@@ -1181,6 +1237,10 @@ export default function ChatPage() {
draft
=
{
draft
}
onDraftChange
=
{
handleDraftChange
}
onSend
=
{
handleSend
}
onTip
=
{
selectedOrchestrator
===
"
feedback
"
?
handleFeedbackTip
:
undefined
}
onRevealSolution
=
{
selectedOrchestrator
===
"
feedback
"
?
handleRevealSolution
:
undefined
}
isSending
=
{
isSending
}
onHistoryNavigate
=
{
handleHistoryNavigate
}
onToggleCanvas
=
{
handleToggleCanvas
}
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment