Intelligence artificielle
1Introduction
Temma propose une source de données unifiée \Temma\Datasources\Ai pour interroger des modèles de langage (LLM) de différents fournisseurs à travers une interface unique.
Cette source de données supporte :
- L'échange de texte (prompt / réponse)
- Les prompts système et la configuration de la température
- Les conversations multi-tours (historique des échanges)
- Les pièces jointes en entrée (images, audio, vidéo, PDF)
- La sortie structurée en JSON
Six providers sont intégrés (OpenAI, Claude, Gemini, Mistral, OpenRouter, Ollama), et tout service compatible avec l'API OpenAI peut être utilisé via la syntaxe à crochets.
Pour la documentation de référence de la source de données, voir la page de la source de données AI.
2Configuration
2.1Format du DSN
Le DSN (Data Source Name) de connexion s'écrit de la forme :
ai://PROVIDER/MODÈLE#CLÉ_API
- PROVIDER : nom du fournisseur (voir la liste ci-dessous).
- MODÈLE : identifiant du modèle de langage. Peut contenir des / et des :.
- CLÉ_API : votre clé d'API (optionnelle pour certains providers comme Ollama).
2.2Exemple de configuration
Dans le fichier etc/temma.php :
<?php
return [
'application' => [
'dataSources' => [
// connexion à OpenAI
'ai' => 'ai://openai/gpt-4o#sk-proj-xxxxxxxxxxxxx',
// ou à Claude
'ai' => 'ai://claude/claude-sonnet-4-20250514#sk-ant-xxxxxxxxxxxxx',
// ou à un modèle local via Ollama
'ai' => 'ai://ollama/llama3:70b',
],
],
];
3Providers intégrés
3.1Tableau récapitulatif
| Provider | Texte | Images | Audio | Vidéo | JSON | |
|---|---|---|---|---|---|---|
| openai | oui | oui | oui | oui | ||
| claude | oui | oui | oui | oui | ||
| gemini | oui | oui | oui | oui | oui | oui |
| mistral | oui | oui | oui | oui | oui | |
| openrouter | oui | oui | oui | oui | oui | |
| ollama | oui | oui | oui |
Le support effectif dépend aussi du modèle utilisé. Par exemple, tous les modèles OpenAI ne supportent pas la vision.
3.2Exemples de DSN
# OpenAI
ai://openai/gpt-4o#sk-proj-XXX
# Claude (Anthropic)
ai://claude/claude-sonnet-4-20250514#sk-ant-XXX
# Google Gemini
ai://gemini/gemini-2.5-flash#AIza-XXX
# Mistral
ai://mistral/mistral-small-latest#XXX
# OpenRouter (le modèle contient un "/" séparant le fournisseur du modèle)
ai://openrouter/openai/gpt-4o#sk-or-XXX
ai://openrouter/anthropic/claude-sonnet-4#sk-or-XXX
# Ollama (local, sans clé API)
ai://ollama/llama3:70b
ai://ollama/mistral:latest
4Services compatibles OpenAI
4.1Syntaxe à crochets (URL)
De nombreux services proposent une API compatible avec celle d'OpenAI. Pour les utiliser, il suffit de placer l'URL de l'endpoint entre crochets dans le DSN :
ai://[URL_ENDPOINT]/MODÈLE#CLÉ_API
Quelques services courants :
| Service | URL de l'endpoint |
|---|---|
| Groq | https://api.groq.com/openai/v1/chat/completions |
| Together AI | https://api.together.xyz/v1/chat/completions |
| Fireworks AI | https://api.fireworks.ai/inference/v1/chat/completions |
| DeepInfra | https://api.deepinfra.com/v1/openai/chat/completions |
Exemples :
# Groq
ai://[https://api.groq.com/openai/v1/chat/completions]/llama-3.3-70b#gsk-XXX
# Together AI (modèle avec "/" dans le nom)
ai://[https://api.together.xyz/v1/chat/completions]/meta-llama/Meta-Llama-3-70B#XXX
# LiteLLM auto-hébergé
ai://[https://my-litellm.internal/v1/chat/completions]/model#key
4.2Providers personnalisés
Il est aussi possible de fournir le nom d'une classe PHP entre crochets. Cette classe sera instanciée et utilisée comme provider :
ai://[\App\MyProvider]/model#key
La classe doit implémenter les méthodes buildPayload() et parseResponse(), comme les providers intégrés (voir les classes dans \Temma\Datasources\Ai\*).
5Utilisation
5.1Accès de type tableau
La notation tableau envoie un prompt et retourne la réponse sous forme de texte brut.
$response = $this->ai['Quelle est la capitale de la France ?'];
// $response contient "La capitale de la France est Paris."
5.2Méthode read()
La méthode read() retourne une réponse texte brute. Le deuxième paramètre est une valeur par défaut (scalaire ou callback) utilisée en cas d'erreur. Le troisième paramètre est un tableau d'options.
// prompt simple
$response = $this->ai->read('Quelle est la capitale de la France ?');
// avec une valeur par défaut
$response = $this->ai->read('Traduis en anglais : Bonjour', 'Hello');
// avec un callback en cas d'erreur
$response = $this->ai->read('Traduis en anglais : Bonjour', function() {
return 'Valeur de remplacement';
});
// avec des options
$response = $this->ai->read('Explique la photosynthèse', null, [
'system' => 'Tu es un professeur de biologie.',
'temperature' => 0.3,
]);
5.3Méthode get()
La méthode get() active automatiquement le mode JSON : le LLM est instruit de répondre en JSON valide, et la réponse est automatiquement décodée en tableau PHP.
// demande des données structurées
$data = $this->ai->get('Liste les 3 plus grandes villes de France avec leur population');
// $data contient un tableau PHP, par exemple :
// [
// ['ville' => 'Paris', 'population' => 2161000],
// ['ville' => 'Marseille', 'population' => 873076],
// ['ville' => 'Lyon', 'population' => 522250],
// ]
// avec des options
$recette = $this->ai->get("Crée une recette à partir de : œufs, tomates, fromage", null, [
'system' => "Tu es un chef cuisinier. Retourne un JSON avec les clés : titre, difficulte (1-5), ingredients (liste), etapes (liste).",
]);
6Options
Les méthodes read() et get() acceptent un troisième paramètre $options, un tableau associatif :
- system : (string) Prompt système définissant le comportement de l'assistant.
- messages : (array) Historique des messages précédents pour une conversation multi-tours (voir plus bas).
- temperature : (float) Température d'échantillonnage, entre 0 et 2. Les valeurs basses rendent les réponses plus déterministes, les valeurs hautes plus créatives.
- max_tokens : (int) Nombre maximal de tokens dans la réponse.
- attachments : (array) Pièces jointes à envoyer avec le prompt (voir la section suivante).
- output : (string) Format de sortie souhaité. Peut être un alias ('json', 'csv', 'audio', 'image', 'pdf', 'video', 'html', 'xml', 'wav') ou un type MIME complet ('application/json', 'audio/ogg', etc.).
Exemple complet :
$response = $this->ai->read('Décris cette image en détail', null, [
'system' => "Tu es un expert en analyse d'images.",
'temperature' => 0.5,
'max_tokens' => 1000,
'attachments' => ['/path/to/photo.jpg'],
]);
7Pièces jointes
7.1Formats acceptés
L'option attachments accepte un tableau de pièces jointes. Chaque élément peut être :
- Une chaîne de caractères : chemin vers un fichier (si file_exists() retourne true) ou contenu binaire. Le type MIME est détecté automatiquement.
-
Un tableau associatif avec les clés :
- path : chemin vers un fichier.
- data : contenu binaire.
- mime : (optionnel) type MIME explicite.
Exemples :
// chemin vers un fichier (MIME auto-détecté)
'attachments' => ['/path/to/photo.jpg']
// contenu binaire (MIME auto-détecté)
'attachments' => [$binaryContent]
// binaire avec MIME explicite
'attachments' => [
['data' => $binaryContent, 'mime' => 'image/png'],
]
// fichier avec MIME explicite
'attachments' => [
['path' => '/path/to/document.pdf', 'mime' => 'application/pdf'],
]
// plusieurs pièces jointes
'attachments' => [
'/path/to/image1.jpg',
['data' => $pdfContent, 'mime' => 'application/pdf'],
]
7.2Type MIME
Si le type MIME n'est pas fourni explicitement, il est détecté automatiquement via finfo. Lorsque vous avez le contenu binaire en mémoire, il est recommandé de fournir le MIME explicitement pour éviter une détection inutile.
Le support des pièces jointes dépend du provider et du modèle utilisé (voir le tableau récapitulatif ci-dessus). Si un type de pièce jointe n'est pas supporté par le provider, il sera ignoré.
8Sortie JSON
Deux approches pour obtenir du JSON structuré :
Méthode get() : active automatiquement le mode JSON. Le LLM reçoit une instruction système lui demandant de répondre en JSON valide. La réponse est automatiquement décodée en tableau PHP.
$data = $this->ai->get('Les 5 langages de programmation les plus populaires');
// $data est un tableau PHP
Méthode read() avec l'option output : permet de demander du JSON tout en utilisant read(). La réponse reste une chaîne JSON brute (non décodée).
$json = $this->ai->read('Les 5 langages les plus populaires', null, [
'output' => 'json',
]);
// $json est une chaîne JSON brute
$data = json_decode($json, true);
9Conversation multi-tours
L'option messages permet de fournir l'historique des échanges précédents. Chaque message est un tableau associatif avec une clé user ou ai :
$response = $this->ai->read('Et celle de l\'Italie ?', null, [
'system' => 'Tu es un assistant géographique.',
'messages' => [
['user' => 'Quelle est la capitale de la France ?'],
['ai' => 'La capitale de la France est Paris.'],
],
]);
// $response contient "La capitale de l'Italie est Rome."
Les messages d'historique peuvent aussi contenir des pièces jointes :
$response = $this->ai->read('Et celle-ci ?', null, [
'messages' => [
['user' => 'Décris cette image', 'attachments' => ['/path/to/photo1.jpg']],
['ai' => "C'est un chat roux assis sur un canapé."],
],
'attachments' => ['/path/to/photo2.jpg'],
]);