Skip to content

Commit

Permalink
Feat: API key permission system development completed (#112)
Browse files Browse the repository at this point in the history
* fix: try to fix ci

* wip: add level functionality to forward key

* update doc

* Only cache successful responses.

* forward key现在可以精确控制有权限访问的模型

* 为解决leveldb环境问题,更新dockerfile基础镜像,镜像大小将有所膨胀

* 增添test case
  • Loading branch information
KenyonY authored Jan 30, 2024
1 parent 9f60482 commit 8fff3a7
Show file tree
Hide file tree
Showing 21 changed files with 573 additions and 268 deletions.
11 changes: 7 additions & 4 deletions .env
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# 建议使用WebUI进行配置,配置后可导出.env文件

# Sample and explanation can be found in .env.example

LOG_GENERAL=true
Expand All @@ -18,20 +20,21 @@ DEFAULT_REQUEST_CACHING_VALUE=false

FORWARD_CONFIG=[{"base_url":"https://api.openai.com","route":"/","type":"openai"}]

#OPENAI_API_KEY={"sk-xxx": 0}
#FORWARD_KEY={"fk-xxxxxx": 0}
#OPENAI_API_KEY=
#FORWARD_KEY={"fk-0": 0, "fk-1": 1, "fk-2": 2}
#LEVEL_MODELS={"1": ["gpt-4"], "2": ["gpt-3.5-turbo"]}


# `REQ_RATE_LIMIT`: i.e., Request rate limit for specified routes, user specific
# format: {route: ratelimit-string}
# 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
REQ_RATE_LIMIT={"/v1/chat/completions":"100/2minutes", "/v1/completions":"60/minute;600/hour"}
REQ_RATE_LIMIT={"/v1/chat/completions":"100/2minutes","/v1/completions":"60/minute;600/hour"}

# Backend for rate limiting: [memory, redis, memcached, ...] :ref: https://limits.readthedocs.io/en/stable/storage.html#
#REQ_RATE_LIMIT_BACKEND=redis://localhost:6379

# `GLOBAL_RATE_LIMIT`: Limits all routes not specified by `REQ_RATE_LIMIT`. If not set, there's no limit by default.
GLOBAL_RATE_LIMIT=100/minute
GLOBAL_RATE_LIMIT=200/minute

#`RATE_LIMIT_STRATEGY` Options: (fixed-window, fixed-window-elastic-expiry, moving-window) :ref: https://limits.readthedocs.io/en/latest/strategies.html
# `fixed-window`: most memory efficient strategy; `moving-window`:most effective for preventing bursts but has higher memory cost.
Expand Down
3 changes: 3 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# 建议使用WebUI进行配置,配置后可导出.env文件

GENERAL_LOG=true
OPENAI_LOG=true

Expand All @@ -18,6 +20,7 @@ FORWARD_CONFIG=[{"base_url":"https://api.openai.com","route":"/","type":"openai"

#OPENAI_API_KEY={"sk-***":0,"***":0}
#FORWARD_KEY={"fk-***":0,"***":0}
#LEVEL_MODELS={"1": ["gpt-4"], "2": ["gpt-3.5-turbo"]}


# `REQ_RATE_LIMIT`: 指定路由的请求速率限制(区分用户)
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/docker-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ jobs:
file: ./webui.Dockerfile
platforms: linux/amd64,linux/arm64
push: true
tags: webui-${{ steps.meta.outputs.tags }}
tags: webui-${{ github.ref_name }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
31 changes: 18 additions & 13 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,21 +1,26 @@
FROM python:3.10-alpine
LABEL maintainer="kunyuan"
FROM python:3.10-slim
LABEL maintainer="K.Y"
ENV LC_ALL=C.UTF-8
ENV LANG=C.UTF-8
ENV TZ=Asia/Shanghai
RUN apk update && \
apk add tzdata --no-cache && \
cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
apk del tzdata && \
mkdir -p /usr/share/zoneinfo/Asia/ && \
ln -s /etc/localtime /usr/share/zoneinfo/Asia/Shanghai

RUN apt update && \
apt install -y tzdata && \
ln -fs /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
dpkg-reconfigure -f noninteractive tzdata && \
apt clean && \
rm -rf /var/lib/apt/lists/*

COPY . /home/openai-forward
WORKDIR /home/openai-forward
RUN apk add patch g++ libstdc++ leveldb-dev linux-headers --no-cache && \
pip install -e . --no-cache-dir && \
pip install "lmdb>=1.4.1" "plyvel>=1.5.0" --no-cache-dir && \
apk del g++ gcc && rm -rf /var/cache/apk/*
RUN apt-get update && \
apt-get install -y patch g++ gcc libstdc++6 libtcmalloc-minimal4 libleveldb-dev cmake make build-essential && \
pip3 install -e . --no-cache-dir && \
apt-get remove -y patch g++ gcc cmake make build-essential && \
apt-get autoremove -y && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*


EXPOSE 8000
ENTRYPOINT ["python", "-m", "openai_forward.__main__", "run"]
ENTRYPOINT ["python3", "-m", "openai_forward.__main__", "run"]
41 changes: 5 additions & 36 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@

## 主要特性

OpenAI-Forward 提供以下核心功能:

- **全能转发**:可转发几乎所有类型的请求
- **性能优先**:出色的异步性能
Expand All @@ -73,6 +72,7 @@ OpenAI-Forward 提供以下核心功能:
- **实时响应日志**:提升LLMs可观察性
- **自定义秘钥**:替代原始API密钥
- **多目标路由**:转发多个服务地址至同一服务下的不同路由
- **黑白名单**:可对指定IP进行黑白名单限制
- **自动重试**:确保服务的稳定性,请求失败时将自动重试
- **快速部署**:支持通过pip和docker在本地或云端进行快速部署

Expand Down Expand Up @@ -220,56 +220,25 @@ curl --location 'https://api.openai-forward.com/v1/images/generations' \
(更多)



<a>
<img src="https://raw.githubusercontent.com/KenyonY/openai-forward/main/.github/images/separators/aqua.png" height=8px width="100%">
</a>

## 配置

### 命令行参数

执行 `aifd run --help` 获取参数详情

<details open>
<summary>Click for more details</summary>

| 配置项 | 说明 | 默认值 |
|-----------|-------|:----:|
| --port | 服务端口号 | 8000 |
| --workers | 工作进程数 | 1 |

</details>
执行 `aifd run --webui` 进入配置页面 (默认服务地址 http://localhost:8001)

### 环境变量详情

你可以在项目的运行目录下创建 .env 文件来定制各项配置。参考配置可见根目录下的
[.env.example](.env.example)文件

| 环境变量 | 说明 | 默认值 |
|-------------------------------|----------------------------------------------------------------------|:-------------------------------------------------------------------:|
| FORWARD_CONFIG | 配置转发base url与 转发路由 | [{"base_url":"https://api.openai.com","route":"/","type":"openai"}] |
| OPENAI_API_KEY | 配置OpenAI 接口风格的API密钥,支持使用多个密钥,通过逗号分隔 ||
| FORWARD_KEY | 设定用于代理的自定义密钥,多个密钥可用逗号分隔。如果未设置(不建议),将直接使用 `OPENAI_API_KEY` ||
| EXTRA_BASE_URL | 用于配置额外代理服务的基础URL ||
| EXTRA_ROUTE_PREFIX | 定义额外代理服务的路由前缀 ||
| REQ_RATE_LIMIT | 设置特定路由的用户请求速率限制 (区分用户) ||
| GLOBAL_RATE_LIMIT | 配置全局请求速率限制,适用于未在 `REQ_RATE_LIMIT` 中指定的路由 ||
| RATE_LIMIT_STRATEGY | 选择速率限制策略,选项包括:fixed-window、fixed-window-elastic-expiry、moving-window ||
| TOKEN_RATE_LIMIT | 限制流式响应中每个token(或SSE chunk)的输出速率 ||
| PROXY | 设置HTTP代理地址 ||
| LOG_CHAT | 开关聊天内容的日志记录,用于调试和监控 | `false` |
| CACHE_BACKEND | cache后端,支持内存后端和数据库后端,默认为内存后端,可选lmdb、leveldb数据库后端 | `lmdb` |
| CACHE_CHAT_COMPLETION | 是否缓存/v1/chat/completions 结果 | `false` |
| DEFAULT_REQUEST_CACHING_VALUE | 是否默认开启缓存 | `false` |

详细配置说明可参见 [.env.example](.env.example) 文件。(待完善)

> 注意:如果你设置了 OPENAI_API_KEY 但未设置 FORWARD_KEY,客户端在调用时将不需要提供密钥。由于这可能存在安全风险,除非有明确需求,否则不推荐将
> FORWARD_KEY 置空。

### 智能缓存

开启缓存后,将会对指定路由的内容进行缓存,其中转发类型分别为`openai``general`两者行为略有不同,
使用`general`转发时,默认会将相同的请求一律使用缓存返回,
使用`openai`转发时,在开启缓存后,可以通过OpenAI 的`extra_body`参数来控制缓存的行为,如

**Python**

Expand Down
41 changes: 6 additions & 35 deletions README_EN.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ OpenAI-Forward offers the following capabilities:
- **User Traffic Control**: Customize request and Token rates.
- **Real-time Response Logs**: Enhances observability of the call chain.
- **Custom Secret Keys**: Replaces the original API keys.
- **Black and White List**: IP-based black and white list restrictions can be implemented.
- **Multi-target Routing**: Forwards to multiple service addresses under a single service to different routes.
- **Automatic Retries**: Ensures service stability; will automatically retry on failed requests.
- **Quick Deployment**: Supports fast deployment locally or on the cloud via pip and docker.
Expand Down Expand Up @@ -233,46 +234,16 @@ curl --location 'https://api.openai-forward.com/v1/images/generations' \

## Configuration

### Command Line Arguments

Execute `aifd run --help` to get details on arguments.

<details open>
<summary>Click for more details</summary>

| Configuration | Description | Default Value |
|---------------|-------------|:-------------:|
| --port | Service port | 8000 |
| --workers | Number of working processes | 1 |

</details>

### Environment Variable Details

You can create a .env file in the project's run directory to customize configurations. For a reference configuration, see the [.env.example](.env.example) file in the root directory.

| Environment Variable | Description | Default Value |
|-----------------------|-------------------------------------------------------------------------------------------------|:----------------------:|
| FORWARD_CONFIG | | [{"base_url":"https://api.openai.com","route":"/","type":"openai"}] |
| OPENAI_API_KEY | Configure API key in OpenAI style, supports using multiple keys separated by commas | None |
| FORWARD_KEY | Set a custom key for proxying, multiple keys can be separated by commas. If not set (not recommended), it will directly use `OPENAI_API_KEY` | None |
| EXTRA_BASE_URL | Configure the base URL for additional proxy services | None |
| EXTRA_ROUTE_PREFIX | Define the route prefix for additional proxy services | None |
| REQ_RATE_LIMIT | Set the user request rate limit for specific routes (user distinguished) | None |
| GLOBAL_RATE_LIMIT | Configure a global request rate limit applicable to routes not specified in `REQ_RATE_LIMIT` | None |
| RATE_LIMIT_STRATEGY | Choose a rate limit strategy, options include: fixed-window, fixed-window-elastic-expiry, moving-window | None |
| TOKEN_RATE_LIMIT | Limit the output rate of each token (or SSE chunk) in a streaming response | None |
| PROXY | Set HTTP proxy address | None |
| LOG_CHAT | Toggle chat content logging for debugging and monitoring | `false` |
| CACHE_BACKEND | Cache backend, supports memory backend and database backend. By default, it's memory backend, optional database backends are lmdb, and leveldb | `lmdb` |
| CACHE_CHAT_COMPLETION | Whether to cache /v1/chat/completions results | `false` |
Execute `aifd run --webui` to enter the configuration page (default service address http://localhost:8001).

Detailed configuration descriptions can be seen in the [.env.example](.env.example) file. (To be completed)

> Note: If you set OPENAI_API_KEY but did not set FORWARD_KEY, clients will not need to provide a key when calling. As this may pose a security risk, it's not recommended to leave FORWARD_KEY unset unless there's a specific need.

### Caching

After enabling caching, the content of specified routes will be cached. The forwarding types are divided into `openai` and `general`, with slightly different behaviors for each.
When using `general` forwarding, by default, the same requests will all be responded to using the cache.
When using `openai` forwarding, after enabling caching, the caching behavior can be controlled through OpenAI's `extra_body` parameter, such as

**Python**
```diff
Expand Down Expand Up @@ -302,7 +273,7 @@ curl https://smart.openai.com/v1/chat/completions \

```

### Custom Keys
### Custom Api Keys

<details open>
<summary>Click for more details</summary>
Expand Down
1 change: 0 additions & 1 deletion deploy.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@ docker run --env-file .env -d -p 8000:8000 beidongjiedeguang/openai-forward:late
将映射宿主机的8000端口,通过`http://{ip}:8000`访问服务。
容器内日志路径为`/home/openai-forward/Log/`, 可在启动时将其映射出来。

注:同样可以在启动命令中通过-e传入环境变量OPENAI_API_KEY=sk-xxx作为默认api key
启用SSL同上.
环境变量配置见[环境变量配置](README.md#配置)

Expand Down
3 changes: 1 addition & 2 deletions deploy_en.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,7 @@ docker run --env-file .env -d -p 8000:8000 beidongjiedeguang/openai-forward:late
This will map the host's 8000 port. Access the service via `http://{ip}:8000`.
The log path inside the container is `/home/openai-forward/Log/`. It can be mapped when starting up.

Note: Similarly, the default API key can be passed in as an environment variable OPENAI_API_KEY=sk-xxx during startup using the -e flag.
For SSL setup, refer to the above. Environment variable configuration can be found [here](README_EN.md#configuration).
Note: For SSL setup, refer to the above. Environment variable configuration can be found [here](README_EN.md#configuration).

## Source Code Deployment

Expand Down
2 changes: 1 addition & 1 deletion openai_forward/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
__version__ = "0.7.0"
__version__ = "0.7.1"

from dotenv import load_dotenv

Expand Down
1 change: 0 additions & 1 deletion openai_forward/content/openai.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import os
import pickle
import threading
import time
from abc import ABC, abstractmethod
Expand Down
Loading

0 comments on commit 8fff3a7

Please sign in to comment.