Commit bf7cc21d authored by Kantz's avatar Kantz
Browse files

orchestator API removed caus not longer relevant

parent cd7358c0
...@@ -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"
......
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),
)
...@@ -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,
) )
......
...@@ -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:
......
...@@ -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:
......
...@@ -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)
...@@ -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:
......
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(),
};
}
...@@ -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[];
}; };
......
...@@ -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:
......
...@@ -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,
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment