Konfiguration

Konfigurations- und Einrichtungsanleitung für Qwen Image Edit

Konfiguration

Erweiterte Konfiguration und Optimierung von Qwen Image Edit für verschiedene Umgebungen und Anwendungsfälle.

🚀 Grundkonfiguration

Umgebungsvariablen

# .env.development
QWEN_API_KEY=ihr-entwicklungs-api-schluessel
QWEN_REGION=eu-west-1
QWEN_TIMEOUT=30000
QWEN_DEBUG=true
QWEN_CACHE_ENABLED=true
QWEN_MAX_RETRIES=3

# .env.production
QWEN_API_KEY=ihr-produktions-api-schluessel
QWEN_REGION=eu-west-1
QWEN_TIMEOUT=60000
QWEN_DEBUG=false
QWEN_CACHE_ENABLED=true
QWEN_MAX_RETRIES=5
QWEN_RATE_LIMIT_REQUESTS=1000
QWEN_RATE_LIMIT_PERIOD=60000

# .env.test
QWEN_API_KEY=ihr-test-api-schluessel
QWEN_REGION=eu-west-1
QWEN_TIMEOUT=10000
QWEN_DEBUG=true
QWEN_CACHE_ENABLED=false
QWEN_MOCK_ENABLED=true

Client-Setup

import { QwenImageEdit } from 'qwen-image-edit';

// Grundlegende Konfiguration
const editor = new QwenImageEdit({
  apiKey: process.env.QWEN_API_KEY,
  region: process.env.QWEN_REGION || 'eu-west-1',
  timeout: parseInt(process.env.QWEN_TIMEOUT) || 30000,
  debug: process.env.QWEN_DEBUG === 'true'
});

// Erweiterte Konfiguration
const editor = new QwenImageEdit({
  // Authentifizierung
  apiKey: process.env.QWEN_API_KEY,
  region: 'eu-west-1',
  
  // Netzwerk-Einstellungen
  timeout: 60000,
  maxRetries: 5,
  retryDelay: 2000,
  retryMultiplier: 2,
  maxRetryDelay: 30000,
  
  // Basis-URL (für Enterprise-Kunden)
  baseURL: process.env.QWEN_BASE_URL || 'https://api.qwen.com/v1',
  
  // User-Agent
  userAgent: 'MeineApp/1.0.0 (qwen-image-edit)',
  
  // Debug und Logging
  debug: process.env.NODE_ENV === 'development',
  logger: console,
  
  // Validierung
  validateInputs: true,
  strictMode: false
});

💾 Cache-Konfiguration

In-Memory Cache

// Einfacher In-Memory Cache
const editor = new QwenImageEdit({
  apiKey: process.env.QWEN_API_KEY,
  cache: {
    enabled: true,
    type: 'memory',
    maxSize: 100,                    // Maximale Anzahl gecachter Elemente
    ttl: 3600000,                    // Cache-Lebensdauer in ms (1 Stunde)
    checkPeriod: 600000              // Aufräumintervall in ms (10 Minuten)
  }
});

// Erweiterte Memory-Cache-Konfiguration
const editor = new QwenImageEdit({
  apiKey: process.env.QWEN_API_KEY,
  cache: {
    enabled: true,
    type: 'memory',
    maxSize: 500,
    ttl: 7200000,                    // 2 Stunden
    maxMemoryUsage: 100 * 1024 * 1024, // 100MB
    compressionEnabled: true,
    evictionPolicy: 'lru'            // least-recently-used
  }
});

Redis Cache

import Redis from 'ioredis';

// Redis-Client erstellen
const redis = new Redis({
  host: process.env.REDIS_HOST || 'localhost',
  port: parseInt(process.env.REDIS_PORT) || 6379,
  password: process.env.REDIS_PASSWORD,
  db: parseInt(process.env.REDIS_DB) || 0,
  retryDelayOnFailover: 100,
  maxRetriesPerRequest: 3
});

