70 lines
2.7 KiB
Python
70 lines
2.7 KiB
Python
|
|
"""
|
||
|
|
Preset „Nächste aus Kontext“: LLM leitet Erwartungsprofil aus Planungskontext ab.
|
||
|
|
|
||
|
|
Prompt: planning_exercise_expectation_profile (Migration 074)
|
||
|
|
"""
|
||
|
|
from __future__ import annotations
|
||
|
|
|
||
|
|
import logging
|
||
|
|
from typing import Any, Dict, Mapping, Optional, Tuple
|
||
|
|
|
||
|
|
from planning_exercise_intent import (
|
||
|
|
PlanningQueryIntentParsed,
|
||
|
|
_compact_json,
|
||
|
|
_load_compact_catalog,
|
||
|
|
_load_skills_catalog_compact,
|
||
|
|
parse_planning_query_intent_response,
|
||
|
|
)
|
||
|
|
from ai_prompt_runtime import AiPromptUnavailableError, load_and_render_ai_prompt
|
||
|
|
from openrouter_chat import (
|
||
|
|
effective_openrouter_model_for_prompt_row,
|
||
|
|
normalize_openrouter_env,
|
||
|
|
openrouter_chat_completion,
|
||
|
|
)
|
||
|
|
|
||
|
|
_logger = logging.getLogger("shinkan.planning_exercise_expectation")
|
||
|
|
|
||
|
|
|
||
|
|
def try_build_planning_expectation_from_context(
|
||
|
|
cur,
|
||
|
|
*,
|
||
|
|
heuristic_intent: str,
|
||
|
|
context_summary: Mapping[str, Any],
|
||
|
|
target_profile_summary: Mapping[str, Any],
|
||
|
|
) -> Tuple[Optional[PlanningQueryIntentParsed], bool]:
|
||
|
|
"""
|
||
|
|
LLM-Erwartungsprofil für preset_next / leere Anfrage mit Planungsbezug.
|
||
|
|
Returns (parsed overlay, applied).
|
||
|
|
"""
|
||
|
|
api_key, _ = normalize_openrouter_env()
|
||
|
|
if not api_key:
|
||
|
|
return None, False
|
||
|
|
|
||
|
|
variables = {
|
||
|
|
"heuristic_intent": heuristic_intent or "suggest_next",
|
||
|
|
"planning_context_json": _compact_json(dict(context_summary or {})),
|
||
|
|
"target_profile_json": _compact_json(dict(target_profile_summary or {})),
|
||
|
|
"skills_catalog_json": _compact_json(_load_skills_catalog_compact(cur)),
|
||
|
|
"focus_areas_catalog_json": _compact_json(_load_compact_catalog(cur, "focus_areas", "id")),
|
||
|
|
"training_types_catalog_json": _compact_json(_load_compact_catalog(cur, "training_types", "id")),
|
||
|
|
"style_directions_catalog_json": _compact_json(_load_compact_catalog(cur, "style_directions", "id")),
|
||
|
|
"target_groups_catalog_json": _compact_json(_load_compact_catalog(cur, "target_groups", "id")),
|
||
|
|
}
|
||
|
|
|
||
|
|
try:
|
||
|
|
prow, rendered = load_and_render_ai_prompt(cur, "planning_exercise_expectation_profile", variables)
|
||
|
|
model = effective_openrouter_model_for_prompt_row(prow)
|
||
|
|
raw = openrouter_chat_completion(api_key=api_key, model=model, user_content=rendered.text)
|
||
|
|
parsed = parse_planning_query_intent_response(raw)
|
||
|
|
if parsed.scenario not in ("preset_next", "continue_plan", "free_search"):
|
||
|
|
parsed = parsed.model_copy(update={"scenario": "preset_next"})
|
||
|
|
return parsed, True
|
||
|
|
except AiPromptUnavailableError:
|
||
|
|
return None, False
|
||
|
|
except Exception as exc:
|
||
|
|
_logger.warning("Planungs-Erwartungsprofil-LLM fehlgeschlagen: %s", exc)
|
||
|
|
return None, False
|
||
|
|
|
||
|
|
|
||
|
|
__all__ = ["try_build_planning_expectation_from_context"]
|