Skip to content

Commit

Permalink
feat: multi-reverse proxys support (#56)
Browse files Browse the repository at this point in the history
* 多接口服务转发支持(用例见.env.example)
* 环境变量读取格式更变:多值分隔符由空格分隔更变为逗号 , 分 (用例见.env.example)
* 本地请求代理支持 (用例见.env.example)
* 请求性能优化
* 潜在bug修复
* 依赖缩减
  • Loading branch information
KenyonY authored Aug 10, 2023
1 parent 4f30c1e commit e7d09ce
Show file tree
Hide file tree
Showing 41 changed files with 641 additions and 409 deletions.
16 changes: 15 additions & 1 deletion .env
Original file line number Diff line number Diff line change
@@ -1,8 +1,22 @@
# 示例见 .env.example

# LOG_CHAT: 是否开启日志
LOG_CHAT=false

# OPENAI_BASE_URL: 转发openai风格的任何服务地址,允许指定多个, 以逗号隔开。
# 如果指定超过一个,则任何OPENAI_ROUTE_PREFIX/EXTRA_ROUTE_PREFIX都不能为根路由/
OPENAI_BASE_URL=https://api.openai.com

# OPENAI_ROUTE_PREFIX: 可指定所有openai风格(为记录日志)服务的转发路由前缀
OPENAI_ROUTE_PREFIX=/

OPENAI_API_KEY=
FORWARD_KEY=
ROUTE_PREFIX=

# EXTRA_BASE_URL: 可指定任意服务转发
EXTRA_BASE_URL=
# EXTRA_ROUTE_PREFIX: 与 EXTRA_BASE_URL 匹配的路由前缀
EXTRA_ROUTE_PREFIX=

# 设定时区
TZ=Asia/Shanghai
27 changes: 20 additions & 7 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,16 +1,29 @@
# LOG_CHAT: 是否Log 对话记录
LOG_CHAT=True
# LOG_CHAT: 是否开启日志
LOG_CHAT=true

OPENAI_BASE_URL=https://api.openai.com

# OPENAI_API_KEY:允许输入多个api key 形成轮询池
OPENAI_API_KEY=sk-xxx1 sk-xxx2 sk-xxx3
# OPENAI_BASE_URL: 转发openai风格的任何服务地址,允许指定多个, 以逗号隔开。
# 如果指定超过一个,则任何OPENAI_ROUTE_PREFIX/EXTRA_ROUTE_PREFIX都不能为根路由/
OPENAI_BASE_URL=https://api.openai.com, http:localhost:8080

# OPENAI_ROUTE_PREFIX: 可指定所有openai风格(为记录日志)服务的转发路由前缀
OPENAI_ROUTE_PREFIX=/openai, /localai

# OPENAI_API_KEY:允许输入多个api key, 以逗号隔开, 形成轮询池
OPENAI_API_KEY=sk-xxx1,sk-xxx2,sk-xxx3

# FORWARD_KEY: 当前面的OPENAI_API_KEY被设置,就可以设置这里的FORWARD_KEY,客户端调用时可以使用FORWARD_KEY作为api key
FORWARD_KEY=fk-xxx1

# ROUTE_PREFIX: 可指定整个转发服务的根路由前缀
ROUTE_PREFIX=

# EXTRA_BASE_URL: 可指定任意服务转发
EXTRA_BASE_URL=http://localhost:8882, http://localhost:8881

# EXTRA_ROUTE_PREFIX: 与 EXTRA_BASE_URL 匹配的路由前缀
EXTRA_ROUTE_PREFIX=/tts,/translate

# PROXY 配置代理
PROXY=http://localhost:7890

# 设定时区
TZ=Asia/Shanghai
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ jobs:
run: |
python -m pip install --upgrade pip
python -m pip install pytest psutil
python -m pip install .
python -m pip install .[test]
# python -m pip install codecov pytest-cov
- name: Run tests
run: |
Expand Down
15 changes: 15 additions & 0 deletions .github/workflows/issue-translator.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
name: Issue Translator
on:
issue_comment:
types: [created]
issues:
types: [opened]

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: usthe/[email protected]
with:
IS_MODIFY_TITLE: false
CUSTOM_BOT_NOTE: Bot detected the issue body's language is not English, translate it automatically.
3 changes: 3 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# Install
# 1. pip install pre-commit
# 2. pre-commit install (first time)
repos:
- repo: https://github.com/timothycrosley/isort
rev: 5.12.0
Expand Down
3 changes: 2 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,13 @@ RUN apk update && \

RUN pip install --no-cache-dir \
"loguru" \
"sparrow-python>=0.1.3" \
"fastapi" \
"uvicorn" \
"orjson" \
"python-dotenv" \
"httpx" \
"fire" \
"rich" \
"pytz"

COPY . /home/openai-forward
Expand Down
1 change: 1 addition & 0 deletions Examples/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
config.yaml
30 changes: 26 additions & 4 deletions Examples/chat.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,34 @@
import time

import openai
from rich import print
from sparrow import yaml_load

config = yaml_load("config.yaml", rel_path=True)
print(f"{config=}")
openai.api_base = config["api_base"]
openai.api_key = config["api_key"]

openai.api_base = "https://api.openai-forward.com/v1"
openai.api_key = "sk-******"
stream = True
user_content = """
用c实现快速平方根算法
"""

resp = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=[
{"role": "user", "content": "Who won the world series in 2020?"},
{"role": "user", "content": user_content},
],
stream=stream,
)
print(resp.choices)

