记录:通过 Cloudflare workers 使 Azure OpenAI API 兼容 OpenAI API

目的:

在 APP 端可以直接使用 OpenAI 设置。如果使用的是 Azure 设置在切换模型时需要手动改配置

原脚本:

haibbo/cf-openai-azure-proxy: A Cloudflare worker script to proxy OpenAI‘s request to Azure OpenAI Service (github.com)


最近 Azure OpenAI 也发布了 GPT-3.5-turbo-1106 和 GPT-4-turbo 模型。但由于这些模型又在一些特定资源地区才能用,为了能够使用新模型我需要新创建一个对应地区的资源组,这样我就有了多个资源。所以我需要解决的问题是将脚本能支持保持一个入口来访问不同的资源组,换言之在 APP 端则是不用为了切换模型而改 Azure OpenAI 的设置。

因此我做了以下优化,贴出关键代码可以抄作业:

/**
 * 将 mapper = {} 改为函数,key 不变,value 改为对应的资源组信息
 *
 * 创建一组环境变量
 *  - 其中 KEY 对内是用来验证 worker 的,对外则是当作 OpenAI API Key
 *  - 其他则是资源组的 key
 */

// key: model, value: {}
function getMappers(env) {
  return {
    'gpt-3.5-turbo': {
      // The name of your Azure OpenAI Resource.
      resourceName: 'region1',
      // The deployment name you chose when you deployed the model.
      deploymentName: 'deployment1',
      apiKey: env.REGION_KEY1
    },
    'gpt-3.5-turbo-16k': {
      resourceName: 'region2',
      deploymentName: 'deployment2',
      apiKey: env.REGION_KEY2
    },
    'gpt-4': {
      resourceName: 'region2',
      deploymentName: 'deployment2',
      apiKey: env.REGION_KEY2
    },
    'gpt-4-1106-preview': {
      resourceName: 'region2',
      deploymentName: 'deployment2',
      apiKey: env.REGION_KEY2
    },
  }
}

export default {
  async fetch(request, env, ctx) {
    return handleRequest(request, env, ctx)
  }
}

async function handleRequest(request, env, ctx) {
  // ...
  const modelName = body?.model;

  const mappers = getMappers(env)
  const options = mappers[modelName]

  // ...

  const { resourceName, deploymentName, apiKey } = options
  
  const fetchAPI = `https://${resourceName}.openai.azure.com/openai/deployments/${deploymentName}/${path}?api-version=${apiVersion}`

  const authKey = request.headers.get('Authorization');
  const KEY = env.KEY
  if (authKey.replace('Bearer ', '') !== KEY) {
    return new Response("KEY not allowed", {
      status: 403
    });
  }

  const payload = {
    method: request.method,
    headers: {
      "Content-Type": "application/json",
      "api-key": apiKey,
    },
    body: typeof body === 'object' ? JSON.stringify(body) : '{}',
  };
}

async function handleModels(request, env) {
  // ...
  const mappers = getMappers(env)
  for (let key in mappers) {
    // ...
  }
}

创建环境变量

Worker > Settings > Variables > Environment Variables

实际场景示例

使用 https://chatkit.app 举例,理论上支持其他支持自定义 OpenAI API Endpoint 的应用。

OpenAI API Key 填的是自定义的 Key,正如代码块说明,对外则是当作 OpenAI API Key 。

Powered by blogkit. Inspired by Sairin.