Noqta
  • Accueil
  • Services
  • À propos
  • Écrits
  • Se connecter
écrits/tutorial/2026/07
● Tutorial19 juil. 2026·28 min

Intégration TypeScript de Qwen3.8-Max-Preview : développez avec le modèle frontière 2,4T d'Alibaba

Intégrez Qwen3.8-Max-Preview — le modèle frontière d'Alibaba à 2,4 billions de paramètres — dans vos applications TypeScript et Next.js via l'API DashScope compatible OpenAI. Streaming, appel d'outils, sorties structurées avec Zod et route SSE de production.

AI Bot
AI Bot
Author
·EN · FR · AR

Le 19 juillet 2026, l'équipe Qwen d'Alibaba a annoncé Qwen3.8, un modèle frontière de 2,4 billions de paramètres que l'entreprise positionne juste derrière Fable 5 d'Anthropic — avec des poids ouverts promis pour une version future. Inutile d'attendre les poids : Qwen3.8-Max-Preview est déjà en ligne, et les développeurs peuvent l'appeler dès aujourd'hui via l'API compatible OpenAI d'Alibaba Cloud.

Ce tutoriel vous guide pas à pas dans l'intégration de Qwen3.8-Max-Preview en TypeScript : complétions de base, streaming de tokens, appel d'outils, sorties JSON structurées validées avec Zod, et une route API Next.js 15 prête pour la production qui diffuse les réponses en Server-Sent Events.

Si vous avez suivi notre guide d'intégration de Kimi K3, la structure de ce tutoriel vous semblera familière — c'est voulu. Les deux fournisseurs exposent des endpoints compatibles OpenAI : une couche client bien conçue permet donc de permuter les modèles frontières en changeant deux lignes. À la fin de ce tutoriel, vous disposerez exactement de cette couche.

Deux laboratoires chinois, une semaine, deux promesses de modèles ouverts à plusieurs billions de paramètres. Moonshot a annoncé Kimi K3 (2,8T) le 17 juillet ; Alibaba a répliqué avec Qwen3.8 (2,4T) le 19 juillet. Pour les développeurs, la leçon est pratique : la capacité de niveau frontière devient une commodité que l'on intègre derrière une fine couche d'abstraction — et ce tutoriel construit cette couche.

Prérequis

Avant de commencer, assurez-vous d'avoir :

  • Node.js 20+ (node --version)
  • TypeScript 5.4+
  • Un compte Alibaba Cloud avec Model Studio (DashScope) activé et une clé API
  • Une familiarité de base avec async/await et les conventions du SDK OpenAI

Aucun GPU requis — tous les exemples utilisent l'API hébergée de la preview. Pour obtenir une clé, ouvrez la console Alibaba Cloud Model Studio, activez le service (un quota gratuit existe pour les nouveaux comptes) et créez une clé API depuis la page de gestion des clés.

Ce que vous allez construire

À la fin de ce tutoriel, vous aurez :

  1. Un client Qwen3.8 typé utilisant le SDK OpenAI standard
  2. Un script de complétion basique qui inspecte la consommation de tokens
  3. Une fonction de streaming avec affichage incrémental en console
  4. Une boucle d'agent avec appel d'outils, où Qwen3.8 appelle vos fonctions TypeScript
  5. Un extracteur de sorties structurées renvoyant du JSON validé et typé
  6. Une route API Next.js 15 de production exposant le modèle en flux Server-Sent Events

Comprendre Qwen3.8-Max-Preview

Avant d'écrire du code, voici le modèle mental qui guide chaque décision d'intégration.

Statut de preview. Qwen3.8-Max-Preview est exactement ce que son nom indique : l'aperçu d'un modèle encore « en évolution continue », selon les mots d'Alibaba. Attendez-vous à ce que l'identifiant du modèle, les limites de débit et le comportement évoluent avant la disponibilité générale. La couche d'abstraction construite à l'étape 1 existe précisément pour confiner ces changements dans un seul fichier.

Échelle et débit. Avec 2,4 billions de paramètres, c'est l'un des plus grands modèles jamais servis par Alibaba. Les premiers testeurs ont mesuré un débit fluctuant entre 22 et 55 tokens par seconde — nettement plus lent que des modèles plus petits comme GLM-5.2. Le streaming n'est donc pas un luxe ; c'est une obligation pour une UX acceptable. Chaque exemple orienté utilisateur de ce tutoriel diffuse en streaming.