// Editor mit Redis-Cache
const editor = new QwenImageEdit({
  apiKey: process.env.QWEN_API_KEY,
  cache: {
    enabled: true,
    type: 'redis',
    client: redis,
    keyPrefix: 'qwen:cache:',
    ttl: 86400000,                   // 24 Stunden
    compression: true,
    serialization: 'json'            // 'json' oder 'msgpack'
  }
});

Datei-basierter Cache

import path from 'path';

const editor = new QwenImageEdit({
  apiKey: process.env.QWEN_API_KEY,
  cache: {
    enabled: true,
    type: 'file',
    directory: path.join(process.cwd(), '.cache', 'qwen'),
    maxSize: 1000,
    ttl: 86400000,                   // 24 Stunden
    cleanupInterval: 3600000,        // Aufräumen alle Stunde
    compression: true,
    fileExtension: '.cache'
  }
});

Custom Cache-Implementierung

class CustomCache {
  constructor(options = {}) {
    this.options = options;
    this.storage = new Map();
  }
  
  async get(key) {
    const item = this.storage.get(key);
    if (!item) return null;
    
    if (Date.now() > item.expires) {
      this.storage.delete(key);
      return null;
    }
    
    return item.data;
  }
  
  async set(key, data, ttl = this.options.ttl) {
    this.storage.set(key, {
      data,
      expires: Date.now() + ttl,
      created: Date.now()
    });
  }
  
  async delete(key) {
    return this.storage.delete(key);
  }
  
  async clear() {
    this.storage.clear();
  }
  
  async size() {
    return this.storage.size;
  }
}

const customCache = new CustomCache({ ttl: 3600000 });

const editor = new QwenImageEdit({
  apiKey: process.env.QWEN_API_KEY,
  cache: {
    enabled: true,
    type: 'custom',
    implementation: customCache
  }
});

🌐 Proxy-Konfiguration

HTTP-Proxy

const editor = new QwenImageEdit({
  apiKey: process.env.QWEN_API_KEY,
  proxy: {
    protocol: 'http',
    host: 'proxy.unternehmen.com',
    port: 8080,
    auth: {
      username: process.env.PROXY_USER,
      password: process.env.PROXY_PASS
    },
    timeout: 10000
  }
});

SOCKS-Proxy

const editor = new QwenImageEdit({
  apiKey: process.env.QWEN_API_KEY,
  proxy: {
    protocol: 'socks5',
    host: 'socks-proxy.example.com',
    port: 1080,
    auth: {
      username: 'benutzer',
      password: 'passwort'
    }
  }
});

Proxy mit Zertifikaten

import fs from 'fs';

const editor = new QwenImageEdit({
  apiKey: process.env.QWEN_API_KEY,
  proxy: {
    protocol: 'https',
    host: 'secure-proxy.example.com',
    port: 443,
    ca: fs.readFileSync('./certs/ca.pem'),
    cert: fs.readFileSync('./certs/client.pem'),
    key: fs.readFileSync('./certs/client-key.pem'),
    rejectUnauthorized: true
  }
});

🏗️ Umgebungsspezifische Konfigurationen

Entwicklungsumgebung

// config/development.js
export const developmentConfig = {
  apiKey: process.env.QWEN_API_KEY,
  region: 'eu-west-1',
  
  // Entwicklungsfreundliche Einstellungen
  debug: true,
  timeout: 30000,
  maxRetries: 2,
  
  // Schneller Cache für Entwicklung
  cache: {
    enabled: true,
    type: 'memory',
    maxSize: 50,
    ttl: 1800000                     // 30 Minuten
  },
  
  // Ausführliches Logging
  logger: {
    level: 'debug',
    format: 'pretty',
    timestamp: true
  },
  
  // Validierung aktiviert
  validateInputs: true,
  strictMode: true,
  
  // Mock für Tests
  mock: {
    enabled: process.env.NODE_ENV === 'test',
    responses: {
      editText: {
        imageUrl: 'https://mock.example.com/edited.jpg',
        credits: 1,
        processingTime: 1000
      }
    }
  }
};

