github models worker 分享

之前讲过调用 github models 可以直接走:
https://models.inference.ai.azure.com/chat/completions#
不过这样 /v1/models、/v1/embeddings 的路由依旧没法请求,有些应用可能需要强制获取 models 才能调用 api (比如sider,openwebui),而且 github 获取 models 的响应格式、字段和 oai 的也有区别[1],索性薅个 cf worker,开个帖子记录并分享一下

cf worker
addEventListener('fetch', event => {
  event.respondWith(handleRequest(event.request))
})

/**
 * 处理传入的请求
 * @param {Request} request
 */
async function handleRequest(request) {
  const { method, url } = request
  const originalUrl = new URL(url)

  // 允许的方法
  const allowedMethods = ['OPTIONS', 'GET', 'POST']
  if (!allowedMethods.includes(method)) {
    return new Response('Method Not Allowed', { status: 405 })
  }

  // 处理 CORS 预检请求
  if (method === 'OPTIONS') {
    return handleOptions()
  }

  // 修改目标 URL
  const targetUrl = new URL(request.url)
  targetUrl.hostname = 'models.inference.ai.azure.com'
  // 移除路径中的 /v1 前缀
  targetUrl.pathname = originalUrl.pathname.replace(/^\/v1/, '')

  // 创建新的请求,保留原始请求的头部和方法
  const newRequest = new Request(targetUrl.toString(), {
    method: request.method,
    headers: request.headers,
    body: request.method === 'POST' ? request.body : null,
    redirect: 'follow'
  })

  try {
    const response = await fetch(newRequest)

    // 如果请求路径是 /v1/models,则修改响应
    if (originalUrl.pathname === '/v1/models') {
      // 解析响应为 JSON
      const data = await response.json()

      // 确保响应是一个数组
      if (Array.isArray(data)) {
        let modifiedData = data.map(item => {
          const newItem = { ...item }
          if ('id' in newItem) {
            newItem.id_original = newItem.id
            delete newItem.id
          }
          if ('name' in newItem) {
            newItem.id = newItem.name
            delete newItem.name
          }
          return newItem
        })
        modifiedData = JSON.stringify(
          {'data': modifiedData}
        )
        
        // 返回修改后的响应
        return new Response(modifiedData, {
          status: response.status,
          statusText: response.statusText,
          headers: {
            ...response.headers,
            'Content-Type': 'application/json'
          }
        })
      } else {
        // 如果响应不是数组,直接返回原始响应
        return response
      }
    }

    // 对于其他路径,直接返回原始响应
    return response
  } catch (error) {
    return new Response('Internal Server Error', { status: 500 })
  }
}

/**
 * 处理 CORS 预检请求
 */
function handleOptions() {
  return new Response(null, {
    status: 204,
    headers: {
      'Access-Control-Allow-Origin': '*',
      'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
      'Access-Control-Allow-Headers': 'Content-Type, Authorization',
      'Access-Control-Max-Age': '86400'
    }
  })
}

前情摘要:


  1. oai 的 /v1/models 响应格式是: { “data”: [{“id”: model1,xxx}, {“id”: model2,xxx}], … },
    github models 的响应格式是: [ {“name”: model1, xxx}, {“name”: model2, xxx}, …],修改操作主要就是做了字段重命名,多余的字段没有处理 ↩︎

21 个赞

我也去更新一下,谢谢佬友

2 个赞

就没有大佬给源头提PR么

1 个赞

可以 :xhs_033:等会试试

不错不错:+1::+1::+1::+1:

源头,什么源头,要一个个客户端去反馈嘛,那多麻烦,而且 sider 是人家闭源的产品唉,人家本来也是按照 openai 格式设计的,是 github 不直接按照规范来,github 这种提供了完整请求参数了的,也不好意思让它更换格式吧

1 个赞

:joy: :joy:是的,被佬友惯坏了,习惯了白嫖

干活满满啊,感谢

感谢大佬分享

太强了宝贝!

大佬太强了!

厉害了,佬,强强