Envoyer votre première requête
Une clé, l'URL de base d'Evanesca et le SDK d'OpenAI que vous utilisez déjà : une requête de chat, puis le streaming, le choix du modèle et les en-têtes qui disent où l'appel a tourné.
BientôtOuverture prochaine : ce qui suit décrit le service tel qu'il fonctionnera.
Créer une clé
Vous créez vos clés dans votre compte Evanesca, une fois le service ouvert. Elles commencent par sk-eva- ; la clé complète ne s'affiche qu'une fois, à sa création, puis seulement ses premiers caractères. Gardez-la côté serveur, dans une variable d'environnement — les exemples lisent EVANESCA_API_KEY (authentification).
# Votre clé commence par sk-eva-. Gardez-la côté serveur.
export EVANESCA_API_KEY="<votre clé>"Envoyer la requête
La même requête de quatre façons. Python et JavaScript passent par le SDK officiel d'OpenAI (pip install openai, npm install openai) : il n'y a pas de bibliothèque Evanesca à installer.
curl https://evanesca.app/api/v1/chat/completions \
-H "Authorization: Bearer $EVANESCA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gemma-4-26b",
"messages": [{"role": "user", "content": "Bonjour"}]
}'import os
from openai import OpenAI
client = OpenAI(
base_url="https://evanesca.app/api/v1",
api_key=os.environ["EVANESCA_API_KEY"],
)
answer = client.chat.completions.create(
model="gemma-4-26b",
messages=[{"role": "user", "content": "Bonjour"}],
)
print(answer.choices[0].message.content)import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://evanesca.app/api/v1",
apiKey: process.env.EVANESCA_API_KEY,
});
const answer = await client.chat.completions.create({
model: "gemma-4-26b",
messages: [{ role: "user", content: "Bonjour" }],
});
console.log(answer.choices[0].message.content);package main
import (
"fmt"
"io"
"net/http"
"os"
"strings"
)
func main() {
body := strings.NewReader(`{"model": "gemma-4-26b", "messages": [{"role": "user", "content": "Bonjour"}]}`)
req, err := http.NewRequest("POST", "https://evanesca.app/api/v1/chat/completions", body)
if err != nil {
panic(err)
}
req.Header.Set("Authorization", "Bearer "+os.Getenv("EVANESCA_API_KEY"))
req.Header.Set("Content-Type", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
out, _ := io.ReadAll(res.Body)
fmt.Println(res.Status, string(out))
}La réponse est un objet chat.completion standard. Son champ model porte le nom que l'opérateur donne au modèle qui a répondu ; son bloc usage est ce que votre crédit paie, au token près (tous les paramètres).
{
"id": "chatcmpl-…",
"object": "chat.completion",
"model": "…",
"choices": [
{
"index": 0,
"message": { "role": "assistant", "content": "…" },
"finish_reason": "stop"
}
],
"usage": { "prompt_tokens": 9, "completion_tokens": 12, "total_tokens": 21 }
}Streamer la réponse
Avec "stream": true, la réponse arrive en server-sent events : des lignes data: qui portent des fragments au format OpenAI, jusqu'à data: [DONE]. C'est le format d'OpenAI, donc les fonctions de streaming des SDK marchent telles quelles.
curl -N https://evanesca.app/api/v1/chat/completions \
-H "Authorization: Bearer $EVANESCA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gemma-4-26b",
"messages": [{"role": "user", "content": "Bonjour"}],
"stream": true
}'stream = client.chat.completions.create(
model="gemma-4-26b",
messages=[{"role": "user", "content": "Bonjour"}],
stream=True,
)
for chunk in stream:
if chunk.choices and chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="")const stream = await client.chat.completions.create({
model: "gemma-4-26b",
messages: [{ role: "user", content: "Bonjour" }],
stream: true,
});
for await (const chunk of stream) {
process.stdout.write(chunk.choices[0]?.delta?.content ?? "");
}Evanesca demande toujours l'usage à l'opérateur dans le flux (stream_options.include_usage) : le dernier fragment avant [DONE] porte l'objet usage et un tableau choices vide. C'est lui qui permet de facturer un appel en streaming au token près — attendez-vous à le voir si vous lisez le flux vous-même.
Choisir un modèle
Le champ model prend un identifiant du catalogue — gemma-4-26b dans ces exemples. GET /models renvoie la liste en JSON, sans clé ; elle mêle modèles de chat, d'embedding et d'image, et ?kind=chat ne garde que les premiers (la référence). Un identifiant qu'Evanesca ne sert pas répond 404 model_not_found.
curl https://evanesca.app/api/v1/models?kind=chatOù tourne chaque modèle, ce que garde chaque opérateur, quels modèles appellent des outils ou raisonnent avant de répondre : Modèles et Europe.
Lire où l'appel a tourné
Toute réponse de chat, d'embeddings ou d'images qui a atteint un opérateur, en streaming ou non, porte deux en-têtes :
| En-tête de réponse | Valeur |
|---|---|
x-evanesca-operator | L'opérateur qui a servi l'appel : mistral, aki, scaleway, ovhcloud ou infomaniak. |
x-evanesca-location | Où il a tourné : paris (Paris, France), gravelines (Gravelines, France), mistral-eu-region (Région UE de Mistral AI), germany (Allemagne) ou switzerland (Suisse). |
curl -i https://evanesca.app/api/v1/chat/completions \
-H "Authorization: Bearer $EVANESCA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model": "gemma-4-26b", "messages": [{"role": "user", "content": "Bonjour"}]}'HTTP/2 200
content-type: application/json
x-evanesca-operator: aki
x-evanesca-location: germany