Introduction
Azure OpenAI Service est la version managée d'OpenAI sur Azure, offrant une scalabilité entreprise, conformité RGPD, sécurité avancée et quotas dédiés. Contrairement à l'API OpenAI publique, Azure permet des déploiements privés, monitoring via Azure Monitor et intégration native avec Azure AI Search pour RAG (Retrieval-Augmented Generation).
Ce tutoriel avancé cible les développeurs seniors : nous couvrons le déploiement CLI, l'API SDK Node.js pour chat streaming, tool calling (exécution de fonctions), embeddings et indexation vectorielle. Imaginez une app qui interroge une base de connaissances en temps réel – c'est ce que nous construisons.
Pourquoi 2026 ? Les modèles GPT-4o-mini et o1-preview dominent, avec support natif pour agents multi-outils. À la fin, vous aurez un projet complet, bookmarquable, avec 100% de code fonctionnel. Durée estimée : 2h pour implémenter.
Prérequis
- Compte Azure gratuit (crédit 200$ offert)
- Azure CLI 2.60+ installée
- Node.js 20+ et npm
- Connaissances avancées en TypeScript et async/await
- VS Code avec extensions Azure et TypeScript
- Accès admin à un subscription Azure (pour créer des ressources)
Installation Azure CLI et login
#!/bin/bash
# Installer Azure CLI si pas présent (macOS/Linux)
curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
# Login interactif
az login
# Définir subscription par défaut (remplacez YOUR_SUB_ID)
# az account list --output table
az account set --subscription "YOUR_SUBSCRIPTION_ID"
# Vérifier
az account show --query name -o tsvCe script installe Azure CLI, connecte votre compte et sélectionne la subscription. Remplacez YOUR_SUBSCRIPTION_ID par votre ID réel (obtenu via az account list). Piège : sans login, toutes les commandes échouent avec 401 Unauthorized.
Création de la ressource Azure OpenAI
Nous créons une ressource OpenAI dans le groupe de ressources learni-openai-rg. Utilisez un emplacement proche (ex: francecentral) pour minimiser la latence. La ressource est provisionnée en 5-10 min.
Créer ressource et déploiement GPT-4o
#!/bin/bash
RESOURCE_GROUP="learni-openai-rg"
LOCATION="francecentral"
RESOURCE_NAME="learni-openai-$(date +%s)"
# Créer groupe de ressources
az group create --name $RESOURCE_GROUP --location $LOCATION
# Créer ressource OpenAI (S0 pour prod, quota 1000 RPM)
az cognitiveservices account create \
--name $RESOURCE_NAME \
--resource-group $RESOURCE_GROUP \
--kind OpenAI \
--sku S0 \
--location $LOCATION
# Récupérer endpoint et clé
ENDPOINT=$(az cognitiveservices account show --name $RESOURCE_NAME --resource-group $RESOURCE_GROUP --query properties.endpoint -o tsv)
KEY=$(az cognitiveservices account keys list --name $RESOURCE_NAME --resource-group $RESOURCE_GROUP --query key1 -o tsv)
echo "Endpoint: $ENDPOINT"
echo "Key: $KEY"
# Déployer GPT-4o-mini (économique, rapide)
az cognitiveservices account deployment create \
--name $RESOURCE_NAME \
--resource-group $RESOURCE_GROUP \
--deployment-name gpt-4o-mini \
--model-name gpt-4o-mini \
--model-version 2024-07-18 \
--model-format ChatCompletion \
--sku-capacity 1Crée la ressource, récupère endpoint/clé (stockez en secret manager prod), et déploie GPT-4o-mini. Utilisez gpt-4o pour plus de puissance. Piège : SKU F0 est gratuit mais limité ; S0 pour advanced. Vérifiez quotas via Portal.
Installation du SDK Node.js
Utilisez @azure/openai officiel, plus sûr que openai car gère les proxies Azure. Créez un projet Node.js avec dotenv pour les secrets.
Initialiser projet et installer dépendances
#!/bin/bash
mkdir azure-openai-app && cd azure-openai-app
npm init -y
npm install @azure/openai dotenv typescript @types/node ts-node
npm install -D @types/node
cat > .env << EOF
AZURE_OPENAI_ENDPOINT=https://YOUR_RESOURCE.openai.azure.com/
AZURE_OPENAI_KEY=your_key_here
AZURE_OPENAI_DEPLOYMENT=gpt-4o-mini
EOF
cat > tsconfig.json << 'EOF'
{
"compilerOptions": {
"target": "ES2022",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"strict": true,
"esModuleInterop": true
}
}
EOFInitialise le projet avec SDK Azure OpenAI et config TS stricte. Copiez endpoint/clé de l'étape précédente dans .env. Piège : Oubliez dotenv.config() et les vars sont undefined, causant 401.
Client basique pour chat completions
import { AzureOpenAI } from '@azure/openai';
import dotenv from 'dotenv';
dotenv.config();
const client = new AzureOpenAI({
endpoint: process.env.AZURE_OPENAI_ENDPOINT!,
apiKey: process.env.AZURE_OPENAI_KEY!,
apiVersion: '2024-10-21',
});
async function chatBasic() {
const response = await client.getChatCompletions(
process.env.AZURE_OPENAI_DEPLOYMENT!,
[
{ role: 'system', content: 'Tu es un expert Azure.' },
{ role: 'user', content: 'Explique tool calling en 3 points.' },
],
{
temperature: 0.7,
maxTokens: 500,
}
);
console.log(response.choice[0]?.message?.content);
}
chatBasic().catch(console.error);Crée un client AzureOpenAI et envoie un chat simple. apiVersion est critique pour features 2026. Piège : Sans deployment exact, erreur 404. Exécutez avec npx ts-node chat-basic.ts.
Streaming et tool calling avancés
Passons au streaming pour UX réactive, puis tool calling pour exécuter du code réel (ex: requête API météo). Analogie : streaming comme un flux Netflix vs vidéo complète.
Chat avec streaming et tools
import { AzureOpenAI } from '@azure/openai';
import dotenv from 'dotenv';
dotenv.config();
const client = new AzureOpenAI({
endpoint: process.env.AZURE_OPENAI_ENDPOINT!,
apiKey: process.env.AZURE_OPENAI_KEY!,
apiVersion: '2024-10-21',
});
// Tool exemple: fonction météo mock
const tools = [
{
type: 'function',
function: {
name: 'get_weather',
description: 'Obtenir la météo pour une ville',
parameters: {
type: 'object',
properties: {
city: { type: 'string' },
},
required: ['city'],
},
},
},
];
function getWeather(city: string): string {
return `Météo à ${city}: 22°C, ensoleillé.`;
}
async function chatStreamTools() {
const stream = await client.getChatCompletionsStream(
process.env.AZURE_OPENAI_DEPLOYMENT!,
[{ role: 'user', content: 'Quelle est la météo à Paris ?' }],
{ tools, temperature: 0 }
);
let toolCalls: any[] = [];
for await (const event of stream) {
const delta = event.choice[0]?.delta;
if (delta?.toolCalls) {
toolCalls.push(...delta.toolCalls);
} else if (delta?.content) {
process.stdout.write(delta.content);
}
}
// Exécuter tools si appelés
for (const toolCall of toolCalls) {
if (toolCall.function.name === 'get_weather') {
const args = JSON.parse(toolCall.function.arguments);
const result = getWeather(args.city);
console.log(`\nRésultat tool: ${result}`);
}
}
}
chatStreamTools().catch(console.error);Streaming via getChatCompletionsStream pour réponses incrémentales ; tool calling parse et exécute fonctions. Implémentez auth réelle pour tools prod. Piège : Gérer delta correctement, sinon tools ignorés.
Embeddings et vector search avec AI Search
Pour RAG : générez embeddings, indexez dans Azure AI Search, query vectorielle. Nécessite une ressource Search (créez-la via CLI).
Créer AI Search et embeddings
#!/bin/bash
RESOURCE_GROUP="learni-openai-rg"
SEARCH_NAME="learni-search-$(date +%s)"
LOCATION="francecentral"
# Créer AI Search (Basic pour test)
az search service create --name $SEARCH_NAME --resource-group $RESOURCE_GROUP --sku Basic --location $LOCATION
SEARCH_ENDPOINT=$(az search service show --name $SEARCH_NAME --resource-group $RESOURCE_GROUP --query "hostingConfiguration.publicNetworkAccess" -o tsv | grep -o 'https[^ ]*')
SEARCH_KEY=$(az search admin-key show --service-name $SEARCH_NAME --resource-group $RESOURCE_GROUP --query primaryKey -o tsv)
echo "Search Endpoint: $SEARCH_ENDPOINT"
echo "Search Key: $SEARCH_KEY"
# Ajouter à .env
cat >> .env << EOF
AZURE_SEARCH_ENDPOINT=$SEARCH_ENDPOINT
AZURE_SEARCH_KEY=$SEARCH_KEY
EOFCrée Azure AI Search pour index vectoriel. Basic SKU suffit pour dev. Piège : Clé admin vs query key ; utilisez queryKey pour app.
Générer embeddings et query RAG
import { AzureOpenAI } from '@azure/openai';
import dotenv from 'dotenv';
import { SearchClient, AzureKeyCredential, VectorizedSearchOptions } from '@azure/search-documents';
dotenv.config();
const openai = new AzureOpenAI({
endpoint: process.env.AZURE_OPENAI_ENDPOINT!,
apiKey: process.env.AZURE_OPENAI_KEY!,
apiVersion: '2024-10-21',
});
const searchClient = new SearchClient(
process.env.AZURE_SEARCH_ENDPOINT! + '/indexes/rag-index',
'contentVector',
new AzureKeyCredential(process.env.AZURE_SEARCH_KEY!)
);
async function generateEmbeddings(text: string) {
const emb = await openai.getEmbeddings('text-embedding-3-small', [{ input: text }]);
return emb.embedding?.[0];
}
async function ragQuery(query: string) {
const queryEmb = await generateEmbeddings(query);
const searchOptions: VectorizedSearchOptions = {
vectorQueries: [{ kind: 'vector', vector: queryEmb!, k: 3, fields: 'contentVector' }],
};
const results = await searchClient.search('*', searchOptions);
console.log('Top docs:', results.results.map(r => r.document));
// RAG: chat avec context
const context = results.results.map(r => r.document.pageContent).join('\n');
const chatResponse = await openai.getChatCompletions(
process.env.AZURE_OPENAI_DEPLOYMENT!,
[
{ role: 'system', content: 'Réponds basé sur ce contexte:' },
{ role: 'user', content: `${query}\nContexte: ${context}` },
]
);
console.log(chatResponse.choice[0]?.message?.content);
}
ragQuery('Quels sont les prérequis Azure OpenAI ?').catch(console.error);Génère embeddings avec text-embedding-3-small (déployez-le avant), query vectorielle sur index rag-index (créez manuellement via Portal). RAG complète. Piège : Dimensions embedding match (1536 pour small) ; indexez vos docs d'abord.
Bonnes pratiques
- Secrets management : Utilisez Azure Key Vault, jamais .env en prod.
- Rate limiting : Implémentez retry avec exponential backoff via
retrySDK. - Monitoring : Activez Application Insights pour traces et coûts.
- Quotas : Surveillez TPM/RPM via Metrics ; scalez deployments.
- Sécurité : RBAC sur ressource OpenAI ; private endpoints.
Erreurs courantes à éviter
- 404 Deployment not found : Vérifiez nom exact via
az cognitiveservices account deployment list. - 401 Unauthorized : Clé expirée ou mauvais endpoint (doit finir par
/). - 429 Too Many Requests : Pas de batching ; utilisez
streampour long outputs. - Vector mismatch : Embeddings dims ne correspondent pas à schema index.
Pour aller plus loin
- Docs officielles : Azure OpenAI
- SDK JS : npm @azure/openai
- Avancé : Agents avec Assistants API et fine-tuning (GPT-4o).
- Formations Learni sur Azure AI pour certification DP-600.