最佳实践
本章节提供使用XAI-SDK开发AI应用的最佳实践和性能优化技巧。
🚀 性能优化
1. 请求优化
批量处理
当需要处理多个相似请求时,使用批量处理可以显著提高效率:
javascript
// ❌ 不推荐:逐个处理
const results = [];
for (const item of items) {
const result = await sdk.chat(`处理:${item}`);
results.push(result);
}
// ✅ 推荐:批量处理
const messages = items.map(item => `处理:${item}`);
const results = await sdk.batchChat(messages);
并发控制
javascript
// 控制并发数量,避免API限制
const pLimit = require('p-limit');
const limit = pLimit(5); // 最多5个并发请求
const promises = items.map(item => limit(() => sdk.chat(`处理:${item}`)));
const results = await Promise.all(promises);
2. 缓存策略
响应缓存
javascript
// 启用智能缓存
const sdk = new XAI_SDK({
apiKey: process.env.OPENAI_API_KEY,
provider: 'openai',
cache: {
enabled: true,
ttl: 3600, // 1小时
maxSize: 1000,
// 自定义缓存键生成
keyGenerator: (message, options) => {
return `${message}-${JSON.stringify(options)}`;
},
},
});
本地缓存实现
javascript
class LocalCache {
constructor(maxSize = 100) {
this.cache = new Map();
this.maxSize = maxSize;
}
get(key) {
const item = this.cache.get(key);
if (item && item.expires > Date.now()) {
return item.value;
}
this.cache.delete(key);
return null;
}
set(key, value, ttl = 3600000) {
if (this.cache.size >= this.maxSize) {
const firstKey = this.cache.keys().next().value;
this.cache.delete(firstKey);
}
this.cache.set(key, {
value,
expires: Date.now() + ttl,
});
}
}
const cache = new LocalCache();
// 使用缓存包装SDK调用
const cachedChat = async message => {
const cacheKey = `chat:${message}`;
const cached = cache.get(cacheKey);
if (cached) {
return cached;
}
const result = await sdk.chat(message);
cache.set(cacheKey, result);
return result;
};
3. 连接管理
javascript
// 配置连接池
const sdk = new XAI_SDK({
apiKey: process.env.OPENAI_API_KEY,
provider: 'openai',
pool: {
maxConnections: 10,
keepAlive: true,
timeout: 30000,
retryDelay: 1000,
},
});
// 优雅关闭
process.on('SIGTERM', async () => {
console.log('正在关闭SDK连接...');
await sdk.close();
process.exit(0);
});
🛡️ 错误处理
1. 重试机制
javascript
class RetryableSDK {
constructor(sdk, options = {}) {
this.sdk = sdk;
this.maxRetries = options.maxRetries || 3;
this.baseDelay = options.baseDelay || 1000;
this.maxDelay = options.maxDelay || 10000;
}
async chatWithRetry(message, options = {}) {
let lastError;
for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
try {
return await this.sdk.chat(message, options);
} catch (error) {
lastError = error;
// 不重试的错误类型
if (this.isNonRetryableError(error)) {
throw error;
}
if (attempt < this.maxRetries) {
const delay = Math.min(
this.baseDelay * Math.pow(2, attempt),
this.maxDelay
);
console.log(
`重试 ${attempt + 1}/${this.maxRetries},${delay}ms后重试`
);
await this.sleep(delay);
}
}
}
throw lastError;
}
isNonRetryableError(error) {
const nonRetryableCodes = [
'INVALID_API_KEY',
'INSUFFICIENT_QUOTA',
'INVALID_REQUEST',
];
return nonRetryableCodes.includes(error.code);
}
sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
}
// 使用示例
const retryableSDK = new RetryableSDK(sdk, {
maxRetries: 3,
baseDelay: 1000,
});
try {
const result = await retryableSDK.chatWithRetry('你好');
console.log(result);
} catch (error) {
console.error('最终失败:', error.message);
}
2. 错误分类处理
javascript
class ErrorHandler {
static handle(error) {
switch (error.code) {
case 'RATE_LIMIT_EXCEEDED':
return this.handleRateLimit(error);
case 'NETWORK_ERROR':
return this.handleNetworkError(error);
case 'INVALID_API_KEY':
return this.handleAuthError(error);
case 'INSUFFICIENT_QUOTA':
return this.handleQuotaError(error);
default:
return this.handleUnknownError(error);
}
}
static handleRateLimit(error) {
const retryAfter = error.retryAfter || 60;
console.warn(`请求频率限制,${retryAfter}秒后重试`);
return { shouldRetry: true, delay: retryAfter * 1000 };
}
static handleNetworkError(error) {
console.warn('网络错误,将重试');
return { shouldRetry: true, delay: 2000 };
}
static handleAuthError(error) {
console.error('API密钥无效,请检查配置');
return { shouldRetry: false };
}
static handleQuotaError(error) {
console.error('配额不足,请检查账户余额');
return { shouldRetry: false };
}
static handleUnknownError(error) {
console.error('未知错误:', error.message);
return { shouldRetry: false };
}
}
// 使用错误处理器
const chatWithErrorHandling = async message => {
try {
return await sdk.chat(message);
} catch (error) {
const handling = ErrorHandler.handle(error);
if (handling.shouldRetry) {
await new Promise(resolve => setTimeout(resolve, handling.delay));
return chatWithErrorHandling(message); // 递归重试
}
throw error;
}
};
🔒 安全最佳实践
1. API密钥管理
javascript
// ✅ 推荐:使用环境变量
const sdk = new XAI_SDK({
apiKey: process.env.OPENAI_API_KEY,
provider: 'openai',
});
// ❌ 不推荐:硬编码API密钥
const sdk = new XAI_SDK({
apiKey: 'sk-xxxxxxxxxxxxxxxx', // 永远不要这样做!
provider: 'openai',
});
// 密钥验证
if (!process.env.OPENAI_API_KEY) {
throw new Error('OPENAI_API_KEY环境变量未设置');
}
2. 输入验证和清理
javascript
class InputValidator {
static sanitize(input) {
if (typeof input !== 'string') {
throw new Error('输入必须是字符串');
}
// 移除潜在的恶意内容
return input
.trim()
.slice(0, 4000) // 限制长度
.replace(/[<>"'&]/g, ''); // 移除HTML特殊字符
}
static validateMessage(message) {
if (!message || message.length === 0) {
throw new Error('消息不能为空');
}
if (message.length > 4000) {
throw new Error('消息长度不能超过4000字符');
}
// 检查敏感内容
const sensitivePatterns = [
/password/i,
/api[_-]?key/i,
/secret/i,
/token/i,
];
for (const pattern of sensitivePatterns) {
if (pattern.test(message)) {
console.warn('检测到可能的敏感信息');
break;
}
}
return true;
}
}
// 安全的聊天函数
const secureChat = async rawMessage => {
try {
InputValidator.validateMessage(rawMessage);
const sanitizedMessage = InputValidator.sanitize(rawMessage);
return await sdk.chat(sanitizedMessage);
} catch (error) {
console.error('输入验证失败:', error.message);
throw error;
}
};
3. 访问控制
javascript
class AccessControl {
constructor() {
this.rateLimits = new Map();
this.maxRequestsPerMinute = 60;
}
checkRateLimit(userId) {
const now = Date.now();
const userRequests = this.rateLimits.get(userId) || [];
// 清理过期的请求记录
const validRequests = userRequests.filter(
timestamp => now - timestamp < 60000
);
if (validRequests.length >= this.maxRequestsPerMinute) {
throw new Error('请求频率过高,请稍后重试');
}
validRequests.push(now);
this.rateLimits.set(userId, validRequests);
return true;
}
async authorizedChat(userId, message) {
this.checkRateLimit(userId);
return await secureChat(message);
}
}
const accessControl = new AccessControl();
// 使用访问控制
app.post('/chat', async (req, res) => {
try {
const { userId, message } = req.body;
const result = await accessControl.authorizedChat(userId, message);
res.json({ success: true, result });
} catch (error) {
res.status(429).json({ success: false, error: error.message });
}
});
📊 监控和日志
1. 性能监控
javascript
class PerformanceMonitor {
constructor() {
this.metrics = {
totalRequests: 0,
successfulRequests: 0,
failedRequests: 0,
totalResponseTime: 0,
averageResponseTime: 0,
};
}
async monitoredChat(message) {
const startTime = Date.now();
this.metrics.totalRequests++;
try {
const result = await sdk.chat(message);
this.metrics.successfulRequests++;
const responseTime = Date.now() - startTime;
this.metrics.totalResponseTime += responseTime;
this.metrics.averageResponseTime =
this.metrics.totalResponseTime / this.metrics.successfulRequests;
console.log(`请求成功,耗时: ${responseTime}ms`);
return result;
} catch (error) {
this.metrics.failedRequests++;
console.error(`请求失败,耗时: ${Date.now() - startTime}ms`);
throw error;
}
}
getStats() {
return {
...this.metrics,
successRate: this.metrics.successfulRequests / this.metrics.totalRequests,
errorRate: this.metrics.failedRequests / this.metrics.totalRequests,
};
}
logStats() {
const stats = this.getStats();
console.log('性能统计:', {
总请求数: stats.totalRequests,
成功率: `${(stats.successRate * 100).toFixed(2)}%`,
平均响应时间: `${stats.averageResponseTime.toFixed(2)}ms`,
});
}
}
const monitor = new PerformanceMonitor();
// 定期输出统计信息
setInterval(() => {
monitor.logStats();
}, 60000); // 每分钟输出一次
2. 结构化日志
javascript
const winston = require('winston');
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: 'error.log', level: 'error' }),
new winston.transports.File({ filename: 'combined.log' }),
new winston.transports.Console({
format: winston.format.simple(),
}),
],
});
class LoggingSDK {
constructor(sdk) {
this.sdk = sdk;
}
async chat(message, options = {}) {
const requestId = this.generateRequestId();
const startTime = Date.now();
logger.info('开始处理请求', {
requestId,
message: message.substring(0, 100), // 只记录前100个字符
options,
});
try {
const result = await this.sdk.chat(message, options);
const duration = Date.now() - startTime;
logger.info('请求处理成功', {
requestId,
duration,
responseLength: result.length,
});
return result;
} catch (error) {
const duration = Date.now() - startTime;
logger.error('请求处理失败', {
requestId,
duration,
error: error.message,
stack: error.stack,
});
throw error;
}
}
generateRequestId() {
return Math.random().toString(36).substring(2, 15);
}
}
const loggingSDK = new LoggingSDK(sdk);
🧪 测试策略
1. 单元测试
javascript
const { jest } = require('@jest/globals');
// 模拟SDK
const mockSDK = {
chat: jest.fn(),
};
describe('ChatService', () => {
beforeEach(() => {
mockSDK.chat.mockClear();
});
test('应该正确处理正常响应', async () => {
mockSDK.chat.mockResolvedValue('测试响应');
const service = new ChatService(mockSDK);
const result = await service.processMessage('测试消息');
expect(result).toBe('测试响应');
expect(mockSDK.chat).toHaveBeenCalledWith('测试消息');
});
test('应该正确处理错误', async () => {
const error = new Error('API错误');
mockSDK.chat.mockRejectedValue(error);
const service = new ChatService(mockSDK);
await expect(service.processMessage('测试消息')).rejects.toThrow('API错误');
});
});
2. 集成测试
javascript
describe('SDK集成测试', () => {
let sdk;
beforeAll(() => {
sdk = new XAI_SDK({
apiKey: process.env.TEST_API_KEY,
provider: 'openai',
});
});
afterAll(async () => {
await sdk.close();
});
test('应该能够进行基础对话', async () => {
const response = await sdk.chat('你好');
expect(response).toBeTruthy();
expect(typeof response).toBe('string');
}, 10000); // 10秒超时
test('应该能够处理流式响应', async () => {
const chunks = [];
const stream = sdk.streamChat('计数到5');
for await (const chunk of stream) {
chunks.push(chunk);
}
expect(chunks.length).toBeGreaterThan(0);
}, 15000);
});
🚀 部署最佳实践
1. 环境配置
javascript
// config/production.js
module.exports = {
sdk: {
apiKey: process.env.OPENAI_API_KEY,
provider: 'openai',
model: 'gpt-3.5-turbo',
timeout: 30000,
retries: 3,
cache: {
enabled: true,
ttl: 3600,
maxSize: 1000,
},
pool: {
maxConnections: 20,
keepAlive: true,
},
},
logging: {
level: 'info',
format: 'json',
},
monitoring: {
enabled: true,
interval: 60000,
},
};
// config/development.js
module.exports = {
sdk: {
apiKey: process.env.OPENAI_API_KEY,
provider: 'openai',
model: 'gpt-3.5-turbo',
timeout: 10000,
debug: true,
},
logging: {
level: 'debug',
format: 'simple',
},
};
2. 健康检查
javascript
class HealthChecker {
constructor(sdk) {
this.sdk = sdk;
}
async checkHealth() {
const checks = {
sdk: await this.checkSDK(),
memory: this.checkMemory(),
uptime: process.uptime(),
};
const isHealthy = Object.values(checks).every(check =>
typeof check === 'object' ? check.status === 'ok' : check
);
return {
status: isHealthy ? 'healthy' : 'unhealthy',
checks,
timestamp: new Date().toISOString(),
};
}
async checkSDK() {
try {
const startTime = Date.now();
await this.sdk.chat('健康检查');
const responseTime = Date.now() - startTime;
return {
status: 'ok',
responseTime,
};
} catch (error) {
return {
status: 'error',
error: error.message,
};
}
}
checkMemory() {
const usage = process.memoryUsage();
const totalMB = Math.round(usage.heapTotal / 1024 / 1024);
const usedMB = Math.round(usage.heapUsed / 1024 / 1024);
return {
status: usedMB < 500 ? 'ok' : 'warning', // 500MB阈值
totalMB,
usedMB,
usage: `${usedMB}/${totalMB}MB`,
};
}
}
// Express健康检查端点
app.get('/health', async (req, res) => {
const healthChecker = new HealthChecker(sdk);
const health = await healthChecker.checkHealth();
const statusCode = health.status === 'healthy' ? 200 : 503;
res.status(statusCode).json(health);
});
🔧 故障排除
常见问题和解决方案
1. API密钥问题
bash
# 错误:INVALID_API_KEY
# 解决方案:
# 1. 检查环境变量
echo $OPENAI_API_KEY
# 2. 验证密钥格式
# OpenAI密钥格式:sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# 3. 检查密钥权限和配额
2. 网络连接问题
javascript
// 配置代理
const sdk = new XAI_SDK({
apiKey: process.env.OPENAI_API_KEY,
provider: 'openai',
proxy: {
host: 'proxy.company.com',
port: 8080,
auth: {
username: 'user',
password: 'pass',
},
},
});
// 配置超时
const sdk = new XAI_SDK({
apiKey: process.env.OPENAI_API_KEY,
provider: 'openai',
timeout: 60000, // 60秒
retries: 5,
});
3. 内存泄漏问题
javascript
// 定期清理缓存
setInterval(() => {
sdk.clearCache();
if (global.gc) {
global.gc();
}
}, 300000); // 每5分钟清理一次
// 监控内存使用
setInterval(() => {
const usage = process.memoryUsage();
console.log('内存使用:', {
rss: Math.round(usage.rss / 1024 / 1024) + 'MB',
heapTotal: Math.round(usage.heapTotal / 1024 / 1024) + 'MB',
heapUsed: Math.round(usage.heapUsed / 1024 / 1024) + 'MB',
});
}, 60000); // 每分钟检查一次
📈 性能基准
推荐配置
场景 | 并发数 | 超时时间 | 缓存TTL | 重试次数 |
---|---|---|---|---|
开发环境 | 1-5 | 10s | 1h | 2 |
测试环境 | 5-10 | 30s | 30m | 3 |
生产环境 | 10-50 | 60s | 1h | 5 |
高并发 | 50-100 | 30s | 2h | 3 |
性能优化检查清单
- [ ] 启用响应缓存
- [ ] 配置合适的连接池大小
- [ ] 实现请求重试机制
- [ ] 使用批量处理
- [ ] 监控内存使用
- [ ] 设置合理的超时时间
- [ ] 实现优雅关闭
- [ ] 配置日志记录
- [ ] 添加健康检查
- [ ] 实现错误处理
🤝 社区贡献
贡献指南
报告问题
- 使用GitHub Issues报告bug
- 提供详细的复现步骤
- 包含环境信息和错误日志
提交代码
- Fork项目并创建特性分支
- 遵循代码规范
- 添加测试用例
- 更新文档
改进文档
- 修正错误和不准确的信息
- 添加使用示例
- 翻译文档
开发环境设置
bash
# 克隆项目
git clone https://github.com/xai-sdk/xai-sdk.git
cd xai-sdk
# 安装依赖
npm install
# 运行测试
npm test
# 构建项目
npm run build
# 启动开发服务器
npm run dev
通过遵循这些最佳实践,您可以构建出高性能、可靠且安全的AI应用。如果您有任何问题或建议,欢迎参与社区讨论!