9 Commits

Author SHA1 Message Date
Vinlic
fc5c13b650 Release 0.0.11 2024-03-14 23:38:30 +08:00
Vinlic
4949b16091 支持多路refresh_token 2024-03-14 23:21:22 +08:00
Vinlic
17809274a5 update 2024-03-14 15:52:27 +08:00
Vinlic
228d18712b 补充Nginx反代优化 2024-03-14 15:09:46 +08:00
Vinlic
2da3e804f3 增加响应耗时比较 2024-03-14 14:43:30 +08:00
Vinlic
efdf5a229c 流传输耗时显示 2024-03-13 22:58:50 +08:00
Vinlic
4083abf4e0 Release 0.0.10 2024-03-13 22:47:50 +08:00
Vinlic
153ebdc1c8 添加流传输完毕提示 2024-03-13 22:44:14 +08:00
Vinlic
c54f89e9f8 修复新token的存储 2024-03-13 22:39:35 +08:00
4 changed files with 63 additions and 13 deletions

View File

@@ -5,7 +5,7 @@
![](https://img.shields.io/github/forks/llm-red-team/kimi-free-api.svg)
![](https://img.shields.io/docker/pulls/vinlic/kimi-free-api.svg)
支持高速流式输出、支持多轮对话、支持联网搜索、支持长文档解读、支持图像解析,零配置部署,自动清理会话痕迹。
支持高速流式输出、支持多轮对话、支持联网搜索、支持长文档解读、支持图像解析,零配置部署,多路token支持自动清理会话痕迹。
与ChatGPT接口完全兼容。
@@ -15,6 +15,7 @@
* [在线体验](#在线体验)
* [效果示例](#效果示例)
* [接入准备](#接入准备)
* [多账号接入](#多账号接入)
* [Docker部署](#Docker部署)
* [Docker-compose部署](#Docker-compose部署)
* [原生部署](#原生部署)
@@ -22,14 +23,16 @@
* [对话补全](#对话补全)
* [文档解读](#文档解读)
* [图像解析](#图像解析)
* [注意事项](#注意事项)
* [Nginx反代优化](#Nginx反代优化)
## 声明
仅限自用,禁止对外提供服务,避免对官方造成服务压力,否则风险自担!
仅限自用,禁止对外提供服务或商用,避免对官方造成服务压力,否则风险自担!
仅限自用,禁止对外提供服务,避免对官方造成服务压力,否则风险自担!
仅限自用,禁止对外提供服务或商用,避免对官方造成服务压力,否则风险自担!
仅限自用,禁止对外提供服务,避免对官方造成服务压力,否则风险自担!
仅限自用,禁止对外提供服务或商用,避免对官方造成服务压力,否则风险自担!
## 在线体验
@@ -59,14 +62,26 @@ https://udify.app/chat/Po0F6BMJ15q5vu2P
![图像解析](./doc/example-3.png)
### 响应流畅度一致
![响应流畅度一致](https://github.com/LLM-Red-Team/kimi-free-api/assets/20235341/48c7ec00-2b03-46c4-95d0-452d3075219b)
## 接入准备
从 [kimi.moonshot.cn](https://kimi.moonshot.cn) 获取refresh_token
进入kimi随便发起一个对话然后F12打开开发者工具从Application > Local Storage中找到refresh_token的值这将作为Authorization的Bearer KEY值。
进入kimi随便发起一个对话然后F12打开开发者工具从Application > Local Storage中找到refresh_token的值这将作为Authorization的Bearer Token值`Authorization: Bearer TOKEN`
![example0](./doc/example-0.png)
### 多账号接入
目前kimi限制普通账号每3小时内只能进行30轮长文本的问答你可以通过提供多个账号的refresh_token并使用`,`拼接提供:
`Authorization: Bearer TOKEN1,TOKEN2,TOKEN3`
每次请求服务会从中挑选一个。
## Docker部署
请准备一台具有公网IP的服务器并将8000端口开放。
@@ -342,3 +357,21 @@ Authorization: Bearer [refresh_token]
}
```
## 注意事项
### Nginx反代优化
如果您正在使用Nginx反向代理kimi-free-api请添加以下配置项优化流的输出效果优化体验感。
```nginx
# 关闭代理缓冲。当设置为off时Nginx会立即将客户端请求发送到后端服务器并立即将从后端服务器接收到的响应发送回客户端。
proxy_buffering off;
# 启用分块传输编码。分块传输编码允许服务器为动态生成的内容分块发送数据,而不需要预先知道内容的大小。
chunked_transfer_encoding on;
# 开启TCP_NOPUSH这告诉Nginx在数据包发送到客户端之前尽可能地发送数据。这通常在sendfile使用时配合使用可以提高网络效率。
tcp_nopush on;
# 开启TCP_NODELAY这告诉Nginx不延迟发送数据立即发送小数据包。在某些情况下这可以减少网络的延迟。
tcp_nodelay on;
# 设置保持连接的超时时间这里设置为120秒。如果在这段时间内客户端和服务器之间没有进一步的通信连接将被关闭。
keepalive_timeout 120;
```

View File

@@ -1,6 +1,6 @@
{
"name": "kimi-free-api",
"version": "0.0.9",
"version": "0.0.11",
"description": "Kimi Free API Server",
"type": "module",
"main": "dist/index.js",

View File

@@ -102,8 +102,10 @@ async function acquireToken(refreshToken: string): Promise<string> {
result = await requestToken(refreshToken);
accessTokenMap.set(refreshToken, result);
}
if (util.unixTimestamp() > result.refreshTime)
if (util.unixTimestamp() > result.refreshTime) {
result = await requestToken(refreshToken);
accessTokenMap.set(refreshToken, result);
}
return result.accessToken;
}
@@ -190,8 +192,10 @@ async function createCompletion(messages: any[], refreshToken: string, useSearch
responseType: 'stream'
});
const streamStartTime = util.timestamp();
// 接收流为输出文本
const answer = await receiveStream(convId, result.data);
logger.success(`Stream has completed transfer ${util.timestamp() - streamStartTime}ms`);
// 异步移除会话,如果消息不合规,此操作可能会抛出数据库错误异常,请忽略
removeConversation(convId, refreshToken)
@@ -234,9 +238,10 @@ async function createCompletionStream(messages: any[], refreshToken: string, use
validateStatus: () => true,
responseType: 'stream'
});
const streamStartTime = util.timestamp();
// 创建转换流将消息格式转换为gpt兼容格式
return createTransStream(convId, result.data, () => {
logger.success(`Stream has completed transfer ${util.timestamp() - streamStartTime}ms`);
// 流传输结束后异步移除会话,如果消息不合规,此操作可能会抛出数据库错误异常,请忽略
removeConversation(convId, refreshToken)
.catch(err => console.error(err));
@@ -614,8 +619,18 @@ function createTransStream(convId: string, stream: any, endCallback?: Function)
return transStream;
}
/**
* Token切分
*
* @param authorization 认证字符串
*/
function tokenSplit(authorization: string) {
return authorization.replace('Bearer ', '').split(',');
}
export default {
createConversation,
createCompletion,
createCompletionStream
createCompletionStream,
tokenSplit
};

View File

@@ -15,17 +15,19 @@ export default {
request
.validate('body.messages', _.isArray)
.validate('headers.authorization', _.isString)
const token = request.headers.authorization;
const refreshToken = token.replace('Bearer ', '');
// refresh_token切分
const tokens = chat.tokenSplit(request.headers.authorization);
// 随机挑选一个refresh_token
const token = _.sample(tokens);
const messages = request.body.messages;
if (request.body.stream) {
const stream = await chat.createCompletionStream(request.body.messages, refreshToken, request.body.use_search);
const stream = await chat.createCompletionStream(request.body.messages, token, request.body.use_search);
return new Response(stream, {
type: "text/event-stream"
});
}
else
return await chat.createCompletion(messages, refreshToken, request.body.use_search);
return await chat.createCompletion(messages, token, request.body.use_search);
}
}