使用Node.js构建轻量级服务代理转发请求至Taotoken聚合接口
告别海外账号与网络限制稳定直连全球优质大模型限时半价接入中。 点击领取海量免费额度使用Node.js构建轻量级服务代理转发请求至Taotoken聚合接口在开发基于大模型的应用时直接在前端或业务代码中硬编码API调用逻辑会带来维护复杂、密钥暴露风险等问题。本文将指导你使用Node.js和openai包构建一个简单的服务层统一管理向Taotoken发送的请求。这个服务层可以实现请求转发、异步处理、错误重试和基础的用量日志记录让你的应用架构更清晰、更健壮。1. 项目初始化与环境配置首先创建一个新的Node.js项目目录并初始化。我们将使用openai官方Node.js SDK来与Taotoken的OpenAI兼容接口通信。mkdir taotoken-proxy-service cd taotoken-proxy-service npm init -y接下来安装必要的依赖。核心是openaiSDK此外我们还需要express来创建HTTP服务以及dotenv来管理环境变量。npm install openai express dotenv npm install --save-dev nodemon在项目根目录创建.env文件用于安全地存储你的Taotoken API密钥。请确保将此文件添加到.gitignore中避免密钥泄露。# .env TAOTOKEN_API_KEY你的_Taotoken_API_Key PORT3000你需要在Taotoken控制台创建API Key并在模型广场查看你想使用的模型ID例如claude-sonnet-4-6或gpt-4o。2. 核心代理服务实现我们创建一个server.js文件作为服务入口。核心是初始化OpenAI客户端并配置正确的baseURL指向Taotoken。// server.js require(dotenv).config(); const express require(express); const OpenAI require(openai); const app express(); app.use(express.json()); // 初始化 OpenAI 客户端配置 Taotoken 端点 const client new OpenAI({ apiKey: process.env.TAOTOKEN_API_KEY, baseURL: https://taotoken.net/api, // 关键使用 Taotoken 的 OpenAI 兼容端点 }); // 简单的内存日志存储生产环境应替换为数据库 const requestLogs []; app.post(/v1/chat/completions, async (req, res) { const startTime Date.now(); const requestId req_${Date.now()}_${Math.random().toString(36).substr(2, 9)}; const userModel req.body.model || claude-sonnet-4-6; // 允许客户端指定或使用默认 const logEntry { id: requestId, timestamp: new Date().toISOString(), model: userModel, requestBody: req.body, status: pending, }; requestLogs.push(logEntry); try { // 调用 Taotoken 接口 const completion await client.chat.completions.create({ model: userModel, messages: req.body.messages, // 可以在这里传递其他参数如 temperature, max_tokens 等 ...req.body, }); const endTime Date.now(); logEntry.status success; logEntry.durationMs endTime - startTime; logEntry.response completion; // 简单记录用量实际应更精细如记录 token 数 logEntry.usage completion.usage; res.json(completion); } catch (error) { const endTime Date.now(); logEntry.status error; logEntry.durationMs endTime - startTime; logEntry.error error.message; console.error([${requestId}] 请求失败:, error.message); // 可以根据错误类型决定重试或返回特定状态码 res.status(500).json({ error: { message: 代理服务请求失败: ${error.message}, requestId: requestId, }, }); } }); // 添加一个简单的日志查询端点仅用于演示 app.get(/admin/logs, (req, res) { res.json({ total: requestLogs.length, logs: requestLogs.slice(-20).reverse(), // 返回最近20条 }); }); const PORT process.env.PORT || 3000; app.listen(PORT, () { console.log(Taotoken 代理服务运行在 http://localhost:${PORT}); });这个服务创建了一个/v1/chat/completions端点它接收与OpenAI Chat Completions API格式相同的请求体然后使用配置好的OpenAI客户端将其转发至Taotoken。所有请求都会被记录在内存数组中并包含状态、耗时等基本信息。3. 增强功能错误重试与基础日志上述基础版本缺乏健壮性。我们接下来实现一个简单的错误重试机制并改进日志记录使其包含更多对成本治理有用的信息。创建一个新的文件proxyService.js封装更健壮的请求逻辑。// proxyService.js const OpenAI require(openai); class TaotokenProxyService { constructor(apiKey) { this.client new OpenAI({ apiKey: apiKey, baseURL: https://taotoken.net/api, }); this.logs []; } async createChatCompletion(requestBody, maxRetries 2) { const requestId this._generateRequestId(); const startTime Date.now(); const model requestBody.model; const logEntry { id: requestId, timestamp: new Date().toISOString(), model: model, requestBody: { ...requestBody, messages: [...] }, // 简略化消息体保护隐私 retries: 0, status: pending, }; this.logs.push(logEntry); for (let attempt 0; attempt maxRetries; attempt) { try { logEntry.attempt attempt 1; console.log([${requestId}] 尝试第 ${attempt 1} 次请求模型: ${model}); const completion await this.client.chat.completions.create(requestBody); const endTime Date.now(); logEntry.status success; logEntry.durationMs endTime - startTime; logEntry.usage completion.usage; // 记录输入输出token用于成本分析 logEntry.provider completion.provider; // 如果Taotoken返回了供应商信息 console.log([${requestId}] 请求成功耗时 ${logEntry.durationMs}ms); return completion; } catch (error) { logEntry.lastError error.message; console.warn([${requestId}] 第 ${attempt 1} 次尝试失败:, error.message); // 判断是否为可重试错误例如网络错误、速率限制 if (this._isRetryableError(error) attempt maxRetries) { const delay Math.pow(2, attempt) * 1000; // 指数退避1s, 2s, 4s... console.log([${requestId}] ${delay}ms 后重试...); await new Promise(resolve setTimeout(resolve, delay)); continue; } else { // 不可重试或重试次数用尽 const endTime Date.now(); logEntry.status failed; logEntry.durationMs endTime - startTime; console.error([${requestId}] 请求最终失败); throw error; // 将错误抛给上层处理 } } } } _generateRequestId() { return req_${Date.now()}_${Math.random().toString(36).substr(2, 9)}; } _isRetryableError(error) { // 根据错误类型判断是否应该重试 // 网络错误、5xx服务器错误、速率限制通常可重试 const retryableMessages [timeout, network, rate limit, server error, ECONNRESET]; const errorMsg error.message.toLowerCase(); return retryableMessages.some(msg errorMsg.includes(msg)); } getRecentLogs(limit 50) { return this.logs.slice(-limit).reverse(); } // 一个简单的用量统计方法 getUsageSummary() { const successfulLogs this.logs.filter(log log.status success log.usage); const totalInputTokens successfulLogs.reduce((sum, log) sum (log.usage.prompt_tokens || 0), 0); const totalOutputTokens successfulLogs.reduce((sum, log) sum (log.usage.completion_tokens || 0), 0); return { totalRequests: this.logs.length, successfulRequests: successfulLogs.length, totalInputTokens, totalOutputTokens, estimatedCost: null, // 此处可接入具体模型的单价进行计算 }; } } module.exports TaotokenProxyService;然后更新server.js使用这个增强的服务类。// server.js (更新版) require(dotenv).config(); const express require(express); const TaotokenProxyService require(./proxyService); const app express(); app.use(express.json()); const proxyService new TaotokenProxyService(process.env.TAOTOKEN_API_KEY); app.post(/v1/chat/completions, async (req, res) { try { const completion await proxyService.createChatCompletion(req.body); res.json(completion); } catch (error) { console.error(代理请求失败:, error); res.status(500).json({ error: { message: Internal proxy server error, type: proxy_error, }, }); } }); app.get(/admin/logs, (req, res) { res.json({ logs: proxyService.getRecentLogs(20), summary: proxyService.getUsageSummary(), }); }); const PORT process.env.PORT || 3000; app.listen(PORT, () { console.log(增强版 Taotoken 代理服务运行在 http://localhost:${PORT}); });4. 客户端调用与部署建议现在你的前端或其他服务可以像调用本地API一样向这个代理服务发送请求了。// 前端或另一个Node.js服务中的调用示例 async function callTaotokenViaProxy(userMessage) { const response await fetch(http://localhost:3000/v1/chat/completions, { method: POST, headers: { Content-Type: application/json, // 可以在这里添加你自己的认证头例如内部API Key // X-Internal-Key: your-internal-secret }, body: JSON.stringify({ model: claude-sonnet-4-6, // 或从你的配置中读取 messages: [{ role: user, content: userMessage }], temperature: 0.7, }), }); if (!response.ok) { throw new Error(HTTP error! status: ${response.status}); } return await response.json(); }对于部署你有几个选择。对于生产环境建议使用pm2或docker来管理Node.js进程确保服务稳定运行。将.env中的PORT改为80或通过Nginx等反向代理进行转发。此外强烈建议将内存中的日志this.logs替换为持久化存储如写入文件系统或数据库例如SQLite、PostgreSQL并考虑按时间或大小进行日志轮转。这个轻量级代理服务为你提供了一个统一的管理平面未来可以轻松地在此基础之上添加更多功能如请求限流、更精细的模型路由策略基于性能或成本、将用量数据同步到数据库进行深度分析等。所有与大模型API相关的配置和变更都只需在这个服务中调整极大提升了项目的可维护性。 告别海外账号与网络限制稳定直连全球优质大模型限时半价接入中。 点击领取海量免费额度