feat(stt): Asa agentique — boucle d'outils (function calling, Phase 1) (#48)

Asa ne répondait qu'à partir d'un contexte figé (RAG doc ou blocs live
pré-câblés, à présélectionner) → les questions à état live (« gpu-01 tourne
bien ? ») tombaient sur « la doc ne le précise pas ». Bascule vers une boucle
de function-calling : le modèle décide quels outils appeler puis répond à
partir de leurs résultats.

- Nouveau contexte `asa` (STT_DEFAULT_CONTEXT=asa, défaut prod) + tools.py
  (registre schémas OpenAI + exécuteurs) + brain.ask_with_tools (boucle bornée
  STT_TOOL_MAX_ITERS=4, réponse forcée au-delà ; _post factorisé + retry).
- Outils Phase 1, LECTURE SEULE : search_docs (RAG funk-docs), host_health
  (gpu-01|storage-01 : up/charge/RAM + llama-server), cluster_status,
  prometheus_query (PromQL arbitraire). Réutilisent sources.py / knowledge.py.
- Trace des outils renvoyée dans `context` → visualiseur HUD (un bloc par appel).
- 100 % local (Qwen3-8B) : tool-calling natif llama.cpp validé, survit au
  /no_think. LiteLLM transmet bien les tools. PromQL validés contre le vrai
  Prometheus in-cluster. 3 tests unitaires de la boucle (hors-ligne).

Web search (SearXNG in-cluster) = Phase 2 ; actions admin pilotées par le LLM
(hermes-exec comme outil) = Phase 3.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
ALI YESILKAYA 2026-06-22 21:52:28 +02:00 committed by GitHub
parent de1cd6c407
commit 7cafc06069
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 566 additions and 42 deletions

View file

@ -29,10 +29,26 @@ class Context:
description: str
system_prompt: str
sources: tuple[str, ...] = () # "docs","ghostfolio","alerts","cluster","metrics"
tools: tuple[str, ...] = () # outils function-calling (cf. tools.py) → boucle agentique
# Le contexte « funk » garde le prompt grounding-strict historique (env override possible).
CONTEXTS: dict[str, Context] = {
# Contexte « asa » : boucle d'outils (function calling). Asa décide elle-même quand
# sonder l'état live du homelab ou chercher dans la doc, puis répond. C'est le contexte
# par défaut côté production (STT_DEFAULT_CONTEXT=asa) — « gpu-01 tourne bien ? » marche
# sans présélection. Les outils sont en LECTURE SEULE (volet actions = contexte « agent »).
"asa": Context(
id="asa", label="Asa · agent", icon="",
description="Asa répond en s'appuyant sur des outils (doc + état live du homelab).",
system_prompt=_BASE + " Tu disposes d'outils pour obtenir l'état RÉEL et LIVE du "
"homelab (santé des machines, état du cluster, métriques Prometheus) et pour chercher "
"dans la documentation Funk. Dès qu'une question porte sur l'état courant, un fait "
"précis ou la config du homelab, APPELLE l'outil adéquat puis réponds à partir de son "
"résultat — n'invente jamais. Si les outils ne donnent pas l'information, dis-le "
"simplement. Pour le bavardage général, réponds directement sans outil.",
tools=("search_docs", "host_health", "cluster_status", "prometheus_query"),
),
"funk": Context(
id="funk", label="Funk · cluster", icon="🛠️",
description="Questions sur le homelab depuis la documentation.",