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 PDF 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'],
]);