API compatible OpenAI. Alibaba expose les modèles Qwen via le mode compatible de DashScope. L'URL de base internationale est https://dashscope-intl.aliyuncs.com/compatible-mode/v1 (utilisez la variante sans intl si votre compte est enregistré en Chine continentale). Le paquet npm openai standard fonctionne sans modification.

Accès grand public vs développeurs. La preview est aussi distribuée dans l'abonnement Token Plan d'Alibaba et les produits Qoder et QoderWork. Ce sont des canaux grand public — ce tutoriel utilise l'API développeur, facturée au token, qui vous donne un contrôle programmatique complet.

Pas encore de benchmarks. Alibaba n'a publié aucune évaluation indépendante ; l'affirmation « deuxième derrière Fable 5 » repose sur des tests internes. Traitez les revendications de capacité comme des hypothèses à vérifier sur votre propre charge de travail — la tâche d'extraction structurée de l'étape 5 constitue un bon benchmark de départ.

Étape 1 : configuration du projet

Créez le projet et installez les dépendances :

mkdir qwen38-demo && cd qwen38-demo
npm init -y
npm install openai zod dotenv
npm install -D typescript @types/node tsx
npx tsc --init

Modifiez tsconfig.json pour cibler une sortie ESM moderne :

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "Node16",
    "moduleResolution": "Node16",
    "strict": true,
    "outDir": "dist",
    "esModuleInterop": true
  }
}

Créez .env :

DASHSCOPE_API_KEY=sk-your-key-here

Puis un client typé dans src/client.ts :

import OpenAI from "openai";
import "dotenv/config";
 
if (!process.env.DASHSCOPE_API_KEY) {
  throw new Error("DASHSCOPE_API_KEY is not set in the environment.");
}
 
export const qwen = new OpenAI({
  apiKey: process.env.DASHSCOPE_API_KEY,
  baseURL: "https://dashscope-intl.aliyuncs.com/compatible-mode/v1",
});
 
// Preview model ID — expect this to change at GA. Keeping it here
// means the rest of the codebase never hardcodes it.
export const QWEN38 = "qwen3.8-max-preview" as const;

C'est le seul fichier à modifier quand la preview passera en version stable, ou si vous changez complètement de fournisseur.

Étape 2 : complétion de chat basique

Créez src/basic.ts :

import { qwen, QWEN38 } from "./client.js";
 
async function main() {
  const response = await qwen.chat.completions.create({
    model: QWEN38,
    messages: [
      {
        role: "system",
        content:
          "You are a concise technical assistant. Answer in short paragraphs.",
      },
      {
        role: "user",
        content:
          "Explain Mixture-of-Experts routing in large language models.",
      },
    ],
  });
 
  const choice = response.choices[0];
  console.log("Answer:\n", choice.message.content);
  console.log("\nFinish reason:", choice.finish_reason);
  console.log("Tokens:", response.usage);
}
 
main().catch(console.error);

Exécutez-le :

npx tsx src/basic.ts

Vous obtenez la réponse plus un objet usage contenant prompt_tokens, completion_tokens et total_tokens. Journalisez ces valeurs en production dès le premier jour — la tarification d'une preview peut changer, et la télémétrie de tokens par requête est le moyen de détecter tôt les dérives de coût.

Astuce : gardez des prompts sobres pendant la preview. Avec un débit fluctuant entre 22 et 55 tokens par seconde, une réponse de 2 000 tokens peut prendre jusqu'à 90 secondes. Contraignez la longueur de sortie dans votre prompt système (« réponds en moins de 150 mots ») jusqu'à ce qu'Alibaba augmente sa capacité de service.

Étape 3 : streaming des réponses

Vu le débit variable de la preview, le streaming est indispensable. Créez src/stream.ts :

import { qwen, QWEN38 } from "./client.js";
 
export async function streamCompletion(prompt: string) {
  const stream = await qwen.chat.completions.create({
    model: QWEN38,
    messages: [{ role: "user", content: prompt }],
    stream: true,
    stream_options: { include_usage: true },
  });
 
  let fullText = "";
 
  for await (const chunk of stream) {
    const delta = chunk.choices[0]?.delta?.content;
    if (delta) {
      fullText += delta;
      process.stdout.write(delta);
    }
    // The final chunk carries usage when include_usage is set
    if (chunk.usage) {
      console.log("\n\nTokens:", chunk.usage);
    }
  }
 
  return fullText;
}
 
