maltose1 commited on
Commit
f290067
·
verified ·
1 Parent(s): 46a964e

Upload 5 files

Browse files
Files changed (2) hide show
  1. README.md +71 -84
  2. app.js +147 -123
README.md CHANGED
@@ -1,84 +1,71 @@
1
- # DeepInfra to OpenAI API Adapter
2
-
3
- [![Deploy to Hugging Face Spaces](https://img.shields.io/badge/🤗%20Deploy%20to%20Hugging%20Face-Spaces-blue)](https://huggingface.co/new/space?template=deepinfra-openai-adapter)
4
-
5
- 这是一个代理服务,可以将 [DeepInfra](https://deepinfra.com/) 的模型 API 转换为与 OpenAI API 兼容的格式。这使得在各种为 OpenAI API 设计的客户端和工具中使用 DeepInfra 的模型成为可能。
6
-
7
- ## ✨ 功能
8
-
9
- - **OpenAI 格式兼容**:将 DeepInfra API 无缝转换为 OpenAI Chat Completions API 格式。
10
- - **模型列表接口**:支持 `/v1/models` 接口,可以获取预设的模型列表。
11
- - **自定义鉴权**:通过环境变量设置 `TOKEN`,保护你的 API 不被滥用。
12
- - **轻松部署**:可以一键部署到 Hugging Face Spaces
13
-
14
- ## 🚀 部署到 Hugging Face Spaces
15
-
16
- 按照以下步骤,你可以轻松地将此服务部署到你自己的 Hugging Face Space。
17
-
18
- 1. **创建 Space**
19
- - 点击上方的 "Deploy to Hugging Face Spaces" 徽章,或访问 [Hugging Face 新建 Space 页面](https://huggingface.co/new/space)。
20
- - 给你的 Space 起一个名字(`Space name`)。
21
- - `Select the Space SDK` 选项中,选择 **Docker**。
22
- - 在 `Docker template` 中,选择 **Blank**。
23
- - 点击 `Create Space`。
24
-
25
- 2. **上传文件**
26
- - 在你的 Space 页面,进入 `Files` 标签页。
27
- - 点击 `Add file` -> `Upload file`。
28
- - 将项目中的 `app.js` `Dockerfile` 这两个文件上传。
29
-
30
- 3. **设置 API 密钥**
31
- - 在你的 Space 页面,进入 `Settings` 标签页。
32
- - 找到 `Secrets management` 部分,点击 `New secret`。
33
- - 在 `Name` 字段中输入 `TOKEN`。
34
- - 在 `Value` 字段中输入一个你自己的密码,例如 `sk-my-secret-key-12345`。这个密码将作为访问你服务的 API Key。
35
- - 点击 `Save secret`。Hugging Face 会自动重新构建你的 Space 以应用这个密钥。
36
-
37
- 部署完成后,你的 Space 页面应该会显示 `Running` 状态。
38
-
39
- ## 🛠️ 如何使用
40
-
41
- 部署成功后,你就可以在任何支持 OpenAI API 的客户端或代码中配置并使用你的代理了。
42
-
43
- - **API 地址 (Endpoint / Base URL)**:
44
- 你的 Hugging Face Space 的公开 URL,格式为 `https://<你的用户名>-<你的Space名>.hf.space`。
45
- **重要**: 请在 URL 后面加上 `/v1`,完整的地址应该是 `https://<你的用户名>-<你的Space名>.hf.space/v1`。
46
-
47
- - **API 密钥 (API Key)**:
48
- 你在 Hugging Face `TOKEN` 密钥中设置的值。
49
-
50
- - **模型名称**:
51
- 任何 DeepInfra 支持的模型,或者使用 `/v1/models` 接口中提供的模型,例如:
52
- - `deepseek-ai/DeepSeek-R1-0528-Turbo`
53
- - `deepseek-ai/DeepSeek-V3-0324-Turbo`
54
- - `deepseek-ai/DeepSeek-R1-Distill-Llama-70B`
55
-
56
- ### 使用 cURL 测试
57
-
58
- 你可以使用 `curl` 命令来测试你的服务是否正常工作。
59
-
60
- #### 获取模型列表
61
- ```bash
62
- curl https://<你的用户名>-<你的Space名>.hf.space/v1/models \
63
- -H "Authorization: Bearer <你的TOKEN>"
64
- ```
65
-
66
- #### 发起聊天请求
67
- ```bash
68
- curl https://<你的用户名>-<你的Space名>.hf.space/v1/chat/completions \
69
- -H "Content-Type: application/json" \
70
- -H "Authorization: Bearer <你的TOKEN>" \
71
- -d '{
72
- "model": "deepseek-ai/DeepSeek-R1-0528-Turbo",
73
- "messages": [
74
- {
75
- "role": "user",
76
- "content": "Hello, how are you?"
77
- }
78
- ],
79
- "stream": false
80
- }'
81
- ```
82
- > 将 `<你的用户名>-<你的Space名>` 和 `<你的TOKEN>` 替换为你自己的信息。
83
-
84
- 现在你可以随时随地使用 DeepInfra 上的优秀模型了!
 
1
+ ---
2
+ title: DeepInfra to OpenAI Adapter
3
+ emoji: 🚀
4
+ colorFrom: blue
5
+ colorTo: green
6
+ sdk: docker
7
+ pinned: false
8
+ ---
9
+
10
+ # DeepInfra to OpenAI API Adapter
11
+
12
+ [![Deploy to Hugging Face Spaces](https://img.shields.io/badge/🤗%20Deploy%20to%20Hugging%20Face-Spaces-blue)](https://huggingface.co/new/space?template=deepinfra-openai-adapter)
13
+
14
+ 这是一个代理服务,可以将 [DeepInfra](https://deepinfra.com/) 的模型 API 转换为与 OpenAI API 兼容的格式。这使得在各种为 OpenAI API 设计的客户端和工具中使用 DeepInfra 的模型成为可能。
15
+
16
+ ## 功能
17
+
18
+ - **OpenAI 格式兼容**:将 DeepInfra API 无缝转换为 OpenAI Chat Completions API 格式。
19
+ - **模型列表接口**:支持 `/v1/models` 接口,可以获取预设的模型列表。
20
+ - **自定义鉴权**:通过环境变量设置 `TOKEN`,保护你的 API 不被滥用。
21
+ - **轻松部署**:可以一键部署到 Hugging Face Spaces。
22
+
23
+ ## 🚀 部署到 Hugging Face Spaces
24
+
25
+ 按照以下步骤,你可以轻松地将此服务部署到你自己的 Hugging Face Space。
26
+
27
+ 1. **创建 Space**
28
+ - 点击上方的 "Deploy to Hugging Face Spaces" 徽章,或访问 [Hugging Face 新建 Space 页面](https://huggingface.co/new/space)。
29
+ - 给你的 Space 起一个名字(`Space name`)。
30
+ - `Select the Space SDK` 选项中,选择 **Docker**。
31
+ - `Docker template` 中,选择 **Blank**。
32
+ - 点击 `Create Space`。
33
+
34
+ 2. **上传文件**
35
+ - 在你的 Space 页面,进入 `Files` 标签页。
36
+ - 点击 `Add file` -> `Upload file`。
37
+ - 将项目中的 `app.js` `Dockerfile` 这两个文件上传。
38
+
39
+ 3. **设置 API 密钥**
40
+ - 在你的 Space 页面,进入 `Settings` 标签页。
41
+ - 找到 `Secrets management` 部分,点击 `New secret`。
42
+ - 在 `Name` 字段中输入 `TOKEN`。
43
+ - `Value` 字段中输入一个你自己的密码,例如 `sk-my-secret-key-12345`。这个密码将作为访问你服务的 API Key。
44
+ - 点击 `Save secret`。Hugging Face 会自动重新构建你的 Space 以应用这个密钥。
45
+
46
+ 部署完成后,你的 Space 页面应该会显示 `Running` 状态。
47
+
48
+ ## 🛠️ 如何使用
49
+
50
+ 部署成功后,你就可以在任何支持 OpenAI API 的客户端或代码中配置并使用你的代理了。
51
+
52
+ - **API 地址 (Endpoint / Base URL)**:
53
+ 你的 Hugging Face Space 的公开 URL,格式为 `https://<你的用户名>-<你的Space名>.hf.space`。
54
+ **重要**: 请在 URL 后面加上 `/v1`,完整的地址应该是 `https://<你的用户名>-<你的Space名>.hf.space/v1`。
55
+
56
+ - **API 密钥 (API Key)**:
57
+ 你在 Hugging Face `TOKEN` 密钥中设置的值。
58
+
59
+ - **模型名称**:
60
+ 任何 DeepInfra 支持的模型,或者使用 `/v1/models` 接口中提供的模型,例如:
61
+ - `deepseek-ai/DeepSeek-R1-0528-Turbo`
62
+ - `deepseek-ai/DeepSeek-V3-0324-Turbo`
63
+ - `deepseek-ai/DeepSeek-R1-Distill-Llama-70B`
64
+ - `zai-org/GLM-4.6`
65
+ - `moonshotai/Kimi-K2-Instruct`
66
+ - `deepseek-ai/DeepSeek-V3.2-Exp`
67
+ - `deepseek-ai/DeepSeek-V3.1-Terminus`
68
+
69
+ ### 使用 cURL 测试
70
+
71
+ 你可以使用 `
 
 
 
 
 
 
 
 
 
 
 
 
 
app.js CHANGED
@@ -1,123 +1,147 @@
1
- import { serve } from "https://deno.land/std/http/server.ts";
2
-
3
- const handler = async (request) => {
4
- const url = new URL(request.url);
5
-
6
- // Handle CORS preflight requests
7
- if (request.method === "OPTIONS") {
8
- return new Response(null, {
9
- headers: {
10
- "Access-Control-Allow-Origin": "*",
11
- "Access-Control-Allow-Methods": "POST, GET, OPTIONS",
12
- "Access-Control-Allow-Headers": "Content-Type, Authorization",
13
- "Access-Control-Max-Age": "86400",
14
- },
15
- });
16
- }
17
-
18
- const TOKEN = Deno.env.get("TOKEN");
19
-
20
- // Authentication check
21
- if (TOKEN) {
22
- const authHeader = request.headers.get("Authorization");
23
- if (!authHeader || authHeader !== `Bearer ${TOKEN}`) {
24
- return new Response("Unauthorized", {
25
- status: 401,
26
- headers: {
27
- "Content-Type": "application/json",
28
- "Access-Control-Allow-Origin": "*",
29
- },
30
- });
31
- }
32
- }
33
-
34
- // Handle /v1/models endpoint
35
- if (url.pathname === "/v1/models" && request.method === "GET") {
36
- const models = {
37
- object: "list",
38
- data: [
39
- {
40
- id: "deepseek-ai/DeepSeek-R1-0528-Turbo",
41
- object: "model",
42
- created: 1624980000,
43
- owned_by: "deepseek-ai",
44
- },
45
- {
46
- id: "deepseek-ai/DeepSeek-V3-0324-Turbo",
47
- object: "model",
48
- created: 1632000000,
49
- owned_by: "deepseek-ai",
50
- },
51
- {
52
- id: "deepseek-ai/DeepSeek-R1-Distill-Llama-70B",
53
- object: "model",
54
- created: 1640000000,
55
- owned_by: "deepseek-ai",
56
- },
57
- ],
58
- };
59
-
60
- return new Response(JSON.stringify(models), {
61
- headers: {
62
- "Content-Type": "application/json",
63
- "Access-Control-Allow-Origin": "*",
64
- },
65
- });
66
- }
67
-
68
- // Handle chat completions
69
- if (url.pathname === "/v1/chat/completions" && request.method === "POST") {
70
- try {
71
- const body = await request.json();
72
- const headers = new Headers({
73
- "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36 Edg/133.0.0.0",
74
- "Accept": "text/event-stream",
75
- "Accept-Encoding": "gzip, deflate, br, zstd",
76
- "Content-Type": "application/json",
77
- "sec-ch-ua-platform": "Windows",
78
- "X-Deepinfra-Source": "web-page",
79
- "sec-ch-ua": '"Not(A:Brand";v="99", "Microsoft Edge";v="133", "Chromium";v="133"',
80
- "sec-ch-ua-mobile": "?0",
81
- "Origin": "https://deepinfra.com",
82
- "Sec-Fetch-Site": "same-site",
83
- "Sec-Fetch-Mode": "cors",
84
- "Sec-Fetch-Dest": "empty",
85
- "Referer": "https://deepinfra.com/",
86
- });
87
-
88
- const response = await fetch("https://api.deepinfra.com/v1/openai/chat/completions", {
89
- method: "POST",
90
- headers: headers,
91
- body: JSON.stringify(body),
92
- });
93
-
94
- return new Response(response.body, {
95
- status: response.status,
96
- statusText: response.statusText,
97
- headers: {
98
- "Access-Control-Allow-Origin": "*",
99
- "Content-Type": response.headers.get("Content-Type") || "application/json",
100
- },
101
- });
102
- } catch (error) {
103
- return new Response(JSON.stringify({ error: error.message }), {
104
- status: 500,
105
- headers: {
106
- "Content-Type": "application/json",
107
- "Access-Control-Allow-Origin": "*",
108
- },
109
- });
110
- }
111
- }
112
-
113
- return new Response("Not Found", {
114
- status: 404,
115
- headers: {
116
- "Access-Control-Allow-Origin": "*",
117
- }
118
- });
119
- };
120
-
121
- const port = Deno.env.get("PORT") ? parseInt(Deno.env.get("PORT")) : 7860;
122
- console.log(`HTTP server running. Access it at: http://localhost:${port}/`);
123
- serve(handler, { port });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { serve } from "https://deno.land/std/http/server.ts";
2
+
3
+ const handler = async (request) => {
4
+ const url = new URL(request.url);
5
+
6
+ // Handle CORS preflight requests
7
+ if (request.method === "OPTIONS") {
8
+ return new Response(null, {
9
+ headers: {
10
+ "Access-Control-Allow-Origin": "*",
11
+ "Access-Control-Allow-Methods": "POST, GET, OPTIONS",
12
+ "Access-Control-Allow-Headers": "Content-Type, Authorization",
13
+ "Access-Control-Max-Age": "86400",
14
+ },
15
+ });
16
+ }
17
+
18
+ const TOKEN = Deno.env.get("TOKEN");
19
+
20
+ // Authentication check
21
+ if (TOKEN) {
22
+ const authHeader = request.headers.get("Authorization");
23
+ if (!authHeader || authHeader !== `Bearer ${TOKEN}`) {
24
+ return new Response("Unauthorized", {
25
+ status: 401,
26
+ headers: {
27
+ "Content-Type": "application/json",
28
+ "Access-Control-Allow-Origin": "*",
29
+ },
30
+ });
31
+ }
32
+ }
33
+
34
+ // Handle /v1/models endpoint
35
+ if (url.pathname === "/v1/models" && request.method === "GET") {
36
+ const models = {
37
+ object: "list",
38
+ data: [
39
+ {
40
+ id: "deepseek-ai/DeepSeek-R1-0528-Turbo",
41
+ object: "model",
42
+ created: 1624980000,
43
+ owned_by: "deepseek-ai",
44
+ },
45
+ {
46
+ id: "deepseek-ai/DeepSeek-V3-0324-Turbo",
47
+ object: "model",
48
+ created: 1632000000,
49
+ owned_by: "deepseek-ai",
50
+ },
51
+ {
52
+ id: "deepseek-ai/DeepSeek-R1-Distill-Llama-70B",
53
+ object: "model",
54
+ created: 1640000000,
55
+ owned_by: "deepseek-ai",
56
+ },
57
+ {
58
+ id: "zai-org/GLM-4.6",
59
+ object: "model",
60
+ created: 1720000000,
61
+ owned_by: "zai-org",
62
+ },
63
+ {
64
+ id: "moonshotai/Kimi-K2-Instruct",
65
+ object: "model",
66
+ created: 1721000000,
67
+ owned_by: "moonshotai",
68
+ },
69
+ {
70
+ id: "deepseek-ai/DeepSeek-V3.2-Exp",
71
+ object: "model",
72
+ created: 1722000000,
73
+ owned_by: "deepseek-ai",
74
+ },
75
+ {
76
+ id: "deepseek-ai/DeepSeek-V3.1-Terminus",
77
+ object: "model",
78
+ created: 1723000000,
79
+ owned_by: "deepseek-ai",
80
+ },
81
+ ],
82
+ };
83
+
84
+ return new Response(JSON.stringify(models), {
85
+ headers: {
86
+ "Content-Type": "application/json",
87
+ "Access-Control-Allow-Origin": "*",
88
+ },
89
+ });
90
+ }
91
+
92
+ // Handle chat completions
93
+ if (url.pathname === "/v1/chat/completions" && request.method === "POST") {
94
+ try {
95
+ const body = await request.json();
96
+ const headers = new Headers({
97
+ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36 Edg/133.0.0.0",
98
+ "Accept": "text/event-stream",
99
+ "Accept-Encoding": "gzip, deflate, br, zstd",
100
+ "Content-Type": "application/json",
101
+ "sec-ch-ua-platform": "Windows",
102
+ "X-Deepinfra-Source": "web-page",
103
+ "sec-ch-ua": '"Not(A:Brand";v="99", "Microsoft Edge";v="133", "Chromium";v="133"',
104
+ "sec-ch-ua-mobile": "?0",
105
+ "Origin": "https://deepinfra.com",
106
+ "Sec-Fetch-Site": "same-site",
107
+ "Sec-Fetch-Mode": "cors",
108
+ "Sec-Fetch-Dest": "empty",
109
+ "Referer": "https://deepinfra.com/",
110
+ });
111
+
112
+ const response = await fetch("https://api.deepinfra.com/v1/openai/chat/completions", {
113
+ method: "POST",
114
+ headers: headers,
115
+ body: JSON.stringify(body),
116
+ });
117
+
118
+ return new Response(response.body, {
119
+ status: response.status,
120
+ statusText: response.statusText,
121
+ headers: {
122
+ "Access-Control-Allow-Origin": "*",
123
+ "Content-Type": response.headers.get("Content-Type") || "application/json",
124
+ },
125
+ });
126
+ } catch (error) {
127
+ return new Response(JSON.stringify({ error: error.message }), {
128
+ status: 500,
129
+ headers: {
130
+ "Content-Type": "application/json",
131
+ "Access-Control-Allow-Origin": "*",
132
+ },
133
+ });
134
+ }
135
+ }
136
+
137
+ return new Response("Not Found", {
138
+ status: 404,
139
+ headers: {
140
+ "Access-Control-Allow-Origin": "*",
141
+ }
142
+ });
143
+ };
144
+
145
+ const port = Deno.env.get("PORT") ? parseInt(Deno.env.get("PORT")) : 7860;
146
+ console.log(`HTTP server running. Access it at: http://localhost:${port}/`);
147
+ serve(handler, { port });