diff --git a/.vscode/launch.json b/api/.vscode/launch.json similarity index 90% rename from .vscode/launch.json rename to api/.vscode/launch.json index 515deb4c0cf85b..9f89168677d87c 100644 --- a/.vscode/launch.json +++ b/api/.vscode/launch.json @@ -10,7 +10,7 @@ "request": "launch", "module": "flask", "env": { - "FLASK_APP": "api/app.py", + "FLASK_APP": "app.py", "FLASK_DEBUG": "1", "GEVENT_SUPPORT": "True" }, @@ -21,7 +21,7 @@ "--debug" ], "jinja": true, - "justMyCode": true + "justMyCode": false } ] } \ No newline at end of file diff --git a/api/controllers/console/__init__.py b/api/controllers/console/__init__.py index 2476d918870c6f..ac881dc126c0d0 100644 --- a/api/controllers/console/__init__.py +++ b/api/controllers/console/__init__.py @@ -6,7 +6,7 @@ api = ExternalApi(bp) # Import other controllers -from . import setup, version, apikey, admin +from . import extension, setup, version, apikey, admin # Import app controllers from .app import advanced_prompt_template, app, site, completion, model_config, statistic, conversation, message, generator, audio diff --git a/api/controllers/console/extension.py b/api/controllers/console/extension.py new file mode 100644 index 00000000000000..0b5ead214bf508 --- /dev/null +++ b/api/controllers/console/extension.py @@ -0,0 +1,23 @@ +from flask_restful import Resource, reqparse + +from controllers.console import api +from controllers.console.setup import setup_required +from controllers.console.wraps import account_initialization_required +from libs.login import login_required +from services.extension_service import ExtensionService + + +class CodeBasedExtension(Resource): + + @setup_required + @login_required + @account_initialization_required + def get(self): + parser = reqparse.RequestParser() + parser.add_argument('module', type=str, required=True, location='args') + args = parser.parse_args() + + return ExtensionService.get_code_based_extensions(args['module']) + + +api.add_resource(CodeBasedExtension, '/code-based-extensions') \ No newline at end of file diff --git a/api/core/__init__.py b/api/core/__init__.py index e69de29bb2d1d6..8c986fc8bd8afa 100644 --- a/api/core/__init__.py +++ b/api/core/__init__.py @@ -0,0 +1 @@ +import core.moderation.base \ No newline at end of file diff --git a/api/core/helper/extensible.py b/api/core/helper/extensible.py new file mode 100644 index 00000000000000..5a08d1cd3797bf --- /dev/null +++ b/api/core/helper/extensible.py @@ -0,0 +1,37 @@ +import json +import os +import copy + +class Extensible: + _extensions = {} + + def __init_subclass__(cls, **kwargs): + super().__init_subclass__(**kwargs) + cls.register() + + @classmethod + def register(cls): + subclass_path = os.path.abspath(cls.__module__.replace(".", os.path.sep) + '.py') + subclass_dir_path = os.path.dirname(subclass_path) + parent_folder_name = os.path.basename(os.path.dirname(subclass_dir_path)) + + if parent_folder_name == 'core': + return + + json_path = os.path.join(subclass_dir_path, 'schema.json') + json_data = {} + if os.path.exists(json_path): + with open(json_path, 'r') as f: + json_data = json.load(f) + + if parent_folder_name not in cls._extensions: + cls._extensions[parent_folder_name] = { + "module": parent_folder_name, + "data": [] + } + + cls._extensions[parent_folder_name]["data"].append(json_data) + + @classmethod + def get_extensions(cls) -> dict: + return copy.deepcopy(cls._extensions) \ No newline at end of file diff --git a/api/core/moderation/__init__.py b/api/core/moderation/__init__.py new file mode 100644 index 00000000000000..727a8a1e99897c --- /dev/null +++ b/api/core/moderation/__init__.py @@ -0,0 +1,4 @@ +from core.moderation.openai.openai import OpenAIModeration +from core.moderation.keywords.keywords import KeywordsModeration +from core.moderation.api_based.api_based import ApiBasedModeration +from core.moderation.cloud_service.cloud_service import CloudServiceModeration \ No newline at end of file diff --git a/api/core/moderation/api_based/__init__.py b/api/core/moderation/api_based/__init__.py new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/api/core/moderation/api_based/api_based.py b/api/core/moderation/api_based/api_based.py new file mode 100644 index 00000000000000..5e8a490cdf39bc --- /dev/null +++ b/api/core/moderation/api_based/api_based.py @@ -0,0 +1,4 @@ +from core.moderation.base import BaseModeration + +class ApiBasedModeration(BaseModeration): + pass \ No newline at end of file diff --git a/api/core/moderation/api_based/schema.json b/api/core/moderation/api_based/schema.json new file mode 100644 index 00000000000000..d0f88d0f4b2272 --- /dev/null +++ b/api/core/moderation/api_based/schema.json @@ -0,0 +1,12 @@ +{ + "name": "api_based", + "label": { + "en-US": "API-based Extension", + "zh-Hans": "基于 API 的扩展" + }, + "form_schema": {}, + "extra-config": { + "inputs_preset_response_display": false, + "onputs_preset_response_display": false + } +} \ No newline at end of file diff --git a/api/core/moderation/base.py b/api/core/moderation/base.py new file mode 100644 index 00000000000000..15b70d63e77535 --- /dev/null +++ b/api/core/moderation/base.py @@ -0,0 +1,4 @@ +from core.helper.extensible import Extensible + +class BaseModeration(Extensible): + pass \ No newline at end of file diff --git a/api/core/moderation/cloud_service/__init__.py b/api/core/moderation/cloud_service/__init__.py new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/api/core/moderation/cloud_service/cloud_service.py b/api/core/moderation/cloud_service/cloud_service.py new file mode 100644 index 00000000000000..d48dfc9cc518a6 --- /dev/null +++ b/api/core/moderation/cloud_service/cloud_service.py @@ -0,0 +1,4 @@ +from core.moderation.base import BaseModeration + +class CloudServiceModeration(BaseModeration): + pass \ No newline at end of file diff --git a/api/core/moderation/cloud_service/schema.json b/api/core/moderation/cloud_service/schema.json new file mode 100644 index 00000000000000..b9491de91dedc0 --- /dev/null +++ b/api/core/moderation/cloud_service/schema.json @@ -0,0 +1,51 @@ +{ + "name": "cloud_service", + "label": { + "en-US": "Cloud Service", + "zh-Hans": "云服务" + }, + "form_schema": [ + { + "select": { + "label": { + "en-US": "Cloud Provider", + "zh-Hans": "云计算厂商" + }, + "variable": "cloud_provider", + "required": true, + "options": [ + "腾讯云", + "阿里云", + "AWS" + ], + "default": "", + "placeholder": "" + } + }, + { + "text-input": { + "label": { + "en-US": "API Endpoint", + "zh-Hans": "API Endpoint" + }, + "variable": "api_endpoint", + "required": true, + "max_length": 100, + "default": "", + "placeholder": "" + } + }, + { + "paragraph": { + "label": { + "en-US": "API Key", + "zh-Hans": "API Key" + }, + "variable": "api_keys", + "required": true, + "default": "", + "placeholder": "" + } + } + ] +} \ No newline at end of file diff --git a/api/core/moderation/keywords/__init__.py b/api/core/moderation/keywords/__init__.py new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/api/core/moderation/keywords/keywords.py b/api/core/moderation/keywords/keywords.py new file mode 100644 index 00000000000000..9797907c2cc37b --- /dev/null +++ b/api/core/moderation/keywords/keywords.py @@ -0,0 +1,4 @@ +from core.moderation.base import BaseModeration + +class KeywordsModeration(BaseModeration): + pass \ No newline at end of file diff --git a/api/core/moderation/keywords/schema.json b/api/core/moderation/keywords/schema.json new file mode 100644 index 00000000000000..8f0c38b2c9e582 --- /dev/null +++ b/api/core/moderation/keywords/schema.json @@ -0,0 +1,8 @@ +{ + "name": "keywords", + "label": { + "en-US": "Keywords", + "zh-Hans": "关键词" + }, + "form_schema": {} +} \ No newline at end of file diff --git a/api/core/moderation/openai/__init__.py b/api/core/moderation/openai/__init__.py new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/api/core/moderation/openai/openai.py b/api/core/moderation/openai/openai.py new file mode 100644 index 00000000000000..2fa5e0ce1ca636 --- /dev/null +++ b/api/core/moderation/openai/openai.py @@ -0,0 +1,4 @@ +from core.moderation.base import BaseModeration + +class OpenAIModeration(BaseModeration): + pass \ No newline at end of file diff --git a/api/core/moderation/openai/schema.json b/api/core/moderation/openai/schema.json new file mode 100644 index 00000000000000..72dd25d44f46a2 --- /dev/null +++ b/api/core/moderation/openai/schema.json @@ -0,0 +1,8 @@ +{ + "name": "openai", + "label": { + "en-US": "Open AI Moderation", + "zh-Hans": "Open AI Moderation" + }, + "form_schema": {} +} \ No newline at end of file diff --git a/api/services/extension_service.py b/api/services/extension_service.py new file mode 100644 index 00000000000000..08ecf50efc84a2 --- /dev/null +++ b/api/services/extension_service.py @@ -0,0 +1,7 @@ +from core.helper.extensible import Extensible + +class ExtensionService: + + @classmethod + def get_code_based_extensions(cls, module: str) -> list[dict]: + return Extensible.get_extensions().get(module, []) \ No newline at end of file