Produktionsumgebung

// config/production.js
export const productionConfig = {
  apiKey: process.env.QWEN_API_KEY,
  region: process.env.QWEN_REGION || 'eu-west-1',
  
  // Produktionsoptimierte Einstellungen
  debug: false,
  timeout: 60000,
  maxRetries: 5,
  retryDelay: 2000,
  
  // Robuster Cache
  cache: {
    enabled: true,
    type: 'redis',
    client: redisClient,
    ttl: 86400000,                   // 24 Stunden
    compression: true
  },
  
  // Strukturiertes Logging
  logger: {
    level: 'info',
    format: 'json',
    destination: './logs/qwen.log',
    rotation: {
      size: '10MB',
      keep: 7
    }
  },
  
  // Rate Limiting
  rateLimit: {
    requests: parseInt(process.env.QWEN_RATE_LIMIT) || 1000,
    period: 60000,
    strategy: 'sliding-window'
  },
  
  // Monitoring
  monitoring: {
    enabled: true,
    metricsEndpoint: '/metrics',
    healthCheckEndpoint: '/health'
  },
  
  // Sicherheit
  security: {
    validateInputs: true,
    sanitizeOutputs: true,
    maxImageSize: 10 * 1024 * 1024,  // 10MB
    allowedFormats: ['jpg', 'png', 'webp']
  }
};

Testumgebung

// config/test.js
export const testConfig = {
  apiKey: 'test-api-key',
  region: 'eu-west-1',
  
  // Test-optimierte Einstellungen
  debug: true,
  timeout: 5000,
  maxRetries: 1,
  
  // Kein Cache für Tests
  cache: {
    enabled: false
  },
  
  // Mock aktiviert
  mock: {
    enabled: true,
    latency: 100,                    // Simulierte Latenz
    errorRate: 0.1,                  // 10% Fehlerrate für Robustheitstests
    responses: {
      editText: {
        imageUrl: 'https://test.example.com/edited.jpg',
        credits: 1,
        processingTime: 500
      },
      analyzeImage: {
        analysis: {
          text: { content: 'Test Text', confidence: 0.95 },
          objects: [{ name: 'test-object', confidence: 0.9 }]
        },
        credits: 1
      }
    }
  },
  
  // Test-Logger
  logger: {
    level: 'silent'                  // Keine Logs während Tests
  }
};

📊 Logging-Konfiguration

Grundlegendes Logging

const editor = new QwenImageEdit({
  apiKey: process.env.QWEN_API_KEY,
  logger: {
    level: 'info',                   // 'silent', 'error', 'warn', 'info', 'debug'
    format: 'pretty',                // 'pretty', 'json', 'simple'
    timestamp: true,
    colorize: true
  }
});

Erweiterte Logging-Konfiguration

import winston from 'winston';

// Winston-Logger erstellen
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' 
    })
  ]
});

// In Entwicklung auch zur Konsole loggen
if (process.env.NODE_ENV !== 'production') {
  logger.add(new winston.transports.Console({
    format: winston.format.simple()
  }));
}

const editor = new QwenImageEdit({
  apiKey: process.env.QWEN_API_KEY,
  logger: logger,
  logRequests: true,
  logResponses: true,
  logErrors: true
});

Strukturiertes Logging

const editor = new QwenImageEdit({
  apiKey: process.env.QWEN_API_KEY,
  logger: {
    level: 'info',
    format: 'json',
    fields: {
      service: 'qwen-image-edit',
      version: '1.0.0',
      environment: process.env.NODE_ENV
    },
    redactSensitive: true,           // API-Schlüssel und andere sensible Daten ausblenden
    includeRequestId: true,
    includeTimestamp: true
  }
});

🔒 Sicherheitskonfiguration

Input-Validierung