if stream:
chunk_message = next(resp)['choices'][0]['delta']
print(f"{chunk_message['role']}: ")
for chunk in resp:
chunk_message = chunk['choices'][0]['delta']
content = chunk_message.get("content", "")
print(content, end="")
print()
else:
print(resp.choices)
9 changes: 9 additions & 0 deletions Examples/chat.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/bin/bash

curl http://localhost:8000/openai/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer sk-******" \
-d '{
"model": "gpt-3.5-turbo",
"messages": [{"role": "user", "content": "Hello!"}]
}' &
2 changes: 2 additions & 0 deletions Examples/config.example.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
api_base: http://localhost:8000/v1
api_key: sk-******
6 changes: 4 additions & 2 deletions Examples/embedding.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import openai
from sparrow import yaml_load

openai.api_base = "http://localhost:8000/v1"
openai.api_key = "sk-******"
config = yaml_load("config.yaml")
openai.api_base = config["api_base"]
openai.api_key = config["api_key"]
response = openai.Embedding.create(
input="Your text string goes here", model="text-embedding-ada-002"
)
Expand Down
8 changes: 4 additions & 4 deletions Examples/whisper.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# Note: you need to be using OpenAI Python v0.27.0 for the code below to work
import openai
from sparrow import relp

openai.api_base = "https://api.openai-forward.com/v1"
openai.api_key = "sk-******"
from sparrow import relp, yaml_load

config = yaml_load("config.yaml")
openai.api_base = config["api_base"]
openai.api_key = config["api_key"]
audio_file = open(relp("../.github/data/whisper.m4a"), "rb")
transcript = openai.Audio.transcribe("whisper-1", audio_file)
print(transcript)
6 changes: 3 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ start:
docker run -d \
--name $(container) \
--env-file .env \
-p 27001:8000 \
-p 8000:8000 \
-v $(shell pwd)/Log:/home/openai-forward/Log \
-v $(shell pwd)/openai_forward:/home/openai-forward/openai_forward \
$(image)


exec:
docker exec -it $(container) bash
docker exec -it $(container) sh

log:
docker logs -f $(container)
Expand Down Expand Up @@ -49,4 +49,4 @@ pull:
docker pull $(image)

deploy:
vercel --prod
vercel --prod
54 changes: 33 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<img alt="GitHub repo size" src="https://img.shields.io/github/repo-size/beidongjiedeguang/openai-forward">
</a>
<a href="https://hub.docker.com/r/beidongjiedeguang/openai-forward">
<img alt="docer image size" src="https://img.shields.io/docker/image-size/beidongjiedeguang/openai-forward?style=flat&label=docker image">
<img alt="docker image size" src="https://img.shields.io/docker/image-size/beidongjiedeguang/openai-forward?style=flat&label=docker image">
</a>
<a href="https://github.com/beidongjiedeguang/openai-forward/actions/workflows/ci.yml">
<img alt="tests" src="https://img.shields.io/github/actions/workflow/status/beidongjiedeguang/openai-forward/ci.yml?label=tests">
Expand Down Expand Up @@ -70,16 +70,17 @@
- [x] 支持指定转发路由前缀
- [x] docker部署
- [x] pip 安装部署
- [x] cloudflare 部署
- [x] Vercel一键部署
- [x] Railway 一键部署
- [x] Render 一键部署
- [x] cloudflare 部署
- [x] Vercel一键部署

**高级功能**

