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
bf7cc21d
Commit
bf7cc21d
authored
Jun 18, 2026
by
Kantz
Browse files
orchestator API removed caus not longer relevant
parent
cd7358c0
Changes
11
Hide whitespace changes
Inline
Side-by-side
math-tutor/backend/.env-example
View file @
bf7cc21d
...
@@ -11,7 +11,6 @@ LLM_TOOL_USE_ENABLED="False" # "True" or "False"
...
@@ -11,7 +11,6 @@ LLM_TOOL_USE_ENABLED="False" # "True" or "False"
MCP_SHARED_SECRET=""
MCP_SHARED_SECRET=""
MCP_BASE_URL=""
MCP_BASE_URL=""
ORCHESTRATOR="task" # "tutor", "task" or "qa"
TASK_FOLDER="tasks"
TASK_FOLDER="tasks"
LLM_PROVIDER="gwdg" # "openai", "gwdg", "mistral", or "ollama"
LLM_PROVIDER="gwdg" # "openai", "gwdg", "mistral", or "ollama"
...
...
math-tutor/backend/app/api/orchestrator.py
deleted
100644 → 0
View file @
cd7358c0
from
__future__
import
annotations
from
fastapi
import
APIRouter
from
pydantic
import
BaseModel
from
app.deterministic_services.orchestrators.registry
import
(
AVAILABLE_ORCHESTRATORS
,
get_default_orchestrator
,
)
router
=
APIRouter
()
class
OrchestratorConfigResponse
(
BaseModel
):
default_orchestrator
:
str
available_orchestrators
:
list
[
str
]
@
router
.
get
(
"/api/orchestrator/config"
,
response_model
=
OrchestratorConfigResponse
)
def
get_orchestrator_config
()
->
OrchestratorConfigResponse
:
return
OrchestratorConfigResponse
(
default_orchestrator
=
get_default_orchestrator
(),
available_orchestrators
=
list
(
AVAILABLE_ORCHESTRATORS
),
)
math-tutor/backend/app/api/tasks.py
View file @
bf7cc21d
...
@@ -6,13 +6,10 @@ from fastapi import APIRouter, HTTPException
...
@@ -6,13 +6,10 @@ from fastapi import APIRouter, HTTPException
from
fastapi.responses
import
FileResponse
from
fastapi.responses
import
FileResponse
from
pydantic
import
BaseModel
,
Field
from
pydantic
import
BaseModel
,
Field
import
app.config
as
config
from
app.deterministic_services
import
context_store
,
task_catalog
,
socratic_oranisator
from
app.deterministic_services
import
context_store
,
task_catalog
,
socratic_oranisator
router
=
APIRouter
()
router
=
APIRouter
()
TASK_ORCHESTRATORS
=
{
"task"
,
"socratic"
}
class
TaskImage
(
BaseModel
):
class
TaskImage
(
BaseModel
):
src
:
str
src
:
str
...
@@ -38,8 +35,6 @@ class TaskFile(BaseModel):
...
@@ -38,8 +35,6 @@ class TaskFile(BaseModel):
class
TasksResponse
(
BaseModel
):
class
TasksResponse
(
BaseModel
):
orchestrator
:
str
enabled
:
bool
task_files
:
List
[
TaskFile
]
task_files
:
List
[
TaskFile
]
...
@@ -52,8 +47,6 @@ class TaskDetailsResponse(BaseModel):
...
@@ -52,8 +47,6 @@ class TaskDetailsResponse(BaseModel):
class
SocraticResponse
(
BaseModel
):
class
SocraticResponse
(
BaseModel
):
orchestrator
:
str
enabled
:
bool
topics
:
List
[
TopicEntry
]
=
Field
(
default_factory
=
list
)
topics
:
List
[
TopicEntry
]
=
Field
(
default_factory
=
list
)
class
SelectTaskRequest
(
BaseModel
):
class
SelectTaskRequest
(
BaseModel
):
...
@@ -108,11 +101,8 @@ def get_task_asset(asset_path: str) -> FileResponse:
...
@@ -108,11 +101,8 @@ def get_task_asset(asset_path: str) -> FileResponse:
@
router
.
get
(
"/api/tasks"
,
response_model
=
TasksResponse
)
@
router
.
get
(
"/api/tasks"
,
response_model
=
TasksResponse
)
def
list_tasks
()
->
TasksResponse
:
def
list_tasks
()
->
TasksResponse
:
orchestrator
=
config
.
get_orchestrator
()
task_files
=
list
(
task_catalog
.
build_cached_task_metadata_catalog
())
task_files
=
list
(
task_catalog
.
build_cached_task_metadata_catalog
())
return
TasksResponse
(
return
TasksResponse
(
orchestrator
=
orchestrator
,
enabled
=
orchestrator
in
TASK_ORCHESTRATORS
,
task_files
=
task_files
,
task_files
=
task_files
,
)
)
...
@@ -127,11 +117,8 @@ def get_task_details(file_id: str, task_id: str) -> TaskDetailsResponse:
...
@@ -127,11 +117,8 @@ def get_task_details(file_id: str, task_id: str) -> TaskDetailsResponse:
@
router
.
get
(
"/api/tasks/socratic-topics"
,
response_model
=
SocraticResponse
)
@
router
.
get
(
"/api/tasks/socratic-topics"
,
response_model
=
SocraticResponse
)
def
list_socratic_topics
()
->
SocraticResponse
:
def
list_socratic_topics
()
->
SocraticResponse
:
orchestrator
=
config
.
get_orchestrator
()
topics
=
socratic_oranisator
.
build_topic_catalog
()
topics
=
socratic_oranisator
.
build_topic_catalog
()
return
SocraticResponse
(
return
SocraticResponse
(
orchestrator
=
orchestrator
,
enabled
=
orchestrator
==
"socratic"
,
topics
=
topics
,
topics
=
topics
,
)
)
...
...
math-tutor/backend/app/config.py
View file @
bf7cc21d
...
@@ -23,11 +23,6 @@ class EmbeddingSettings(BaseModel):
...
@@ -23,11 +23,6 @@ class EmbeddingSettings(BaseModel):
target_dim
:
int
=
1024
target_dim
:
int
=
1024
def
get_orchestrator
()
->
str
:
return
os
.
getenv
(
"ORCHESTRATOR"
,
"qa"
).
lower
()
def
get_task_folder
()
->
Path
:
def
get_task_folder
()
->
Path
:
value
=
os
.
getenv
(
"TASK_FOLDER"
,
"tasks"
).
strip
()
value
=
os
.
getenv
(
"TASK_FOLDER"
,
"tasks"
).
strip
()
if
not
value
:
if
not
value
:
...
...
math-tutor/backend/app/deterministic_services/orchestrators/registry.py
View file @
bf7cc21d
...
@@ -2,7 +2,6 @@ from __future__ import annotations
...
@@ -2,7 +2,6 @@ from __future__ import annotations
from
typing
import
Any
from
typing
import
Any
import
app.config
as
config
from
app.deterministic_services.orchestrators
import
(
from
app.deterministic_services.orchestrators
import
(
orchestrator_qa
,
orchestrator_qa
,
orchestrator_socratic
,
orchestrator_socratic
,
...
@@ -11,6 +10,7 @@ from app.deterministic_services.orchestrators import (
...
@@ -11,6 +10,7 @@ from app.deterministic_services.orchestrators import (
)
)
AVAILABLE_ORCHESTRATORS
:
tuple
[
str
,
...]
=
(
"qa"
,
"tutor"
,
"task"
,
"socratic"
)
AVAILABLE_ORCHESTRATORS
:
tuple
[
str
,
...]
=
(
"qa"
,
"tutor"
,
"task"
,
"socratic"
)
DEFAULT_ORCHESTRATOR
=
"qa"
_ORCHESTRATOR_MODULES
:
dict
[
str
,
Any
]
=
{
_ORCHESTRATOR_MODULES
:
dict
[
str
,
Any
]
=
{
"qa"
:
orchestrator_qa
,
"qa"
:
orchestrator_qa
,
...
@@ -21,10 +21,7 @@ _ORCHESTRATOR_MODULES: dict[str, Any] = {
...
@@ -21,10 +21,7 @@ _ORCHESTRATOR_MODULES: dict[str, Any] = {
def
get_default_orchestrator
()
->
str
:
def
get_default_orchestrator
()
->
str
:
configured
=
str
(
config
.
get_orchestrator
()
or
""
).
strip
().
lower
()
return
DEFAULT_ORCHESTRATOR
if
configured
in
_ORCHESTRATOR_MODULES
:
return
configured
return
"qa"
def
is_valid_orchestrator
(
value
:
str
)
->
bool
:
def
is_valid_orchestrator
(
value
:
str
)
->
bool
:
...
...
math-tutor/backend/app/main.py
View file @
bf7cc21d
...
@@ -3,7 +3,7 @@ import logging
...
@@ -3,7 +3,7 @@ import logging
from
fastapi
import
FastAPI
from
fastapi
import
FastAPI
from
fastapi.middleware.cors
import
CORSMiddleware
from
fastapi.middleware.cors
import
CORSMiddleware
from
app.api
import
canvas
,
chat
,
context
,
health
,
orchestrator
,
tasks
from
app.api
import
canvas
,
chat
,
context
,
health
,
tasks
from
app.config
import
get_frontend_url
from
app.config
import
get_frontend_url
from
app.deterministic_services
import
embedding_provider
,
llm_quota
from
app.deterministic_services
import
embedding_provider
,
llm_quota
from
app
import
config
from
app
import
config
...
@@ -58,5 +58,4 @@ app.include_router(chat.router)
...
@@ -58,5 +58,4 @@ app.include_router(chat.router)
app
.
include_router
(
canvas
.
router
)
app
.
include_router
(
canvas
.
router
)
app
.
include_router
(
context
.
router
)
app
.
include_router
(
context
.
router
)
app
.
include_router
(
health
.
router
)
app
.
include_router
(
health
.
router
)
app
.
include_router
(
orchestrator
.
router
)
app
.
include_router
(
tasks
.
router
)
app
.
include_router
(
tasks
.
router
)
math-tutor/backend/test/task_catalog_socratic_test.py
View file @
bf7cc21d
...
@@ -431,7 +431,7 @@ class TaskApiSocraticTest(unittest.TestCase):
...
@@ -431,7 +431,7 @@ class TaskApiSocraticTest(unittest.TestCase):
}
}
]
]
with
patch
(
"app.api.tasks.config.get_orchestrator"
,
return_value
=
"socratic"
),
patch
(
with
patch
(
"app.api.tasks.task_catalog.build_cached_task_metadata_catalog"
,
"app.api.tasks.task_catalog.build_cached_task_metadata_catalog"
,
return_value
=
payload
,
return_value
=
payload
,
):
):
...
@@ -439,7 +439,6 @@ class TaskApiSocraticTest(unittest.TestCase):
...
@@ -439,7 +439,6 @@ class TaskApiSocraticTest(unittest.TestCase):
self
.
assertEqual
(
response
.
status_code
,
200
)
self
.
assertEqual
(
response
.
status_code
,
200
)
body
=
response
.
json
()
body
=
response
.
json
()
self
.
assertEqual
(
body
[
"orchestrator"
],
"socratic"
)
self
.
assertEqual
(
body
[
"task_files"
],
payload
)
self
.
assertEqual
(
body
[
"task_files"
],
payload
)
self
.
assertNotIn
(
"topics"
,
body
)
self
.
assertNotIn
(
"topics"
,
body
)
...
@@ -505,7 +504,7 @@ class TaskApiSocraticTest(unittest.TestCase):
...
@@ -505,7 +504,7 @@ class TaskApiSocraticTest(unittest.TestCase):
}
}
]
]
with
patch
(
"app.api.tasks.config.get_orchestrator"
,
return_value
=
"socratic"
),
patch
(
with
patch
(
"app.api.tasks.socratic_oranisator.build_topic_catalog"
,
"app.api.tasks.socratic_oranisator.build_topic_catalog"
,
return_value
=
topics
,
return_value
=
topics
,
):
):
...
@@ -513,8 +512,6 @@ class TaskApiSocraticTest(unittest.TestCase):
...
@@ -513,8 +512,6 @@ class TaskApiSocraticTest(unittest.TestCase):
self
.
assertEqual
(
response
.
status_code
,
200
)
self
.
assertEqual
(
response
.
status_code
,
200
)
body
=
response
.
json
()
body
=
response
.
json
()
self
.
assertEqual
(
body
[
"orchestrator"
],
"socratic"
)
self
.
assertTrue
(
body
[
"enabled"
])
self
.
assertEqual
(
body
[
"topics"
],
topics
)
self
.
assertEqual
(
body
[
"topics"
],
topics
)
def
test_select_topic_endpoint_returns_selected_key
(
self
)
->
None
:
def
test_select_topic_endpoint_returns_selected_key
(
self
)
->
None
:
...
...
math-tutor/frontend/src/api/orchestratorApi.ts
deleted
100644 → 0
View file @
cd7358c0
import
{
DEFAULT_ORCHESTRATOR
,
FALLBACK_ORCHESTRATORS
,
normalizeOrchestrator
,
type
OrchestratorName
,
}
from
"
../utils/orchestrator
"
;
export
type
OrchestratorConfigResponse
=
{
default_orchestrator
:
OrchestratorName
;
available_orchestrators
:
OrchestratorName
[];
};
export
const
getFallbackOrchestrators
=
():
OrchestratorName
[]
=>
[...
FALLBACK_ORCHESTRATORS
];
export
async
function
fetchOrchestratorConfig
():
Promise
<
OrchestratorConfigResponse
>
{
const
response
=
await
fetch
(
"
/api/orchestrator/config
"
);
if
(
!
response
.
ok
)
{
throw
new
Error
(
`Orchestrator config failed:
${
response
.
status
}
`
);
}
const
payload
=
await
response
.
json
();
const
defaultOrchestrator
=
normalizeOrchestrator
(
String
(
payload
?.
default_orchestrator
||
""
))
||
DEFAULT_ORCHESTRATOR
;
const
availableRaw
=
Array
.
isArray
(
payload
?.
available_orchestrators
)
?
payload
.
available_orchestrators
:
[];
const
available
=
availableRaw
.
map
((
item
:
unknown
)
=>
normalizeOrchestrator
(
String
(
item
||
""
)))
.
filter
((
item
:
OrchestratorName
|
null
):
item
is
OrchestratorName
=>
Boolean
(
item
));
return
{
default_orchestrator
:
defaultOrchestrator
,
available_orchestrators
:
available
.
length
?
available
:
getFallbackOrchestrators
(),
};
}
math-tutor/frontend/src/api/taskApi.ts
View file @
bf7cc21d
...
@@ -21,8 +21,6 @@ export type TopicOption = {
...
@@ -21,8 +21,6 @@ export type TopicOption = {
};
};
export
type
TasksResponse
=
{
export
type
TasksResponse
=
{
orchestrator
:
string
;
enabled
:
boolean
;
task_files
:
TaskFile
[];
task_files
:
TaskFile
[];
};
};
...
@@ -35,8 +33,6 @@ export type TaskDetailsResponse = {
...
@@ -35,8 +33,6 @@ export type TaskDetailsResponse = {
};
};
export
type
SocraticResponse
=
{
export
type
SocraticResponse
=
{
orchestrator
:
string
;
enabled
:
boolean
;
topics
:
TopicOption
[];
topics
:
TopicOption
[];
};
};
...
...
math-tutor/frontend/src/i18n.ts
View file @
bf7cc21d
...
@@ -56,7 +56,6 @@
...
@@ -56,7 +56,6 @@
noSavedChatsYet
:
"
No saved chats yet.
"
,
noSavedChatsYet
:
"
No saved chats yet.
"
,
canvasHidden
:
"
Canvas hidden
"
,
canvasHidden
:
"
Canvas hidden
"
,
failedLoadTasks
:
"
Could not load tasks.
"
,
failedLoadTasks
:
"
Could not load tasks.
"
,
failedLoadOrchestratorConfig
:
"
Could not load orchestrator config. Fallback mode active.
"
,
chatRequestFailed
:
"
The chat request failed. Please check backend logs.
"
,
chatRequestFailed
:
"
The chat request failed. Please check backend logs.
"
,
noStoredSolution
:
"
No stored solution is available for this task yet.
"
,
noStoredSolution
:
"
No stored solution is available for this task yet.
"
,
retrievalFailed
:
"
Source retrieval failed. Please check backend logs.
"
,
retrievalFailed
:
"
Source retrieval failed. Please check backend logs.
"
,
...
@@ -156,8 +155,6 @@
...
@@ -156,8 +155,6 @@
noSavedChatsYet
:
"
Noch keine gespeicherten Chats.
"
,
noSavedChatsYet
:
"
Noch keine gespeicherten Chats.
"
,
canvasHidden
:
"
Canvas ausgeblendet
"
,
canvasHidden
:
"
Canvas ausgeblendet
"
,
failedLoadTasks
:
"
Aufgaben konnten nicht geladen werden.
"
,
failedLoadTasks
:
"
Aufgaben konnten nicht geladen werden.
"
,
failedLoadOrchestratorConfig
:
"
Orchestrator-Konfiguration konnte nicht geladen werden. Fallback-Modus aktiv.
"
,
chatRequestFailed
:
chatRequestFailed
:
"
Da ist wohl die Chat-Anfrage fehlgeschlagen. Gib gerne deinem Dozenten bescheid. In vielen Fällen hilft es die Seite neu zu laden.
"
,
"
Da ist wohl die Chat-Anfrage fehlgeschlagen. Gib gerne deinem Dozenten bescheid. In vielen Fällen hilft es die Seite neu zu laden.
"
,
noStoredSolution
:
noStoredSolution
:
...
...
math-tutor/frontend/src/state/tutorSession.tsx
View file @
bf7cc21d
...
@@ -10,12 +10,9 @@ import {
...
@@ -10,12 +10,9 @@ import {
type
PropsWithChildren
,
type
PropsWithChildren
,
}
from
"
react
"
;
}
from
"
react
"
;
import
{
t
}
from
"
../i18n
"
;
import
{
t
}
from
"
../i18n
"
;
import
{
fetchOrchestratorConfig
,
getFallbackOrchestrators
,
}
from
"
../api/orchestratorApi
"
;
import
{
import
{
DEFAULT_ORCHESTRATOR
,
DEFAULT_ORCHESTRATOR
,
FALLBACK_ORCHESTRATORS
,
isTaskCoupledOrchestrator
,
isTaskCoupledOrchestrator
,
type
OrchestratorName
,
type
OrchestratorName
,
}
from
"
../utils/orchestrator
"
;
}
from
"
../utils/orchestrator
"
;
...
@@ -105,10 +102,8 @@ export function TutorSessionProvider({ children }: PropsWithChildren) {
...
@@ -105,10 +102,8 @@ export function TutorSessionProvider({ children }: PropsWithChildren) {
const
[
selectedOrchestrator
,
setSelectedOrchestratorState
]
=
const
[
selectedOrchestrator
,
setSelectedOrchestratorState
]
=
useState
<
OrchestratorName
>
(
DEFAULT_ORCHESTRATOR
);
useState
<
OrchestratorName
>
(
DEFAULT_ORCHESTRATOR
);
const
[
availableOrchestrators
,
setAvailableOrchestrators
]
=
useState
<
OrchestratorName
[]
>
(
const
[
availableOrchestrators
,
setAvailableOrchestrators
]
=
useState
<
OrchestratorName
[]
>
(
()
=>
getFallbackOrchestrators
()
()
=>
[...
FALLBACK_ORCHESTRATORS
]
);
);
const
[
isOrchestratorSelectable
,
setIsOrchestratorSelectable
]
=
useState
(
false
);
const
[
orchestratorError
,
setOrchestratorError
]
=
useState
<
string
|
null
>
(
null
);
const
[
isTasksInitialized
,
setIsTasksInitialized
]
=
useState
(
false
);
const
[
isTasksInitialized
,
setIsTasksInitialized
]
=
useState
(
false
);
const
[
taskFiles
,
setTaskFiles
]
=
useState
<
TaskFile
[]
>
([]);
const
[
taskFiles
,
setTaskFiles
]
=
useState
<
TaskFile
[]
>
([]);
const
[
topics
,
setTopics
]
=
useState
<
TopicOption
[]
>
([]);
const
[
topics
,
setTopics
]
=
useState
<
TopicOption
[]
>
([]);
...
@@ -317,26 +312,19 @@ export function TutorSessionProvider({ children }: PropsWithChildren) {
...
@@ -317,26 +312,19 @@ export function TutorSessionProvider({ children }: PropsWithChildren) {
},
[
loadTaskDetails
]);
},
[
loadTaskDetails
]);
const
initTasks
=
useCallback
(
async
()
=>
{
const
initTasks
=
useCallback
(
async
()
=>
{
setOrchestratorError
(
null
);
try
{
try
{
const
orchestratorPayload
=
await
fetchOrchestratorConfig
();
const
available
=
[...
FALLBACK_ORCHESTRATORS
];
const
available
=
orchestratorPayload
.
available_orchestrators
.
length
?
orchestratorPayload
.
available_orchestrators
:
getFallbackOrchestrators
();
const
nextOrchestrator
=
available
.
includes
(
selectedOrchestrator
)
const
nextOrchestrator
=
available
.
includes
(
selectedOrchestrator
)
?
selectedOrchestrator
?
selectedOrchestrator
:
orchestratorPayload
.
default_orchestrator
;
:
DEFAULT_ORCHESTRATOR
;
setAvailableOrchestrators
(
available
);
setAvailableOrchestrators
(
available
);
setIsOrchestratorSelectable
(
true
);
setSelectedOrchestratorState
(
nextOrchestrator
);
setSelectedOrchestratorState
(
nextOrchestrator
);
await
loadSelectionData
(
nextOrchestrator
);
await
loadSelectionData
(
nextOrchestrator
);
}
catch
(
error
)
{
}
catch
(
error
)
{
setAvailableOrchestrators
(
getFallbackOrchestrators
());
setAvailableOrchestrators
([...
FALLBACK_ORCHESTRATORS
]);
setSelectedOrchestratorState
(
"
qa
"
);
setSelectedOrchestratorState
(
DEFAULT_ORCHESTRATOR
);
setIsOrchestratorSelectable
(
false
);
await
loadSelectionData
(
DEFAULT_ORCHESTRATOR
);
setOrchestratorError
(
t
(
"
failedLoadOrchestratorConfig
"
));
await
loadSelectionData
(
"
qa
"
);
void
error
;
void
error
;
}
finally
{
}
finally
{
setIsTasksInitialized
(
true
);
setIsTasksInitialized
(
true
);
...
@@ -477,8 +465,8 @@ export function TutorSessionProvider({ children }: PropsWithChildren) {
...
@@ -477,8 +465,8 @@ export function TutorSessionProvider({ children }: PropsWithChildren) {
availableOrchestrators
,
availableOrchestrators
,
setSelectedOrchestrator
,
setSelectedOrchestrator
,
switchOrchestrator
,
switchOrchestrator
,
isOrchestratorSelectable
,
isOrchestratorSelectable
:
true
,
orchestratorError
,
orchestratorError
:
null
,
taskFiles
,
taskFiles
,
topics
,
topics
,
selectedTaskRef
,
selectedTaskRef
,
...
...
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