const editor = new QwenImageEdit({
  apiKey: process.env.QWEN_API_KEY,
  security: {
    // Input-Validierung
    validateInputs: true,
    maxImageSize: 10 * 1024 * 1024,  // 10MB
    allowedFormats: ['jpg', 'jpeg', 'png', 'webp'],
    maxPromptLength: 1000,
    
    // Content-Filtering
    contentFilter: {
      enabled: true,
      blockInappropriate: true,
      blockViolence: true,
      blockAdult: true
    },
    
    // Rate Limiting pro IP
    rateLimitByIP: {
      enabled: true,
      requests: 100,
      period: 3600000,               // 1 Stunde
      blockDuration: 3600000         // 1 Stunde Sperre
    },
    
    // API-Schlüssel-Rotation
    keyRotation: {
      enabled: true,
      rotationInterval: 30 * 24 * 60 * 60 * 1000, // 30 Tage
      gracePeriod: 7 * 24 * 60 * 60 * 1000        // 7 Tage Übergangszeit
    }
  }
});

API-Schlüssel-Rotation

class APIKeyManager {
  constructor(options = {}) {
    this.currentKey = options.primaryKey;
    this.backupKey = options.backupKey;
    this.rotationInterval = options.rotationInterval || 30 * 24 * 60 * 60 * 1000;
    this.lastRotation = options.lastRotation || Date.now();
  }
  
  getCurrentKey() {
    // Prüfe ob Rotation nötig ist
    if (Date.now() - this.lastRotation > this.rotationInterval) {
      this.rotateKeys();
    }
    return this.currentKey;
  }
  
  rotateKeys() {
    console.log('🔄 Rotiere API-Schlüssel');
    
    // Tausche Schlüssel
    const temp = this.currentKey;
    this.currentKey = this.backupKey;
    this.backupKey = temp;
    
    this.lastRotation = Date.now();
    
    // Speichere neue Konfiguration
    this.saveConfiguration();
  }
  
  saveConfiguration() {
    // Implementierung zum Speichern der Konfiguration
    // z.B. in Datenbank oder Konfigurationsdatei
  }
}

const keyManager = new APIKeyManager({
  primaryKey: process.env.QWEN_API_KEY_PRIMARY,
  backupKey: process.env.QWEN_API_KEY_BACKUP
});

const editor = new QwenImageEdit({
  apiKey: () => keyManager.getCurrentKey(),  // Dynamischer API-Schlüssel
  region: 'eu-west-1'
});

⚡ Performance-Konfiguration

Connection Pooling

const editor = new QwenImageEdit({
  apiKey: process.env.QWEN_API_KEY,
  connectionPool: {
    enabled: true,
    maxConnections: 50,
    maxIdleTime: 30000,              // 30 Sekunden
    keepAlive: true,
    keepAliveMsecs: 1000,
    maxSockets: 10,
    maxFreeSockets: 5
  }
});

Bildkomprimierung

const editor = new QwenImageEdit({
  apiKey: process.env.QWEN_API_KEY,
  imageOptimization: {
    enabled: true,
    
    // Automatische Größenanpassung vor Upload
    autoResize: {
      enabled: true,
      maxWidth: 2048,
      maxHeight: 2048,
      quality: 85
    },
    
    // Komprimierung
    compression: {
      enabled: true,
      quality: 85,
      progressive: true,
      optimizeScans: true
    },
    
    // Format-Optimierung
    formatOptimization: {
      enabled: true,
      preferWebP: true,
      fallbackToJPEG: true
    }
  }
});

Memory Management

const editor = new QwenImageEdit({
  apiKey: process.env.QWEN_API_KEY,
  memoryManagement: {
    enabled: true,
    maxMemoryUsage: 512 * 1024 * 1024, // 512MB
    gcInterval: 60000,               // Garbage Collection alle Minute
    
    // Buffer-Pool für Bildverarbeitung
    bufferPool: {
      enabled: true,
      maxBuffers: 20,
      bufferSize: 10 * 1024 * 1024   // 10MB pro Buffer
    },
    
    // Streaming für große Dateien
    streaming: {
      enabled: true,
      threshold: 5 * 1024 * 1024,    // 5MB Schwellenwert
      chunkSize: 1024 * 1024         // 1MB Chunks
    }
  }
});

