mirror of
https://github.com/Yanyutin753/RefreshToV1Api.git
synced 2025-12-19 01:01:31 +08:00
Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1fc6fa7784 | ||
|
|
aae4fd64d7 | ||
|
|
cd983f0a0c | ||
|
|
76993fcce8 | ||
|
|
fa645a80d8 | ||
|
|
1e3e233adc | ||
|
|
002ff558b0 | ||
|
|
6f66431bb5 | ||
|
|
d815bf991e | ||
|
|
10488aeaa5 | ||
|
|
97f1c4f45f | ||
|
|
0d0ae4a95a | ||
|
|
37b0dd7c36 | ||
|
|
4a852bd070 | ||
|
|
0ca230a853 | ||
|
|
6eeadb49ac |
46
.github/workflows/xyhelper-deploy.yml
vendored
46
.github/workflows/xyhelper-deploy.yml
vendored
@@ -1,46 +0,0 @@
|
||||
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 }}
|
||||
33
Readme.md
33
Readme.md
@@ -2,28 +2,20 @@
|
||||
|
||||
> [!IMPORTANT]
|
||||
>
|
||||
> Respect `xyhelper` ,Respect `ninja` , Respect `Wizerd`!
|
||||
> Respect Zhile大佬 , Respect Wizerd!
|
||||
|
||||
感谢xyhelper、ninja和Wizerd大佬们的付出,敬礼!!!
|
||||
感谢pandoraNext和Wizerd的付出,敬礼!!!
|
||||
|
||||
本项目支持:
|
||||
|
||||
1. 将 xyhelper `proxy` 模式下的 `backend-api免费接口` 转为 `/v1/chat/completions` 接口,支持流式和非流式响应。
|
||||
1. 将 ninja `proxy` 模式下的 `backend-api` 转为 `/v1/chat/completions` 接口,支持流式和非流式响应。
|
||||
|
||||
2. 将 xyhelper `proxy` 模式下的 `backend-api免费接口` 转为 `/v1/images/generations` 接口
|
||||
2. 将 ninja `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) 来和大家一起交流一下~
|
||||
@@ -67,13 +59,13 @@
|
||||
## 注意
|
||||
|
||||
> [!CAUTION]
|
||||
> 1. 本项目的运行需要 xyhelper 的免费接口
|
||||
> 1. 本项目的运行需要 ninja
|
||||
>
|
||||
> 2. 本项目实际为将来自 `/v1/chat/completions` 的请求转发到xyhelper免费接口的 `/backend-api/conversation` 接口,因此本项目并不支持高并发操作,请不要接入如 `沉浸式翻译` 等高并发项目。
|
||||
> 2. 本项目实际为将来自 `/v1/chat/completions` 的请求转发到ninja的 `/backend-api/conversation` 接口,因此本项目并不支持高并发操作,请不要接入如 `沉浸式翻译` 等高并发项目。
|
||||
>
|
||||
> 3. 本项目支持使用apple平台的refresh_token作为请求key.
|
||||
>
|
||||
> 4. 本项目并不能绕过 OpenAI 和 xyhelper 官方的限制,只提供便利,不提供绕过。
|
||||
> 4. 本项目并不能绕过 OpenAI 和 ninja 官方的限制,只提供便利,不提供绕过。
|
||||
>
|
||||
> 5. 提问的艺术:当出现项目不能正常运行时,请携带 `DEBUG` 级别的日志在 `Issue` 或者社区群内提问,否则将开启算命模式~
|
||||
|
||||
@@ -103,9 +95,9 @@
|
||||
|
||||
- `process_threads`: 用于设置线程数,如果不需要设置,可以保持不变,如果需要设置,可以设置为需要设置的值,如果设置为 `1`,则会强制设置为单线程模式。
|
||||
|
||||
- `upstream_base_url`: xyhelper 的免费接口地址,如:`https://demo.xyhelper.cn`,注意:不要以 `/` 结尾。
|
||||
- `upstream_base_url`: ninja 的部署地址,如:`https://pandoranext.com`,注意:不要以 `/` 结尾。可以填写为本项目可以访问到的 PandoraNext 的内网地址。
|
||||
|
||||
- `upstream_api_prefix`: 默认为""
|
||||
- `upstream_api_prefix`: PandoraNext Proxy 模式下的 API 前缀
|
||||
|
||||
- `backend_container_url`: 用于dalle模型生成图片的时候展示所用,需要设置为使用如 [ChatGPT-Next-Web](https://github.com/ChatGPTNextWebTeam/ChatGPT-Next-Web) 的用户可以访问到的本项目地址,如:`http://1.2.3.4:50011`,同原环境变量中的 `UPLOAD_BASE_URL`
|
||||
|
||||
@@ -151,8 +143,7 @@ PS. 注意,arkose_urls中的地址需要支持PandoraNext的Arkose Token获取
|
||||
|
||||
- `enableOai`:用于设置是否使用官网通过refresh_token刷新access_token,仅在 `enableOai` 为 `true` 时生效。
|
||||
|
||||
- `xyhelper_refreshToAccess_Url`:用于设置使用xyhelper来进行使用refresh_token刷新access_token,enableOai为false的时候必填
|
||||
- 默认为"https://demo.xyhelper.cn/applelogin"
|
||||
- `ninja_refreshToAccess_Url`:用于设置使用ninja来进行使用refresh_token刷新access_token,enableOai为false的时候必填。
|
||||
|
||||
- `redis`
|
||||
|
||||
@@ -191,7 +182,7 @@ PS. 注意,arkose_urls中的地址需要支持PandoraNext的Arkose Token获取
|
||||
|
||||
请求方式:`POST`
|
||||
|
||||
请求头:正常携带 `Authorization` 和 `Content-Type` 即可,`Authorization` 的值为 `Bearer <refresh_token>`,`Content-Type` 的值为 `application/json`
|
||||
请求头:正常携带 `Authorization` 和 `Content-Type` 即可,`Authorization` 的值为 `Bearer <ninja 的 fk>`,`Content-Type` 的值为 `application/json`
|
||||
|
||||
请求体格式示例:
|
||||
|
||||
@@ -388,4 +379,4 @@ services:
|
||||
|
||||
## Star History
|
||||
|
||||
[](https://star-history.com/#Yanyutin753/xyhelperV1Api_refresh&Date)
|
||||
[](https://star-history.com/#Yanyutin753/ninjaToV1Api_refresh&Date)
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"process_workers": 2,
|
||||
"process_threads": 2,
|
||||
"proxy": "",
|
||||
"upstream_base_url": "https://demo.xyhelper.cn",
|
||||
"upstream_base_url": "",
|
||||
"upstream_api_prefix": "",
|
||||
"backend_container_url": "",
|
||||
"backend_container_api_prefix": "",
|
||||
@@ -27,7 +27,7 @@
|
||||
"refresh_ToAccess": {
|
||||
"stream_sleep_time": 0,
|
||||
"enableOai":"true",
|
||||
"xyhelper_refreshToAccess_Url": "https://demo.xyhelper.cn/applelogin"
|
||||
"ninja_refreshToAccess_Url": ""
|
||||
},
|
||||
"redis": {
|
||||
"host": "redis",
|
||||
|
||||
@@ -1 +1,5 @@
|
||||
{}
|
||||
{
|
||||
"gpt-4-classic": {
|
||||
"id":"g-YyyyMT9XH-chatgpt-classic"
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@ version: '3'
|
||||
|
||||
services:
|
||||
backend-to-api:
|
||||
image: yangclivia/pandora-to-api:0.7.8
|
||||
image: yangclivia/pandora-to-api:0.7.7
|
||||
restart: always
|
||||
ports:
|
||||
- "50011:33333"
|
||||
|
||||
102
main.py
102
main.py
@@ -62,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'
|
||||
|
||||
# xyhelperToV1Api_refresh
|
||||
# ninjaToV1Api_refresh
|
||||
REFRESH_TOACCESS = CONFIG.get('refresh_ToAccess', {})
|
||||
REFRESH_TOACCESS_ENABLEOAI = REFRESH_TOACCESS.get('enableOai', 'true').lower() == 'true'
|
||||
REFRESH_TOACCESS_XYHELPER_REFRESHTOACCESS_URL = REFRESH_TOACCESS.get('xyhelper_refreshToAccess_Url', '')
|
||||
REFRESH_TOACCESS_NINJA_REFRESHTOACCESS_URL = REFRESH_TOACCESS.get('ninja_refreshToAccess_Url', '')
|
||||
STEAM_SLEEP_TIME = REFRESH_TOACCESS.get('steam_sleep_time', 0)
|
||||
|
||||
NEED_DELETE_CONVERSATION_AFTER_RESPONSE = CONFIG.get('need_delete_conversation_after_response',
|
||||
@@ -198,15 +198,12 @@ def oaiGetAccessToken(refresh_token):
|
||||
return None
|
||||
|
||||
|
||||
# xyhelper获得access_token
|
||||
def xyhelperGetAccessToken(getAccessTokenUrl, refresh_token):
|
||||
# ninja获得access_token
|
||||
def ninjaGetAccessToken(getAccessTokenUrl, refresh_token):
|
||||
try:
|
||||
logger.info("将通过这个网址请求access_token:" + getAccessTokenUrl)
|
||||
|
||||
data = {
|
||||
'refresh_token': refresh_token,
|
||||
}
|
||||
response = requests.post(getAccessTokenUrl, data=data)
|
||||
headers = {"Authorization": "Bearer " + refresh_token}
|
||||
response = requests.post(getAccessTokenUrl, headers=headers)
|
||||
if not response.ok:
|
||||
logger.error("Request 失败: " + response.text.strip())
|
||||
return None
|
||||
@@ -230,7 +227,7 @@ def updateGptsKey():
|
||||
if REFRESH_TOACCESS_ENABLEOAI:
|
||||
access_token = oaiGetAccessToken(KEY_FOR_GPTS_INFO)
|
||||
else:
|
||||
access_token = xyhelperGetAccessToken(REFRESH_TOACCESS_XYHELPER_REFRESHTOACCESS_URL, KEY_FOR_GPTS_INFO)
|
||||
access_token = ninjaGetAccessToken(REFRESH_TOACCESS_NINJA_REFRESHTOACCESS_URL, KEY_FOR_GPTS_INFO)
|
||||
if access_token.startswith("eyJhb"):
|
||||
KEY_FOR_GPTS_INFO_ACCESS_TOKEN = access_token
|
||||
logging.info("KEY_FOR_GPTS_INFO_ACCESS_TOKEN被更新:" + KEY_FOR_GPTS_INFO_ACCESS_TOKEN)
|
||||
@@ -276,17 +273,15 @@ def add_config_to_global_list(base_url, proxy_api_prefix, gpts_data):
|
||||
if gizmo_info:
|
||||
redis_client.set(model_id, str(gizmo_info))
|
||||
logger.info(f"Cached gizmo info for {model_name}, {model_id}")
|
||||
|
||||
if gizmo_info:
|
||||
# 检查模型名称是否已经在列表中
|
||||
if not any(d['name'] == model_name for d in gpts_configurations):
|
||||
gpts_configurations.append({
|
||||
'name': model_name,
|
||||
'id': model_id,
|
||||
'config': gizmo_info
|
||||
})
|
||||
else:
|
||||
logger.info(f"Model already exists in the list, skipping...")
|
||||
# 检查模型名称是否已经在列表中
|
||||
if not any(d['name'] == model_name for d in gpts_configurations):
|
||||
gpts_configurations.append({
|
||||
'name': model_name,
|
||||
'id': model_id,
|
||||
'config': gizmo_info
|
||||
})
|
||||
else:
|
||||
logger.info(f"Model already exists in the list, skipping...")
|
||||
|
||||
|
||||
def generate_gpts_payload(model, messages):
|
||||
@@ -324,9 +319,9 @@ scheduler.start()
|
||||
# PANDORA_UPLOAD_URL = 'files.pandoranext.com'
|
||||
|
||||
|
||||
VERSION = '0.7.8'
|
||||
VERSION = '0.7.7.1'
|
||||
# VERSION = 'test'
|
||||
UPDATE_INFO = '项目将脱离ninja,使用xyhelper,xyhelper_refreshToAccess_Url等配置需修改'
|
||||
UPDATE_INFO = '支持gpt-4-gizmo-XXX,动态配置GPTS'
|
||||
# UPDATE_INFO = '【仅供临时测试使用】 '
|
||||
|
||||
# 解析响应中的信息
|
||||
@@ -405,7 +400,7 @@ with app.app_context():
|
||||
|
||||
logger.info(f"REFRESH_TOACCESS_ENABLEOAI: {REFRESH_TOACCESS_ENABLEOAI}")
|
||||
if not REFRESH_TOACCESS_ENABLEOAI:
|
||||
logger.info(f"REFRESH_TOACCESS_XYHELPER_REFRESHTOACCESS_URL: {REFRESH_TOACCESS_XYHELPER_REFRESHTOACCESS_URL}")
|
||||
logger.info(f"REFRESH_TOACCESS_NINJA_REFRESHTOACCESS_URL: {REFRESH_TOACCESS_NINJA_REFRESHTOACCESS_URL}")
|
||||
|
||||
if BOT_MODE_ENABLED:
|
||||
logger.info(f"enabled_markdown_image_output: {BOT_MODE_ENABLED_MARKDOWN_IMAGE_OUTPUT}")
|
||||
@@ -413,10 +408,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}")
|
||||
|
||||
# xyhelperToV1Api_refresh
|
||||
# ninjaToV1Api_refresh
|
||||
|
||||
logger.info(f"REFRESH_TOACCESS_ENABLEOAI: {REFRESH_TOACCESS_ENABLEOAI}")
|
||||
logger.info(f"REFRESH_TOACCESS_XYHELPER_REFRESHTOACCESS_URL: {REFRESH_TOACCESS_XYHELPER_REFRESHTOACCESS_URL}")
|
||||
logger.info(f"REFRESH_TOACCESS_NINJA_REFRESHTOACCESS_URL: {REFRESH_TOACCESS_NINJA_REFRESHTOACCESS_URL}")
|
||||
logger.info(f"STEAM_SLEEP_TIME: {STEAM_SLEEP_TIME}")
|
||||
|
||||
if not BASE_URL:
|
||||
@@ -864,10 +859,14 @@ def send_text_prompt_and_get_response(messages, api_key, stream, model):
|
||||
|
||||
# 查找模型配置
|
||||
model_config = find_model_config(model)
|
||||
if model_config:
|
||||
if model_config or 'gpt-4-gizmo-' in model:
|
||||
# 检查是否有 ori_name
|
||||
ori_model_name = model_config.get('ori_name', model)
|
||||
logger.info(f"原模型名: {ori_model_name}")
|
||||
if model_config:
|
||||
ori_model_name = model_config.get('ori_name', model)
|
||||
logger.info(f"原模型名: {ori_model_name}")
|
||||
else:
|
||||
logger.info(f"请求模型名: {model}")
|
||||
ori_model_name = model
|
||||
if ori_model_name == 'gpt-4-s':
|
||||
payload = {
|
||||
# 构建 payload
|
||||
@@ -918,6 +917,32 @@ def send_text_prompt_and_get_response(messages, api_key, stream, model):
|
||||
"force_paragen": False,
|
||||
"force_rate_limit": False
|
||||
}
|
||||
elif 'gpt-4-gizmo-' in model:
|
||||
payload = generate_gpts_payload(model, formatted_messages)
|
||||
if not payload:
|
||||
global gpts_configurations
|
||||
# 假设 model是 'gpt-4-gizmo-123'
|
||||
split_name = model.split('gpt-4-gizmo-')
|
||||
model_id = split_name[1] if len(split_name) > 1 else None
|
||||
gizmo_info = fetch_gizmo_info(BASE_URL, PROXY_API_PREFIX, model_id)
|
||||
logging.info(gizmo_info)
|
||||
|
||||
# 如果成功获取到数据,则将其存入 Redis
|
||||
if gizmo_info:
|
||||
redis_client.set(model_id, str(gizmo_info))
|
||||
logger.info(f"Cached gizmo info for {model}, {model_id}")
|
||||
# 检查模型名称是否已经在列表中
|
||||
if not any(d['name'] == model for d in gpts_configurations):
|
||||
gpts_configurations.append({
|
||||
'name': model,
|
||||
'id': model_id,
|
||||
'config': gizmo_info
|
||||
})
|
||||
else:
|
||||
logger.info(f"Model already exists in the list, skipping...")
|
||||
payload = generate_gpts_payload(model, formatted_messages)
|
||||
else:
|
||||
raise Exception('KEY_FOR_GPTS_INFO is not accessible')
|
||||
else:
|
||||
payload = generate_gpts_payload(model, formatted_messages)
|
||||
if not payload:
|
||||
@@ -2248,7 +2273,7 @@ def chat_completions():
|
||||
messages = data.get('messages')
|
||||
model = data.get('model')
|
||||
accessible_model_list = get_accessible_model_list()
|
||||
if model not in accessible_model_list:
|
||||
if model not in accessible_model_list and not 'gpt-4-gizmo-' in model:
|
||||
return jsonify({"error": "model is not accessible"}), 401
|
||||
|
||||
stream = data.get('stream', False)
|
||||
@@ -2266,7 +2291,7 @@ def chat_completions():
|
||||
if REFRESH_TOACCESS_ENABLEOAI:
|
||||
api_key = oaiGetAccessToken(api_key)
|
||||
else:
|
||||
api_key = xyhelperGetAccessToken(REFRESH_TOACCESS_XYHELPER_REFRESHTOACCESS_URL, api_key)
|
||||
api_key = ninjaGetAccessToken(REFRESH_TOACCESS_NINJA_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)
|
||||
@@ -2406,7 +2431,7 @@ def images_generations():
|
||||
# messages = data.get('messages')
|
||||
model = data.get('model')
|
||||
accessible_model_list = get_accessible_model_list()
|
||||
if model not in accessible_model_list:
|
||||
if model not in accessible_model_list and not 'gpt-4-gizmo-' in model:
|
||||
return jsonify({"error": "model is not accessible"}), 401
|
||||
|
||||
prompt = data.get('prompt', '')
|
||||
@@ -2431,7 +2456,7 @@ def images_generations():
|
||||
refresh_token = api_key
|
||||
api_key = oaiGetAccessToken(api_key)
|
||||
else:
|
||||
api_key = xyhelperGetAccessToken(REFRESH_TOACCESS_XYHELPER_REFRESHTOACCESS_URL, api_key)
|
||||
api_key = ninjaGetAccessToken(REFRESH_TOACCESS_NINJA_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)
|
||||
@@ -2611,7 +2636,7 @@ def updateRefresh_dict():
|
||||
if REFRESH_TOACCESS_ENABLEOAI:
|
||||
access_token = oaiGetAccessToken(key)
|
||||
else:
|
||||
access_token = xyhelperGetAccessToken(REFRESH_TOACCESS_XYHELPER_REFRESHTOACCESS_URL, key)
|
||||
access_token = ninjaGetAccessToken(REFRESH_TOACCESS_NINJA_REFRESHTOACCESS_URL, key)
|
||||
if not access_token.startswith("eyJhb"):
|
||||
logger.debug("refresh_token is wrong or refresh_token url is wrong!")
|
||||
error_num += 1
|
||||
@@ -2619,18 +2644,17 @@ def updateRefresh_dict():
|
||||
success_num += 1
|
||||
logging.info("更新成功: " + str(success_num) + ", 失败: " + str(error_num))
|
||||
logger.info(f"==========================================")
|
||||
logging.info("开始更新KEY_FOR_GPTS_INFO_ACCESS_TOKEN和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)
|
||||
|
||||
|
||||
accessible_model_list = get_accessible_model_list()
|
||||
logger.info(f"当前可用 GPTS 列表: {accessible_model_list}")
|
||||
|
||||
# 检查列表中是否有重复的模型名称
|
||||
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"当前可用 GPTS 列表: {accessible_model_list}")
|
||||
logger.info(f"==========================================")
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user