Aller au contenu
TukaiDevelopers

Rechercher dans la documentation

Console
Sommaire de la documentation

Exemples

Brouillons de réponse à des messages clients

Un petit script qui propose une réponse courte, en français, en derja ou en anglais, à des messages clients — toujours relue par un humain avant envoi.

Vérifié le 4 octobre 2026Version MarkdownSignaler une erreur sur cette page

Ce que fait la recette : pour chaque message d'un fichier, elle demande au modèle un brouillon de réponse de trois phrases au plus, dans la langue choisie, et l'imprime. Rien n'est envoyé à un client : une personne relit chaque brouillon.

Ce qu'il vous faut : Node.js 20 ou plus récent, une clé tuk_sk_ (voir Premier appel) et un compte avec des crédits.

Coût : une génération par message. Le mode à blanc et la vérification sont gratuits.

Les fichiers

Messages d'exemple, fictifs :

messages.json
[
  {
    "id": "M1",
    "langue_reponse": "fr",
    "texte": "Bonjour, j'ai commandé une table la semaine dernière et je n'ai pas encore reçu de date de livraison. Pouvez-vous me tenir informé ?"
  },
  {
    "id": "M2",
    "langue_reponse": "ar",
    "texte": "عسلامة، نحب نعرف كان عندكم الكرسي هذا باللون الأخضر؟"
  },
  {
    "id": "M3",
    "langue_reponse": "en",
    "texte": "Hello, can I change the delivery address of my order before it ships?"
  }
]

Le script :

repondre.mjs
// Brouillons de réponse à des messages clients, à relire par un humain avant tout envoi.
//
//   node repondre.mjs --a-blanc   affiche les requêtes sans rien envoyer (gratuit)
//   node repondre.mjs             envoie une requête par message (payant)
//
// Aucun message n'est envoyé à un client : le script imprime des brouillons.
import { readFileSync } from "node:fs";
import OpenAI from "openai";

const URL_DE_BASE = process.env.TUKAI_BASE_URL ?? "https://chat.tuk-ai.com/v1";
const MODELE = process.env.TUKAI_MODELE ?? "chat-aion-labs-aion-3-0-mini";
const LANGUES = {
  fr: "français",
  ar: "arabe tunisien (derja), en écriture arabe",
  en: "anglais",
};
const aBlanc = process.argv.includes("--a-blanc");

const messages = JSON.parse(
  readFileSync(new URL("./messages.json", import.meta.url), "utf8"),
);

function requete(message) {
  const langue = LANGUES[message.langue_reponse];
  if (!langue) throw new Error(`Langue inconnue : ${message.langue_reponse}`);
  return {
    model: MODELE,
    max_tokens: 200,
    messages: [
      {
        role: "system",
        content:
          `Tu rédiges un brouillon de réponse courte (3 phrases au plus) au message d'un client, en ${langue}. ` +
          "Ton poli et précis. N'invente ni prix, ni délai, ni engagement : si l'information manque, propose de vérifier.",
      },
      { role: "user", content: message.texte },
    ],
  };
}

if (aBlanc) {
  for (const m of messages) console.log(JSON.stringify(requete(m), null, 2));
  console.log(`\n${messages.length} requête(s) préparée(s), aucune envoyée.`);
  process.exit(0);
}

if (!process.env.TUKAI_API_KEY) {
  console.error("TUKAI_API_KEY est vide. Voir README.md, étape 2.");
  process.exit(1);
}

const client = new OpenAI({
  baseURL: URL_DE_BASE,
  apiKey: process.env.TUKAI_API_KEY,
});

for (const m of messages) {
  try {
    const { data, response } = await client.chat.completions
      .create(requete(m))
      .withResponse();
    console.log(`\n— Message ${m.id} (${m.langue_reponse})\n${m.texte}`);
    console.log(`\nBrouillon à relire :\n${data.choices[0].message.content}`);
    console.log(`(x-request-id : ${response.headers.get("x-request-id")})`);
  } catch (erreur) {
    // Pas de nouvelle tentative automatique : relancer une génération réussie la facture deux fois.
    console.error(
      `\nMessage ${m.id} : échec ${erreur.status ?? ""} ${erreur.error?.type ?? erreur.message}`,
    );
    if (erreur.status === 402) {
      console.error(
        "Solde insuffisant : rechargez sur https://chat.tuk-ai.com/pay/checkout puis relancez.",
      );
      process.exit(1);
    }
  }
}