📈 Monitoring-Konfiguration

Metriken

import { createPrometheusMetrics } from 'qwen-image-edit/metrics';

const metrics = createPrometheusMetrics();

const editor = new QwenImageEdit({
  apiKey: process.env.QWEN_API_KEY,
  monitoring: {
    enabled: true,
    metrics: metrics,
    
    // Metriken-Konfiguration
    collectMetrics: {
      requests: true,
      responses: true,
      errors: true,
      latency: true,
      credits: true,
      cacheHits: true
    },
    
    // Custom Labels
    labels: {
      service: 'image-processing',
      version: process.env.APP_VERSION,
      environment: process.env.NODE_ENV
    }
  }
});

// Metriken-Endpoint für Prometheus
app.get('/metrics', async (req, res) => {
  res.set('Content-Type', metrics.register.contentType);
  res.end(await metrics.register.metrics());
});

Health Checks

const editor = new QwenImageEdit({
  apiKey: process.env.QWEN_API_KEY,
  healthCheck: {
    enabled: true,
    interval: 30000,                 // Alle 30 Sekunden
    timeout: 5000,
    endpoint: '/health',
    
    // Health Check Tests
    checks: {
      api: true,                     // API-Erreichbarkeit
      credits: true,                 // Credit-Status
      cache: true,                   // Cache-Funktionalität
      memory: true,                  // Speicherverbrauch
      disk: true                     // Festplattenspeicher
    },
    
    // Schwellenwerte
    thresholds: {
      memoryUsage: 0.8,              // 80% Speichernutzung
      diskUsage: 0.9,                // 90% Festplattennutzung
      responseTime: 5000             // 5 Sekunden Antwortzeit
    }
  }
});

// Health Check Endpoint
app.get('/health', async (req, res) => {
  const health = await editor.getHealthStatus();
  
  const statusCode = health.status === 'healthy' ? 200 : 503;
  res.status(statusCode).json(health);
});

🛠️ Entwicklungstools

Hot Reload

// webpack.config.js oder ähnlich
if (process.env.NODE_ENV === 'development') {
  const editor = new QwenImageEdit({
    apiKey: process.env.QWEN_API_KEY,
    development: {
      hotReload: {
        enabled: true,
        watchFiles: ['./config/**/*.js'],
        reloadDelay: 1000
      },
      
      // Automatisches Neuladen der Konfiguration
      configReload: {
        enabled: true,
        watchConfig: true,
        validateOnReload: true
      }
    }
  });
}

Mock für Tests

// test-utils/mock-editor.js
export class MockQwenImageEdit {
  constructor(options = {}) {
    this.options = options;
    this.mockResponses = options.mockResponses || {};
  }
  
  async editText(options) {
    // Simuliere Latenz
    await new Promise(resolve => 
      setTimeout(resolve, this.options.latency || 100)
    );
    
    // Simuliere gelegentliche Fehler
    if (Math.random() < (this.options.errorRate || 0)) {
      throw new Error('Mock-Fehler für Tests');
    }
    
    return this.mockResponses.editText || {
      imageUrl: 'https://mock.example.com/edited.jpg',
      credits: 1,
      processingTime: 500
    };
  }
  
  async analyzeImage(options) {
    await new Promise(resolve => 
      setTimeout(resolve, this.options.latency || 50)
    );
    
    return this.mockResponses.analyzeImage || {
      analysis: {
        text: { content: 'Mock Text', confidence: 0.95 }
      },
      credits: 1
    };
  }
}

// In Tests verwenden
import { MockQwenImageEdit } from './test-utils/mock-editor.js';