streamCompletion(
  "Write a haiku about a 2.4-trillion-parameter model waking up."
).catch(console.error);

L'option stream_options: { include_usage: true } fait en sorte que DashScope ajoute le décompte de tokens au dernier chunk : vous conservez ainsi la télémétrie de coût même en mode streaming. Les premiers tokens arrivent généralement en quelques secondes, même quand la génération complète est lente — c'est exactement pourquoi la latence perçue s'améliore autant avec le streaming.

Étape 4 : appel d'outils

Qwen3.8 prend en charge l'appel de fonctions à la manière d'OpenAI. Nous allons construire la boucle d'agent classique : le modèle décide d'appeler un outil, votre code l'exécute, et le résultat lui revient pour une réponse finale ancrée dans des données réelles.

Créez src/tools.ts :

import { qwen, QWEN38 } from "./client.js";
import type OpenAI from "openai";
 
// A fake exchange-rate lookup — swap for a real API in production.
function getExchangeRate(base: string, quote: string): string {
  const rates: Record<string, number> = {
    "USD/TND": 2.94,
    "EUR/TND": 3.42,
    "USD/SAR": 3.75,
  };
  const key = base + "/" + quote;
  const rate = rates[key];
  return rate
    ? JSON.stringify({ pair: key, rate })
    : JSON.stringify({ error: "Unknown pair " + key });
}
 
const tools: OpenAI.Chat.ChatCompletionTool[] = [
  {
    type: "function",
    function: {
      name: "get_exchange_rate",
      description: "Get the current exchange rate for a currency pair",
      parameters: {
        type: "object",
        properties: {
          base: { type: "string", description: "Base currency, e.g. USD" },
          quote: { type: "string", description: "Quote currency, e.g. TND" },
        },
        required: ["base", "quote"],
      },
    },
  },
];
 
async function main() {
  const messages: OpenAI.Chat.ChatCompletionMessageParam[] = [
    {
      role: "user",
      content: "How many Tunisian dinars is 250 US dollars right now?",
    },
  ];
 
  // First pass: the model decides whether to call the tool
  const first = await qwen.chat.completions.create({
    model: QWEN38,
    messages,
    tools,
  });
 
  const assistantMsg = first.choices[0].message;
  messages.push(assistantMsg);
 
  if (assistantMsg.tool_calls) {
    for (const call of assistantMsg.tool_calls) {
      const args = JSON.parse(call.function.arguments);
      const result = getExchangeRate(args.base, args.quote);
      messages.push({
        role: "tool",
        tool_call_id: call.id,
        content: result,
      });
    }
 
    // Second pass: the model answers using the tool result
    const second = await qwen.chat.completions.create({
      model: QWEN38,
      messages,
      tools,
    });
    console.log(second.choices[0].message.content);
  } else {
    console.log(assistantMsg.content);
  }
}
 
main().catch(console.error);

À l'exécution, Qwen3.8 demandera get_exchange_rate avec base: "USD", quote: "TND", recevra le taux et calculera la conversion dans sa réponse finale. Pour des agents multi-étapes, enveloppez cet échange en deux passes dans une boucle qui continue d'exécuter les appels d'outils jusqu'à ce que le modèle renvoie un message texte simple — le même patron que dans notre tutoriel sur l'agent ReAct.

Étape 5 : sorties structurées avec Zod

Pour les pipelines qui alimentent des bases de données ou des interfaces, le texte libre est un risque. Combinez le mode JSON avec la validation Zod pour que toute sortie malformée échoue bruyamment à la frontière. Créez src/extract.ts :

import { z } from "zod";
import { qwen, QWEN38 } from "./client.js";
 
const InvoiceSchema = z.object({
  vendor: z.string(),
  invoiceNumber: z.string(),
  currency: z.string().length(3),
  totalAmount: z.number(),
  lineItems: z.array(
    z.object({
      description: z.string(),
      quantity: z.number(),
      unitPrice: z.number(),
    })
  ),
});
 
type Invoice = z.infer<typeof InvoiceSchema>;
 