Configuration (à copier en .env ou à exporter dans le terminal, jamais à versionner) :

.env.example
# Copiez ce fichier en .env (non versionné) ou exportez ces variables dans votre terminal.
# La clé se crée dans https://chat.tuk-ai.com (réglages, onglet API keys) ; ne la versionnez jamais.
TUKAI_API_KEY=
# Facultatif : un modèle coché sur votre clé (identifiants : https://developers.tuk-ai.com/models)
TUKAI_MODELE=chat-aion-labs-aion-3-0-mini

Dépendance :

package.json
{
  "name": "tukai-exemple-assistant-messages",
  "private": true,
  "type": "module",
  "description": "Brouillons de réponse à des messages clients avec l'API Tukai, relus par un humain.",
  "engines": {
    "node": ">=20"
  },
  "scripts": {
    "a-blanc": "node repondre.mjs --a-blanc",
    "verifier": "node verifier.mjs",
    "repondre": "node repondre.mjs"
  },
  "dependencies": {
    "openai": "^7.27.0"
  }
}

Lancer

  1. Créez un dossier, copiez-y les quatre fichiers, puis npm install.
  2. Exportez TUKAI_API_KEY (voir Premier appel).
  3. npm run a-blanc : affiche les requêtes, n'envoie rien.
  4. npm run verifier : vérifie que la clé est définie (sans l'afficher) et que le modèle figure au catalogue, sans générer. Il ne vérifie pas que le modèle est coché sur la clé.
  5. npm run repondre : génère les brouillons.
verifier.mjs
// Vérification gratuite : configuration, modèle présent au catalogue, URL de base joignable.
// N'envoie aucune requête de génération et n'affiche jamais la clé.
import OpenAI from "openai";

const URL_DE_BASE = process.env.TUKAI_BASE_URL ?? "https://chat.tuk-ai.com/v1";
const MODELE = process.env.TUKAI_MODELE ?? "chat-aion-labs-aion-3-0-mini";
let ok = true;

console.log(
  process.env.TUKAI_API_KEY?.startsWith("tuk_sk_")
    ? "✓ TUKAI_API_KEY est définie"
    : "✗ TUKAI_API_KEY absente ou ne commence pas par tuk_sk_",
);
if (!process.env.TUKAI_API_KEY?.startsWith("tuk_sk_")) ok = false;

// Le catalogue est public : la liste se lit sans clé, donc sans coût.
const client = new OpenAI({
  baseURL: URL_DE_BASE,
  apiKey: process.env.TUKAI_API_KEY || "non-utilisee",
});
const ids = [];
for await (const m of client.models.list()) ids.push(m.id);
console.log(
  `✓ ${URL_DE_BASE}/models répond (${ids.length} modèles au catalogue)`,
);
if (ids.includes(MODELE))
  console.log(
    `✓ ${MODELE} est au catalogue (vérifiez qu'il est coché sur votre clé)`,
  );
else {
  console.log(`✗ ${MODELE} n'est pas au catalogue`);
  ok = false;
}
process.exit(ok ? 0 : 1);

Résultat attendu

Pour chaque message : le texte d'origine, un brouillon de réponse, et l'identifiant x-request-id de l'appel. Le texte généré varie d'un appel à l'autre.

Limites

  • La qualité de la derja dépend du modèle choisi et n'est pas garantie : faites relire par un locuteur avant tout usage réel. Le message en derja de l'exemple est lui-même un texte d'exemple non relu.
  • Le script ne fait aucune nouvelle tentative automatique : relancer une génération réussie la facture deux fois.
  • Les vrais messages de vos clients contiennent des données personnelles : lisez la section Données de Mise en production avant de les envoyer.