Configuration
Guide de configuration et de configuration pour Qwen Image Edit
Configuration
Guide complet pour configurer Qwen Image Edit selon vos besoins, de l'installation de base aux paramètres avancés.
🚀 Configuration Initiale
Variables d'Environnement
Créez un fichier .env
à la racine de votre projet :
# Configuration de base
QWEN_API_KEY=votre_cle_api_ici
QWEN_REGION=eu-west-1
QWEN_TIMEOUT=30000
# Configuration avancée
QWEN_MAX_RETRIES=3
QWEN_RETRY_DELAY=1000
QWEN_MAX_CONCURRENCY=5
# Cache
QWEN_CACHE_ENABLED=true
QWEN_CACHE_TTL=3600
QWEN_CACHE_MAX_SIZE=100
# Logging
QWEN_LOG_LEVEL=info
QWEN_LOG_FILE=./logs/qwen.log
# Proxy (optionnel)
QWEN_PROXY_HOST=proxy.example.com
QWEN_PROXY_PORT=8080
QWEN_PROXY_USERNAME=user
QWEN_PROXY_PASSWORD=pass
Configuration du Client
import { QwenImageEdit } from 'qwen-image-edit';
// Configuration de base
const editor = new QwenImageEdit({
apiKey: process.env.QWEN_API_KEY,
region: process.env.QWEN_REGION || 'eu-west-1'
});
// Configuration complète
const editorAvance = new QwenImageEdit({
// Authentification
apiKey: process.env.QWEN_API_KEY,
region: 'eu-west-1',
// Timeouts et retries
timeout: 30000,
retries: 3,
retryDelay: 1000,
// Concurrence
maxConcurrency: 5,
// Cache
cache: {
enabled: true,
ttl: 3600,
maxSize: 100,
type: 'memory' // 'memory', 'redis', 'file'
},
// Proxy
proxy: {
host: 'proxy.example.com',
port: 8080,
protocol: 'http',
auth: {
username: 'user',
password: 'pass'
}
},
// Logging
logging: {
level: 'info',
destination: './logs/qwen.log',
format: 'json',
maxFiles: 5,
maxSize: '10MB'
},
// Webhooks
webhooks: {
endpoint: 'https://votre-site.com/webhook',
secret: 'votre_secret',
events: ['processing.completed', 'processing.failed']
}
});
🗄️ Configuration du Cache
Cache en Mémoire
const editor = new QwenImageEdit({
apiKey: process.env.QWEN_API_KEY,
cache: {
type: 'memory',
enabled: true,
ttl: 3600, // 1 heure
maxSize: 100, // 100 entrées max
checkPeriod: 600 // Vérification toutes les 10 minutes
}
});
Cache Redis
import Redis from 'ioredis';
const redis = new Redis({
host: 'localhost',
port: 6379,
password: 'votre_mot_de_passe',
db: 0
});
const editor = new QwenImageEdit({
apiKey: process.env.QWEN_API_KEY,
cache: {
type: 'redis',
enabled: true,
ttl: 7200, // 2 heures
client: redis,
keyPrefix: 'qwen:cache:',
compression: true
}
});
Cache Fichier
const editor = new QwenImageEdit({
apiKey: process.env.QWEN_API_KEY,
cache: {
type: 'file',
enabled: true,
ttl: 86400, // 24 heures
directory: './cache/qwen',
maxSize: '1GB',
compression: true
}
});
Cache Personnalisé
class CachePersonnalise {
constructor() {
this.cache = new Map();
}
async get(key) {
const item = this.cache.get(key);
if (!item) return null;
if (Date.now() > item.expiry) {
this.cache.delete(key);
return null;
}
return item.value;
}
async set(key, value, ttl = 3600) {
this.cache.set(key, {
value,
expiry: Date.now() + (ttl * 1000)
});
}
async delete(key) {
this.cache.delete(key);
}
async clear() {
this.cache.clear();
}
}
const editor = new QwenImageEdit({
apiKey: process.env.QWEN_API_KEY,
cache: {
type: 'custom',
enabled: true,
client: new CachePersonnalise()
}
});
🌐 Configuration Proxy
Proxy HTTP
const editor = new QwenImageEdit({
apiKey: process.env.QWEN_API_KEY,
proxy: {
protocol: 'http',
host: 'proxy.entreprise.com',
port: 8080,
auth: {
username: 'utilisateur',
password: 'mot_de_passe'
},
timeout: 10000
}
});
Proxy SOCKS
const editor = new QwenImageEdit({
apiKey: process.env.QWEN_API_KEY,
proxy: {
protocol: 'socks5',
host: 'socks-proxy.com',
port: 1080,
auth: {
username: 'user',
password: 'pass'
}
}
});
Proxy avec Certificats
import fs from 'fs';
const editor = new QwenImageEdit({
apiKey: process.env.QWEN_API_KEY,
proxy: {
protocol: 'https',
host: 'secure-proxy.com',
port: 443,
ca: fs.readFileSync('./certs/ca.pem'),
cert: fs.readFileSync('./certs/client.pem'),
key: fs.readFileSync('./certs/client-key.pem'),
rejectUnauthorized: true
}
});
🏗️ Configuration par Environnement
Développement
// config/development.js
export default {
apiKey: process.env.QWEN_API_KEY,
region: 'eu-west-1',
timeout: 60000, // Plus long pour le debug
retries: 1, // Moins de retries
cache: {
enabled: false // Pas de cache en dev
},
logging: {
level: 'debug',
destination: 'console',
format: 'pretty'
},
webhooks: {
endpoint: 'http://localhost:3000/webhook'
}
};
Production
// config/production.js
export default {
apiKey: process.env.QWEN_API_KEY,
region: process.env.QWEN_REGION,
timeout: 30000,
retries: 3,
retryDelay: 2000,
maxConcurrency: 10,
cache: {
enabled: true,
type: 'redis',
ttl: 7200,
client: redisClient
},
logging: {
level: 'warn',
destination: './logs/qwen-prod.log',
format: 'json',
maxFiles: 10,
maxSize: '50MB'
},
webhooks: {
endpoint: 'https://api.monsite.com/webhook',
secret: process.env.WEBHOOK_SECRET
}
};
Test
// config/test.js
export default {
apiKey: 'test_key',
region: 'eu-west-1',
timeout: 5000,
retries: 0,
cache: {
enabled: false
},
logging: {
level: 'error',
destination: 'console'
},
mock: true // Utiliser des réponses mockées
};
Chargement de Configuration
// config/index.js
import development from './development.js';
import production from './production.js';
import test from './test.js';
const configs = {
development,
production,
test
};
const env = process.env.NODE_ENV || 'development';
export default configs[env];
// app.js
import config from './config/index.js';
import { QwenImageEdit } from 'qwen-image-edit';
const editor = new QwenImageEdit(config);
📝 Configuration du Logging
Logging Basique
const editor = new QwenImageEdit({
apiKey: process.env.QWEN_API_KEY,
logging: {
level: 'info', // 'debug', 'info', 'warn', 'error'
destination: './logs/qwen.log'
}
});
Logging Avancé
import winston from 'winston';
// Logger personnalisé
const logger = winston.createLogger({
level: 'info',
format: winston.format.combine(
winston.format.timestamp(),
winston.format.errors({ stack: true }),
winston.format.json()
),
transports: [
new winston.transports.File({
filename: './logs/qwen-error.log',
level: 'error'
}),
new winston.transports.File({
filename: './logs/qwen-combined.log'
}),
new winston.transports.Console({
format: winston.format.simple()
})
]
});
const editor = new QwenImageEdit({
apiKey: process.env.QWEN_API_KEY,
logging: {
logger: logger,
logRequests: true,
logResponses: true,
logErrors: true,
sensitiveFields: ['apiKey', 'password'] // Champs à masquer
}
});
Logging Structuré
const editor = new QwenImageEdit({
apiKey: process.env.QWEN_API_KEY,
logging: {
level: 'info',
format: 'json',
destination: './logs/qwen.log',
fields: {
service: 'qwen-image-edit',
version: '1.0.0',
environment: process.env.NODE_ENV
},
rotation: {
maxFiles: 5,
maxSize: '10MB',
datePattern: 'YYYY-MM-DD'
}
}
});
🔒 Configuration de Sécurité
Validation des Entrées
import Joi from 'joi';
const schemaValidation = {
editText: Joi.object({
image: Joi.alternatives().try(
Joi.string().uri(),
Joi.string().dataUri(),
Joi.object().instance(Buffer),
Joi.object().instance(File)
).required(),
prompt: Joi.string().min(1).max(1000).required(),
options: Joi.object({
preserveStyle: Joi.boolean(),
language: Joi.string().length(2),
fontSize: Joi.string().valid('small', 'medium', 'large'),
// ... autres validations
})
})
};
const editor = new QwenImageEdit({
apiKey: process.env.QWEN_API_KEY,
validation: {
enabled: true,
schemas: schemaValidation,
strict: true
}
});
Rotation des Clés API
class GestionnaireClésAPI {
constructor() {
this.cles = [
process.env.QWEN_API_KEY_1,
process.env.QWEN_API_KEY_2,
process.env.QWEN_API_KEY_3
];
this.indexActuel = 0;
}
obtenirCleActuelle() {
return this.cles[this.indexActuel];
}
changerCle() {
this.indexActuel = (this.indexActuel + 1) % this.cles.length;
console.log(`Changement vers la clé ${this.indexActuel + 1}`);
}
marquerCleInvalide() {
console.warn(`Clé ${this.indexActuel + 1} marquée comme invalide`);
this.changerCle();
}
}
const gestionnaireCles = new GestionnaireClésAPI();
const editor = new QwenImageEdit({
apiKey: gestionnaireCles.obtenirCleActuelle(),
region: 'eu-west-1',
onError: (error) => {
if (error.code === 'INVALID_API_KEY') {
gestionnaireCles.marquerCleInvalide();
// Recréer l'instance avec la nouvelle clé
editor.updateConfig({
apiKey: gestionnaireCles.obtenirCleActuelle()
});
}
}
});
Limitation de Débit
import { RateLimiter } from 'limiter';
const limiteur = new RateLimiter({
tokensPerInterval: 10,
interval: 'minute'
});
const editor = new QwenImageEdit({
apiKey: process.env.QWEN_API_KEY,
rateLimiter: {
enabled: true,
limiter: limiteur,
onLimitReached: (retryAfter) => {
console.log(`Limite atteinte, retry dans ${retryAfter}ms`);
}
}
});
⚡ Configuration des Performances
Pool de Connexions
const editor = new QwenImageEdit({
apiKey: process.env.QWEN_API_KEY,
connectionPool: {
maxConnections: 20,
maxIdleTime: 30000,
keepAlive: true,
timeout: 5000
}
});
Compression d'Images
const editor = new QwenImageEdit({
apiKey: process.env.QWEN_API_KEY,
compression: {
enabled: true,
quality: 85,
maxWidth: 2048,
maxHeight: 2048,
format: 'webp', // Format de sortie préféré
progressive: true
}
});
Gestion Mémoire
const editor = new QwenImageEdit({
apiKey: process.env.QWEN_API_KEY,
memory: {
maxImageSize: 50 * 1024 * 1024, // 50MB
maxCacheSize: 100 * 1024 * 1024, // 100MB
gcInterval: 300000, // Garbage collection toutes les 5 minutes
lowMemoryThreshold: 0.8 // 80% de la mémoire disponible
}
});
📊 Configuration du Monitoring
Métriques
import { createPrometheusMetrics } from 'prom-client';
const metriques = createPrometheusMetrics();
const editor = new QwenImageEdit({
apiKey: process.env.QWEN_API_KEY,
metrics: {
enabled: true,
provider: 'prometheus',
client: metriques,
labels: {
service: 'qwen-image-edit',
version: '1.0.0'
},
collectDefaultMetrics: true
}
});
Health Checks
const editor = new QwenImageEdit({
apiKey: process.env.QWEN_API_KEY,
healthCheck: {
enabled: true,
interval: 60000, // Vérification toutes les minutes
timeout: 5000,
endpoint: '/health',
onHealthy: () => console.log('✅ Service en bonne santé'),
onUnhealthy: (error) => console.error('❌ Service défaillant:', error)
}
});
// Endpoint de health check
app.get('/health', async (req, res) => {
try {
const sante = await editor.checkHealth();
res.status(200).json(sante);
} catch (error) {
res.status(503).json({ status: 'unhealthy', error: error.message });
}
});
🛠️ Configuration de Développement
Hot Reload
// En mode développement
if (process.env.NODE_ENV === 'development') {
const editor = new QwenImageEdit({
apiKey: process.env.QWEN_API_KEY,
hotReload: {
enabled: true,
watchFiles: ['./config/**/*.js'],
onReload: (newConfig) => {
console.log('🔄 Configuration rechargée');
editor.updateConfig(newConfig);
}
}
});
}
Mock pour Tests
const editor = new QwenImageEdit({
apiKey: process.env.QWEN_API_KEY,
mock: {
enabled: process.env.NODE_ENV === 'test',
responses: {
editText: {
imageUrl: 'https://example.com/mock-image.jpg',
credits: 1,
processingTime: 100
},
analyzeImage: {
text: [{ content: 'Mock text', confidence: 0.95 }],
objects: [{ name: 'mock object', confidence: 0.9 }]
}
},
delay: 500 // Simuler la latence réseau
}
});
📋 Bonnes Pratiques
Configuration Centralisée
// config/qwen.js
class ConfigurationQwen {
constructor() {
this.config = this.chargerConfiguration();
}
chargerConfiguration() {
const env = process.env.NODE_ENV || 'development';
const configBase = {
apiKey: process.env.QWEN_API_KEY,
region: process.env.QWEN_REGION || 'eu-west-1'
};
const configsEnv = {
development: {
...configBase,
timeout: 60000,
logging: { level: 'debug' },
cache: { enabled: false }
},
production: {
...configBase,
timeout: 30000,
logging: { level: 'warn' },
cache: { enabled: true, type: 'redis' }
},
test: {
...configBase,
mock: { enabled: true },
logging: { level: 'error' }
}
};
return configsEnv[env] || configsEnv.development;
}
obtenirConfig() {
return this.config;
}
mettreAJourConfig(nouvelleConfig) {
this.config = { ...this.config, ...nouvelleConfig };
}
}
export default new ConfigurationQwen();
Validation de Configuration
import Joi from 'joi';
const schemaConfig = Joi.object({
apiKey: Joi.string().required(),
region: Joi.string().valid('eu-west-1', 'us-east-1', 'ap-southeast-1').required(),
timeout: Joi.number().min(1000).max(300000),
retries: Joi.number().min(0).max(10),
cache: Joi.object({
enabled: Joi.boolean(),
type: Joi.string().valid('memory', 'redis', 'file'),
ttl: Joi.number().min(60)
}),
logging: Joi.object({
level: Joi.string().valid('debug', 'info', 'warn', 'error'),
destination: Joi.string()
})
});
function validerConfiguration(config) {
const { error, value } = schemaConfig.validate(config);
if (error) {
throw new Error(`Configuration invalide: ${error.message}`);
}
return value;
}
// Utilisation
try {
const configValidee = validerConfiguration(config);
const editor = new QwenImageEdit(configValidee);
} catch (error) {
console.error('Erreur de configuration:', error.message);
process.exit(1);
}
Gestion des Secrets
// Utilisation d'un gestionnaire de secrets
import { SecretManagerServiceClient } from '@google-cloud/secret-manager';
class GestionnaireSecrets {
constructor() {
this.client = new SecretManagerServiceClient();
}
async obtenirSecret(nom) {
const [version] = await this.client.accessSecretVersion({
name: `projects/mon-projet/secrets/${nom}/versions/latest`
});
return version.payload.data.toString();
}
}
const gestionnaire = new GestionnaireSecrets();
// Configuration avec secrets sécurisés
const editor = new QwenImageEdit({
apiKey: await gestionnaire.obtenirSecret('qwen-api-key'),
region: 'eu-west-1',
webhooks: {
secret: await gestionnaire.obtenirSecret('webhook-secret')
}
});
Configuration terminée ! Votre instance Qwen Image Edit est maintenant optimisée pour votre environnement.