github models worker

我自己的号也被扬了一个

用 cursor 撸了一个 worker 代码

功能:

  1. 借助 KV, 直接进行迭代轮询
  2. 支持 流/非流
  3. 转发 tools 等

AUTH_TOKEN USER_API_KEYS 然后部署, 就行了

// 定义GitHub模型的端点
const ENDPOINT = 'https://models.inference.ai.azure.com';
const SUPPORTED_MODELS = ['gpt-4o', 'gpt-4o-mini'];

// 硬编码的固定token
const AUTH_TOKEN = 'sk-*'; // 请替换为您想要的16字符token

// 添加用户名和密钥的映射
const USER_API_KEYS = {
    "user_name": "ghp_..."
};

// 硬编码的API密钥列表
const API_KEYS = Object.values(USER_API_KEYS);

// 添加检查 API 密钥有效性的函数
async function checkApiKey(apiKey) {
    const response = await fetch(`${ENDPOINT}/chat/completions`, {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            'Authorization': `Bearer ${apiKey}`
        },
        body: JSON.stringify({
            messages: [{ role: 'user', content: 'Hello' }],
            max_tokens: 1,
            model: 'gpt-4o-mini'
        })
    });
    return response.status === 200;
}

async function getCurrentKeyIndex(env) {
    if (!env || !env.API_KEYS_KV) {
        console.error('env 或 API_KEYS_KV 未定义');
        return 0; // 返回默认值
    }
    try {
        let currentKeyIndex = await env.API_KEYS_KV.get('currentKeyIndex');
        if (currentKeyIndex === null) {
            currentKeyIndex = '0';
            await env.API_KEYS_KV.put('currentKeyIndex', currentKeyIndex);
        }
        return parseInt(currentKeyIndex);
    } catch (error) {
        console.error('获取或设置 currentKeyIndex 时出错:', error);
        return 0; // 返回默认值
    }
}

export default {
    async fetch(request, env, ctx) {
        const url = new URL(request.url);

        if (url.pathname === '/live' && request.method === 'GET') {
            const results = {};
            for (const [username, apiKey] of Object.entries(USER_API_KEYS)) {
                results[username] = await checkApiKey(apiKey);
            }
            return new Response(JSON.stringify(results), {
                headers: { 'Content-Type': 'application/json' }
            });
        }

        if (request.method !== 'POST' || (url.pathname !== '/chat/completions' && url.pathname !== '/v1/chat/completions')) {
            return new Response('Method Not Allowed', { status: 405 });
        }

        try {
            // 验证token
            const authHeader = request.headers.get('Authorization');
            if (!authHeader || !authHeader.startsWith('Bearer ') || authHeader.split(' ')[1] !== AUTH_TOKEN) {
                return new Response('Unauthorized', { status: 401 });
            }

            // 获取请求体
            const requestBody = await request.json();

            // 验证并清理消息
            if (!Array.isArray(requestBody.messages) || requestBody.messages.length === 0) {
                return new Response('Invalid request: messages must be a non-empty array', { status: 400 });
            }

            const cleanedMessages = requestBody.messages.map(message => ({
                role: message.role || 'user',
                content: message.content || ''
            }));

            // 验证模型
            const requestedModel = requestBody.model || SUPPORTED_MODELS[0];
            if (!SUPPORTED_MODELS.includes(requestedModel)) {
                return new Response(`Unsupported model: ${requestedModel}. Supported models are: ${SUPPORTED_MODELS.join(', ')}`, { status: 400 });
            }

            // 获取当前的API密钥索引
            let currentKeyIndex = await getCurrentKeyIndex(env);

            // 选择当前的API密��
            const apiKey = API_KEYS[currentKeyIndex];

            // 更新索引为下一个并存储到KV
            const nextIndex = (currentKeyIndex + 1) % API_KEYS.length;
            if (env && env.API_KEYS_KV) {
                await env.API_KEYS_KV.put('currentKeyIndex', nextIndex.toString());
            }

            // 准备请求参数
            const requestParams = {
                messages: cleanedMessages,
                model: requestedModel,
                stream: requestBody.stream || false // 添加 stream 参数
            };

            // 如果请求体中包含tools,则添加到请求参数中
            if (requestBody.tools) {
                requestParams.tools = requestBody.tools;
            }

            console.log('Request params:', JSON.stringify(requestParams));

            // 发送请求到OpenAI
            const response = await fetch(`${ENDPOINT}/chat/completions`, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'Authorization': `Bearer ${apiKey}`
                },
                body: JSON.stringify(requestParams)
            });

            console.log('Response status:', response.status);
            console.log('Response headers:', JSON.stringify(Object.fromEntries(response.headers)));

            // 处理流式响应
            if (requestParams.stream) {
                // 创建一个 TransformStream 来处理流式数据
                const { readable, writable } = new TransformStream({
                    async transform(chunk, controller) {
                        controller.enqueue(chunk);
                    },
                });

                // 开始流式传输响应
                response.body.pipeTo(writable);

                // 返回流式响应
                return new Response(readable, {
                    headers: {
                        'Content-Type': 'text/event-stream',
                        'Cache-Control': 'no-cache',
                        'Connection': 'keep-alive',
                    },
                });
            } else {
                // 非流式响应的处理保持不变
                const responseText = await response.text();
                console.log('Response body:', responseText);

                if (!response.ok) {
                    return new Response(`API request failed: ${response.status} ${response.statusText}\n${responseText}`, { status: response.status });
                }

                // 尝试解析 JSON
                let data;
                try {
                    data = JSON.parse(responseText);
                } catch (error) {
                    console.error('Failed to parse JSON:', error);
                    return new Response(`Failed to parse JSON response: ${responseText}`, { status: 500 });
                }

                // 返回响应
                return new Response(JSON.stringify(data), {
                    headers: { 'Content-Type': 'application/json' },
                });
            }
        } catch (error) {
            console.error('处理请求时发生错误:', error);
            return new Response(`Internal Server Error: ${error.message}`, { status: 500 });
        }
    }
};

22 个赞

感谢分享 这就部署上去

感谢佬友的解答!

github都被你们薅哭了 :sob:

楼主这个是部署在cloudflare上吗?

啊,还没通过

cloudflare workers

2 个赞

不至于不至于, 对于人微软来说, 这都是九牛一毛上的毛尖见

感谢分享~ 等我把号拿来了试试

再来一个多账号模式更完美 :rofl:

什么多账号?

直接切key,不就是了么?

感谢 分享 点赞