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
a4c0b261
Commit
a4c0b261
authored
Mar 13, 2026
by
Kantz
Browse files
Feedback mit Thinking
parent
6c805864
Changes
12
Hide whitespace changes
Inline
Side-by-side
math-tutor/backend/app/LLM_services/feedback_LLM.py
0 → 100644
View file @
a4c0b261
from
__future__
import
annotations
from
app.deterministic_services
import
llm_client
SYSTEM_PROMPT
=
"""
Du bist ein didaktischer Mathe-Tutor. Du gibts Feedback zu den Lösungen des Nutzers zur Gegebenen Frage.
Vergleiche das Ergebnis mit der korrekten Lösung.
Stelle Nachfragen wenn der Lösungsweg nicht vollständig ist.
Zitiere 1 zu 1 aus der AKTUELLE Eingabe des Nutzers wenn du auf Fehler aufmerksam machst.
verwende die $ für mathematische Formeln, z.B. $a^2 + b^2 = c^2$
Halte dich kurz und präzise.
"""
def
generate_hint
(
query
:
str
|
None
,
task
:
str
,
hints
:
list
[
str
],
solution
:
str
,
history
:
list
[
dict
]
|
None
=
None
,
sources
:
str
|
None
=
None
,
)
->
str
:
context_parts
=
[
f
"Hier ist die zu lösende Aufgaben:
{
task
}
\n
"
,
f
"Hier ist eine korrekte Lösung als Referenz:
{
solution
}
\n
"
,
f
"Hier ist ein exemplarischer Lösungsweg:
{
hints
}
\n
"
]
if
sources
:
context_parts
.
append
(
f
"Kontext/Sources:
\n
{
sources
}
"
)
messages
=
[{
"role"
:
"system"
,
"content"
:
SYSTEM_PROMPT
}]
# Kompakter Kontext als eine Nachricht (kein langer Fließtext mit History mischen)
messages
.
append
({
"role"
:
"user"
,
"content"
:
"
\n\n
"
.
join
(
context_parts
)})
# History als echte Turns (und ggf. begrenzen, siehe Punkt 2)
if
history
:
messages
.
extend
(
history
)
# Aktuelle Frage als letzte Nachricht, fett hervorgehoben durch Struktur/Delimiters
messages
.
append
({
"role"
:
"user"
,
"content"
:
f
"AKTUELLE Eingabe des Studenten (höchste Priorität):
\n
{
query
}
"
})
result
=
llm_client
.
chat
(
messages
=
messages
)
return
llm_client
.
get_message_content
(
result
)
math-tutor/backend/app/api/chat.py
View file @
a4c0b261
...
@@ -75,7 +75,7 @@ def chat(request: ChatRequest) -> ChatResponse:
...
@@ -75,7 +75,7 @@ def chat(request: ChatRequest) -> ChatResponse:
try
:
try
:
payload_messages
=
[{
"role"
:
m
.
role
,
"content"
:
m
.
text
}
for
m
in
request
.
messages
]
payload_messages
=
[{
"role"
:
m
.
role
,
"content"
:
m
.
text
}
for
m
in
request
.
messages
]
if
orchestrator_name
==
"task"
:
if
orchestrator_name
in
{
"task"
,
"feedback"
}
:
result
=
orchestrator_impl
.
run_chat
(
result
=
orchestrator_impl
.
run_chat
(
payload_messages
,
payload_messages
,
draft
=
request
.
draft
,
draft
=
request
.
draft
,
...
...
math-tutor/backend/app/api/tasks.py
View file @
a4c0b261
...
@@ -10,6 +10,8 @@ from app.deterministic_services import context_store, task_catalog
...
@@ -10,6 +10,8 @@ from app.deterministic_services import context_store, task_catalog
router
=
APIRouter
()
router
=
APIRouter
()
TASK_ORCHESTRATORS
=
{
"task"
,
"feedback"
}
class
TaskItem
(
BaseModel
):
class
TaskItem
(
BaseModel
):
task_id
:
str
task_id
:
str
...
@@ -46,7 +48,7 @@ class SelectTaskResponse(BaseModel):
...
@@ -46,7 +48,7 @@ class SelectTaskResponse(BaseModel):
@
router
.
get
(
"/api/tasks/config"
)
@
router
.
get
(
"/api/tasks/config"
)
def
get_task_config
()
->
dict
[
str
,
object
]:
def
get_task_config
()
->
dict
[
str
,
object
]:
orchestrator
=
config
.
get_orchestrator
()
orchestrator
=
config
.
get_orchestrator
()
return
{
"orchestrator"
:
orchestrator
,
"enabled"
:
orchestrator
==
"task"
}
return
{
"orchestrator"
:
orchestrator
,
"enabled"
:
orchestrator
in
TASK_ORCHESTRATORS
}
@
router
.
get
(
"/api/tasks"
,
response_model
=
TasksResponse
)
@
router
.
get
(
"/api/tasks"
,
response_model
=
TasksResponse
)
...
@@ -55,7 +57,7 @@ def list_tasks() -> TasksResponse:
...
@@ -55,7 +57,7 @@ def list_tasks() -> TasksResponse:
task_files
=
task_catalog
.
build_task_catalog
()
task_files
=
task_catalog
.
build_task_catalog
()
return
TasksResponse
(
return
TasksResponse
(
orchestrator
=
orchestrator
,
orchestrator
=
orchestrator
,
enabled
=
orchestrator
==
"task"
,
enabled
=
orchestrator
in
TASK_ORCHESTRATORS
,
task_files
=
task_files
,
task_files
=
task_files
,
)
)
...
...
math-tutor/backend/app/deterministic_services/orchestrators/orchestrator_feedback.py
0 → 100644
View file @
a4c0b261
from
__future__
import
annotations
from
app.LLM_services
import
feedback_LLM
import
app.config
as
config
from
app.deterministic_services
import
(
context_store
,
retrieval_store
,
task_catalog
,
)
from
app.deterministic_services.orchestrators
import
orchestrator_base
as
base
def
_ensure_context_task_fields
(
state
:
base
.
ChatState
,
query_text
:
str
)
->
tuple
[
str
,
str
]
|
None
:
store_new
=
context_store
.
context_store_new
has_task
=
bool
(
store_new
.
get_task
(
state
.
sheet
))
has_hints
=
bool
(
store_new
.
get_hints
(
state
.
sheet
))
has_solution
=
bool
(
store_new
.
get_solution
(
state
.
sheet
))
if
has_task
and
has_hints
and
has_solution
:
selected
=
task_catalog
.
get_selected_task_ids
(
state
.
sheet
)
if
selected
[
0
]
and
selected
[
1
]:
was_selected
=
task_catalog
.
select_task_by_ids
(
state
.
sheet
,
selected
[
0
],
selected
[
1
],
)
if
was_selected
:
return
selected
[
0
],
selected
[
1
]
sources_text
=
"
\n
"
.
join
([
source
.
to_string
()
for
source
in
context_store
.
get_retrieval
(
state
.
sheet
)])
selection
=
task_catalog
.
select_task_for_context
(
state
.
sheet
,
query_text
=
query_text
,
sources_text
=
sources_text
,
history
=
context_store
.
get_history_turns
(
state
.
sheet
),
)
if
not
selection
:
return
None
task_file
,
task_entry
=
selection
selected_file_id
=
str
(
task_file
.
get
(
"_file_id"
,
""
))
selected_task_id
=
str
(
task_entry
.
get
(
"id"
,
""
)).
zfill
(
2
)
base
.
append_tool_log
(
state
.
tool_log
,
"task_json_selected"
,
{
"tasks_dir"
:
str
(
task_catalog
.
TASKS_DIR
)},
{
"file"
:
task_file
.
get
(
"_path"
,
""
),
"file_id"
:
selected_file_id
,
"task_id"
:
selected_task_id
,
"hint_count"
:
len
(
store_new
.
get_hints
(
state
.
sheet
)),
"has_solution"
:
bool
(
store_new
.
get_solution
(
state
.
sheet
)),
},
)
return
selected_file_id
,
selected_task_id
def
_retrieve_context_for_task
(
state
:
base
.
ChatState
,
query_text
:
str
)
->
int
:
refs
=
task_catalog
.
get_selected_task_subsection_refs
(
state
.
sheet
)
if
not
refs
:
return
0
def
_retrieve
()
->
dict
:
sources
=
retrieval_store
.
retrieve_for_subsections
(
pg_url
=
config
.
get_postgres_url
(),
subsection_refs
=
refs
,
)
context_store
.
update_retrieval_context
(
state
.
sheet
,
sources
)
return
{
"subsection_refs"
:
refs
,
"source_count"
:
len
(
sources
),
}
result
=
base
.
log_timed_call
(
state
.
tool_log
,
"retrieve_context_with_task_subsections"
,
{
"query"
:
query_text
,
"subsection_refs"
:
refs
,
},
_retrieve
,
)
return
int
(
result
.
get
(
"source_count"
,
0
))
def
_on_bootstrap
(
state
:
base
.
ChatState
,
query_text
:
str
)
->
None
:
source_count
=
_retrieve_context_for_task
(
state
,
query_text
)
print
(
f
"_retrieve_context_for_task source_count=
{
source_count
}
"
)
if
source_count
>
0
:
_ensure_context_task_fields
(
state
,
query_text
)
task_text
=
context_store
.
context_store_new
.
get_task
(
state
.
sheet
).
strip
()
retrieval_query
=
query_text
if
task_text
:
retrieval_query
=
f
"Aufgabe:
\n
{
task_text
}
\n\n
{
query_text
}
"
base
.
bootstrap_retrieval
(
state
.
sheet
,
retrieval_query
,
state
.
tool_log
)
def
_on_turn_logic
(
state
:
base
.
ChatState
)
->
None
:
_ensure_context_task_fields
(
state
,
state
.
last_user
)
def
_on_build_reply
(
state
:
base
.
ChatState
)
->
str
|
None
:
store_new
=
context_store
.
context_store_new
history_turns
=
context_store
.
get_history_turns
(
state
.
sheet
)
args
=
{
"query"
:
state
.
last_user
if
not
state
.
new_chat
else
None
,
"task"
:
store_new
.
get_task
(
state
.
sheet
),
"hints"
:
store_new
.
get_hints
(
state
.
sheet
),
"solution"
:
store_new
.
get_solution
(
state
.
sheet
),
"history"
:
history_turns
,
"sources"
:
"
\n
"
.
join
([
source
.
to_string
()
for
source
in
context_store
.
get_retrieval
(
state
.
sheet
)]),
}
return
base
.
log_timed_call
(
state
.
tool_log
,
"new_generate_feedback"
,
args
,
lambda
:
feedback_LLM
.
generate_hint
(
**
args
),
)
def
run_chat
(
messages
:
list
[
dict
],
draft
:
str
|
None
=
None
,
selected_task
:
dict
|
None
=
None
,
)
->
dict
:
def
_apply_selected_task
(
state
:
base
.
ChatState
)
->
None
:
if
not
selected_task
:
return
selected_file_id
=
str
(
selected_task
.
get
(
"file_id"
,
""
)).
strip
()
selected_task_id
=
str
(
selected_task
.
get
(
"task_id"
,
""
)).
strip
()
if
selected_file_id
and
selected_task_id
:
task_catalog
.
select_task_by_ids
(
state
.
sheet
,
selected_file_id
,
selected_task_id
,
)
def
on_bootstrap
(
state
:
base
.
ChatState
,
query_text
:
str
)
->
None
:
_apply_selected_task
(
state
)
_on_bootstrap
(
state
,
query_text
)
def
on_turn_logic
(
state
:
base
.
ChatState
)
->
None
:
_apply_selected_task
(
state
)
_on_turn_logic
(
state
)
return
base
.
run_chat_common
(
messages
=
messages
,
draft
=
draft
,
on_bootstrap
=
on_bootstrap
,
on_turn_logic
=
on_turn_logic
,
on_build_reply
=
_on_build_reply
,
)
math-tutor/backend/app/deterministic_services/orchestrators/registry.py
View file @
a4c0b261
...
@@ -4,17 +4,19 @@ from typing import Any
...
@@ -4,17 +4,19 @@ from typing import Any
import
app.config
as
config
import
app.config
as
config
from
app.deterministic_services.orchestrators
import
(
from
app.deterministic_services.orchestrators
import
(
orchestrator_feedback
,
orchestrator_qa
,
orchestrator_qa
,
orchestrator_task
,
orchestrator_task
,
orchestrator_tutor
,
orchestrator_tutor
,
)
)
AVAILABLE_ORCHESTRATORS
:
tuple
[
str
,
...]
=
(
"qa"
,
"tutor"
,
"task"
)
AVAILABLE_ORCHESTRATORS
:
tuple
[
str
,
...]
=
(
"qa"
,
"tutor"
,
"task"
,
"feedback"
)
_ORCHESTRATOR_MODULES
:
dict
[
str
,
Any
]
=
{
_ORCHESTRATOR_MODULES
:
dict
[
str
,
Any
]
=
{
"qa"
:
orchestrator_qa
,
"qa"
:
orchestrator_qa
,
"tutor"
:
orchestrator_tutor
,
"tutor"
:
orchestrator_tutor
,
"task"
:
orchestrator_task
,
"task"
:
orchestrator_task
,
"feedback"
:
orchestrator_feedback
,
}
}
...
...
math-tutor/frontend/src/api/orchestratorApi.ts
View file @
a4c0b261
export
type
OrchestratorName
=
"
qa
"
|
"
tutor
"
|
"
task
"
;
export
type
OrchestratorName
=
"
qa
"
|
"
tutor
"
|
"
task
"
|
"
feedback
"
;
export
type
OrchestratorConfigResponse
=
{
export
type
OrchestratorConfigResponse
=
{
default_orchestrator
:
OrchestratorName
;
default_orchestrator
:
OrchestratorName
;
available_orchestrators
:
OrchestratorName
[];
available_orchestrators
:
OrchestratorName
[];
};
};
const
FALLBACK_ORCHESTRATORS
:
OrchestratorName
[]
=
[
"
qa
"
,
"
tutor
"
,
"
task
"
];
const
FALLBACK_ORCHESTRATORS
:
OrchestratorName
[]
=
[
"
qa
"
,
"
tutor
"
,
"
task
"
,
"
feedback
"
];
const
normalizeOrchestrator
=
(
value
:
string
):
OrchestratorName
|
null
=>
{
const
normalizeOrchestrator
=
(
value
:
string
):
OrchestratorName
|
null
=>
{
if
(
value
===
"
qa
"
||
value
===
"
tutor
"
||
value
===
"
task
"
)
{
if
(
value
===
"
qa
"
||
value
===
"
tutor
"
||
value
===
"
task
"
||
value
===
"
feedback
"
)
{
return
value
;
return
value
;
}
}
return
null
;
return
null
;
...
...
math-tutor/frontend/src/components/Chat/MessageBubble.tsx
View file @
a4c0b261
...
@@ -29,7 +29,10 @@ export default function MessageBubble({
...
@@ -29,7 +29,10 @@ export default function MessageBubble({
}:
MessageBubbleProps
)
{
}:
MessageBubbleProps
)
{
const
bubbleRef
=
useRef
<
HTMLDivElement
|
null
>
(
null
);
const
bubbleRef
=
useRef
<
HTMLDivElement
|
null
>
(
null
);
const
[
isRawView
,
setIsRawView
]
=
useState
(
false
);
const
[
isRawView
,
setIsRawView
]
=
useState
(
false
);
const
renderedText
=
useMemo
(()
=>
escapeAsterisksInsideMath
(
text
),
[
text
]);
const
renderedText
=
useMemo
(
()
=>
escapeAsterisksInsideMath
(
text
.
replaceAll
(
"
</think>
"
,
"
\n
---
\n
"
)),
[
text
]
);
useEffect
(()
=>
{
useEffect
(()
=>
{
if
(
isRawView
)
{
if
(
isRawView
)
{
...
...
math-tutor/frontend/src/components/Orchestrator/OrchestratorSelect.tsx
View file @
a4c0b261
...
@@ -13,11 +13,13 @@ type ModeMeta = {
...
@@ -13,11 +13,13 @@ type ModeMeta = {
labelKey
:
labelKey
:
|
"
orchestratorModeQaLabel
"
|
"
orchestratorModeQaLabel
"
|
"
orchestratorModeTutorLabel
"
|
"
orchestratorModeTutorLabel
"
|
"
orchestratorModeTaskLabel
"
;
|
"
orchestratorModeTaskLabel
"
|
"
orchestratorModeFeedbackLabel
"
;
descriptionKey
:
descriptionKey
:
|
"
orchestratorModeQaDescription
"
|
"
orchestratorModeQaDescription
"
|
"
orchestratorModeTutorDescription
"
|
"
orchestratorModeTutorDescription
"
|
"
orchestratorModeTaskDescription
"
;
|
"
orchestratorModeTaskDescription
"
|
"
orchestratorModeFeedbackDescription
"
;
};
};
const
modeMetaMap
:
Record
<
OrchestratorName
,
ModeMeta
>
=
{
const
modeMetaMap
:
Record
<
OrchestratorName
,
ModeMeta
>
=
{
...
@@ -33,6 +35,10 @@ const modeMetaMap: Record<OrchestratorName, ModeMeta> = {
...
@@ -33,6 +35,10 @@ const modeMetaMap: Record<OrchestratorName, ModeMeta> = {
labelKey
:
"
orchestratorModeTaskLabel
"
,
labelKey
:
"
orchestratorModeTaskLabel
"
,
descriptionKey
:
"
orchestratorModeTaskDescription
"
,
descriptionKey
:
"
orchestratorModeTaskDescription
"
,
},
},
feedback
:
{
labelKey
:
"
orchestratorModeFeedbackLabel
"
,
descriptionKey
:
"
orchestratorModeFeedbackDescription
"
,
},
};
};
type
ModeDescriptionDisplay
=
"
tooltip
"
|
"
helperText
"
|
"
optionSuffix
"
;
type
ModeDescriptionDisplay
=
"
tooltip
"
|
"
helperText
"
|
"
optionSuffix
"
;
...
...
math-tutor/frontend/src/i18n.ts
View file @
a4c0b261
...
@@ -20,10 +20,12 @@
...
@@ -20,10 +20,12 @@
orchestratorModeQaLabel
:
"
QA
"
,
orchestratorModeQaLabel
:
"
QA
"
,
orchestratorModeTutorLabel
:
"
Tutor
"
,
orchestratorModeTutorLabel
:
"
Tutor
"
,
orchestratorModeTaskLabel
:
"
Task
"
,
orchestratorModeTaskLabel
:
"
Task
"
,
orchestratorModeFeedbackLabel
:
"
Feedback
"
,
orchestratorModeDescriptionTitle
:
"
Mode help
"
,
orchestratorModeDescriptionTitle
:
"
Mode help
"
,
orchestratorModeQaDescription
:
"
Direct answers based on the script
"
,
orchestratorModeQaDescription
:
"
Direct answers based on the script
"
,
orchestratorModeTutorDescription
:
"
Help with your own questions
"
,
orchestratorModeTutorDescription
:
"
Help with your own questions
"
,
orchestratorModeTaskDescription
:
"
Help with textbook exercises
"
,
orchestratorModeTaskDescription
:
"
Help with textbook exercises
"
,
orchestratorModeFeedbackDescription
:
"
Short feedback on your solution for textbook exercises
"
,
directChildren
:
"
Direct children
"
,
directChildren
:
"
Direct children
"
,
taskChildren
:
"
Task sources
"
,
taskChildren
:
"
Task sources
"
,
indirectChildren
:
"
Indirect children
"
,
indirectChildren
:
"
Indirect children
"
,
...
@@ -95,10 +97,12 @@
...
@@ -95,10 +97,12 @@
orchestratorModeQaLabel
:
"
QA
"
,
orchestratorModeQaLabel
:
"
QA
"
,
orchestratorModeTutorLabel
:
"
Tutor
"
,
orchestratorModeTutorLabel
:
"
Tutor
"
,
orchestratorModeTaskLabel
:
"
Task
"
,
orchestratorModeTaskLabel
:
"
Task
"
,
orchestratorModeFeedbackLabel
:
"
Feedback
"
,
orchestratorModeDescriptionTitle
:
"
Modus-Hilfe
"
,
orchestratorModeDescriptionTitle
:
"
Modus-Hilfe
"
,
orchestratorModeQaDescription
:
"
Direkte Antworten basierend auf dem Skript
"
,
orchestratorModeQaDescription
:
"
Direkte Antworten basierend auf dem Skript
"
,
orchestratorModeTutorDescription
:
"
Hilfe bei selbst gestellten Fragen
"
,
orchestratorModeTutorDescription
:
"
Hilfe bei selbst gestellten Fragen
"
,
orchestratorModeTaskDescription
:
"
Hilfe bei Aufgaben aus dem Lehrwerk
"
,
orchestratorModeTaskDescription
:
"
Hilfe bei Aufgaben aus dem Lehrwerk
"
,
orchestratorModeFeedbackDescription
:
"
Kurzes Feedback zu deiner Lösung bei Aufgaben aus dem Lehrwerk
"
,
directChildren
:
"
Direkte Quellen
"
,
directChildren
:
"
Direkte Quellen
"
,
taskChildren
:
"
Aufgaben-Quellen
"
,
taskChildren
:
"
Aufgaben-Quellen
"
,
indirectChildren
:
"
Indirekte Quellen
"
,
indirectChildren
:
"
Indirekte Quellen
"
,
...
...
math-tutor/frontend/src/pages/ChatPage.tsx
View file @
a4c0b261
...
@@ -17,12 +17,15 @@ import sumintLogo from "../../SuMINT-Logo.png";
...
@@ -17,12 +17,15 @@ import sumintLogo from "../../SuMINT-Logo.png";
const
initialMessages
:
ChatMessage
[]
=
[];
const
initialMessages
:
ChatMessage
[]
=
[];
const
normalizeOrchestrator
=
(
value
:
string
|
null
|
undefined
):
OrchestratorName
|
null
=>
{
const
normalizeOrchestrator
=
(
value
:
string
|
null
|
undefined
):
OrchestratorName
|
null
=>
{
if
(
value
===
"
qa
"
||
value
===
"
tutor
"
||
value
===
"
task
"
)
{
if
(
value
===
"
qa
"
||
value
===
"
tutor
"
||
value
===
"
task
"
||
value
===
"
feedback
"
)
{
return
value
;
return
value
;
}
}
return
null
;
return
null
;
};
};
const
isTaskCoupledOrchestrator
=
(
value
:
string
|
null
|
undefined
):
boolean
=>
value
===
"
task
"
||
value
===
"
feedback
"
;
type
ArchivedChatSummary
=
{
type
ArchivedChatSummary
=
{
chat_id
:
string
;
chat_id
:
string
;
saved_at
:
string
;
saved_at
:
string
;
...
@@ -163,7 +166,7 @@ export default function ChatPage() {
...
@@ -163,7 +166,7 @@ export default function ChatPage() {
:
rawTaskId
;
:
rawTaskId
;
const
hasFileId
=
Boolean
(
fileId
);
const
hasFileId
=
Boolean
(
fileId
);
const
hasTaskId
=
Boolean
(
taskId
);
const
hasTaskId
=
Boolean
(
taskId
);
const
isTaskOrchestrator
=
orchestrator
===
"
task
"
;
const
isTaskOrchestrator
=
isTaskCoupledOrchestrator
(
orchestrator
)
;
const
hasAnyTaskParam
=
hasFileId
||
hasTaskId
;
const
hasAnyTaskParam
=
hasFileId
||
hasTaskId
;
const
hasRequiredParams
=
hasFileId
&&
hasTaskId
;
const
hasRequiredParams
=
hasFileId
&&
hasTaskId
;
const
key
=
`
${
orchestrator
}
|
${
fileId
}
|
${
taskId
}
`
;
const
key
=
`
${
orchestrator
}
|
${
fileId
}
|
${
taskId
}
`
;
...
@@ -208,7 +211,11 @@ export default function ChatPage() {
...
@@ -208,7 +211,11 @@ export default function ChatPage() {
return
;
return
;
}
}
setSelectedOrchestrator
(
"
task
"
);
setSelectedOrchestrator
(
deepLinkTarget
.
isTaskOrchestrator
&&
searchParams
.
get
(
"
orchestrator
"
)
===
"
feedback
"
?
"
feedback
"
:
"
task
"
);
setTaskRef
({
fileId
:
selectedFile
.
file_id
,
taskId
:
selectedTask
.
task_id
});
setTaskRef
({
fileId
:
selectedFile
.
file_id
,
taskId
:
selectedTask
.
task_id
});
unlockTask
();
unlockTask
();
...
@@ -536,7 +543,7 @@ export default function ChatPage() {
...
@@ -536,7 +543,7 @@ export default function ChatPage() {
:
selectedOrchestrator
;
:
selectedOrchestrator
;
setSelectedOrchestrator
(
nextOrchestrator
);
setSelectedOrchestrator
(
nextOrchestrator
);
if
(
nextOrchestrator
===
"
task
"
)
{
if
(
isTaskCoupledOrchestrator
(
nextOrchestrator
)
)
{
const
restoredTask
=
payload
.
selected_task
;
const
restoredTask
=
payload
.
selected_task
;
if
(
restoredTask
?.
file_id
&&
restoredTask
?.
task_id
)
{
if
(
restoredTask
?.
file_id
&&
restoredTask
?.
task_id
)
{
setTaskRef
({
setTaskRef
({
...
@@ -671,7 +678,7 @@ export default function ChatPage() {
...
@@ -671,7 +678,7 @@ export default function ChatPage() {
}
}
resetChatState
();
resetChatState
();
switchOrchestrator
(
next
);
switchOrchestrator
(
next
);
navigate
(
next
===
"
task
"
?
"
/select-task
"
:
"
/chat
"
);
navigate
(
isTaskCoupledOrchestrator
(
next
)
?
"
/select-task
"
:
"
/chat
"
);
};
};
const
handleCanvasSave
=
async
(
dataUrl
:
string
)
=>
{
const
handleCanvasSave
=
async
(
dataUrl
:
string
)
=>
{
...
...
math-tutor/frontend/src/pages/TaskSelectionPage.tsx
View file @
a4c0b261
...
@@ -8,6 +8,9 @@ import { useTutorSession } from "../state/tutorSession";
...
@@ -8,6 +8,9 @@ import { useTutorSession } from "../state/tutorSession";
import
"
../styles/theme.css
"
;
import
"
../styles/theme.css
"
;
import
sumintLogo
from
"
../../SuMINT-Logo.png
"
;
import
sumintLogo
from
"
../../SuMINT-Logo.png
"
;
const
isTaskCoupledOrchestrator
=
(
value
:
OrchestratorName
):
boolean
=>
value
===
"
task
"
||
value
===
"
feedback
"
;
export
default
function
TaskSelectionPage
()
{
export
default
function
TaskSelectionPage
()
{
const
navigate
=
useNavigate
();
const
navigate
=
useNavigate
();
const
{
const
{
...
@@ -86,7 +89,7 @@ export default function TaskSelectionPage() {
...
@@ -86,7 +89,7 @@ export default function TaskSelectionPage() {
return
;
return
;
}
}
switchOrchestrator
(
next
);
switchOrchestrator
(
next
);
navigate
(
next
===
"
task
"
?
"
/select-task
"
:
"
/chat
"
,
{
replace
:
true
});
navigate
(
isTaskCoupledOrchestrator
(
next
)
?
"
/select-task
"
:
"
/chat
"
,
{
replace
:
true
});
};
};
if
(
!
isTasksInitialized
)
{
if
(
!
isTasksInitialized
)
{
...
...
math-tutor/frontend/src/state/tutorSession.tsx
View file @
a4c0b261
...
@@ -68,6 +68,9 @@ export const getDefaultTaskId = (tasks: Array<{ task_id: string }>): string =>
...
@@ -68,6 +68,9 @@ export const getDefaultTaskId = (tasks: Array<{ task_id: string }>): string =>
const
isSelectableTaskFile
=
(
file
:
TaskFile
):
boolean
=>
const
isSelectableTaskFile
=
(
file
:
TaskFile
):
boolean
=>
Array
.
isArray
(
file
.
subsections
)
&&
file
.
subsections
.
length
>
0
;
Array
.
isArray
(
file
.
subsections
)
&&
file
.
subsections
.
length
>
0
;
const
isTaskCoupledOrchestrator
=
(
value
:
OrchestratorName
):
boolean
=>
value
===
"
task
"
||
value
===
"
feedback
"
;
export
function
TutorSessionProvider
({
children
}:
PropsWithChildren
)
{
export
function
TutorSessionProvider
({
children
}:
PropsWithChildren
)
{
const
[
chatSessionId
,
setChatSessionId
]
=
useState
<
string
>
(()
=>
createSessionId
());
const
[
chatSessionId
,
setChatSessionId
]
=
useState
<
string
>
(()
=>
createSessionId
());
const
[
selectedOrchestrator
,
setSelectedOrchestratorState
]
=
const
[
selectedOrchestrator
,
setSelectedOrchestratorState
]
=
...
@@ -83,7 +86,7 @@ export function TutorSessionProvider({ children }: PropsWithChildren) {
...
@@ -83,7 +86,7 @@ export function TutorSessionProvider({ children }: PropsWithChildren) {
const
[
tasksError
,
setTasksError
]
=
useState
<
string
|
null
>
(
null
);
const
[
tasksError
,
setTasksError
]
=
useState
<
string
|
null
>
(
null
);
const
[
taskLocked
,
setTaskLocked
]
=
useState
(
false
);
const
[
taskLocked
,
setTaskLocked
]
=
useState
(
false
);
const
isTaskModeEnabled
=
selectedOrchestrator
===
"
task
"
;
const
isTaskModeEnabled
=
isTaskCoupledOrchestrator
(
selectedOrchestrator
)
;
const
selectedTask
=
useMemo
<
SelectedTask
|
null
>
(()
=>
{
const
selectedTask
=
useMemo
<
SelectedTask
|
null
>
(()
=>
{
if
(
!
selectedTaskRef
)
{
if
(
!
selectedTaskRef
)
{
...
@@ -228,7 +231,7 @@ export function TutorSessionProvider({ children }: PropsWithChildren) {
...
@@ -228,7 +231,7 @@ export function TutorSessionProvider({ children }: PropsWithChildren) {
setSelectedOrchestratorState
(
value
);
setSelectedOrchestratorState
(
value
);
setChatSessionId
(
createSessionId
());
setChatSessionId
(
createSessionId
());
setTaskLocked
(
false
);
setTaskLocked
(
false
);
if
(
value
!==
"
task
"
)
{
if
(
!
isTaskCoupledOrchestrator
(
value
)
)
{
setSelectedTaskRef
(
null
);
setSelectedTaskRef
(
null
);
}
}
},
[]);
},
[]);
...
...
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