- [x] 允许输入多个openai api key 组成轮询池
- [x] 自定义 转发api key (见[高级配置](#高级配置))
- [x] 流式响应对话日志
- [x] 多接口转发

## 部署指南

Expand Down Expand Up @@ -195,37 +196,42 @@ curl --location 'https://api.openai-forward.com/v1/images/generations' \

**`aifd run`参数配置项**

| 配置项 | 说明 | 默认值 |
|-----------------|-------------------|:----------------------:|
| --port | 服务端口号 | 8000 |
| --workers | 工作进程数 | 1 |
| --base_url | 同 OPENAI_BASE_URL | https://api.openai.com |
| --api_key | 同 OPENAI_API_KEY | `None` |
| --forward_key | 同 FORWARD_KEY | `None` |
| --route_prefix | 同 ROUTE_PREFIX | `None` |
| --log_chat | 同 LOG_CHAT | `False` |
| 配置项 | 说明 | 默认值 |
|-----------------------|-----------------------|:----------------------:|
| --port | 服务端口号 | 8000 |
| --workers | 工作进程数 | 1 |
| --openai_base_url | 同 OPENAI_BASE_URL | https://api.openai.com |
| --openai_route_prefix | 同 OPENAI_ROUTE_PREFIX | `None` |
| --api_key | 同 OPENAI_API_KEY | `None` |
| --forward_key | 同 FORWARD_KEY | `None` |
| --extra_base_url | 同 EXTRA_BASE_URL | `None` |
| --extra_route_prefix | 同 EXTRA_ROUTE_PREFIX | `None` |
| --log_chat | 同 LOG_CHAT | `False` |

</details>

### 环境变量配置项

支持从运行目录下的`.env`文件中读取

| 环境变量 | 说明 | 默认值 |
|-----------------|-----------------------------------------------------------------------------------------------------------------------------------|:------------------------:|
| OPENAI_BASE_URL | 默认 openai官方 api 地址 | https://api.openai.com |
| OPENAI_API_KEY | 默认openai api key,支持多个默认api key, 以 `sk-` 开头, 以空格分割 ||
| FORWARD_KEY | 允许调用方使用该key代替openai api key,支持多个forward key, 以空格分割; 如果设置了OPENAI_API_KEY,而没有设置FORWARD_KEY, 则客户端调用时无需提供密钥, 此时出于安全考虑不建议FORWARD_KEY置空 ||
| ROUTE_PREFIX | 路由前缀 ||
| LOG_CHAT | 是否记录聊天内容 | `false` |
| 环境变量 | 说明 | 默认值 |
|---------------------|-----------------------------------------------------------------------------------------------------------------------------------|:----------------------:|
| OPENAI_BASE_URL | 默认 openai官方 api 地址 | https://api.openai.com |
| OPENAI_ROUTE_PREFIX | openai(接口格式)路由前缀 | / |
| OPENAI_API_KEY | 默认openai api key,支持多个默认api key, 以 `sk-` 开头, 以逗号分隔 ||
| FORWARD_KEY | 允许调用方使用该key代替openai api key,支持多个forward key, 以逗号分隔; 如果设置了OPENAI_API_KEY,而没有设置FORWARD_KEY, 则客户端调用时无需提供密钥, 此时出于安全考虑不建议FORWARD_KEY置空 ||
| EXTRA_BASE_URL | 额外转发服务地址 ||
| EXTRA_ROUTE_PREFIX | 额外转发服务路由前缀 ||
| LOG_CHAT | 是否记录聊天内容 | `false` |

## 高级配置

**设置openai api_key为自定义的forward key**
需要配置 OPENAI_API_KEY 和 FORWARD_KEY, 例如
### 设置openai api_key为自定义的forward key
<details markdown="1">
<summary>Click for more details</summary>

需要配置 OPENAI_API_KEY 和 FORWARD_KEY, 例如

```bash
OPENAI_API_KEY=sk-*******
FORWARD_KEY=fk-****** # 这里fk-token由我们自己定义
Expand Down Expand Up @@ -269,6 +275,12 @@ docker run -d \

</details>

### 多路由转发

支持转发不同地址的服务至同一端口的不同路由下,基本可以转发任何服务。
用例见 `.env.example`


## 对话日志

默认不记录对话日志,若要开启需设置环境变量`LOG_CHAT=true`
Expand Down
3 changes: 1 addition & 2 deletions deploy.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ http://{ip}:{port}/v1/chat/completions
proxy_buffering off;
```

然后就可以https进行流式访问了。


## Docker部署
Expand Down Expand Up @@ -113,7 +112,7 @@ Render的免费计划: 每月750小时免费实例时间(意味着单个实例

注:默认render在15分钟内没有服务请求时会自动休眠(好处是休眠后不会占用750h的免费实例时间),休眠后下一次请求会被阻塞 5~10s。
若不希望服务15分钟自动休眠,可以使用定时脚本(如每14分钟)去请求服务进行保活。
如果希望零停机部署可以在设置中设置`Health Check Path``/docs`
如果希望零停机部署可以在设置中设置`Health Check Path``/healthz`
> https://render.openai-forward.com
> https://openai-forward.onrender.com
Expand Down
2 changes: 1 addition & 1 deletion docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ services:
ports:
- "8000:8000"
volumes:
- ./Log-caloi-top:/home/openai-forward/Log
- ./Log:/home/openai-forward/Log
- ./openai_forward:/home/openai-forward/openai_forward
command:
- --port=8000
Expand Down
4 changes: 2 additions & 2 deletions openai_forward/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
__version__ = "0.3.0-alpha"
__version__ = "0.4.0"

from dotenv import load_dotenv

load_dotenv()
load_dotenv(override=False)
Loading

0 comments on commit e7d09ce

Please sign in to comment.