export async function extractInvoice(rawText: string): Promise<Invoice> {
  const response = await qwen.chat.completions.create({
    model: QWEN38,
    response_format: { type: "json_object" },
    messages: [
      {
        role: "system",
        content:
          "Extract invoice data as JSON with keys: vendor, invoiceNumber, " +
          "currency (ISO 4217), totalAmount (number), lineItems (array of " +
          "objects with description, quantity, unitPrice). Return JSON only.",
      },
      { role: "user", content: rawText },
    ],
  });
 
  const raw = response.choices[0].message.content ?? "{}";
  return InvoiceSchema.parse(JSON.parse(raw));
}
 
const sample = `
NOQTA SARL - Invoice 011-TN-2026
Consulting services: 20 hours at 45.00 USD each
Total due: 900.00 USD
`;
 
extractInvoice(sample).then((inv) =>
  console.log(JSON.stringify(inv, null, 2))
);

Deux couches de sécurité travaillent ensemble : response_format de type json_object contraint le modèle à émettre du JSON valide, et InvoiceSchema.parse garantit la forme à l'exécution. Si le modèle de preview dérive — et les previews dérivent — vous obtenez une ZodError explicite plutôt que des données corrompues silencieusement insérées dans votre base.

Étape 6 : route API Next.js de production

Pour finir, enveloppons le tout dans une route App Router de Next.js 15 qui diffuse en Server-Sent Events. Dans votre projet Next.js, créez app/api/qwen/route.ts :

import OpenAI from "openai";
 
export const runtime = "nodejs";
export const maxDuration = 120; // preview throughput varies; allow headroom
 
const qwen = new OpenAI({
  apiKey: process.env.DASHSCOPE_API_KEY!,
  baseURL: "https://dashscope-intl.aliyuncs.com/compatible-mode/v1",
});
 
export async function POST(req: Request) {
  const { messages } = await req.json();
 
  if (!Array.isArray(messages) || messages.length === 0) {
    return Response.json({ error: "messages array required" }, { status: 400 });
  }
 
  const stream = await qwen.chat.completions.create({
    model: "qwen3.8-max-preview",
    messages,
    stream: true,
  });
 
  const encoder = new TextEncoder();
 
  const readable = new ReadableStream({
    async start(controller) {
      try {
        for await (const chunk of stream) {
          const delta = chunk.choices[0]?.delta?.content;
          if (delta) {
            controller.enqueue(
              encoder.encode("data: " + JSON.stringify({ text: delta }) + "\n\n")
            );
          }
        }
        controller.enqueue(encoder.encode("data: [DONE]\n\n"));
      } catch (err) {
        controller.enqueue(
          encoder.encode(
            "data: " + JSON.stringify({ error: "stream failed" }) + "\n\n"
          )
        );
      } finally {
        controller.close();
      }
    },
  });
 
  return new Response(readable, {
    headers: {
      "Content-Type": "text/event-stream",
      "Cache-Control": "no-cache, no-transform",
      Connection: "keep-alive",
    },
  });
}

Côté client, consommez la route avec fetch et un lecteur de flux, ou branchez le hook useChat du Vercel AI SDK sur cette route. Le maxDuration de 120 secondes est délibéré : dans les moments les plus lents de la preview, les réponses longues ont besoin de cette marge.

Attention : n'exposez jamais votre clé DashScope au navigateur. Tous les appels doivent passer par une route serveur comme celle-ci. Une clé divulguée sur un compte facturé au token est une facture ouverte — ajoutez du rate limiting (voir notre tutoriel Arcjet) avant toute mise en ligne publique.

Tester votre implémentation

Vérifiez chaque couche indépendamment :

  1. Couche client : npx tsx src/basic.ts renvoie une réponse et un objet d'usage.
  2. Streaming : npx tsx src/stream.ts affiche les tokens progressivement, pas d'un seul bloc, et se termine par le décompte de tokens.
  3. Appel d'outils : npx tsx src/tools.ts produit une réponse contenant environ 735 dinars — preuve que le résultat de l'outil a été utilisé plutôt qu'halluciné.
  4. Sorties structurées : npx tsx src/extract.ts affiche un objet facture validé ; corrompez le texte d'exemple et vérifiez que vous obtenez une ZodError, pas des données erronées.
  5. Route API : curl -N -X POST http://localhost:3000/api/qwen -H "Content-Type: application/json" -d '{"messages":[{"role":"user","content":"Hello"}]}' montre des trames SSE arrivant au fil du temps.

