3766 字
19 分钟
使用代理访问各AI平台的API
项目地址
背景
由于各个 AI 公司对于中国大陆限制了访问,导致我们无法直接访问这些地区的 API,所以需要使用代理来访问这些地区的 API。
比如 OpenAI 的 API 访问限制:
- 中国大陆地区无法访问
- 香港地区无法访问
解决方案
在一台美国服务器上部署一个代理,然后使用这个代理来访问 AI API。
部署
我这里添加了 mongoose 来存储请求记录,所以需要安装 mongoose,如果你不需要则跳过。
# 初始化项目npm init -y# 安装 mongoosenpm install mongoose
使用 pm2 来启动项目:
# 启动项目pm2 start llm-proxy.js --name llm-proxy# 使用环境变量MONGODB_URI=mongodb://localhost:27017/llm-proxy PORT=8088 HOST=0.0.0.0 pm2 start llm-proxy.js --name llm-proxy# 查看项目pm2 list# 停止项目pm2 stop llm-proxy
代码
代理代码
// 导入 Node.js 内置模块const http = require('http');const https = require('https'); // 需要根据目标URL的协议选择 http 或 httpsconst fs = require('fs');const path = require('path');const { URL } = require('url');const mongoose = require('mongoose');
// 获取环境变量const PORT = process.env.PORT || 8088;const HOST = process.env.HOST || '0.0.0.0';const MONGODB_URI = process.env.MONGODB_URI || '';
// 如果 MONGODB_URI 存在,则使用 MongoDB 存储请求记录let AiProxyUsage = null;if (MONGODB_URI) { try { mongoose.connect(MONGODB_URI, { useNewUrlParser: true, useUnifiedTopology: true }); const AiProxyUsageSchema = new mongoose.Schema({ type: { type: String, required: true, }, createTime: { type: String, required: true, }, }); AiProxyUsage = mongoose?.models?.AiProxyUsage || mongoose.model('AiProxyUsage', AiProxyUsageSchema); } catch (error) { console.error(`Error connecting to MongoDB: ${error}`); }}
// API 路由映射const apiMapping = { '/discord': 'https://discord.com/api', '/telegram': 'https://api.telegram.org', '/openai': 'https://api.openai.com', '/claude': 'https://api.anthropic.com', '/gemini': 'https://generativelanguage.googleapis.com', '/meta': 'https://www.meta.ai/api', // 注意:实际的Meta API可能不同 '/groq': 'https://api.groq.com/openai', '/xai': 'https://api.x.ai', '/cohere': 'https://api.cohere.ai', '/huggingface': 'https://api-inference.huggingface.co', '/together': 'https://api.together.xyz', '/novita': 'https://api.novita.ai', '/portkey': 'https://api.portkey.ai', '/fireworks': 'https://api.fireworks.ai', '/openrouter': 'https://openrouter.ai/api'};
// 允许转发到目标 API 的请求头列表(小写)const allowedHeaders = ['accept', 'content-type', 'authorization'];
// 辅助函数:从路径名中提取匹配的前缀和剩余部分function extractPrefixAndRest(pathname, prefixes) { for (const prefix of prefixes) { if (pathname.startsWith(prefix)) { return [prefix, pathname.slice(prefix.length)]; } } return [null, null];}
// 创建 HTTP 服务器const server = http.createServer(async (req, res) => { // 解析请求 URL // Node.js 的 req.url 只包含路径和查询参数,需要结合 host 来构造完整 URL const requestUrl = new URL(req.url, `http://${req.headers.host}`); const pathname = requestUrl.pathname;
// 1. 处理根路径和 index.html -> 提供本地 HTML 文件 if (pathname === '/' || pathname === '/index.html') { const filePath = path.join(__dirname, 'index.html'); // 假设 index.html 在脚本同级目录下 fs.readFile(filePath, (err, data) => { if (err) { console.error(`Error reading index.html: ${err}`); res.writeHead(500, { 'Content-Type': 'text/plain' }); res.end('Internal Server Error - Could not read index.html'); } else { res.writeHead(200, { 'Content-Type': 'text/html' }); res.end(data); } }); return; // 结束请求处理 }
// 2. 处理 robots.txt if (pathname === '/robots.txt') { res.writeHead(200, { 'Content-Type': 'text/plain' }); res.end('User-agent: *\nDisallow: /'); return; // 结束请求处理 }
// 3. 处理 API 代理 const [prefix, rest] = extractPrefixAndRest(pathname, Object.keys(apiMapping));
if (!prefix) { // 如果路径不匹配任何已知前缀,返回 404 res.writeHead(404, { 'Content-Type': 'text/plain' }); res.end('Not Found'); return; // 结束请求处理 }
// 构建目标 API 的 URL const targetBaseUrl = apiMapping[prefix]; const targetUrl = `${targetBaseUrl}${rest}${requestUrl.search}`; // 包含查询参数
// 准备转发请求的选项 const options = { method: req.method, headers: {}, // agent: targetBaseUrl.startsWith('https') ? new https.Agent({ keepAlive: true }) : new http.Agent({ keepAlive: true }) // 可选:使用 agent 进行连接复用 };
// 复制允许的请求头 for (const key in req.headers) { if (allowedHeaders.includes(key.toLowerCase())) { options.headers[key] = req.headers[key]; } } // 确保 host 头部设置为目标主机,而不是代理服务器的主机 options.headers['host'] = new URL(targetBaseUrl).host;
// 选择 http 或 https 模块进行请求 const protocol = targetBaseUrl.startsWith('https') ? https : http;
// 创建代理请求 const proxyReq = protocol.request(targetUrl, options, (proxyRes) => { // 设置响应头 // 复制目标服务器的响应头到客户端响应 const responseHeaders = { ...proxyRes.headers }; // 复制一份
// 添加额外的安全响应头 responseHeaders['X-Content-Type-Options'] = 'nosniff'; responseHeaders['X-Frame-Options'] = 'DENY'; responseHeaders['Referrer-Policy'] = 'no-referrer'; // 可以选择性地删除或修改某些从目标服务器传来的头,例如 'transfer-encoding' // delete responseHeaders['transfer-encoding'];
// 将目标服务器的状态码和处理后的响应头写入客户端响应 res.writeHead(proxyRes.statusCode, responseHeaders);
// 将目标服务器的响应体流式传输到客户端响应 proxyRes.pipe(res, { end: true }); });
// 处理代理请求错误 proxyReq.on('error', (err) => { console.error(`Proxy request error: ${err}`); if (!res.headersSent) { res.writeHead(502, { 'Content-Type': 'text/plain' }); // 502 Bad Gateway } res.end('Bad Gateway'); });
// 使用 MongoDB 存储请求记录 if (MONGODB_URI && AiProxyUsage) { const usage = new AiProxyUsage({ type: prefix, createTime: new Date().toISOString(), }); usage.save(); }
// 将客户端请求体流式传输到代理请求 // 对于 GET, HEAD 等没有 body 的请求,这不会做任何事 req.pipe(proxyReq, { end: true });
});
// 启动服务器server.listen(PORT, HOST, () => { console.log(`Node.js proxy server running on http://${HOST}:${PORT}`); console.log(`Root path serves './index.html'`); console.log('Proxying the following prefixes:'); Object.keys(apiMapping).forEach(prefix => { console.log(` ${prefix} -> ${apiMapping[prefix]}`); });});
// 可选:更优雅地处理关闭信号,以便 pm2 reload/stopprocess.on('SIGINT', () => { console.log('SIGINT signal received: closing HTTP server'); server.close(() => { console.log('HTTP server closed'); process.exit(0); });});
前端页面
<!DOCTYPE html><html lang="zh-CN">
<head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>🚀</text></svg>"> <title>LLM Proxy - 简单、安全、高效</title> <!-- seo --> <meta name="description" content="LLM Proxy - 提供简单、安全、高效、免费的 API 代理服务,让您的 AI 应用更加稳定、快速。"> <meta name="keywords" content="LLM Proxy, API Proxy, AI, 代理, 简单, 安全, 高效"> <meta name="robots" content="index, follow"> <meta name="googlebot" content="index, follow"> <meta name="bingbot" content="index, follow"> <script src="https://cdn.tailwindcss.com?plugins=forms,typography,aspect-ratio,line-clamp"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/highlight.js@11.9.0/lib/languages/javascript.min.js"></script> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/highlight.js@11.9.0/styles/atom-one-light.min.css"> <script> // Tailwind 配置 tailwind.config = { theme: { extend: { fontFamily: { sans: ['-apple-system', 'BlinkMacSystemFont', 'SF Pro Display', 'SF Pro Text', 'Helvetica Neue', 'Arial', 'sans-serif'], mono: ['SF Mono', 'SFMono-Regular', 'Menlo', 'Monaco', 'Consolas', '"Liberation Mono"', '"Courier New"', 'monospace'], }, maxWidth: { 'screen-xl': '1280px', }, colors: { 'apple-blue': { 50: '#E8F2FF', 100: '#C9E0FF', 200: '#A6CDFF', 300: '#83BAFF', 400: '#5FA7FF', 500: '#3C94FF', 600: '#0071E3', // Apple 按钮蓝 700: '#0051A5', 800: '#00356B', 900: '#001A36', }, 'apple-gray': { 50: '#F9F9F9', // 浅灰背景 100: '#F5F5F7', // Apple 官网背景灰 200: '#E8E8ED', 300: '#D2D2D7', 400: '#B1B1B6', 500: '#86868B', // Apple 官网文字灰 600: '#6E6E73', 700: '#414144', 800: '#2D2D2F', 900: '#1D1D1F', // Apple 官网深色文字 } }, boxShadow: { 'apple': '0 2px 5px -1px rgba(0, 0, 0, 0.1), 0 2px 5px -1px rgba(0, 0, 0, 0.06)', 'apple-md': '0 4px 12px -2px rgba(0, 0, 0, 0.08), 0 2px 6px -1px rgba(0, 0, 0, 0.05)', 'apple-lg': '0 10px 20px -5px rgba(0, 0, 0, 0.1), 0 5px 10px -5px rgba(0, 0, 0, 0.04)', }, borderRadius: { 'apple': '10px', 'apple-sm': '6px' } } } } </script> <style type="text/tailwindcss"> body { -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; letter-spacing: -0.2px; } .copy-btn:disabled svg { color: theme('colors.green.500'); } /* 苹果风格滚动条 */ ::-webkit-scrollbar { width: 8px; height: 8px; } ::-webkit-scrollbar-track { background: #f3f4f6; /* gray-100 instead of apple-gray.100 */ border-radius: 100px; } ::-webkit-scrollbar-thumb { background: #d1d5db; /* gray-300 instead of apple-gray.300 */ border-radius: 100px; } ::-webkit-scrollbar-thumb:hover { background: #9ca3af; /* gray-400 instead of apple-gray.400 */ }
/* 代码高亮自定义样式 */ pre { position: relative; background: #f9fafb; /* gray-50 instead of apple-gray.50 */ border-radius: 0.375rem; /* rounded-md instead of borderRadius.apple-sm */ margin: 0; padding: 1rem; overflow: auto; } pre code { font-family: theme('fontFamily.mono'); font-size: 0.9rem; line-height: 1.5; display: block; padding: 0; } /* 关键词高亮样式 */ .hljs-keyword { color: #0033cc; font-weight: 500; } /* 字符串高亮样式 */ .hljs-string { color: #067d17; } /* 注释高亮样式 */ .hljs-comment { color: #888888; font-style: italic; } /* 函数高亮样式 */ .hljs-function { color: #6f42c1; } /* 数字高亮样式 */ .hljs-number { color: #986801; } /* 属性高亮样式 */ .hljs-attr, .hljs-property { color: #e36209; } .code-container { position: relative; border-radius: 0.375rem; /* rounded-md instead of borderRadius.apple-sm */ box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06); /* shadow-sm instead of boxShadow.apple */ overflow: hidden; width: 100%; max-width: 100%; margin: 0 auto; } .code-header { display: flex; justify-content: space-between; align-items: center; padding: 0.5rem 1rem; background: #f3f4f6; /* gray-100 instead of apple-gray.100 */ border-bottom: 1px solid #e5e7eb; /* gray-200 instead of apple-gray.200 */ } .code-title { font-size: 0.85rem; font-weight: 500; color: #4b5563; /* gray-600 instead of apple-gray.600 */ } .code-copy-btn { background: transparent; border: none; cursor: pointer; padding: 0.25rem; border-radius: 4px; color: #6b7280; /* gray-500 instead of apple-gray.500 */ transition: all 0.2s; } .code-copy-btn:hover { color: #2563eb; /* blue-600 instead of apple-blue.600 */ background: rgba(0, 0, 0, 0.05); } </style> <script> // 确保highlight.js在页面加载完成后立即执行高亮 window.onload = function () { hljs.configure({ languages: ['javascript'] }); hljs.highlightAll(); }; </script></head>
<body class="bg-apple-gray-50 text-apple-gray-900 font-sans flex flex-col items-center min-h-screen py-8 px-4">
<div class="w-full max-w-screen-xl space-y-6 md:space-y-8">
<div class="bg-gradient-to-br from-blue-600 to-blue-400 rounded-apple shadow-apple-lg text-center p-8 md:p-12"> <h1 class="text-4xl md:text-6xl font-medium tracking-tight mb-2 md:mb-3 text-white">LLM Proxy</h1> <h2 class="text-xl md:text-2xl font-light mb-6 md:mb-8 text-white/90">简单、安全、高效</h2> <p class="text-base md:text-xl leading-relaxed font-light text-white/90 mx-auto"> 使用美国西部服务器,免费提供简单、安全、高效的 API 代理服务,让您的 AI 应用更加稳定、快速。 </p> </div>
<div class="bg-white rounded-apple shadow-apple-md p-6 md:p-8"> <h2 class="text-xl md:text-2xl font-medium text-apple-gray-900 mb-3 text-left">可用端点</h2> <p class="text-sm md:text-base font-light text-apple-gray-600 mb-6">选择并配置您需要的 AI 服务接口</p> <div class="overflow-x-auto rounded-apple-sm"> <table class="w-full text-left text-sm md:text-base table-fixed"> <thead> <tr> <th class="w-[18%] pb-3 pt-2 px-3 md:px-4 font-medium text-apple-gray-600 border-b border-apple-gray-200"> 服务 </th> <th class="w-[42%] pb-3 pt-2 px-3 md:px-4 font-medium text-apple-gray-600 border-b border-apple-gray-200"> 代理地址 </th> <th class="w-[40%] pb-3 pt-2 px-3 md:px-4 font-medium text-apple-gray-600 border-b border-apple-gray-200"> 原始地址</th> </tr> </thead> <tbody class="divide-y divide-apple-gray-200"> <tr> <td class="py-3.5 px-3 md:px-4 font-medium text-apple-gray-800 align-middle">OpenAI</td> <td class="py-3.5 px-3 md:px-4 align-middle"> <div class="flex items-center gap-1"> <span class="font-mono text-apple-gray-600 break-words min-w-0 text-sm">https://llm-proxy.mihouo.com/openai</span> <button class="copy-btn flex-shrink-0 p-1.5 rounded-full text-apple-gray-500 hover:bg-apple-gray-100 hover:text-apple-blue-600 focus:outline-none focus:ring-1 focus:ring-apple-blue-500 transition-colors duration-150" data-copy-text="https://llm-proxy.mihouo.com/openai" aria-label="复制地址"> </button> </div> </td> <td class="py-3.5 px-3 md:px-4 align-middle"> <a href="https://platform.openai.com/docs/api-reference" target="_blank" rel="noopener noreferrer" class="font-mono text-apple-blue-600 hover:underline break-words text-sm">https://api.openai.com</a> </td> </tr> <tr> <td class="py-3.5 px-3 md:px-4 font-medium text-apple-gray-800 align-middle">Anthropic Claude</td> <td class="py-3.5 px-3 md:px-4 align-middle"> <div class="flex items-center gap-1"> <span class="font-mono text-apple-gray-600 break-words min-w-0 text-sm">https://llm-proxy.mihouo.com/claude</span> <button class="copy-btn flex-shrink-0 p-1.5 rounded-full text-apple-gray-500 hover:bg-apple-gray-100 hover:text-apple-blue-600 focus:outline-none focus:ring-1 focus:ring-apple-blue-500 transition-colors duration-150" data-copy-text="https://llm-proxy.mihouo.com/claude" aria-label="复制地址"> </button> </div> </td> <td class="py-3.5 px-3 md:px-4 align-middle"> <a href="https://docs.anthropic.com/claude/reference/getting-started-with-the-api" target="_blank" rel="noopener noreferrer" class="font-mono text-apple-blue-600 hover:underline break-words text-sm">https://api.anthropic.com</a> </td> </tr> <tr> <td class="py-3.5 px-3 md:px-4 font-medium text-apple-gray-800 align-middle">Google Gemini</td> <td class="py-3.5 px-3 md:px-4 align-middle"> <div class="flex items-center gap-1"> <span class="font-mono text-apple-gray-600 break-words min-w-0 text-sm">https://llm-proxy.mihouo.com/gemini</span> <button class="copy-btn flex-shrink-0 p-1.5 rounded-full text-apple-gray-500 hover:bg-apple-gray-100 hover:text-apple-blue-600 focus:outline-none focus:ring-1 focus:ring-apple-blue-500 transition-colors duration-150" data-copy-text="https://llm-proxy.mihouo.com/gemini" aria-label="复制地址"> </button> </div> </td> <td class="py-3.5 px-3 md:px-4 align-middle"> <a href="https://ai.google.dev/api/rest" target="_blank" rel="noopener noreferrer" class="font-mono text-apple-blue-600 hover:underline break-words text-sm">https://generativelanguage.googleapis.com</a> </td> </tr> <tr> <td class="py-3.5 px-3 md:px-4 font-medium text-apple-gray-800 align-middle">Groq</td> <td class="py-3.5 px-3 md:px-4 align-middle"> <div class="flex items-center gap-1"> <span class="font-mono text-apple-gray-600 break-words min-w-0 text-sm">https://llm-proxy.mihouo.com/groq</span> <button class="copy-btn flex-shrink-0 p-1.5 rounded-full text-apple-gray-500 hover:bg-apple-gray-100 hover:text-apple-blue-600 focus:outline-none focus:ring-1 focus:ring-apple-blue-500 transition-colors duration-150" data-copy-text="https://llm-proxy.mihouo.com/groq" aria-label="复制地址"> </button> </div> </td> <td class="py-3.5 px-3 md:px-4 align-middle"> <a href="https://console.groq.com/docs/api-reference" target="_blank" rel="noopener noreferrer" class="font-mono text-apple-blue-600 hover:underline break-words text-sm">https://api.groq.com</a> </td> </tr> <tr> <td class="py-3.5 px-3 md:px-4 font-medium text-apple-gray-800 align-middle">Meta AI</td> <td class="py-3.5 px-3 md:px-4 align-middle"> <div class="flex items-center gap-1"> <span class="font-mono text-apple-gray-600 break-words min-w-0 text-sm">https://llm-proxy.mihouo.com/meta</span> <button class="copy-btn flex-shrink-0 p-1.5 rounded-full text-apple-gray-500 hover:bg-apple-gray-100 hover:text-apple-blue-600 focus:outline-none focus:ring-1 focus:ring-apple-blue-500 transition-colors duration-150" data-copy-text="https://llm-proxy.mihouo.com/meta" aria-label="复制地址"> </button> </div> </td> <td class="py-3.5 px-3 md:px-4 align-middle"> <a href="https://developers.facebook.com/docs/graph-api" target="_blank" rel="noopener noreferrer" class="font-mono text-apple-blue-600 hover:underline break-words text-sm">https://developers.facebook.com/docs/graph-api</a> </td> </tr> <tr> <td class="py-3.5 px-3 md:px-4 font-medium text-apple-gray-800 align-middle">Cohere</td> <td class="py-3.5 px-3 md:px-4 align-middle"> <div class="flex items-center gap-1"> <span class="font-mono text-apple-gray-600 break-words min-w-0 text-sm">https://llm-proxy.mihouo.com/cohere</span> <button class="copy-btn flex-shrink-0 p-1.5 rounded-full text-apple-gray-500 hover:bg-apple-gray-100 hover:text-apple-blue-600 focus:outline-none focus:ring-1 focus:ring-apple-blue-500 transition-colors duration-150" data-copy-text="https://llm-proxy.mihouo.com/cohere" aria-label="复制地址"> </button> </div> </td> <td class="py-3.5 px-3 md:px-4 align-middle"> <a href="https://docs.cohere.com/reference/about" target="_blank" rel="noopener noreferrer" class="font-mono text-apple-blue-600 hover:underline break-words text-sm">https://api.cohere.ai</a> </td> </tr> <tr> <td class="py-3.5 px-3 md:px-4 font-medium text-apple-gray-800 align-middle">Together AI</td> <td class="py-3.5 px-3 md:px-4 align-middle"> <div class="flex items-center gap-1"> <span class="font-mono text-apple-gray-600 break-words min-w-0 text-sm">https://llm-proxy.mihouo.com/together</span> <button class="copy-btn flex-shrink-0 p-1.5 rounded-full text-apple-gray-500 hover:bg-apple-gray-100 hover:text-apple-blue-600 focus:outline-none focus:ring-1 focus:ring-apple-blue-500 transition-colors duration-150" data-copy-text="https://llm-proxy.mihouo.com/together" aria-label="复制地址"> </button> </div> </td> <td class="py-3.5 px-3 md:px-4 align-middle"> <a href="https://docs.together.ai/reference/inference" target="_blank" rel="noopener noreferrer" class="font-mono text-apple-blue-600 hover:underline break-words text-sm">https://api.together.xyz</a> </td> </tr> <tr> <td class="py-3.5 px-3 md:px-4 font-medium text-apple-gray-800 align-middle">X.ai (Grok)</td> <td class="py-3.5 px-3 md:px-4 align-middle"> <div class="flex items-center gap-1"> <span class="font-mono text-apple-gray-600 break-words min-w-0 text-sm">https://llm-proxy.mihouo.com/xai</span> <button class="copy-btn flex-shrink-0 p-1.5 rounded-full text-apple-gray-500 hover:bg-apple-gray-100 hover:text-apple-blue-600 focus:outline-none focus:ring-1 focus:ring-apple-blue-500 transition-colors duration-150" data-copy-text="https://llm-proxy.mihouo.com/xai" aria-label="复制地址"> </button> </div> </td> <td class="py-3.5 px-3 md:px-4 align-middle"> <a href="https://docs.x.ai/" target="_blank" rel="noopener noreferrer" class="font-mono text-apple-blue-600 hover:underline break-words text-sm">https://api.x.ai</a> </td> </tr> <tr> <td class="py-3.5 px-3 md:px-4 font-medium text-apple-gray-800 align-middle">Hugging Face</td> <td class="py-3.5 px-3 md:px-4 align-middle"> <div class="flex items-center gap-1"> <span class="font-mono text-apple-gray-600 break-words min-w-0 text-sm">https://llm-proxy.mihouo.com/huggingface</span> <button class="copy-btn flex-shrink-0 p-1.5 rounded-full text-apple-gray-500 hover:bg-apple-gray-100 hover:text-apple-blue-600 focus:outline-none focus:ring-1 focus:ring-apple-blue-500 transition-colors duration-150" data-copy-text="https://llm-proxy.mihouo.com/huggingface" aria-label="复制地址"> </button> </div> </td> <td class="py-3.5 px-3 md:px-4 align-middle"> <a href="https://huggingface.co/docs/api-inference/index" target="_blank" rel="noopener noreferrer" class="font-mono text-apple-blue-600 hover:underline break-words text-sm">https://api-inference.huggingface.co</a> </td> </tr> <tr> <td class="py-3.5 px-3 md:px-4 font-medium text-apple-gray-800 align-middle">OpenRouter</td> <td class="py-3.5 px-3 md:px-4 align-middle"> <div class="flex items-center gap-1"> <span class="font-mono text-apple-gray-600 break-words min-w-0 text-sm">https://llm-proxy.mihouo.com/openrouter</span> <button class="copy-btn flex-shrink-0 p-1.5 rounded-full text-apple-gray-500 hover:bg-apple-gray-100 hover:text-apple-blue-600 focus:outline-none focus:ring-1 focus:ring-apple-blue-500 transition-colors duration-150" data-copy-text="https://llm-proxy.mihouo.com/openrouter" aria-label="复制地址"> </button> </div> </td> <td class="py-3.5 px-3 md:px-4 align-middle"> <a href="https://openrouter.ai/docs" target="_blank" rel="noopener noreferrer" class="font-mono text-apple-blue-600 hover:underline break-words text-sm">https://openrouter.ai/api</a> </td> </tr> <tr> <td class="py-3.5 px-3 md:px-4 font-medium text-apple-gray-800 align-middle">Fireworks AI</td> <td class="py-3.5 px-3 md:px-4 align-middle"> <div class="flex items-center gap-1"> <span class="font-mono text-apple-gray-600 break-words min-w-0 text-sm">https://llm-proxy.mihouo.com/fireworks</span> <button class="copy-btn flex-shrink-0 p-1.5 rounded-full text-apple-gray-500 hover:bg-apple-gray-100 hover:text-apple-blue-600 focus:outline-none focus:ring-1 focus:ring-apple-blue-500 transition-colors duration-150" data-copy-text="https://llm-proxy.mihouo.com/fireworks" aria-label="复制地址"> </button> </div> </td> <td class="py-3.5 px-3 md:px-4 align-middle"> <a href="https://readme.fireworks.ai/reference/introduction" target="_blank" rel="noopener noreferrer" class="font-mono text-apple-blue-600 hover:underline break-words text-sm">https://api.fireworks.ai</a> </td> </tr> <tr> <td class="py-3.5 px-3 md:px-4 font-medium text-apple-gray-800 align-middle">Portkey AI</td> <td class="py-3.5 px-3 md:px-4 align-middle"> <div class="flex items-center gap-1"> <span class="font-mono text-apple-gray-600 break-words min-w-0 text-sm">https://llm-proxy.mihouo.com/portkey</span> <button class="copy-btn flex-shrink-0 p-1.5 rounded-full text-apple-gray-500 hover:bg-apple-gray-100 hover:text-apple-blue-600 focus:outline-none focus:ring-1 focus:ring-apple-blue-500 transition-colors duration-150" data-copy-text="https://llm-proxy.mihouo.com/portkey" aria-label="复制地址"> </button> </div> </td> <td class="py-3.5 px-3 md:px-4 align-middle"> <a href="https://portkey.ai/docs/api-reference/introduction" target="_blank" rel="noopener noreferrer" class="font-mono text-apple-blue-600 hover:underline break-words text-sm">https://api.portkey.ai</a> </td> </tr> <tr> <td class="py-3.5 px-3 md:px-4 font-medium text-apple-gray-800 align-middle">Novita AI</td> <td class="py-3.5 px-3 md:px-4 align-middle"> <div class="flex items-center gap-1"> <span class="font-mono text-apple-gray-600 break-words min-w-0 text-sm">https://llm-proxy.mihouo.com/novita</span> <button class="copy-btn flex-shrink-0 p-1.5 rounded-full text-apple-gray-500 hover:bg-apple-gray-100 hover:text-apple-blue-600 focus:outline-none focus:ring-1 focus:ring-apple-blue-500 transition-colors duration-150" data-copy-text="https://llm-proxy.mihouo.com/novita" aria-label="复制地址"> </button> </div> </td> <td class="py-3.5 px-3 md:px-4 align-middle"> <a href="https://docs.novita.ai/api-reference" target="_blank" rel="noopener noreferrer" class="font-mono text-apple-blue-600 hover:underline break-words text-sm">https://api.novita.ai</a> </td> </tr> <tr> <td class="py-3.5 px-3 md:px-4 font-medium text-apple-gray-800 align-middle">Discord</td> <td class="py-3.5 px-3 md:px-4 align-middle"> <div class="flex items-center gap-1"> <span class="font-mono text-apple-gray-600 break-words min-w-0 text-sm">https://llm-proxy.mihouo.com/discord</span> <button class="copy-btn flex-shrink-0 p-1.5 rounded-full text-apple-gray-500 hover:bg-apple-gray-100 hover:text-apple-blue-600 focus:outline-none focus:ring-1 focus:ring-apple-blue-500 transition-colors duration-150" data-copy-text="https://llm-proxy.mihouo.com/discord" aria-label="复制地址"> </button> </div> </td> <td class="py-3.5 px-3 md:px-4 align-middle"> <a href="https://discord.com/developers/docs/intro" target="_blank" rel="noopener noreferrer" class="font-mono text-apple-blue-600 hover:underline break-words text-sm">https://discord.com/api</a> </td> </tr> <tr> <td class="py-3.5 px-3 md:px-4 font-medium text-apple-gray-800 align-middle">Telegram</td> <td class="py-3.5 px-3 md:px-4 align-middle"> <div class="flex items-center gap-1"> <span class="font-mono text-apple-gray-600 break-words min-w-0 text-sm">https://llm-proxy.mihouo.com/telegram</span> <button class="copy-btn flex-shrink-0 p-1.5 rounded-full text-apple-gray-500 hover:bg-apple-gray-100 hover:text-apple-blue-600 focus:outline-none focus:ring-1 focus:ring-apple-blue-500 transition-colors duration-150" data-copy-text="https://llm-proxy.mihouo.com/telegram" aria-label="复制地址"> </button> </div> </td> <td class="py-3.5 px-3 md:px-4 align-middle"> <a href="https://core.telegram.org/bots/api" target="_blank" rel="noopener noreferrer" class="font-mono text-apple-blue-600 hover:underline break-words text-sm">https://core.telegram.org/bots/api</a> </td> </tr> </tbody> </table> </div> </div>
<!-- 使用示例 --> <div class="bg-white rounded-apple shadow-apple-md p-6 md:p-8 text-center"> <h2 class="text-xl md:text-2xl font-medium mb-4 text-apple-gray-800">使用示例</h2> <p class="text-base md:text-lg font-light text-apple-gray-600 mb-6">通过几行简单的代码,即可轻松连接到 API 服务</p>
<div class="code-container mx-auto text-left"> <div class="code-header"> <span class="code-title">JavaScript</span> <button class="code-copy-btn" aria-label="复制代码"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="w-4 h-4" viewBox="0 0 16 16"> <path d="M4 1.5H3a2 2 0 0 0-2 2V14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V3.5a2 2 0 0 0-2-2h-1v1h1a1 1 0 0 1 1 1V14a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V3.5a1 1 0 0 1 1-1h1v-1z"> </path> <path d="M9.5 1a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5h-3a.5.5 0 0 1-.5-.5v-1a.5.5 0 0 1 .5-.5h3zm-3-1A1.5 1.5 0 0 0 5 1.5v1A1.5 1.5 0 0 0 6.5 4h3A1.5 1.5 0 0 0 11 2.5v-1A1.5 1.5 0 0 0 9.5 0h-3z"> </path> </svg> </button> </div> <pre><code class="language-javascript">// 导入 OpenAI 库const { OpenAI } = require('openai');
// 创建 API 客户端实例const openai = new OpenAI({ apiKey: 'sk-**************************************', baseURL: 'https://llm-proxy.mihouo.com/openai/v1',});
// 发送请求示例async function generateResponse() { const response = await openai.chat.completions.create({ model: "gpt-3.5-turbo", messages: [ { role: "system", content: "你是一个专业的AI助手。" }, { role: "user", content: "你好,请介绍一下自己。" } ], temperature: 0.7, });
console.log(response.choices[0].message.content);}</code></pre> </div> </div>
<div class="bg-white rounded-apple shadow-apple-md p-6 text-center"> <div class="flex flex-col md:flex-row items-center justify-center space-y-2 md:space-y-0 md:space-x-8"> <p class="flex items-center text-apple-gray-500 text-sm"> <span class="inline-block w-2.5 h-2.5 bg-green-500 rounded-full mr-2"></span> <span class="font-light">状态:</span> <span class="text-apple-gray-700 font-medium ml-1">运行中</span> </p> <p class="text-sm text-apple-gray-500"> <span class="font-light">北京时间:</span> <span id="live-time" class="font-medium text-apple-gray-700 ml-1">加载中...</span> </p> </div> </div>
</div> <script> // 时间更新脚本 function updateLiveTime() { const timeElement = document.getElementById('live-time'); if (timeElement) { const now = new Date(); const beijingTime = now.toLocaleString('zh-CN', { timeZone: 'Asia/Shanghai', hour12: false, year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit' }); timeElement.textContent = beijingTime.replace(/[\/]/g, '-').replace(/\s+/g, ' ').trim(); } } updateLiveTime(); setInterval(updateLiveTime, 1000);
// --- 复制按钮脚本 --- document.addEventListener('DOMContentLoaded', () => { const copyButtons = document.querySelectorAll('.copy-btn');
// 确保在DOM加载完成后再次尝试高亮 hljs.configure({ languages: ['javascript'] }); hljs.highlightAll();
// 代码块复制功能 const codeBlock = document.querySelector('pre code'); const codeCopyBtn = document.querySelector('.code-copy-btn');
if (codeBlock && codeCopyBtn) { codeCopyBtn.addEventListener('click', () => { const code = codeBlock.textContent;
navigator.clipboard.writeText(code).then(() => { // 复制成功反馈 const originalSvg = codeCopyBtn.innerHTML;
// 替换为成功图标 codeCopyBtn.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="w-4 h-4 text-green-500" viewBox="0 0 16 16"><path d="M12.736 3.97a.733.733 0 0 1 1.047 0c.286.289.29.756.01 1.05L7.88 12.01a.733.733 0 0 1-1.065.02L3.217 8.384a.757.757 0 0 1 0-1.06.733.733 0 0 1 1.047 0l3.052 3.093 5.4-6.425z"/></svg>`;
// 1.5秒后恢复原始图标 setTimeout(() => { codeCopyBtn.innerHTML = originalSvg; }, 1500); }).catch(err => { console.error('无法复制代码: ', err); alert('复制失败,请手动复制。'); }); }); }
// SVG Icons - 苹果风格图标 const originalIconSvg = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="w-4 h-4" viewBox="0 0 16 16"><path d="M4 1.5H3a2 2 0 0 0-2 2V14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V3.5a2 2 0 0 0-2-2h-1v1h1a1 1 0 0 1 1 1V14a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V3.5a1 1 0 0 1 1-1h1v-1z"/><path d="M9.5 1a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5h-3a.5.5 0 0 1-.5-.5v-1a.5.5 0 0 1 .5-.5h3zm-3-1A1.5 1.5 0 0 0 5 1.5v1A1.5 1.5 0 0 0 6.5 4h3A1.5 1.5 0 0 0 11 2.5v-1A1.5 1.5 0 0 0 9.5 0h-3z"/></svg>`; const successIconSvg = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="w-4 h-4" viewBox="0 0 16 16"><path d="M12.736 3.97a.733.733 0 0 1 1.047 0c.286.289.29.756.01 1.05L7.88 12.01a.733.733 0 0 1-1.065.02L3.217 8.384a.757.757 0 0 1 0-1.06.733.733 0 0 1 1.047 0l3.052 3.093 5.4-6.425z"/></svg>`;
copyButtons.forEach(button => { button.innerHTML = originalIconSvg; // 设置初始图标
button.addEventListener('click', () => { const textToCopy = button.dataset.copyText;
if (!textToCopy) { console.error('无复制内容'); return; } if (!navigator.clipboard) { console.error('剪贴板 API 不可用'); alert('抱歉,您的浏览器不支持或未启用剪贴板功能。'); return; }
navigator.clipboard.writeText(textToCopy).then(() => { // 成功反馈 - 苹果风格的平滑过渡 button.innerHTML = successIconSvg; button.disabled = true;
setTimeout(() => { button.innerHTML = originalIconSvg; // 恢复图标 button.disabled = false; }, 1500); // 1.5秒后恢复
}).catch(err => { console.error('无法复制文本: ', err); alert('复制失败,请手动复制。'); }); }); }); }); </script></body>
</html>
使用代理访问各AI平台的API
https://www.mihouo.com/posts/tool-share/llm-api-proxy/