設定
Qwen Image Edit の設定とセットアップガイド
設定
Qwen Image Editの詳細設定とパフォーマンス最適化について説明します。
🚀 初期設定
環境変数
# .env ファイル
QWEN_API_KEY=qwen_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
QWEN_REGION=ap-northeast-1
QWEN_TIMEOUT=30000
QWEN_MAX_RETRIES=3
QWEN_RETRY_DELAY=1000
基本的なクライアント設定
import { QwenImageEdit } from 'qwen-image-edit';
const editor = new QwenImageEdit({
// 必須設定
apiKey: process.env.QWEN_API_KEY,
// オプション設定
region: process.env.QWEN_REGION || 'ap-northeast-1',
timeout: parseInt(process.env.QWEN_TIMEOUT) || 30000,
maxRetries: parseInt(process.env.QWEN_MAX_RETRIES) || 3,
retryDelay: parseInt(process.env.QWEN_RETRY_DELAY) || 1000
});
⚙️ 高度な設定
完全な設定オプション
const editor = new QwenImageEdit({
// 認証
apiKey: 'your-api-key',
region: 'ap-northeast-1',
// ネットワーク設定
timeout: 30000, // リクエストタイムアウト(ミリ秒)
maxRetries: 3, // 最大再試行回数
retryDelay: 1000, // 再試行間隔(ミリ秒)
retryMultiplier: 2, // 再試行間隔の倍数
maxRetryDelay: 10000, // 最大再試行間隔
// エンドポイント設定
baseURL: 'https://api.qwen.com/v1',
apiVersion: 'v1',
// ヘッダー設定
headers: {
'User-Agent': 'MyApp/1.0.0',
'X-Custom-Header': 'custom-value'
},
// SSL/TLS設定
ssl: {
rejectUnauthorized: true,
ca: fs.readFileSync('ca.pem'),
cert: fs.readFileSync('cert.pem'),
key: fs.readFileSync('key.pem')
},
// プロキシ設定
proxy: {
host: 'proxy.example.com',
port: 8080,
auth: {
username: 'proxy-user',
password: 'proxy-pass'
}
},
// キャッシュ設定
cache: {
enabled: true,
ttl: 3600000, // キャッシュ有効期限(ミリ秒)
maxSize: 100, // 最大キャッシュエントリ数
storage: 'memory' // 'memory', 'redis', 'file'
},
// ログ設定
logging: {
level: 'info', // 'debug', 'info', 'warn', 'error'
format: 'json', // 'json', 'text'
destination: 'console' // 'console', 'file', 'custom'
}
});
💾 キャッシュ設定
インメモリキャッシュ
const editor = new QwenImageEdit({
apiKey: 'your-api-key',
cache: {
enabled: true,
storage: 'memory',
ttl: 3600000, // 1時間
maxSize: 100, // 最大100エントリ
compression: true // キャッシュデータを圧縮
}
});
Redisキャッシュ
const editor = new QwenImageEdit({
apiKey: 'your-api-key',
cache: {
enabled: true,
storage: 'redis',
redis: {
host: 'localhost',
port: 6379,
password: 'redis-password',
db: 0,
keyPrefix: 'qwen:cache:',
connectTimeout: 5000,
lazyConnect: true
},
ttl: 7200000, // 2時間
compression: true
}
});
ファイルキャッシュ
const editor = new QwenImageEdit({
apiKey: 'your-api-key',
cache: {
enabled: true,
storage: 'file',
file: {
directory: './cache',
maxSize: '1GB',
cleanupInterval: 3600000 // 1時間ごとにクリーンアップ
},
ttl: 86400000, // 24時間
compression: true
}
});
カスタムキャッシュ
class CustomCache {
constructor() {
this.cache = new Map();
}
async get(key) {
const item = this.cache.get(key);
if (item && Date.now() < item.expiry) {
return item.value;
}
return null;
}
async set(key, value, ttl) {
this.cache.set(key, {
value,
expiry: Date.now() + ttl
});
}
async delete(key) {
this.cache.delete(key);
}
async clear() {
this.cache.clear();
}
}
const editor = new QwenImageEdit({
apiKey: 'your-api-key',
cache: {
enabled: true,
storage: 'custom',
custom: new CustomCache()
}
});
🌐 プロキシ設定
HTTPプロキシ
const editor = new QwenImageEdit({
apiKey: 'your-api-key',
proxy: {
protocol: 'http',
host: 'proxy.company.com',
port: 8080,
auth: {
username: 'proxy-user',
password: 'proxy-password'
},
timeout: 5000
}
});
SOCKSプロキシ
const editor = new QwenImageEdit({
apiKey: 'your-api-key',
proxy: {
protocol: 'socks5',
host: 'socks-proxy.example.com',
port: 1080,
auth: {
username: 'socks-user',
password: 'socks-password'
}
}
});
証明書付きプロキシ
const editor = new QwenImageEdit({
apiKey: 'your-api-key',
proxy: {
host: 'secure-proxy.example.com',
port: 8443,
auth: {
username: 'user',
password: 'pass'
},
ca: fs.readFileSync('./proxy-ca.pem'),
cert: fs.readFileSync('./client-cert.pem'),
key: fs.readFileSync('./client-key.pem')
}
});
🏗️ 環境別設定
開発環境
// config/development.js
module.exports = {
qwen: {
apiKey: process.env.QWEN_API_KEY_DEV,
region: 'ap-northeast-1',
timeout: 60000, // 開発時は長めのタイムアウト
maxRetries: 1, // 開発時は再試行を少なく
cache: {
enabled: false // 開発時はキャッシュを無効
},
logging: {
level: 'debug', // 詳細なログ
format: 'text',
destination: 'console'
},
// 開発用のモック設定
mock: {
enabled: true,
responses: {
editText: {
imageUrl: 'https://example.com/mock-image.jpg',
credits: 1,
processingTime: 1000
}
}
}
}
};
本番環境
// config/production.js
module.exports = {
qwen: {
apiKey: process.env.QWEN_API_KEY_PROD,
region: process.env.QWEN_REGION || 'ap-northeast-1',
timeout: 30000,
maxRetries: 3,
retryDelay: 2000,
cache: {
enabled: true,
storage: 'redis',
redis: {
host: process.env.REDIS_HOST,
port: process.env.REDIS_PORT,
password: process.env.REDIS_PASSWORD,
db: 1
},
ttl: 3600000, // 1時間
compression: true
},
logging: {
level: 'warn', // 本番では警告以上のみ
format: 'json',
destination: 'file',
file: {
path: '/var/log/qwen-image-edit.log',
maxSize: '100MB',
maxFiles: 10
}
},
// 本番用のセキュリティ設定
security: {
validateInput: true,
sanitizePrompts: true,
rateLimiting: {
enabled: true,
maxRequests: 100,
windowMs: 60000 // 1分間
}
}
}
};
テスト環境
// config/test.js
module.exports = {
qwen: {
apiKey: 'test-api-key',
region: 'ap-northeast-1',
timeout: 5000, // テストは短いタイムアウト
maxRetries: 0, // テストでは再試行しない
cache: {
enabled: false // テストではキャッシュを無効
},
logging: {
level: 'error', // テストではエラーのみ
destination: 'console'
},
// テスト用のモック設定
mock: {
enabled: true,
alwaysSucceed: true,
delay: 100 // 100msの遅延をシミュレート
}
}
};
📝 ログ設定
基本的なログ設定
const editor = new QwenImageEdit({
apiKey: 'your-api-key',
logging: {
level: 'info', // debug, info, warn, error
format: 'text', // text, json
destination: 'console', // console, file, custom
timestamp: true, // タイムスタンプを含める
requestId: true // リクエストIDを含める
}
});
高度なログ設定
const editor = new QwenImageEdit({
apiKey: 'your-api-key',
logging: {
level: 'debug',
format: 'json',
destination: 'file',
file: {
path: './logs/qwen-image-edit.log',
maxSize: '50MB',
maxFiles: 5,
compress: true
},
// ログフィルター
filters: {
excludeHeaders: ['authorization'],
excludeBody: true,
includeResponseTime: true
},
// 構造化ログ
structured: {
service: 'qwen-image-edit',
version: '1.0.0',
environment: process.env.NODE_ENV
}
}
});
カスタムログ設定
const winston = require('winston');
const customLogger = 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: 'error.log', level: 'error' }),
new winston.transports.File({ filename: 'combined.log' })
]
});
const editor = new QwenImageEdit({
apiKey: 'your-api-key',
logging: {
destination: 'custom',
custom: customLogger
}
});
🔒 セキュリティ設定
入力検証
const editor = new QwenImageEdit({
apiKey: 'your-api-key',
security: {
validateInput: true,
// 画像検証
imageValidation: {
maxSize: 10 * 1024 * 1024, // 10MB
allowedFormats: ['jpg', 'png', 'webp'],
scanForMalware: true
},
// プロンプト検証
promptValidation: {
maxLength: 1000,
sanitize: true,
blockSensitiveContent: true,
allowedLanguages: ['ja', 'en']
},
// レート制限
rateLimiting: {
enabled: true,
maxRequests: 100,
windowMs: 60000, // 1分間
skipSuccessfulRequests: false
}
}
});
APIキーローテーション
class ApiKeyRotator {
constructor(keys) {
this.keys = keys;
this.currentIndex = 0;
}
getCurrentKey() {
return this.keys[this.currentIndex];
}
rotateKey() {
this.currentIndex = (this.currentIndex + 1) % this.keys.length;
return this.getCurrentKey();
}
}
const keyRotator = new ApiKeyRotator([
'qwen_key_1_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
'qwen_key_2_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
'qwen_key_3_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
]);
const editor = new QwenImageEdit({
apiKey: keyRotator.getCurrentKey(),
// エラー時のキーローテーション
onError: (error) => {
if (error.code === 'RATE_LIMIT_EXCEEDED') {
const newKey = keyRotator.rotateKey();
editor.updateApiKey(newKey);
}
}
});
🚀 パフォーマンス設定
接続プール
const editor = new QwenImageEdit({
apiKey: 'your-api-key',
// HTTP接続プール設定
connectionPool: {
maxSockets: 50, // 最大ソケット数
maxFreeSockets: 10, // 最大フリーソケット数
timeout: 60000, // アイドルタイムアウト
keepAlive: true, // Keep-Aliveを有効
keepAliveMsecs: 1000 // Keep-Alive間隔
}
});
画像圧縮
const editor = new QwenImageEdit({
apiKey: 'your-api-key',
// 自動画像圧縮
imageCompression: {
enabled: true,
maxSize: 5 * 1024 * 1024, // 5MB以上で圧縮
quality: 0.8, // 圧縮品質
format: 'webp', // 圧縮フォーマット
progressive: true // プログレッシブJPEG
}
});
メモリ管理
const editor = new QwenImageEdit({
apiKey: 'your-api-key',
// メモリ管理設定
memory: {
maxHeapSize: '2GB', // 最大ヒープサイズ
gcInterval: 300000, // GC間隔(5分)
imageBufferLimit: 100, // 画像バッファ制限
autoCleanup: true // 自動クリーンアップ
}
});
📊 監視設定
メトリクス収集
const editor = new QwenImageEdit({
apiKey: 'your-api-key',
// メトリクス設定
metrics: {
enabled: true,
// 収集するメトリクス
collect: {
requestCount: true,
responseTime: true,
errorRate: true,
cacheHitRate: true,
creditsUsed: true
},
// エクスポート設定
export: {
format: 'prometheus', // prometheus, json, csv
endpoint: '/metrics',
interval: 60000 // 1分間隔
}
}
});
ヘルスチェック
const editor = new QwenImageEdit({
apiKey: 'your-api-key',
// ヘルスチェック設定
healthCheck: {
enabled: true,
endpoint: '/health',
interval: 30000, // 30秒間隔
// チェック項目
checks: {
apiConnection: true,
cacheConnection: true,
memoryUsage: true,
responseTime: true
},
// 閾値設定
thresholds: {
maxResponseTime: 5000, // 5秒
maxMemoryUsage: 0.8, // 80%
maxErrorRate: 0.05 // 5%
}
}
});
🛠️ 開発ツール
ホットリロード
// 開発環境でのホットリロード設定
if (process.env.NODE_ENV === 'development') {
const chokidar = require('chokidar');
const editor = new QwenImageEdit({
apiKey: 'your-api-key',
// ホットリロード設定
hotReload: {
enabled: true,
watchPaths: ['./config', './src'],
ignorePatterns: ['node_modules', '.git'],
// 設定変更時のコールバック
onConfigChange: (newConfig) => {
console.log('設定が更新されました:', newConfig);
editor.updateConfig(newConfig);
}
}
});
}
テスト用モック
const editor = new QwenImageEdit({
apiKey: 'your-api-key',
// モック設定(テスト環境用)
mock: {
enabled: process.env.NODE_ENV === 'test',
// モックレスポンス
responses: {
editText: {
imageUrl: 'https://example.com/mock-edited-image.jpg',
credits: 1,
processingTime: 1000,
metadata: {
originalSize: { width: 800, height: 600 },
outputSize: { width: 800, height: 600 }
}
},
editElement: {
imageUrl: 'https://example.com/mock-element-image.jpg',
credits: 2,
processingTime: 1500
}
},
// エラーシミュレーション
simulateErrors: {
rateLimitError: 0.1, // 10%の確率でレート制限エラー
networkError: 0.05, // 5%の確率でネットワークエラー
serverError: 0.02 // 2%の確率でサーバーエラー
},
// 遅延シミュレーション
delay: {
min: 500, // 最小遅延(ミリ秒)
max: 2000 // 最大遅延(ミリ秒)
}
}
});
📋 設定のベストプラクティス
設定管理
// config/index.js
const path = require('path');
const fs = require('fs');
class ConfigManager {
constructor() {
this.config = this.loadConfig();
this.watchers = [];
}
loadConfig() {
const env = process.env.NODE_ENV || 'development';
const configPath = path.join(__dirname, `${env}.js`);
if (fs.existsSync(configPath)) {
return require(configPath);
}
return require('./default.js');
}
get(key) {
return key.split('.').reduce((obj, k) => obj?.[k], this.config);
}
set(key, value) {
const keys = key.split('.');
const lastKey = keys.pop();
const target = keys.reduce((obj, k) => obj[k] = obj[k] || {}, this.config);
target[lastKey] = value;
}
watch(callback) {
this.watchers.push(callback);
}
reload() {
const oldConfig = this.config;
this.config = this.loadConfig();
this.watchers.forEach(callback => {
callback(this.config, oldConfig);
});
}
}
const configManager = new ConfigManager();
// 設定の使用
const editor = new QwenImageEdit(configManager.get('qwen'));
// 設定変更の監視
configManager.watch((newConfig, oldConfig) => {
console.log('設定が変更されました');
editor.updateConfig(newConfig.qwen);
});
module.exports = configManager;
設定検証
const Joi = require('joi');
// 設定スキーマ
const configSchema = Joi.object({
apiKey: Joi.string().required(),
region: Joi.string().default('ap-northeast-1'),
timeout: Joi.number().min(1000).max(300000).default(30000),
maxRetries: Joi.number().min(0).max(10).default(3),
cache: Joi.object({
enabled: Joi.boolean().default(true),
storage: Joi.string().valid('memory', 'redis', 'file').default('memory'),
ttl: Joi.number().min(1000).default(3600000)
}).default(),
logging: Joi.object({
level: Joi.string().valid('debug', 'info', 'warn', 'error').default('info'),
format: Joi.string().valid('text', 'json').default('text')
}).default()
});
// 設定検証関数
function validateConfig(config) {
const { error, value } = configSchema.validate(config, {
allowUnknown: true,
stripUnknown: false
});
if (error) {
throw new Error(`設定エラー: ${error.details[0].message}`);
}
return value;
}
// 使用例
try {
const validatedConfig = validateConfig(rawConfig);
const editor = new QwenImageEdit(validatedConfig);
} catch (error) {
console.error('設定が無効です:', error.message);
process.exit(1);
}
シークレット管理
// secrets/manager.js
const AWS = require('aws-sdk');
const { SecretManagerServiceClient, GetSecretValueCommand } = require('@aws-sdk/client-secrets-manager');
class SecretManager {
constructor() {
this.client = new SecretManagerServiceClient({
region: process.env.AWS_REGION || 'ap-northeast-1'
});
this.cache = new Map();
}
async getSecret(secretName) {
// キャッシュから取得
if (this.cache.has(secretName)) {
const cached = this.cache.get(secretName);
if (Date.now() < cached.expiry) {
return cached.value;
}
}
try {
const command = new GetSecretValueCommand({
SecretId: secretName
});
const response = await this.client.send(command);
const secret = JSON.parse(response.SecretString);
// 5分間キャッシュ
this.cache.set(secretName, {
value: secret,
expiry: Date.now() + 300000
});
return secret;
} catch (error) {
console.error(`シークレット取得エラー: ${secretName}`, error);
throw error;
}
}
}
// 使用例
const secretManager = new SecretManager();
async function createEditor() {
const secrets = await secretManager.getSecret('qwen-image-edit-secrets');
return new QwenImageEdit({
apiKey: secrets.apiKey,
region: secrets.region
});
}
🎯 次のステップ
質問がありますか? サポートチームにお気軽にお問い合わせください。