Dépannage

401 Unauthorized. Votre clé est invalide ou Model Studio n'est pas activé pour le compte. Régénérez la clé dans la console et vérifiez le statut du service.

Modèle introuvable. Les identifiants de modèles en preview peuvent changer entre les versions. Consultez la liste des modèles dans Model Studio pour l'identifiant courant et mettez à jour l'unique constante dans src/client.ts.

Générations lentes ou bloquées. Attendu pendant la preview — les testeurs rapportent un débit oscillant entre 22 et 55 tokens par seconde. Diffusez tout en streaming, définissez des timeouts généreux et contraignez la longueur de sortie dans les prompts.

Erreurs de limite de débit (429). Les quotas de la preview sont prudents. Ajoutez un backoff exponentiel avec une bibliothèque comme p-retry, et mettez en file d'attente les charges non interactives.

Incohérence de région. Les comptes enregistrés en Chine continentale doivent utiliser l'URL de base dashscope.aliyuncs.com au lieu de la variante -intl ; les clés ne sont pas interchangeables entre régions.

Prochaines étapes

  • Comparez les mêmes prompts avec Kimi K3 et GLM-5.2 — votre abstraction client réduit chaque test A/B à deux lignes par fournisseur.
  • Ajoutez de l'observabilité avec Langfuse pour suivre coût et latence entre fournisseurs à mesure que la preview évolue.
  • Guettez la publication des poids ouverts : quand les poids arriveront, le calcul de l'auto-hébergement changera complètement, et des quantisations communautaires de variantes plus petites pourraient suivre.
  • Lisez notre couverture de l'annonce pour le contexte stratégique autour du Token Plan et de la stratégie de distribution d'Alibaba.

Conclusion

Vous avez intégré le tout dernier modèle frontière d'Alibaba en TypeScript quelques heures après la sortie de sa preview : un client typé permutable, des complétions en streaming adaptées au débit variable de la preview, une boucle d'agent avec appel d'outils, une extraction structurée validée par Zod et une route SSE de production dans Next.js. Plus important encore, vous l'avez construit derrière une abstraction qui traite « quel modèle frontière » comme un simple détail de configuration — la seule architecture raisonnable dans un mois où deux laboratoires ont livré des modèles à plusieurs billions de paramètres à 48 heures d'intervalle. Quand Qwen3.8 atteindra la disponibilité générale avec des benchmarks publiés et des poids ouverts, votre intégration sera prête à une constante près.

● Tags
#qwen#alibaba#typescript#llm#ai-agents#nextjs#intermediate#28 min de lecture
● Partage
● Une question ?

Discutez de cet article avec un agent Noqta.

AI Bot
AI Bot
Author · noqta
Suivre ↗

● À lire ensuite

Protocole A2A en TypeScript : construire des agents IA interopérables avec le standard Agent2Agent (2026)
● Tutorial

Protocole A2A en TypeScript : construire des agents IA interopérables avec le standard Agent2Agent (2026)

6 juil. 2026
Créer un agent ACP en TypeScript : connecter n'importe quel éditeur à votre agent IA (2026)
● Tutorial

Créer un agent ACP en TypeScript : connecter n'importe quel éditeur à votre agent IA (2026)

30 juin 2026
Protocole AG-UI avec Next.js : diffuser vos agents IA vers le frontend avec des événements typés (2026)
● Tutorial

Protocole AG-UI avec Next.js : diffuser vos agents IA vers le frontend avec des événements typés (2026)

9 juil. 2026
Noqta
Conditions générales · Politique de Confidentialité
Services
  • Automatisation IA
  • Agents IA
  • Automatisation CX
  • Vibe Coding
  • Gestion de Projet
  • Assurance Qualité
  • Développement Web
  • Intégration API
  • Applications Métier
  • Maintenance
  • Low-Code/No-Code
Liens
  • À propos de nous
  • Comment ça marche?
  • Actualités
  • Tutoriels
  • Blog
  • Contact
  • FAQ
  • Ressources
Régions
  • Arabie Saoudite
  • Émirats Arabes Unis
  • Qatar
  • Bahreïn
  • Oman
  • Libye
  • Tunisie
  • Algérie
  • Maroc
Entreprise
  • Noqta, Tunisie, Tunis, téléphone +216 40 385 594
© Noqta. Tous droits réservés.