Skip to content

Instantly share code, notes, and snippets.

@gcgcnfvd
Created January 10, 2024 07:45
Show Gist options
  • Save gcgcnfvd/49acec97b08c66ce823efb08d99004a0 to your computer and use it in GitHub Desktop.
Save gcgcnfvd/49acec97b08c66ce823efb08d99004a0 to your computer and use it in GitHub Desktop.
copilot express server 版
const express = require("express");
const axios = require("axios");
const cors = require("cors");
const bodyParser = require("body-parser");
const crypto = require("crypto");
const app = express();
const defaultToken = ``; // put your github token here!
const ghuToken = process.env.ghuToken || defaultToken;
const tokenCache = {
[ghuToken]: null,
};
// CORS 中间件
app.use(
cors({
origin: "*", // 允许所有来源
methods: ["GET", "POST", "OPTIONS"],
allowedHeaders: "*",
credentials: true,
})
);
// 用于解析JSON的中间件
app.use(bodyParser.json());
// 生成随机十六进制字符串的函数
function genHexStr(length) {
return crypto.randomBytes(length).toString("hex");
}
// 创建模拟请求头
function createHeaders(authorization) {
return {
Authorization: `Bearer ${authorization}`,
"X-Request-Id": `${genHexStr(4)}-${genHexStr(2)}-${genHexStr(
2
)}-${genHexStr(2)}-${genHexStr(6)}`,
"Vscode-Sessionid": `${genHexStr(4)}-${genHexStr(2)}-${genHexStr(
2
)}-${genHexStr(2)}-${genHexStr(12)}`,
"Vscode-Machineid": genHexStr(32),
"Editor-Version": "vscode/1.83.1",
"Editor-Plugin-Version": "copilot-chat/0.8.0",
"Openai-Organization": "github-copilot",
"Openai-Intent": "conversation-panel",
"Content-Type": "text/event-stream; charset=utf-8",
"User-Agent": "GitHubCopilotChat/0.8.0",
Accept: "*/*",
"Accept-Encoding": "gzip,deflate,br",
Connection: "close",
};
}
// 获取copilot token
async function getToken(githubToken) {
if (
tokenCache[githubToken] &&
tokenCache[githubToken]["expires_at"] * 1000 - 5 * 60 * 1000 > Date.now()
) {
return tokenCache[githubToken]["token"];
} else {
const tokenRes = await axios.get(
"https://api.github.com/copilot_internal/v2/token",
{
headers: {
Authorization: `token ${githubToken}`,
contentType: "application/json",
},
}
);
tokenCache[githubToken] = tokenRes.data;
return tokenCache[githubToken]["token"];
}
}
// GPT API
app.post("/v1/chat/completions", async (req, res) => {
const url = "https://api.githubcopilot.com/chat/completions";
const appToken = await getToken(ghuToken);
try {
const headers = createHeaders(appToken);
const response = await axios.post(url, req.body, { headers: headers });
// 处理响应
res.set({
"Transfer-Encoding": "chunked",
"X-Accel-Buffering": "no",
"Content-Type": "text/event-stream; charset=utf-8",
"Cache-Control": "no-cache",
Connection: "keep-alive",
});
res.send(response.data);
} catch (error) {
console.error(error);
res.status(500).send("Error in processing request");
}
});
const PORT = process.env.PORT || 7177;
app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
});
@gcgcnfvd
Copy link
Author

gcgcnfvd commented Jan 10, 2024

Usage:

curl -i -X POST
-H "Content-Type:application/json"
-d
'{
"model": "gpt-4",
"messages": [ {"role": "user", "content": "hello"}]
}'
'http://localhost:7177/v1/chat/completions'

@huaerss
Copy link

huaerss commented Jan 10, 2024

大佬,
就是把原来go的代码换成node 嘛 然后环节一样

@gcgcnfvd
Copy link
Author

大佬, 就是把原来go的代码换成node 嘛 然后环节一样

@huaerss
是的,其实我是把大佬的go代码丢给GPT,让它按照相同的逻辑写一份js版的,然后稍微改吧改吧就OK了

@huaerss
Copy link

huaerss commented Jan 12, 2024

ChatGPT-Next-Web 我使用这个搭建配合大佬你写的后端node 不是流的方式显示唉 是node代码中的问题嘛 @gcgcnfvd

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment