29 Commits
ninja ... 0.7.8

Author SHA1 Message Date
Clivia
c07d1f3268 更新 gpts.json 2024-02-20 10:00:02 +08:00
Clivia
33fb486c82 修改key_for_gpts_info 2024-02-20 01:18:14 +08:00
Clivia
6203fb3535 update KEY_FOR_GPTS_INFO 2024-02-20 01:05:35 +08:00
Clivia
b19586e24a 优化更新gpts的结构 2024-02-19 21:50:02 +08:00
Clivia
9f80493866 Update docker-compose.yml 2024-02-17 17:43:43 +08:00
Clivia
36eede643d Update docker-compose.yml 2024-02-17 17:42:46 +08:00
Clivia
6032546b5d Create ninja-image.yml 2024-02-17 17:41:44 +08:00
Clivia
7328dadefb Update xyhelper-deploy.yml 2024-02-17 17:41:09 +08:00
Clivia
b7e2af8afd Update and rename docker-deploy.yml to xyhelper-deploy.yml 2024-02-17 17:40:48 +08:00
Clivia
04c1599756 Update docker-deploy.yml 2024-02-17 17:38:22 +08:00
Clivia
06665924f6 更新自定义网址更新access_token失败 2024-02-17 02:07:11 +08:00
Clivia
6787069afb 修改部署说明 2024-02-13 18:05:32 +08:00
Clivia
abbdebc24e 修改部署说明 2024-02-11 23:41:50 +08:00
Clivia
e599e2a0cc 修改部署说明 2024-02-11 23:08:37 +08:00
Clivia
0c0dd0e8a7 新增部署说明 2024-02-11 21:32:03 +08:00
Clivia
5524ad2b11 更新部署配置 2024-02-11 21:26:55 +08:00
Clivia
ef27e47f91 项目将脱离ninja,需修改配置 2024-02-11 21:19:30 +08:00
Clivia
26539a0d79 项目将脱离ninja,需修改相应配置 2024-02-11 21:11:53 +08:00
Clivia
a3b5ae310c 修改部署说明 2024-02-11 20:57:09 +08:00
Clivia
c85a228fb9 增加xyhelper渠道 2024-02-11 20:55:23 +08:00
Clivia
4a7338637d 添加xyhelper渠道刷新refresh_token为access_token 2024-02-11 20:54:28 +08:00
Clivia
d02e2d0eb1 Update main.py 2024-02-11 20:52:57 +08:00
Clivia
ebd3c3974f 修改部署说明 2024-02-11 20:04:06 +08:00
Clivia
ab88debcf3 修改部署说明 2024-02-11 19:57:23 +08:00
Clivia
73b14891dd 适配xyhelper的免费接口 2024-02-11 19:56:26 +08:00
Clivia
1f50b3d3a9 修改xyhelper免费部署说明 2024-02-11 19:55:13 +08:00
Clivia
227781a12c 部署说明 2024-02-11 11:11:01 +08:00
Clivia
f06821d54f Update main.py 2024-02-09 15:48:28 +08:00
Clivia
3637133b2e 增加请求头 2024-02-09 15:42:55 +08:00
7 changed files with 102 additions and 50 deletions

View File

@@ -1,4 +1,4 @@
name: Build and Push Docker Image
name: ninja Build and Push Docker Image
on:
release:
@@ -42,6 +42,5 @@ jobs:
push: true
tags: |
yangclivia/pandora-to-api:${{ steps.tag_name.outputs.tag }}
yangclivia/pandora-to-api:latest
platforms: linux/amd64,linux/arm64
build-args: TARGETPLATFORM=${{ matrix.platform }}

46
.github/workflows/xyhelper-deploy.yml vendored Normal file
View File

