Créer un agent MCP dans Open WebUI : des outils de base à un planificateur
Un agent dans Open WebUI pour MCP commence par quelque chose de simple : on donne à l'LLM un ensemble d'outils pour interagir avec ClickHouse et on observe ce qui se passe. Au départ, trois outils basiques sont disponibles : list_databases, list_tables et run_select_queries. Ils gèrent des requêtes SQL simples, mais lorsque les tâches deviennent plus complexes, le modèle peine à comprendre les schémas de données.
Solution : un prompt détaillé avec des exemples concrets. La structure inclut des variables (portfolio_name, start_date, end_date), des instructions pour les filtres LIKE et des motifs comme Dt::date >= '{start_date}'. Par exemple, pour calculer la performance d'un portefeuille, on utilise des fonctions fenêtrées :
WITH log_coef as (SELECT Portfolio, Dt,
sum(log(TWR_dod+1)) OVER (
PARTITION BY InvestmentPortfolioID
ORDER BY Dt ASC ROWS BETWEEN UNBOUNDED PRECEDING AND 0 FOLLOWING
) AS TWR_cumulative_coef
FROM Contribution.contribution_twr_1s_mcp
WHERE lowerUTF8(Portfolio) LIKE '%{portfolio_name}%'
AND Dt::date >= {start_date}
AND Dt::date <= {end_date}
ORDER BY Dt DESC)
SELECT Portfolio, Dt, exp(TWR_cumulative_coef) - 1 AS TWR_cumulative
FROM log_coef;
Les résultats s'améliorent, mais restent instables — des erreurs de syntaxe, des métriques incorrectes persistent. Le RAG dans Open WebUI ne résout pas le problème.
Élargir l’outil : des outils personnalisés sans hallucinations
Vers une détermination absolue : nous construisons des outils prédéfinis grâce à des schémas Pydantic. L'LLM ne fait que sélectionner et paramétrer ces outils ; les requêtes sont fixes. Les classes d'outils incluent :
ClickHouseClientBase: wrapper autour des opérations centrales MCP.ProfitTool: calcule les rendements (TWR par date, arithmétique/géométrique).PortfolioDiscoveryTool: découvre les attributs des portefeuilles (liste, types, stratégies).PortfolioCashflowTool: suit les entrées/sorties, analyse du flux de trésorerie.
Exemple de schéma pour ClickHouseClientBaseParams :
class ClickHouseClientBaseParams(BaseModel):
operation: Literal['list_databases', 'list_tables', 'run_select_query'] = Field(
description='Type d’opération : list_databases, list_tables ou run_select_query'
)
database: Optional[str] = Field(default=None, description='Nom de la base de données')
query: Optional[str] = Field(default=None, description='Requête SQL')
like: Optional[str] = Field(default=None, description='Filtre LIKE')
not_like: Optional[str] = Field(default=None, description='Filtre NOT LIKE')
def clickhouse_client_base(params: ClickHouseClientBaseParams) -> str:
# Logique pour les requêtes HTTP vers http://clickhouse-mcp.services.kfim.int
# Gère list_databases, list_tables, run_select_query
# Remplace automatiquement contribution_twr_1s_mcp par le nom complet de la table
La fonction pydantic_to_openai_schema convertit ces schémas en format compatible OpenAI, éliminant les hallucinations — les outils retournent toujours un JSON prévisible.
Avantages de cette approche :
- Déterminisme : même entrée → même sortie.
- Évolutivité : de nouvelles métriques ajoutées comme outils.
- Débogage : la logique des requêtes est transparente, pas de comportement de boîte noire de l'LLM.
Les limites de la simplicité : quand les outils ne suffisent plus
Un agent naïf échoue sur des tâches complexes : plusieurs portefeuilles, agrégations, JOINs. Le modèle confond les fonctions fenêtrées et les filtres de date. Même avec des exemples, les taux d'erreur atteignent 30–40 %. Étendre l'analyse des portefeuilles exige de traiter de grandes quantités de données — des milliers de lignes TWR, des enregistrements de flux de trésorerie.
Amélioration : séparer planificateur et exécuteur
Deuxième itération : l'agent devient ReWOO — Raisonnement + Action. Le planificateur (un LLM distinct) décompose les tâches en étapes ; l'exécuteur appelle les outils. Cela résout :
- Filtrage des données : recherche plein texte sur les portefeuilles via
PortfolioDiscoveryTool. - Contrôle de séquence : requêtes en chaîne (liste → filtre → agrégation).
- Gestion du contexte : tables fusionnées en une seule pour le rendu UI.
Le planificateur génère un plan :
- Étape 1 : lister les portefeuilles LIKE '%name%'.
- Étape 2 : exécuter la requête TWR.
- Étape 3 : agréger et afficher.
L'exécuteur suit strictement le plan, sans improvisation.
Recherche plein texte en action
Pour les grandes tables — le pré-filtrage est essentiel. L'outil cherche avec lowerUTF8(Portfolio) LIKE '%query%', retourne les ID/types. Cela accélère run_select_query : au lieu de balayages complets, des requêtes ciblées.
Exemple de chaîne :
PortfolioDiscoveryTool(like='stocks')→ retourne la liste des IDs.ProfitTool(portfolios=ids, dates=range)→ récupère les TWR.- Fusionner dans un Pandas/DataFrame pour l'interface.
Points clés
- Outils déterministes basés sur Pydantic réduisent les erreurs de l'LLM en SQL.
- Approche ReWOO sépare planification et exécution pour les workflows complexes.
- Recherche plein texte est indispensable pour filtrer dans de grands jeux de données ClickHouse.
- Intégration Open WebUI permet des appels séquentiels avec rendu final du tableau.
- Prompts en chaîne de raisonnement améliorent la stabilité, même avec des modèles moins puissants.
— Editorial Team
Aucun commentaire pour le moment.