Files
arioch-assistant/assistant/profile.py
2026-04-07 22:06:19 +02:00

101 lines
3.3 KiB
Python

"""
Gestion des profils de personnalité pour l'assistant.
Chaque profil est un fichier YAML dans le dossier profiles/ contenant :
- name : nom affiché
- description : courte description
- system_prompt : prompt système (obligatoire)
- documents : liste de fichiers texte/markdown à injecter dans le contexte (optionnel)
- voice_language : surcharge de VOICE_LANGUAGE (optionnel)
"""
from __future__ import annotations
from dataclasses import dataclass, field
from pathlib import Path
import yaml
PROFILES_DIR = Path(__file__).parent.parent / "profiles"
@dataclass
class Profile:
name: str
system_prompt: str
description: str = ""
documents: list[str] = field(default_factory=list)
voice_language: str | None = None
mcp_servers: list[dict] = field(default_factory=list)
def build_system_prompt(self) -> str:
"""Retourne le prompt système enrichi des documents de contexte."""
parts = [self.system_prompt.strip()]
for doc_path in self.documents:
full_path = PROFILES_DIR / doc_path
if full_path.exists():
content = full_path.read_text(encoding="utf-8").strip()
parts.append(
f"\n---\n## Contexte : {full_path.stem}\n\n{content}"
)
else:
print(f"[Profile] Document introuvable : {full_path}")
return "\n".join(parts)
def list_profiles() -> list[tuple[str, str, str]]:
"""Retourne [(slug, name, description), ...] pour tous les profils disponibles."""
results = []
for yaml_file in sorted(PROFILES_DIR.glob("*.yaml")):
slug = yaml_file.stem
try:
data = yaml.safe_load(yaml_file.read_text(encoding="utf-8"))
results.append((slug, data.get("name", slug), data.get("description", "")))
except Exception as e:
print(f"[Profile] Erreur lecture {yaml_file.name} : {e}")
return results
def load_profile(slug: str) -> Profile:
"""Charge un profil par son slug (nom de fichier sans extension)."""
yaml_file = PROFILES_DIR / f"{slug}.yaml"
if not yaml_file.exists():
raise FileNotFoundError(f"Profil introuvable : {slug} (cherché dans {PROFILES_DIR})")
data = yaml.safe_load(yaml_file.read_text(encoding="utf-8"))
return Profile(
name=data.get("name", slug),
description=data.get("description", ""),
system_prompt=data.get("system_prompt", ""),
documents=data.get("documents", []),
voice_language=data.get("voice_language"),
mcp_servers=data.get("mcp_servers", []),
)
def apply_profile(slug: str) -> Profile:
"""Charge un profil et l'applique à la configuration active."""
from . import config, llm, mcp_client
profile = load_profile(slug)
config.SYSTEM_PROMPT = profile.build_system_prompt()
if profile.voice_language:
config.VOICE_LANGUAGE = profile.voice_language
import assistant.tts as tts
tts._default_voice_id = None
llm.reset_history()
# Réinitialise les serveurs MCP et charge ceux du profil
manager = mcp_client.reset_manager()
if profile.mcp_servers:
from .mcp_client import MCPServerConfig, get_manager
configs = [MCPServerConfig(**s) for s in profile.mcp_servers]
get_manager().load_servers(configs)
return profile