diff --git a/.env b/.env
index 8e75a8b..abe61a2 100644
--- a/.env
+++ b/.env
@@ -23,7 +23,7 @@ EXTRA_ROUTE_PREFIX=
# ratelimit-string format [count] [per|/] [n (optional)] [second|minute|hour|day|month|year] :ref:`ratelimit-string`: https://limits.readthedocs.io/en/stable/quickstart.html#rate-limit-string-notation
ROUTE_RATE_LIMIT={"/healthz": "60/2minutes", "/v1/chat/completions": "15/minute;200/hour"}
-# `GLOBAL_RATE_LIMIT`: 所有`RATE_LIMIT`没有指定的路由. 不填默认无限制
+# `GLOBAL_RATE_LIMIT`: 所有`ROUTE_RATE_LIMIT`没有指定的路由. 不填默认无限制
GLOBAL_RATE_LIMIT=30/minute
#`RATE_LIMIT_STRATEGY` Options: (fixed-window, fixed-window-elastic-expiry, moving-window) :ref: https://limits.readthedocs.io/en/latest/strategies.html
@@ -32,7 +32,7 @@ RATE_LIMIT_STRATEGY=moving-window
# TPM: 返回的token速率限制
-TOKEN_RATE_LIMIT=40/second
+TOKEN_RATE_LIMIT=50/second
TIMEOUT=300
diff --git a/.env.example b/.env.example
index c80fa5d..4e7b3b2 100644
--- a/.env.example
+++ b/.env.example
@@ -29,7 +29,7 @@ ROUTE_RATE_LIMIT='{
"/localai/v1/chat/completions": "2/second"
}'
-# `GLOBAL_RATE_LIMIT`: 所有`RATE_LIMIT`没有指定的路由. 不填默认无限制
+# `GLOBAL_RATE_LIMIT`: 所有`ROUTE_RATE_LIMIT`没有指定的路由. 不填默认无限制
GLOBAL_RATE_LIMIT=2/5seconds
#`RATE_LIMIT_STRATEGY` Options: (fixed-window, fixed-window-elastic-expiry, moving-window) ref: https://limits.readthedocs.io/en/latest/strategies.html
diff --git a/.github/images/startup.png b/.github/images/startup.png
new file mode 100644
index 0000000..5c820c0
Binary files /dev/null and b/.github/images/startup.png differ
diff --git a/.github/workflows/issue-close.yml b/.github/workflows/issue-close.yml
new file mode 100644
index 0000000..593aead
--- /dev/null
+++ b/.github/workflows/issue-close.yml
@@ -0,0 +1,22 @@
+name: Close inactive issues
+on:
+ schedule:
+ - cron: '0 9 * * *'
+
+jobs:
+ close-issues:
+ runs-on: ubuntu-latest
+ permissions:
+ issues: write
+ pull-requests: write
+ steps:
+ - uses: actions/stale@v5
+ with:
+ days-before-issue-stale: 30
+ days-before-issue-close: 7
+ stale-issue-label: stale
+ stale-issue-message: This issue is stale because it has been open for 30 days with no activity.
+ close-issue-message: This issue was closed because it has been inactive for 7 days since being marked as stale.
+ days-before-pr-stale: -1
+ days-before-pr-close: -1
+ repo-token: ${{ secrets.GITHUB_TOKEN }}
\ No newline at end of file
diff --git a/Examples/chat.py b/Examples/chat.py
index 642ac8d..fcf1d9a 100644
--- a/Examples/chat.py
+++ b/Examples/chat.py
@@ -1,5 +1,3 @@
-import time
-
import openai
from rich import print
from sparrow import yaml_load
diff --git a/README.md b/README.md
index 5a2db97..370d0dd 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
- AI forward
+ OpenAI forward
@@ -37,17 +37,20 @@
-[功能](#功能) |
-[部署指南](#部署指南) |
-[应用](#应用) |
-[配置选项](#配置选项) |
+[![Deploy to Render](https://render.com/images/deploy-to-render-button.svg)](https://render.com/deploy?repo=https://github.com/beidongjiedeguang/openai-forward)
+
+[特点](#特点) |
+[部署指南](deploy.md) |
+[使用](#使用) |
+[配置](#配置) |
[对话日志](#对话日志)
-[![Deploy to Render](https://render.com/images/deploy-to-render-button.svg)](https://render.com/deploy?repo=https://github.com/beidongjiedeguang/openai-forward)
-本项目是大模型与用户层之间的一道转发服务,可用于搭建反向代理,用户速率限制,token速率限制,自定义API KEY 等.
+OpenAI-Forward是大模型与用户层之间的一道转发服务,
+用于对请求模型的速率限制,模型返回的Token速率限制,自定义API KEY 等。
+
@@ -56,38 +59,73 @@
### 特点
-AI-Forward支持以下功能:
+OpenAI-Forward支持以下功能:
- **万能代理**: 几乎可以转发任何请求
- **用户速率限制**: 提供请求速率限制(**RPM**)与流式返回的Token速率限制(**TPM**)
-- **自定义秘钥**: 支持用户使用自定义生成的秘钥代替原始api key使用。
+- **自定义秘钥**: 支持用户使用自定义生成的秘钥代替原始api key使用。
- 流式响应的对话日志
- 可同时转发多个目标服务至不同路由
- 失败请求自动重试
-- 一分钟内完成安装与部署
+- 一分钟内完成安装与部署; 一键部署至云端
- ...
-
由本项目搭建的代理服务地址:
> https://api.openai-forward.com
-> https://render.openai-forward.com
+> https://render.openai-forward.com
+
+注:本项目中提供的所有代理服务仅供学习使用,请勿用作其它用途。
+
-注:这里提供的代理地址服务仅限于学生/研究人员使用,若要长期使用请参考部署文档自行搭建。
## 部署指南
-见 👉 [部署文档](deploy.md)
-
+ 👉 [部署文档](deploy.md)
-## 使用方式
+## 使用
+**安装**
+```bash
+pip install openai-forward
+```
+**运行**
+```bash
+aifd run
+```
+如果一切正常将会看到下面的启动信息
-### 反向代理应用:
+```bash
+❯ aifd run
+╭────── 🤗 openai-forward is ready to serve! ───────╮
+│ │
+│ base url https://api.openai.com │
+│ route prefix / │
+│ api keys False │
+│ forward keys False │
+│ Log chat False │
+╰────────────────────────────────────────────────────╯
+╭──────────── ⏱️ Rate Limit configuration ───────────╮
+│ │
+│ strategy moving-window │
+│ /healthz 60/2minutes │
+│ /v1/chat/completions 15/minute;200/hour │
+│ global_rate_limit 30/minute │
+│ token_rate_limit 50/second │
+│ token_interval_time 0.0200s │
+╰────────────────────────────────────────────────────╯
+INFO: Started server process [33811]
+INFO: Waiting for application startup.
+INFO: Application startup complete.
+INFO: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
+```
+
+### 代理OpenAI API:
+这也是`aifd run`的默认选项
#### 在第三方应用中使用
@@ -97,8 +135,6 @@ AI-Forward支持以下功能:
基于开源项目[ChatGPT-Next-Web](https://github.com/Yidadaa/ChatGPT-Next-Web)搭建自己的chatgpt服务
替换docker启动命令中的 `BASE_URL`为自己搭建的代理服务地址
-
-
```bash
docker run -d \
-p 3000:3000 \
@@ -123,7 +159,6 @@ docker run -d \
openai.api_key = "sk-******"
```
-
**JS/TS**
```diff
@@ -162,14 +197,23 @@ curl --location 'https://api.openai-forward.com/v1/images/generations' \
-### 与众大模型服务结合使用
+### 代理本地模型
与 [LocalAI](https://github.com/go-skynet/LocalAI),
-[api-for-open-llm](https://github.com/xusenlinzy/api-for-open-llm),
-[claude-to-chatgpt](https://github.com/jtsang4/claude-to-chatgpt) 等
-一起使用,赋予这些服务接口的RPM,TPM,日志等能力。
-(待补充...)
+[api-for-open-llm](https://github.com/xusenlinzy/api-for-open-llm)等
+一起使用,赋予这些服务接口的RPM限制,TPM限制,日志等能力。
+
+以LocalAI为例:
+假设部署的LocalAI服务运行在 `http://localhost:8080`,
+那么接下来只需修改.env配置中`OPENAI_BASE_URL=http://localhost:8080` 就可以完成对LocalAI的代理。
+
+(待补充)
+### 代理其它云端模型
+
+例如可通过 [claude-to-chatgpt](https://github.com/jtsang4/claude-to-chatgpt)
+将claude的api格式对齐为openai的格式,然后使用`openai-forward`进行代理。
+(待补充)
## 配置
@@ -182,19 +226,18 @@ curl --location 'https://api.openai-forward.com/v1/images/generations' \
**`aifd run`参数配置项**
-| 配置项 | 说明 | 默认值 |
-|-----------------------|-----------------------|:----------------------:|
-| --port | 服务端口号 | 8000 |
-| --workers | 工作进程数 | 1 |
-| --log_chat | 同 LOG_CHAT | `False` |
+| 配置项 | 说明 | 默认值 |
+|------------|------------|:-------:|
+| --port | 服务端口号 | 8000 |
+| --workers | 工作进程数 | 1 |
+| --log_chat | 同 LOG_CHAT | `False` |
### 环境变量配置项
支持从运行目录下的`.env`文件中读取
-配置示例见根目录下的 [.env.example](.env.example)
-
+配置示例见根目录下的 [.env.example](.env.example)
| 环境变量 | 说明 | 默认值 |
|---------------------|-----------------------------------------------------------------------------------------------------------------------------------|:----------------------:|
@@ -204,12 +247,17 @@ curl --location 'https://api.openai-forward.com/v1/images/generations' \
| FORWARD_KEY | 允许调用方使用该key代替openai api key,支持多个forward key, 以逗号分隔; 如果设置了OPENAI_API_KEY,而没有设置FORWARD_KEY, 则客户端调用时无需提供密钥, 此时出于安全考虑不建议FORWARD_KEY置空 | 无 |
| EXTRA_BASE_URL | 额外转发服务地址 | 无 |
| EXTRA_ROUTE_PREFIX | 额外转发服务路由前缀 | 无 |
+| ROUTE_RATE_LIMIT | 指定路由的请求速率限制(区分用户) | 无 |
+| GLOBAL_RATE_LIMIT | 所有`RATE_LIMIT`没有指定的路由. 不填默认无限制 | 无 |
+| RATE_LIMIT_STRATEGY | 速率限制策略(fixed-window, fixed-window-elastic-expiry, moving-window) | 无 |
+| TOKEN_RATE_LIMIT | 对每一份流式返回的token速率限制 (这里的token并不严格等于gpt中定义的token,而是SSE的chunk) | 无 |
+| PROXY | http代理 | 无 |
| LOG_CHAT | 是否记录聊天内容 | `false` |
更多见 [.env.example](.env.example) 中的说明。(待完善)
-
### 自定义秘钥
+
Click for more details
@@ -236,7 +284,6 @@ FORWARD_KEY=fk-****** # 这里fk-token由我们自己定义
支持转发不同地址的服务至同一端口的不同路由下
用例见 `.env.example`
-
### 对话日志
默认不记录对话日志,若要开启需设置环境变量`LOG_CHAT=true`
@@ -298,4 +345,4 @@ aifd convert
## License
-AI-Forward is licensed under the [MIT](https://opensource.org/license/mit/) license.
+OpenAI-Forward is licensed under the [MIT](https://opensource.org/license/mit/) license.
diff --git a/deploy.md b/deploy.md
index 9d9e97f..c322fce 100644
--- a/deploy.md
+++ b/deploy.md
@@ -6,6 +6,11 @@
+一键部署至render
+[![Deploy to Render](https://render.com/images/deploy-to-render-button.svg)](https://render.com/deploy?repo=https://github.com/beidongjiedeguang/openai-forward)
+
+
+
[pip部署](#pip部署) |
[docker部署](#docker部署) |
[render一键部署](#render-一键部署) |
@@ -16,12 +21,12 @@
本文档中提供以下几种部署方式
-**有海外vps方案**
+**本地部署**
1. [pip 安装部署](deploy.md#pip部署)
2. [Docker部署](deploy.md#docker部署)
-**无vps免费部署方案**
+**一键免费云平台部署**
1. [Render一键部署](deploy.md#render-一键部署)
2. [Railway部署](deploy.md#Railway-一键部署)
@@ -43,7 +48,7 @@ pip install openai-forward
**运行服务**
```bash
-openai-forward run # 或者使用别名 aifd run
+aifd run
```
服务就搭建完成了。
配置见[配置](README.md#配置选项)
@@ -64,12 +69,15 @@ http://{ip}:{port}/v1/chat/completions
### 开启SSL (以https访问域名)
首先准备好一个域名, 如本项目中使用的域名为`api.openai-forward.com`
-常用方式是使用nginx(不习惯用命令行配置的话可以考虑用 [Nginx Proxy Manager](https://github.com/NginxProxyManager/nginx-proxy-manager)) 代理转发 openai-forward 服务端口(默认8000)。
-需要注意的是,若要使用流式转发,在nginx配置中需要添加取消代理缓存的配置:
- ```bash
- proxy_cache off;
- proxy_buffering off;
+常用方式是使用nginx(不习惯用命令行配置的话可以考虑用 [Nginx Proxy Manager](https://github.com/NginxProxyManager/nginx-proxy-manager), 它可方便设置Let's Encrypt证书自动申请和自动续期) 代理转发 openai-forward 服务端口(默认8000)。
+需要注意的是,若要使用流式转发,在nginx配置中需要添加关闭代理缓存的配置, 即在Nginx Proxy Manager的 Custom Nginx Configuration中写入:
+```bash
+proxy_buffering off;
```
+
+
+**Q**: 使用Nginx 或 Nginx Proxy Manager可以直接对任何api进行转发,为什么要用这个库?
+**A**: `openai-forward`的转发代理功能只是一项基础功能,它的日志记录、token速率限制、自定义秘钥等功能都是nginx无法直接做到的。
@@ -96,7 +104,7 @@ git clone https://github.com/beidongjiedeguang/openai-forward.git --depth=1
cd openai-forward
pip install -e .
-openai-forward run # 或使用别名 aifd run
+aifd run
```
启用SSL同上.
@@ -111,8 +119,8 @@ openai-forward run # 或使用别名 aifd run
Render应该算是所有部署中最简易的一种, 并且它生成的域名国内可以直接访问!
1. 点击一键部署按钮
- 如果提示需要绑定卡,则可先fork本仓库 -->到Render的Dashboard上 New Web Services --> Connect 到刚刚fork到仓库 后面步骤均默认即可
-2. 填写环境变量,如默认的OPENAI_API_KEY 等,也可以不填
+ 也可先fork本仓库 -->到Render的Dashboard上 New Web Services --> Connect 到刚刚fork到仓库 后面步骤均默认即可
+2. 填写环境变量,`openai-forward`所有配置都可以通过环境变量设置,可以根据自己需要填写。
然后等待部署完成即可。
Render的免费计划: 每月750小时免费实例时间(意味着单个实例可以不间断运行)、100G带宽流量、500分钟构建时长.
@@ -145,13 +153,14 @@ Render的免费计划: 每月750小时免费实例时间(意味着单个实例
-⚠️下面两种部署方式仅提供简单的转发服务,没有任何额外功能。
+⚠️下面两种部署方式仅提供简单的转发服务,没有任何额外功能。
+适合只有简单需求的用户(国内访问openai api服务)。
## Vercel 一键部署
[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fbeidongjiedeguang%2Fopenai-forward&project-name=openai-forward&repository-name=openai-forward&framework=other)
-因python的部署方式在vercel上存在诸多限制,因此现在将Vercel部署方式切换为直接转发。
+因python的部署方式在vercel上存在诸多限制,因此现在将Vercel部署方式切换为直接代理转发,而没有其它功能。
1. 点击按钮即可一键免费部署
也可先fork本仓库,再手动在vercel操作界面import项目
@@ -171,7 +180,7 @@ Render的免费计划: 每月750小时免费实例时间(意味着单个实例
* Pages部署: fork本仓库,在[cloudflare](https://dash.cloudflare.com/)上创建应用程序时选择Pages, 然后选择连接到Git, 选择刚刚fork的仓库即可完成部署。
* Workers部署: 在[cloudflare](https://dash.cloudflare.com/)上创建应用程序时选择Workers, 部署好示例代码后,点击快速修改(quick edit)复制[_worker.js](_worker.js) 至代码编辑器即可完成服务部署。
-绑定自定义域名: cloudflare自动分配的域名国内也无法访问,所以也需要绑定自定义域名. (**目前Pages部署时自动分配的域名国内可以直接访问**)
+绑定自定义域名: **目前Pages部署时cloudflare自动分配的域名国内可以直接访问**, 而Workers部署时分配的则绑定自定义域名国内才可访问.
绑定自定义域名需要将域名默认nameserver(域名服务器)绑定到cloudflare提供的nameserver,大体上过程是:
```mermaid
@@ -184,7 +193,7 @@ stateDiagram-v2
去注册域名机构更改默认nameserver为cloudflare提供的nameserver --> 在cloudflare的worker/page中添加域名: 域名服务器更改验证成功
在cloudflare的worker/page中添加域名 --> 成功
```
-这种部署方式轻便简洁,支持流式转发. 对于没有vps的用户还是十分推荐的。不过目前[_worker.js](_worker.js)这个简单脚本仅提供转发服务, 不支持额外功能。
+这种部署方式轻便简洁,支持流式转发. 不过目前[_worker.js](_worker.js)这个简单脚本仅提供转发服务, 不支持额外功能。
> https://cloudflare.worker.openai-forward.com
> https://cloudflare.page.openai-forward.com
diff --git a/openai_forward/__init__.py b/openai_forward/__init__.py
index ae0f19e..dc133d4 100644
--- a/openai_forward/__init__.py
+++ b/openai_forward/__init__.py
@@ -1,4 +1,4 @@
-__version__ = "0.5.0"
+__version__ = "0.5.1"
from dotenv import load_dotenv
diff --git a/openai_forward/app.py b/openai_forward/app.py
index eb20900..9edba0d 100644
--- a/openai_forward/app.py
+++ b/openai_forward/app.py
@@ -2,7 +2,7 @@
from slowapi import Limiter, _rate_limit_exceeded_handler
from slowapi.errors import RateLimitExceeded
-from .forwarding import get_fwd_anything_objs, get_fwd_openai_style_objs
+from .forwarding import fwd_anything_objs, fwd_openai_objs
from .forwarding.settings import (
RATE_LIMIT_STRATEGY,
dynamic_rate_limit,
@@ -34,5 +34,5 @@ def healthz(request: Request):
methods=["GET", "POST", "PUT", "DELETE", "OPTIONS", "HEAD", "PATCH", "TRACE"],
)
-[add_route(obj) for obj in get_fwd_openai_style_objs()]
-[add_route(obj) for obj in get_fwd_anything_objs()]
+[add_route(obj) for obj in fwd_openai_objs()]
+[add_route(obj) for obj in fwd_anything_objs()]
diff --git a/openai_forward/forwarding/__init__.py b/openai_forward/forwarding/__init__.py
index c26b0d5..ff07014 100644
--- a/openai_forward/forwarding/__init__.py
+++ b/openai_forward/forwarding/__init__.py
@@ -1,2 +1,2 @@
-from .extra import AnyForwarding, get_fwd_anything_objs
-from .openai import OpenaiForwarding, get_fwd_openai_style_objs
+from .extra import AnyForwarding, fwd_anything_objs
+from .openai import OpenaiForwarding, fwd_openai_objs
diff --git a/openai_forward/forwarding/extra.py b/openai_forward/forwarding/extra.py
index ace8c97..912de74 100644
--- a/openai_forward/forwarding/extra.py
+++ b/openai_forward/forwarding/extra.py
@@ -12,7 +12,7 @@ def __init__(self, base_url: str, route_prefix: str, proxy=None):
)
-def get_fwd_anything_objs():
+def fwd_anything_objs():
"""
Generate extra forwarding objects.
diff --git a/openai_forward/forwarding/openai.py b/openai_forward/forwarding/openai.py
index 9a9885c..a76cab2 100644
--- a/openai_forward/forwarding/openai.py
+++ b/openai_forward/forwarding/openai.py
@@ -16,13 +16,11 @@ def __init__(self, base_url: str, route_prefix: str, proxy=None):
self.client = httpx.AsyncClient(
base_url=self.BASE_URL, proxies=proxy, http1=True, http2=False
)
- self.token_counts = 0
- self.token_limit_dict = {'time': time.time(), 'count': 0}
-def get_fwd_openai_style_objs():
+def fwd_openai_objs():
"""
- Generate OPENAI route style forwarding objects.
+ Generate OPENAI api style forwarding objects.
Returns:
fwd_objs (list): A list of OpenaiForwarding objects.