const mockEditor = new MockQwenImageEdit({
  latency: 100,
  errorRate: 0.1,
  mockResponses: {
    editText: {
      imageUrl: 'https://test.example.com/result.jpg',
      credits: 2
    }
  }
});

📋 Best Practices

Konfigurationsmanagement

// config/index.js
import { developmentConfig } from './development.js';
import { productionConfig } from './production.js';
import { testConfig } from './test.js';

const configs = {
  development: developmentConfig,
  production: productionConfig,
  test: testConfig
};

const environment = process.env.NODE_ENV || 'development';
const config = configs[environment];

if (!config) {
  throw new Error(`Keine Konfiguration für Umgebung '${environment}' gefunden`);
}

// Konfiguration validieren
function validateConfig(config) {
  const required = ['apiKey', 'region'];
  
  for (const field of required) {
    if (!config[field]) {
      throw new Error(`Erforderliches Konfigurationsfeld fehlt: ${field}`);
    }
  }
  
  return true;
}

validateConfig(config);

export default config;

Konfigurationsvalidierung

import Joi from 'joi';

const configSchema = 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).default(30000),
  maxRetries: Joi.number().min(0).max(10).default(3),
  debug: Joi.boolean().default(false),
  
  cache: Joi.object({
    enabled: Joi.boolean().default(true),
    type: Joi.string().valid('memory', 'redis', 'file', 'custom').default('memory'),
    maxSize: Joi.number().min(1).default(100),
    ttl: Joi.number().min(1000).default(3600000)
  }).optional(),
  
  proxy: Joi.object({
    protocol: Joi.string().valid('http', 'https', 'socks5'),
    host: Joi.string().required(),
    port: Joi.number().port().required(),
    auth: Joi.object({
      username: Joi.string().required(),
      password: Joi.string().required()
    }).optional()
  }).optional()
});

export function validateConfiguration(config) {
  const { error, value } = configSchema.validate(config, {
    allowUnknown: true,
    stripUnknown: true
  });
  
  if (error) {
    throw new Error(`Konfigurationsfehler: ${error.details[0].message}`);
  }
  
  return value;
}

Secrets Management

// secrets/manager.js
import { SecretsManager } from 'aws-sdk';

class SecretManager {
  constructor(region = 'eu-west-1') {
    this.client = new SecretsManager({ region });
    this.cache = new Map();
    this.cacheTTL = 300000; // 5 Minuten
  }
  
  async getSecret(secretName) {
    // Prüfe Cache
    const cached = this.cache.get(secretName);
    if (cached && Date.now() - cached.timestamp < this.cacheTTL) {
      return cached.value;
    }
    
    try {
      const result = await this.client.getSecretValue({
        SecretId: secretName
      }).promise();
      
      const secret = JSON.parse(result.SecretString);
      
      // Cache aktualisieren
      this.cache.set(secretName, {
        value: secret,
        timestamp: Date.now()
      });
      
      return secret;
    } catch (error) {
      console.error(`Fehler beim Laden des Secrets ${secretName}:`, error);
      throw error;
    }
  }
}

const secretManager = new SecretManager();

// Verwendung
export async function createEditorWithSecrets() {
  const secrets = await secretManager.getSecret('qwen-image-edit-secrets');
  
  return new QwenImageEdit({
    apiKey: secrets.apiKey,
    region: secrets.region,
    // ... weitere Konfiguration
  });
}

📚 Zusätzliche Ressourcen

🚀 Erste Schritte

Schneller Einstieg in die Qwen Image Edit API

Quickstart Guide →

📖 API-Referenz

Vollständige Dokumentation aller verfügbaren Methoden

API-Referenz →

🔧 Fehlerbehebung

Häufige Probleme und deren Lösungen

Fehlerbehebung →

🚀 Erweiterte Funktionen

Fortgeschrittene Features und Optimierungen

Erweiterte Funktionen →