Widgets interactifs
Widgets interactifs
Les messages texte ne suffisent pas toujours. Quand votre agent retourne des données structurées (tableaux, graphiques, cartes), ChatKit permet d’afficher des widgets interactifs directement dans le chat. L’utilisateur peut interagir avec ces widgets sans quitter la conversation.
Le concept de widgets
Un widget est un composant visuel affiché dans un message de l’agent. Quand l’agent retourne des données structurées via un tool, ChatKit peut les afficher sous forme de widget au lieu de texte brut.
Enregistrer un widget
Déclarez vos widgets dans la configuration ChatKit :
import { ChatProvider, ChatWindow, MessageInput } from "@openai/chatkit/react";
// Widget tableau de données
function TableauWidget({ data }) {
return (
<div style={{
overflowX: "auto",
margin: "8px 0",
borderRadius: "8px",
border: "1px solid #334155",
}}>
<table style={{ width: "100%", borderCollapse: "collapse", fontSize: "14px" }}>
<thead>
<tr style={{ background: "#1E293B" }}>
{data.colonnes.map((col, i) => (
<th key={i} style={{ padding: "10px 12px", textAlign: "left", color: "#94A3B8" }}>
{col}
</th>
))}
</tr>
</thead>
<tbody>
{data.lignes.map((ligne, i) => (
<tr key={i} style={{ borderTop: "1px solid #1E293B" }}>
{ligne.map((cell, j) => (
<td key={j} style={{ padding: "10px 12px", color: "#F8FAFC" }}>
{cell}
</td>
))}
</tr>
))}
</tbody>
</table>
</div>
);
}
// Widget carte de produit
function ProduitWidget({ data }) {
return (
<div style={{
display: "flex",
gap: "16px",
padding: "16px",
background: "#1E293B",
borderRadius: "12px",
margin: "8px 0",
}}>
<div style={{ flex: 1 }}>
<h3 style={{ margin: "0 0 8px", color: "#F8FAFC" }}>{data.nom}</h3>
<p style={{ margin: "0 0 4px", color: "#94A3B8" }}>{data.description}</p>
<span style={{
color: "#3B82F6",
fontSize: "20px",
fontWeight: "bold",
}}>
{data.prix}
</span>
</div>
</div>
);
}
// Enregistrement des widgets
const widgets = {
tableau: TableauWidget,
produit: ProduitWidget,
};
function App() {
return (
<ChatProvider endpoint="/api/chat" widgets={widgets}>
<ChatWindow />
<MessageInput />
</ChatProvider>
);
}
Déclencher un widget depuis l’agent
Côté backend, retournez un format spécial dans vos tools pour déclencher un widget :
import json
from agents import function_tool
@function_tool
def lister_produits(categorie: str) -> str:
"""Liste les produits d'une catégorie avec affichage enrichi."""
produits = [
{"nom": "Laptop Pro", "prix": "1 299€", "stock": 45},
{"nom": "Tablet Air", "prix": "599€", "stock": 120},
]
# Format spécial pour déclencher le widget "tableau"
return json.dumps({
"__widget": "tableau",
"colonnes": ["Produit", "Prix", "Stock"],
"lignes": [[p["nom"], p["prix"], p["stock"]] for p in produits],
})
@function_tool
def details_produit(nom: str) -> str:
"""Affiche les détails d'un produit."""
return json.dumps({
"__widget": "produit",
"nom": "Laptop Pro",
"description": "Ordinateur portable haute performance, 16 Go RAM, SSD 1 To",
"prix": "1 299€",
})
Widget avec interactions
Les widgets peuvent déclencher des actions :
function ProduitInteractifWidget({ data, onAction }) {
return (
<div style={{
padding: "16px",
background: "#1E293B",
borderRadius: "12px",
margin: "8px 0",
}}>
<h3 style={{ color: "#F8FAFC", margin: "0 0 8px" }}>{data.nom}</h3>
<p style={{ color: "#94A3B8", margin: "0 0 12px" }}>{data.description}</p>
<div style={{ display: "flex", gap: "8px" }}>
<button
onClick={() => onAction("ajouter_panier", { produit: data.nom })}
style={{
padding: "8px 16px",
background: "#2563EB",
color: "white",
border: "none",
borderRadius: "8px",
cursor: "pointer",
}}
>
Ajouter au panier
</button>
<button
onClick={() => onAction("voir_details", { produit: data.nom })}
style={{
padding: "8px 16px",
background: "transparent",
color: "#3B82F6",
border: "1px solid #3B82F6",
borderRadius: "8px",
cursor: "pointer",
}}
>
Plus de détails
</button>
</div>
</div>
);
}
Quand l’utilisateur clique sur un bouton, onAction envoie un message à l’agent avec le contexte de l’action.
Widget graphique
Pour les données analytiques, intégrez une bibliothèque de graphiques :
// Avec recharts ou une autre bibliothèque
function GraphiqueWidget({ data }) {
return (
<div style={{
padding: "16px",
background: "#1E293B",
borderRadius: "12px",
margin: "8px 0",
}}>
<h4 style={{ color: "#F8FAFC", margin: "0 0 12px" }}>{data.titre}</h4>
<div style={{ display: "flex", gap: "4px", alignItems: "flex-end", height: "120px" }}>
{data.valeurs.map((v, i) => (
<div key={i} style={{ flex: 1, textAlign: "center" }}>
<div style={{
height: `${(v.valeur / Math.max(...data.valeurs.map(x => x.valeur))) * 100}px`,
background: "#3B82F6",
borderRadius: "4px 4px 0 0",
minHeight: "4px",
}} />
<span style={{ fontSize: "10px", color: "#94A3B8" }}>{v.label}</span>
</div>
))}
</div>
</div>
);
}
Points clés à retenir
- Les widgets affichent des données structurées visuellement dans le chat
- Enregistrez vos widgets dans le
ChatProvideravec un identifiant unique - Les tools retournent un objet
__widgetpour déclencher l’affichage - Les widgets interactifs utilisent
onActionpour communiquer avec l’agent - Combinez widgets et bibliothèques de graphiques pour des dashboards dans le chat