@@ -0,0 +1,46 @@
name: xyhelper Build and Push Docker Image
on:
release:
types: [created]
workflow_dispatch:
inputs:
tag:
description: 'Tag Name'
required: true
jobs:
build-and-push:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Login to Docker Hub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_PASSWORD }}
- name: Set tag name
id: tag_name
run: |
if [ "${{ github.event_name }}" = "release" ]; then
echo "::set-output name=tag::${GITHUB_REF#refs/tags/}"
elif [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
echo "::set-output name=tag::${{ github.event.inputs.tag }}"
fi
- name: Build and push Docker image with Release tag
uses: docker/build-push-action@v2
with:
context: .
file: ./Dockerfile
push: true
tags: |
yangclivia/pandora-to-api:${{ steps.tag_name.outputs.tag }}
platforms: linux/amd64,linux/arm64
build-args: TARGETPLATFORM=${{ matrix.platform }}

View File

@@ -2,20 +2,28 @@
> [!IMPORTANT]
>
> Respect Zhile大佬 , Respect Wizerd
> Respect `xyhelper` ,Respect `ninja` , Respect `Wizerd`
感谢pandoraNext和Wizerd的付出敬礼
感谢xyhelper、ninja和Wizerd大佬们的付出,敬礼!!!
本项目支持:
1.ninja `proxy` 模式下的 `backend-api` 转为 `/v1/chat/completions` 接口,支持流式和非流式响应。
1.xyhelper `proxy` 模式下的 `backend-api免费接口` 转为 `/v1/chat/completions` 接口,支持流式和非流式响应。
2.ninja `proxy` 模式下的 `backend-api` 转为 `/v1/images/generations` 接口
2.xyhelper `proxy` 模式下的 `backend-api免费接口` 转为 `/v1/images/generations` 接口
3. 支持直接把refresh_token作为请求key方便接入one_api
4. 支持 gpt-4-mobile 、gpt-4-s 、基本所有的GPTS
* **xyhelper 的 免费 backend-api 接口,无需打码**
* **xyhelper接口每分钟最多请求30次介意请绕行**
* 我是开发者,我想自行修改功能->前往源码库 https://github.com/xyhelper/chatgpt-mirror-server
* 我没服务器,也没有官网账号,只想使用->前往官网购买我们运营的会员服务 https://www.xyhelper.com.cn
* 我想做商业用途,我想自己运营->老板里面请 https://www.xyhelper.com.cn/access
* 我有服务器,我想自己部署->请继续阅读本文档(有条件的话给个star吧)
如果本项目对你有帮助的话,请点个小星星吧~
如果有什么在项目的使用过程中的疑惑或需求,欢迎加入 Community Telegram Channel: [Inker 的魔法世界](https://t.me/InkerWorld) 来和大家一起交流一下~
@@ -59,13 +67,13 @@
## 注意
> [!CAUTION]
> 1. 本项目的运行需要 ninja
> 1. 本项目的运行需要 xyhelper 的免费接口
>
> 2. 本项目实际为将来自 `/v1/chat/completions` 的请求转发到ninja的 `/backend-api/conversation` 接口,因此本项目并不支持高并发操作,请不要接入如 `沉浸式翻译` 等高并发项目。
> 2. 本项目实际为将来自 `/v1/chat/completions` 的请求转发到xyhelper免费接口的 `/backend-api/conversation` 接口,因此本项目并不支持高并发操作,请不要接入如 `沉浸式翻译` 等高并发项目。
>
> 3. 本项目支持使用apple平台的refresh_token作为请求key.
>
> 4. 本项目并不能绕过 OpenAI 和 ninja 官方的限制,只提供便利,不提供绕过。
> 4. 本项目并不能绕过 OpenAI 和 xyhelper 官方的限制,只提供便利,不提供绕过。
>
> 5. 提问的艺术:当出现项目不能正常运行时,请携带 `DEBUG` 级别的日志在 `Issue` 或者社区群内提问,否则将开启算命模式~
@@ -95,9 +103,9 @@
- `process_threads`: 用于设置线程数,如果不需要设置,可以保持不变,如果需要设置,可以设置为需要设置的值,如果设置为 `1`,则会强制设置为单线程模式。
- `upstream_base_url`: ninja 的部署地址,如:`https://pandoranext.com`,注意:不要以 `/` 结尾。可以填写为本项目可以访问到的 PandoraNext 的内网地址。
- `upstream_base_url`: xyhelper 的免费接口地址,如:`https://demo.xyhelper.cn`,注意:不要以 `/` 结尾。
- `upstream_api_prefix`: PandoraNext Proxy 模式下的 API 前缀
- `upstream_api_prefix`: 默认为""
- `backend_container_url`: 用于dalle模型生成图片的时候展示所用需要设置为使用如 [ChatGPT-Next-Web](https://github.com/ChatGPTNextWebTeam/ChatGPT-Next-Web) 的用户可以访问到的本项目地址,如:`http://1.2.3.4:50011`,同原环境变量中的 `UPLOAD_BASE_URL`
@@ -143,7 +151,8 @@ PS. 注意arkose_urls中的地址需要支持PandoraNext的Arkose Token获取
- `enableOai`:用于设置是否使用官网通过refresh_token刷新access_token仅在 `enableOai``true` 时生效。
- `ninja_refreshToAccess_Url`:用于设置使用ninja来进行使用refresh_token刷新access_token,enableOai为false的时候必填
- `xyhelper_refreshToAccess_Url`:用于设置使用xyhelper来进行使用refresh_token刷新access_token,enableOai为false的时候必填
- 默认为"https://demo.xyhelper.cn/applelogin"
- `redis`
@@ -182,7 +191,7 @@ PS. 注意arkose_urls中的地址需要支持PandoraNext的Arkose Token获取
请求方式:`POST`
请求头:正常携带 `Authorization``Content-Type` 即可,`Authorization` 的值为 `Bearer <ninja 的 fk>``Content-Type` 的值为 `application/json`
请求头:正常携带 `Authorization``Content-Type` 即可,`Authorization` 的值为 `Bearer <refresh_token>``Content-Type` 的值为 `application/json`
请求体格式示例:
@@ -379,4 +388,4 @@ services:
## Star History
[![Star History Chart](https://api.star-history.com/svg?repos=Yanyutin753/ninjaToV1Api_refresh&type=Date)](https://star-history.com/#Yanyutin753/ninjaToV1Api_refresh&Date)
[![Star History Chart](https://api.star-history.com/svg?repos=Yanyutin753/xyhelperV1Api_refresh&type=Date)](https://star-history.com/#Yanyutin753/xyhelperV1Api_refresh&Date)

View File

@@ -4,7 +4,7 @@
"process_workers": 2,
"process_threads": 2,
"proxy": "",
"upstream_base_url": "",
"upstream_base_url": "https://demo.xyhelper.cn",
"upstream_api_prefix": "",
"backend_container_url": "",
"backend_container_api_prefix": "",
@@ -27,7 +27,7 @@
"refresh_ToAccess": {
"stream_sleep_time": 0,
"enableOai":"true",
"ninja_refreshToAccess_Url": ""
"xyhelper_refreshToAccess_Url": "https://demo.xyhelper.cn/applelogin"
},
"redis": {
"host": "redis",

View File

@@ -1,5 +1 @@
{
"gpt-4-classic": {
"id":"g-YyyyMT9XH-chatgpt-classic"
}
}
{}

View File

@@ -2,7 +2,7 @@ version: '3'
services:
backend-to-api:
image: yangclivia/pandora-to-api:latest
image: yangclivia/pandora-to-api:0.7.8
restart: always
ports:
- "50011:33333"

58
main.py
View File

@@ -48,6 +48,7 @@ if PROXY_API_PREFIX != '':
PROXY_API_PREFIX = "/" + PROXY_API_PREFIX
UPLOAD_BASE_URL = CONFIG.get('backend_container_url', '')
KEY_FOR_GPTS_INFO = CONFIG.get('key_for_gpts_info', '')
KEY_FOR_GPTS_INFO_ACCESS_TOKEN = CONFIG.get('key_for_gpts_info', '')
API_PREFIX = CONFIG.get('backend_container_api_prefix', '')
GPT_4_S_New_Names = CONFIG.get('gpt_4_s_new_name', 'gpt-4-s').split(',')
GPT_4_MOBILE_NEW_NAMES = CONFIG.get('gpt_4_mobile_new_name', 'gpt-4-mobile').split(',')
@@ -61,10 +62,10 @@ BOT_MODE_ENABLED_CODE_BLOCK_OUTPUT = BOT_MODE.get('enabled_plugin_output', 'fals
BOT_MODE_ENABLED_PLAIN_IMAGE_URL_OUTPUT = BOT_MODE.get('enabled_plain_image_url_output', 'false').lower() == 'true'
# ninjaToV1Api_refresh
# xyhelperToV1Api_refresh
REFRESH_TOACCESS = CONFIG.get('refresh_ToAccess', {})
REFRESH_TOACCESS_ENABLEOAI = REFRESH_TOACCESS.get('enableOai', 'true').lower() == 'true'
REFRESH_TOACCESS_NINJA_REFRESHTOACCESS_URL = REFRESH_TOACCESS.get('ninja_refreshToAccess_Url', '')
REFRESH_TOACCESS_XYHELPER_REFRESHTOACCESS_URL = REFRESH_TOACCESS.get('xyhelper_refreshToAccess_Url', '')
STEAM_SLEEP_TIME = REFRESH_TOACCESS.get('steam_sleep_time', 0)
NEED_DELETE_CONVERSATION_AFTER_RESPONSE = CONFIG.get('need_delete_conversation_after_response',
@@ -197,12 +198,15 @@ def oaiGetAccessToken(refresh_token):
return None
# ninja获得access_token
def ninjaGetAccessToken(refresh_token, getAccessTokenUrl):
# xyhelper获得access_token
def xyhelperGetAccessToken(getAccessTokenUrl, refresh_token):
try:
logger.info("将通过这个网址请求access_token" + getAccessTokenUrl)
headers = {"Authorization": "Bearer " + refresh_token}
response = requests.post(getAccessTokenUrl, headers=headers)
data = {
'refresh_token': refresh_token,
}
response = requests.post(getAccessTokenUrl, data=data)
if not response.ok:
logger.error("Request 失败: " + response.text.strip())
return None
@@ -221,22 +225,22 @@ def ninjaGetAccessToken(refresh_token, getAccessTokenUrl):
def updateGptsKey():
global KEY_FOR_GPTS_INFO
global KEY_FOR_GPTS_INFO_ACCESS_TOKEN
if not KEY_FOR_GPTS_INFO == '' and not KEY_FOR_GPTS_INFO.startswith("eyJhb"):
if REFRESH_TOACCESS_ENABLEOAI:
access_token = oaiGetAccessToken(KEY_FOR_GPTS_INFO)
else:
access_token = ninjaGetAccessToken(REFRESH_TOACCESS_NINJA_REFRESHTOACCESS_URL, KEY_FOR_GPTS_INFO)
access_token = xyhelperGetAccessToken(REFRESH_TOACCESS_XYHELPER_REFRESHTOACCESS_URL, KEY_FOR_GPTS_INFO)
if access_token.startswith("eyJhb"):
KEY_FOR_GPTS_INFO = access_token
logging.info("KEY_FOR_GPTS_INFO被更新:" + KEY_FOR_GPTS_INFO)
KEY_FOR_GPTS_INFO_ACCESS_TOKEN = access_token
logging.info("KEY_FOR_GPTS_INFO_ACCESS_TOKEN被更新:" + KEY_FOR_GPTS_INFO_ACCESS_TOKEN)
# 根据 ID 发送请求并获取配置信息
def fetch_gizmo_info(base_url, proxy_api_prefix, model_id):
url = f"{base_url}{proxy_api_prefix}/backend-api/gizmos/{model_id}"
updateGptsKey()
headers = {
"Authorization": f"Bearer {KEY_FOR_GPTS_INFO}"
"Authorization": f"Bearer {KEY_FOR_GPTS_INFO_ACCESS_TOKEN}"
}
response = requests.get(url, headers=headers)
# logger.debug(f"fetch_gizmo_info_response: {response.text}")
@@ -251,6 +255,7 @@ def fetch_gizmo_info(base_url, proxy_api_prefix, model_id):
# 将配置添加到全局列表
def add_config_to_global_list(base_url, proxy_api_prefix, gpts_data):
global gpts_configurations
updateGptsKey()
# print(f"gpts_data: {gpts_data}")
for model_name, model_info in gpts_data.items():
# print(f"model_name: {model_name}")
@@ -319,9 +324,9 @@ scheduler.start()
# PANDORA_UPLOAD_URL = 'files.pandoranext.com'
VERSION = '0.7.7'
VERSION = '0.7.8'
# VERSION = 'test'
# UPDATE_INFO = '增加Arkose请求头'
UPDATE_INFO = '项目将脱离ninja使用xyhelperxyhelper_refreshToAccess_Url等配置需修改'
# UPDATE_INFO = '【仅供临时测试使用】 '
# 解析响应中的信息
@@ -400,7 +405,7 @@ with app.app_context():
logger.info(f"REFRESH_TOACCESS_ENABLEOAI: {REFRESH_TOACCESS_ENABLEOAI}")
if not REFRESH_TOACCESS_ENABLEOAI:
logger.info(f"REFRESH_TOACCESS_NINJA_REFRESHTOACCESS_URL: {REFRESH_TOACCESS_NINJA_REFRESHTOACCESS_URL}")
logger.info(f"REFRESH_TOACCESS_XYHELPER_REFRESHTOACCESS_URL: {REFRESH_TOACCESS_XYHELPER_REFRESHTOACCESS_URL}")
if BOT_MODE_ENABLED:
logger.info(f"enabled_markdown_image_output: {BOT_MODE_ENABLED_MARKDOWN_IMAGE_OUTPUT}")
@@ -408,10 +413,10 @@ with app.app_context():
logger.info(f"enabled_bing_reference_output: {BOT_MODE_ENABLED_BING_REFERENCE_OUTPUT}")
logger.info(f"enabled_plugin_output: {BOT_MODE_ENABLED_CODE_BLOCK_OUTPUT}")
# ninjaToV1Api_refresh
# xyhelperToV1Api_refresh
logger.info(f"REFRESH_TOACCESS_ENABLEOAI: {REFRESH_TOACCESS_ENABLEOAI}")
logger.info(f"REFRESH_TOACCESS_NINJA_REFRESHTOACCESS_URL: {REFRESH_TOACCESS_NINJA_REFRESHTOACCESS_URL}")
logger.info(f"REFRESH_TOACCESS_XYHELPER_REFRESHTOACCESS_URL: {REFRESH_TOACCESS_XYHELPER_REFRESHTOACCESS_URL}")
logger.info(f"STEAM_SLEEP_TIME: {STEAM_SLEEP_TIME}")
if not BASE_URL:
@@ -926,7 +931,7 @@ def send_text_prompt_and_get_response(messages, api_key, stream, model):
token = get_token()
payload["arkose_token"] = token
# 在headers中添加新字段
headers["Openai-Sentinel-Arkose-Token"] = token
headers["Openai-Sentinel-Arkose-Token"] = token
logger.debug(f"headers: {headers}")
logger.debug(f"payload: {payload}")
response = requests.post(url, headers=headers, json=payload, stream=True)
@@ -2257,11 +2262,11 @@ def chat_completions():
logger.info(f"从缓存读取到api_key.........。")
api_key = refresh_dict.get(api_key)
else:
refresh_token = api_key
if REFRESH_TOACCESS_ENABLEOAI:
refresh_token = api_key
api_key = oaiGetAccessToken(api_key)
else:
api_key = ninjaGetAccessToken(REFRESH_TOACCESS_NINJA_REFRESHTOACCESS_URL, api_key)
api_key = xyhelperGetAccessToken(REFRESH_TOACCESS_XYHELPER_REFRESHTOACCESS_URL, api_key)
if not api_key.startswith("eyJhb"):
return jsonify({"error": "refresh_token is wrong or refresh_token url is wrong!"}), 401
add_to_dict(refresh_token, api_key)
@@ -2426,7 +2431,7 @@ def images_generations():
refresh_token = api_key
api_key = oaiGetAccessToken(api_key)
else:
api_key = ninjaGetAccessToken(REFRESH_TOACCESS_NINJA_REFRESHTOACCESS_URL, api_key)
api_key = xyhelperGetAccessToken(REFRESH_TOACCESS_XYHELPER_REFRESHTOACCESS_URL, api_key)
if not api_key.startswith("eyJhb"):
return jsonify({"error": "refresh_token is wrong or refresh_token url is wrong!"}), 401
add_to_dict(refresh_token, api_key)
@@ -2602,11 +2607,11 @@ def updateRefresh_dict():
logger.info(f"==========================================")
logging.info("开始更新access_token.........")
for key in refresh_dict:
refresh_token = key
if REFRESH_TOACCESS_ENABLEOAI:
refresh_token = key
access_token = oaiGetAccessToken(key)
else:
access_token = ninjaGetAccessToken(REFRESH_TOACCESS_NINJA_REFRESHTOACCESS_URL, key)
access_token = xyhelperGetAccessToken(REFRESH_TOACCESS_XYHELPER_REFRESHTOACCESS_URL, key)
if not access_token.startswith("eyJhb"):
logger.debug("refresh_token is wrong or refresh_token url is wrong!")
error_num += 1
@@ -2614,10 +2619,7 @@ def updateRefresh_dict():
success_num += 1
logging.info("更新成功: " + str(success_num) + ", 失败: " + str(error_num))
logger.info(f"==========================================")
logging.info("开始更新KEY_FOR_GPTS_INFO.........")
updateGptsKey()
# 配置GPTS
logger.info(f"GPTS 配置信息.....................")
logging.info("开始更新KEY_FOR_GPTS_INFO_ACCESS_TOKEN和GPTS配置信息.......")
# 加载配置并添加到全局列表
gpts_data = load_gpts_config("./data/gpts.json")
add_config_to_global_list(BASE_URL, PROXY_API_PREFIX, gpts_data)
@@ -2627,8 +2629,8 @@ def updateRefresh_dict():
# 检查列表中是否有重复的模型名称
if len(accessible_model_list) != len(set(accessible_model_list)):
raise Exception("检测到重复的模型名称,请检查环境变量或配置文件")
raise Exception("检测到重复的模型名称,请检查环境变量或配置文件......")
logging.info("更新KEY_FOR_GPTS_INFO_ACCESS_TOKEN和GPTS配置信息成功......")
logger.info(f"==========================================")