From aa13d140194f843fd0b3eda9ea8f27112b1b55cb Mon Sep 17 00:00:00 2001 From: Patryk Garstecki Date: Sat, 18 May 2024 04:52:48 +0200 Subject: [PATCH] Feat/chat custom disclaimer (#4306) --- api/constants/recommended_apps.json | 87 ++++++--- api/controllers/console/admin.py | 6 + api/controllers/console/app/site.py | 2 + .../console/explore/recommended_app.py | 1 + .../console/workspace/tool_providers.py | 4 + api/controllers/web/site.py | 1 + api/core/tools/tool_manager.py | 3 +- api/fields/app_fields.py | 2 + .../5fda94355fce_custom_disclaimer.py | 45 +++++ api/models/model.py | 2 + api/models/tools.py | 2 + api/services/recommended_app_service.py | 1 + api/services/tools_manage_service.py | 8 +- web/app/components/app/chat/index.tsx | 83 ++++---- .../app/overview/settings/index.tsx | 15 +- .../components/base/chat/chat/chat-input.tsx | 177 +++++++++--------- web/app/components/share/chat/index.tsx | 1 + web/app/components/share/chatbot/index.tsx | 1 + .../edit-custom-collection-modal/index.tsx | 13 ++ web/app/components/tools/types.ts | 1 + web/i18n/de-DE/app-overview.ts | 3 + web/i18n/de-DE/tools.ts | 2 + web/i18n/en-US/app-overview.ts | 3 + web/i18n/en-US/tools.ts | 2 + web/i18n/fr-FR/app-overview.ts | 3 + web/i18n/fr-FR/tools.ts | 2 + web/i18n/ja-JP/app-overview.ts | 3 + web/i18n/ja-JP/tools.ts | 2 + web/i18n/pl-PL/app-overview.ts | 3 + web/i18n/pl-PL/tools.ts | 2 + web/i18n/pt-BR/app-overview.ts | 3 + web/i18n/pt-BR/tools.ts | 2 + web/i18n/uk-UA/app-overview.ts | 3 + web/i18n/uk-UA/tools.ts | 2 + web/i18n/vi-VN/app-overview.ts | 3 + web/i18n/vi-VN/tools.ts | 2 + web/i18n/zh-Hans/app-overview.ts | 3 + web/i18n/zh-Hans/tools.ts | 2 + web/i18n/zh-Hant/app-overview.ts | 3 + web/i18n/zh-Hant/tools.ts | 2 + web/models/explore.ts | 1 + web/models/share.ts | 1 + web/types/app.ts | 2 + 43 files changed, 350 insertions(+), 159 deletions(-) create mode 100644 api/migrations/versions/5fda94355fce_custom_disclaimer.py diff --git a/api/constants/recommended_apps.json b/api/constants/recommended_apps.json index 8a1ee808e482a..68c913f80a751 100644 --- a/api/constants/recommended_apps.json +++ b/api/constants/recommended_apps.json @@ -24,7 +24,8 @@ "description": "Welcome to your personalized Investment Analysis Copilot service, where we delve into the depths of stock analysis to provide you with comprehensive insights. \n", "is_listed": true, "position": 0, - "privacy_policy": null + "privacy_policy": null, + "custom_disclaimer": null }, { "app": { @@ -40,7 +41,8 @@ "description": "Code interpreter, clarifying the syntax and semantics of the code.", "is_listed": true, "position": 13, - "privacy_policy": "https://dify.ai" + "privacy_policy": "https://dify.ai", + "custom_disclaimer": null }, { "app": { @@ -56,7 +58,8 @@ "description": "Hello, I am your creative partner in bringing ideas to vivid life! I can assist you in creating stunning designs by leveraging abilities of DALL\u00b7E 3. ", "is_listed": true, "position": 4, - "privacy_policy": null + "privacy_policy": null, + "custom_disclaimer": null }, { "app": { @@ -72,7 +75,8 @@ "description": "Fully SEO Optimized Article including FAQs", "is_listed": true, "position": 1, - "privacy_policy": null + "privacy_policy": null, + "custom_disclaimer": null }, { "app": { @@ -88,7 +92,8 @@ "description": "Generate Flat Style Image", "is_listed": true, "position": 10, - "privacy_policy": null + "privacy_policy": null, + "custom_disclaimer": null }, { "app": { @@ -104,7 +109,8 @@ "description": "A multilingual translator that provides translation capabilities in multiple languages. Input the text you need to translate and select the target language.", "is_listed": true, "position": 10, - "privacy_policy": "https://dify.ai" + "privacy_policy": "https://dify.ai", + "custom_disclaimer": null }, { "app": { @@ -120,7 +126,8 @@ "description": "I am a YouTube Channel Data Analysis Copilot, I am here to provide expert data analysis tailored to your needs. ", "is_listed": true, "position": 2, - "privacy_policy": null + "privacy_policy": null, + "custom_disclaimer": null }, { "app": { @@ -136,7 +143,8 @@ "description": "Meeting minutes generator", "is_listed": true, "position": 0, - "privacy_policy": "https://dify.ai" + "privacy_policy": "https://dify.ai", + "custom_disclaimer": null }, { "app": { @@ -152,7 +160,8 @@ "description": "Tell me the main elements, I will generate a cyberpunk style image for you. ", "is_listed": true, "position": 10, - "privacy_policy": null + "privacy_policy": null, + "custom_disclaimer": null }, { "app": { @@ -168,7 +177,8 @@ "description": "Write SQL from natural language by pasting in your schema with the request.Please describe your query requirements in natural language and select the target database type.", "is_listed": true, "position": 13, - "privacy_policy": "https://dify.ai" + "privacy_policy": "https://dify.ai", + "custom_disclaimer": null }, { "app": { @@ -184,7 +194,8 @@ "description": "Welcome to your personalized travel service with Consultant! \ud83c\udf0d\u2708\ufe0f Ready to embark on a journey filled with adventure and relaxation? Let's dive into creating your unforgettable travel experience. ", "is_listed": true, "position": 3, - "privacy_policy": null + "privacy_policy": null, + "custom_disclaimer": null }, { "app": { @@ -200,7 +211,8 @@ "description": "I can answer your questions related to strategic marketing.", "is_listed": true, "position": 10, - "privacy_policy": "https://dify.ai" + "privacy_policy": "https://dify.ai", + "custom_disclaimer": null }, { "app": { @@ -216,7 +228,8 @@ "description": "A simulated front-end interviewer that tests the skill level of front-end development through questioning.", "is_listed": true, "position": 19, - "privacy_policy": "https://dify.ai" + "privacy_policy": "https://dify.ai", + "custom_disclaimer": null }, { "app": { @@ -232,7 +245,8 @@ "description": "I'm here to hear about your feature request about Dify and help you flesh it out further. What's on your mind?", "is_listed": true, "position": 6, - "privacy_policy": null + "privacy_policy": null, + "custom_disclaimer": null } ] }, @@ -261,7 +275,8 @@ "description": "\u4e00\u4e2a\u6a21\u62df\u7684\u524d\u7aef\u9762\u8bd5\u5b98\uff0c\u901a\u8fc7\u63d0\u95ee\u7684\u65b9\u5f0f\u5bf9\u524d\u7aef\u5f00\u53d1\u7684\u6280\u80fd\u6c34\u5e73\u8fdb\u884c\u68c0\u9a8c\u3002", "is_listed": true, "position": 20, - "privacy_policy": null + "privacy_policy": null, + "custom_disclaimer": null }, { "app": { @@ -277,7 +292,8 @@ "description": "\u8f93\u5165\u76f8\u5173\u5143\u7d20\uff0c\u4e3a\u4f60\u751f\u6210\u6241\u5e73\u63d2\u753b\u98ce\u683c\u7684\u5c01\u9762\u56fe\u7247", "is_listed": true, "position": 10, - "privacy_policy": null + "privacy_policy": null, + "custom_disclaimer": null }, { "app": { @@ -293,7 +309,8 @@ "description": "\u4e00\u4e2a\u591a\u8bed\u8a00\u7ffb\u8bd1\u5668\uff0c\u63d0\u4f9b\u591a\u79cd\u8bed\u8a00\u7ffb\u8bd1\u80fd\u529b\uff0c\u8f93\u5165\u4f60\u9700\u8981\u7ffb\u8bd1\u7684\u6587\u672c\uff0c\u9009\u62e9\u76ee\u6807\u8bed\u8a00\u5373\u53ef\u3002\u63d0\u793a\u8bcd\u6765\u81ea\u5b9d\u7389\u3002", "is_listed": true, "position": 10, - "privacy_policy": null + "privacy_policy": null, + "custom_disclaimer": null }, { "app": { @@ -309,7 +326,8 @@ "description": "\u6211\u5c06\u5e2e\u52a9\u4f60\u628a\u81ea\u7136\u8bed\u8a00\u8f6c\u5316\u6210\u6307\u5b9a\u7684\u6570\u636e\u5e93\u67e5\u8be2 SQL \u8bed\u53e5\uff0c\u8bf7\u5728\u4e0b\u65b9\u8f93\u5165\u4f60\u9700\u8981\u67e5\u8be2\u7684\u6761\u4ef6\uff0c\u5e76\u9009\u62e9\u76ee\u6807\u6570\u636e\u5e93\u7c7b\u578b\u3002", "is_listed": true, "position": 12, - "privacy_policy": null + "privacy_policy": null, + "custom_disclaimer": null }, { "app": { @@ -325,7 +343,8 @@ "description": "\u9610\u660e\u4ee3\u7801\u7684\u8bed\u6cd5\u548c\u8bed\u4e49\u3002", "is_listed": true, "position": 2, - "privacy_policy": "https://dify.ai" + "privacy_policy": "https://dify.ai", + "custom_disclaimer": null }, { "app": { @@ -341,7 +360,8 @@ "description": "\u8f93\u5165\u76f8\u5173\u5143\u7d20\uff0c\u4e3a\u4f60\u751f\u6210\u8d5b\u535a\u670b\u514b\u98ce\u683c\u7684\u63d2\u753b", "is_listed": true, "position": 10, - "privacy_policy": null + "privacy_policy": null, + "custom_disclaimer": null }, { "app": { @@ -357,7 +377,8 @@ "description": "\u6211\u662f\u4e00\u540dSEO\u4e13\u5bb6\uff0c\u53ef\u4ee5\u6839\u636e\u60a8\u63d0\u4f9b\u7684\u6807\u9898\u3001\u5173\u952e\u8bcd\u3001\u76f8\u5173\u4fe1\u606f\u6765\u6279\u91cf\u751f\u6210SEO\u6587\u7ae0\u3002", "is_listed": true, "position": 10, - "privacy_policy": null + "privacy_policy": null, + "custom_disclaimer": null }, { "app": { @@ -373,7 +394,8 @@ "description": "\u5e2e\u4f60\u91cd\u65b0\u7ec4\u7ec7\u548c\u8f93\u51fa\u6df7\u4e71\u590d\u6742\u7684\u4f1a\u8bae\u7eaa\u8981\u3002", "is_listed": true, "position": 6, - "privacy_policy": "https://dify.ai" + "privacy_policy": "https://dify.ai", + "custom_disclaimer": null }, { "app": { @@ -389,7 +411,8 @@ "description": "\u6b22\u8fce\u4f7f\u7528\u60a8\u7684\u4e2a\u6027\u5316\u7f8e\u80a1\u6295\u8d44\u5206\u6790\u52a9\u624b\uff0c\u5728\u8fd9\u91cc\u6211\u4eec\u6df1\u5165\u7684\u8fdb\u884c\u80a1\u7968\u5206\u6790\uff0c\u4e3a\u60a8\u63d0\u4f9b\u5168\u9762\u7684\u6d1e\u5bdf\u3002", "is_listed": true, "position": 0, - "privacy_policy": null + "privacy_policy": null, + "custom_disclaimer": null }, { "app": { @@ -405,7 +428,8 @@ "description": "\u60a8\u597d\uff0c\u6211\u662f\u60a8\u7684\u521b\u610f\u4f19\u4f34\uff0c\u5c06\u5e2e\u52a9\u60a8\u5c06\u60f3\u6cd5\u751f\u52a8\u5730\u5b9e\u73b0\uff01\u6211\u53ef\u4ee5\u534f\u52a9\u60a8\u5229\u7528DALL\u00b7E 3\u7684\u80fd\u529b\u521b\u9020\u51fa\u4ee4\u4eba\u60ca\u53f9\u7684\u8bbe\u8ba1\u3002", "is_listed": true, "position": 4, - "privacy_policy": null + "privacy_policy": null, + "custom_disclaimer": null }, { "app": { @@ -421,7 +445,8 @@ "description": "\u7ffb\u8bd1\u4e13\u5bb6\uff1a\u63d0\u4f9b\u4e2d\u82f1\u6587\u4e92\u8bd1", "is_listed": true, "position": 4, - "privacy_policy": "https://dify.ai" + "privacy_policy": "https://dify.ai", + "custom_disclaimer": null }, { "app": { @@ -437,7 +462,8 @@ "description": "\u60a8\u7684\u79c1\u4eba\u5b66\u4e60\u5bfc\u5e08\uff0c\u5e2e\u60a8\u5236\u5b9a\u5b66\u4e60\u8ba1\u5212\u5e76\u8f85\u5bfc", "is_listed": true, "position": 26, - "privacy_policy": "https://dify.ai" + "privacy_policy": "https://dify.ai", + "custom_disclaimer": null }, { "app": { @@ -453,7 +479,8 @@ "description": "\u5e2e\u4f60\u64b0\u5199\u8bba\u6587\u6587\u732e\u7efc\u8ff0", "is_listed": true, "position": 7, - "privacy_policy": "https://dify.ai" + "privacy_policy": "https://dify.ai", + "custom_disclaimer": null }, { "app": { @@ -469,7 +496,8 @@ "description": "\u4f60\u597d\uff0c\u544a\u8bc9\u6211\u60a8\u60f3\u5206\u6790\u7684 YouTube \u9891\u9053\uff0c\u6211\u5c06\u4e3a\u60a8\u6574\u7406\u4e00\u4efd\u5b8c\u6574\u7684\u6570\u636e\u5206\u6790\u62a5\u544a\u3002", "is_listed": true, "position": 0, - "privacy_policy": null + "privacy_policy": null, + "custom_disclaimer": null }, { "app": { @@ -485,7 +513,8 @@ "description": "\u6b22\u8fce\u4f7f\u7528\u60a8\u7684\u4e2a\u6027\u5316\u65c5\u884c\u670d\u52a1\u987e\u95ee\uff01\ud83c\udf0d\u2708\ufe0f \u51c6\u5907\u597d\u8e0f\u4e0a\u4e00\u6bb5\u5145\u6ee1\u5192\u9669\u4e0e\u653e\u677e\u7684\u65c5\u7a0b\u4e86\u5417\uff1f\u8ba9\u6211\u4eec\u4e00\u8d77\u6df1\u5165\u6253\u9020\u60a8\u96be\u5fd8\u7684\u65c5\u884c\u4f53\u9a8c\u5427\u3002", "is_listed": true, "position": 0, - "privacy_policy": null + "privacy_policy": null, + "custom_disclaimer": null } ] }, diff --git a/api/controllers/console/admin.py b/api/controllers/console/admin.py index aaa737f83ac69..028be5de548b7 100644 --- a/api/controllers/console/admin.py +++ b/api/controllers/console/admin.py @@ -48,6 +48,7 @@ def post(self): parser.add_argument('desc', type=str, location='json') parser.add_argument('copyright', type=str, location='json') parser.add_argument('privacy_policy', type=str, location='json') + parser.add_argument('custom_disclaimer', type=str, location='json') parser.add_argument('language', type=supported_language, required=True, nullable=False, location='json') parser.add_argument('category', type=str, required=True, nullable=False, location='json') parser.add_argument('position', type=int, required=True, nullable=False, location='json') @@ -62,6 +63,7 @@ def post(self): desc = args['desc'] if args['desc'] else '' copy_right = args['copyright'] if args['copyright'] else '' privacy_policy = args['privacy_policy'] if args['privacy_policy'] else '' + custom_disclaimer = args['custom_disclaimer'] if args['custom_disclaimer'] else '' else: desc = site.description if site.description else \ args['desc'] if args['desc'] else '' @@ -69,6 +71,8 @@ def post(self): args['copyright'] if args['copyright'] else '' privacy_policy = site.privacy_policy if site.privacy_policy else \ args['privacy_policy'] if args['privacy_policy'] else '' + custom_disclaimer = site.custom_disclaimer if site.custom_disclaimer else \ + args['custom_disclaimer'] if args['custom_disclaimer'] else '' recommended_app = RecommendedApp.query.filter(RecommendedApp.app_id == args['app_id']).first() @@ -78,6 +82,7 @@ def post(self): description=desc, copyright=copy_right, privacy_policy=privacy_policy, + custom_disclaimer=custom_disclaimer, language=args['language'], category=args['category'], position=args['position'] @@ -93,6 +98,7 @@ def post(self): recommended_app.description = desc recommended_app.copyright = copy_right recommended_app.privacy_policy = privacy_policy + recommended_app.custom_disclaimer = custom_disclaimer recommended_app.language = args['language'] recommended_app.category = args['category'] recommended_app.position = args['position'] diff --git a/api/controllers/console/app/site.py b/api/controllers/console/app/site.py index 256824981e6c7..592009fd88bc1 100644 --- a/api/controllers/console/app/site.py +++ b/api/controllers/console/app/site.py @@ -23,6 +23,7 @@ def parse_app_site_args(): parser.add_argument('customize_domain', type=str, required=False, location='json') parser.add_argument('copyright', type=str, required=False, location='json') parser.add_argument('privacy_policy', type=str, required=False, location='json') + parser.add_argument('custom_disclaimer', type=str, required=False, location='json') parser.add_argument('customize_token_strategy', type=str, choices=['must', 'allow', 'not_allow'], required=False, location='json') @@ -56,6 +57,7 @@ def post(self, app_model): 'customize_domain', 'copyright', 'privacy_policy', + 'custom_disclaimer', 'customize_token_strategy', 'prompt_public' ]: diff --git a/api/controllers/console/explore/recommended_app.py b/api/controllers/console/explore/recommended_app.py index 2787b7cdbaeb6..6e10e2ec92671 100644 --- a/api/controllers/console/explore/recommended_app.py +++ b/api/controllers/console/explore/recommended_app.py @@ -21,6 +21,7 @@ 'description': fields.String(attribute='description'), 'copyright': fields.String, 'privacy_policy': fields.String, + 'custom_disclaimer': fields.String, 'category': fields.String, 'position': fields.Integer, 'is_listed': fields.Boolean diff --git a/api/controllers/console/workspace/tool_providers.py b/api/controllers/console/workspace/tool_providers.py index 3057de45599e4..63f4613e7d29b 100644 --- a/api/controllers/console/workspace/tool_providers.py +++ b/api/controllers/console/workspace/tool_providers.py @@ -116,6 +116,7 @@ def post(self): parser.add_argument('provider', type=str, required=True, nullable=False, location='json') parser.add_argument('icon', type=dict, required=True, nullable=False, location='json') parser.add_argument('privacy_policy', type=str, required=False, nullable=True, location='json') + parser.add_argument('custom_disclaimer', type=str, required=False, nullable=True, location='json') args = parser.parse_args() @@ -128,6 +129,7 @@ def post(self): args['schema_type'], args['schema'], args.get('privacy_policy', ''), + args.get('custom_disclaimer', ''), ) class ToolApiProviderGetRemoteSchemaApi(Resource): @@ -186,6 +188,7 @@ def post(self): parser.add_argument('original_provider', type=str, required=True, nullable=False, location='json') parser.add_argument('icon', type=dict, required=True, nullable=False, location='json') parser.add_argument('privacy_policy', type=str, required=True, nullable=True, location='json') + parser.add_argument('custom_disclaimer', type=str, required=True, nullable=True, location='json') args = parser.parse_args() @@ -199,6 +202,7 @@ def post(self): args['schema_type'], args['schema'], args['privacy_policy'], + args['custom_disclaimer'], ) class ToolApiProviderDeleteApi(Resource): diff --git a/api/controllers/web/site.py b/api/controllers/web/site.py index 49b0a8bfc0954..a084b56b08802 100644 --- a/api/controllers/web/site.py +++ b/api/controllers/web/site.py @@ -31,6 +31,7 @@ class AppSiteApi(WebApiResource): 'description': fields.String, 'copyright': fields.String, 'privacy_policy': fields.String, + 'custom_disclaimer': fields.String, 'default_language': fields.String, 'prompt_public': fields.Boolean } diff --git a/api/core/tools/tool_manager.py b/api/core/tools/tool_manager.py index d46f1f22a574d..dd28055932a86 100644 --- a/api/core/tools/tool_manager.py +++ b/api/core/tools/tool_manager.py @@ -487,7 +487,8 @@ def user_get_api_provider(cls, provider: str, tenant_id: str) -> dict: 'icon': icon, 'description': provider.description, 'credentials': masked_credentials, - 'privacy_policy': provider.privacy_policy + 'privacy_policy': provider.privacy_policy, + 'custom_disclaimer': provider.custom_disclaimer }) @classmethod diff --git a/api/fields/app_fields.py b/api/fields/app_fields.py index c7cfdd793997c..212c3e7f17986 100644 --- a/api/fields/app_fields.py +++ b/api/fields/app_fields.py @@ -113,6 +113,7 @@ 'customize_domain': fields.String, 'copyright': fields.String, 'privacy_policy': fields.String, + 'custom_disclaimer': fields.String, 'customize_token_strategy': fields.String, 'prompt_public': fields.Boolean, 'app_base_url': fields.String, @@ -146,6 +147,7 @@ 'customize_domain': fields.String, 'copyright': fields.String, 'privacy_policy': fields.String, + 'custom_disclaimer': fields.String, 'customize_token_strategy': fields.String, 'prompt_public': fields.Boolean } diff --git a/api/migrations/versions/5fda94355fce_custom_disclaimer.py b/api/migrations/versions/5fda94355fce_custom_disclaimer.py new file mode 100644 index 0000000000000..a5e2e6ee63cb9 --- /dev/null +++ b/api/migrations/versions/5fda94355fce_custom_disclaimer.py @@ -0,0 +1,45 @@ +"""Custom Disclaimer + +Revision ID: 5fda94355fce +Revises: 47cc7df8c4f3 +Create Date: 2024-05-10 20:04:45.806549 + +""" +import sqlalchemy as sa +from alembic import op + +import models as models + +# revision identifiers, used by Alembic. +revision = '5fda94355fce' +down_revision = '47cc7df8c4f3' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + with op.batch_alter_table('recommended_apps', schema=None) as batch_op: + batch_op.add_column(sa.Column('custom_disclaimer', sa.String(length=255), nullable=False)) + + with op.batch_alter_table('sites', schema=None) as batch_op: + batch_op.add_column(sa.Column('custom_disclaimer', sa.String(length=255), nullable=True)) + + with op.batch_alter_table('tool_api_providers', schema=None) as batch_op: + batch_op.add_column(sa.Column('custom_disclaimer', sa.String(length=255), nullable=True)) + + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + with op.batch_alter_table('tool_api_providers', schema=None) as batch_op: + batch_op.drop_column('custom_disclaimer') + + with op.batch_alter_table('sites', schema=None) as batch_op: + batch_op.drop_column('custom_disclaimer') + + with op.batch_alter_table('recommended_apps', schema=None) as batch_op: + batch_op.drop_column('custom_disclaimer') + + # ### end Alembic commands ### diff --git a/api/models/model.py b/api/models/model.py index 59b88eb3b1e37..befc8539b9873 100644 --- a/api/models/model.py +++ b/api/models/model.py @@ -435,6 +435,7 @@ class RecommendedApp(db.Model): description = db.Column(db.JSON, nullable=False) copyright = db.Column(db.String(255), nullable=False) privacy_policy = db.Column(db.String(255), nullable=False) + custom_disclaimer = db.Column(db.String(255), nullable=False) category = db.Column(db.String(255), nullable=False) position = db.Column(db.Integer, nullable=False, default=0) is_listed = db.Column(db.Boolean, nullable=False, default=True) @@ -1042,6 +1043,7 @@ class Site(db.Model): default_language = db.Column(db.String(255), nullable=False) copyright = db.Column(db.String(255)) privacy_policy = db.Column(db.String(255)) + custom_disclaimer = db.Column(db.String(255)) customize_domain = db.Column(db.String(255)) customize_token_strategy = db.Column(db.String(255), nullable=False) prompt_public = db.Column(db.Boolean, nullable=False, server_default=db.text('false')) diff --git a/api/models/tools.py b/api/models/tools.py index 8a133679e0060..64fc3345498dc 100644 --- a/api/models/tools.py +++ b/api/models/tools.py @@ -107,6 +107,8 @@ class ApiToolProvider(db.Model): credentials_str = db.Column(db.Text, nullable=False) # privacy policy privacy_policy = db.Column(db.String(255), nullable=True) + # custom_disclaimer + custom_disclaimer = db.Column(db.String(255), nullable=True) created_at = db.Column(db.DateTime, nullable=False, server_default=db.text('CURRENT_TIMESTAMP(0)')) updated_at = db.Column(db.DateTime, nullable=False, server_default=db.text('CURRENT_TIMESTAMP(0)')) diff --git a/api/services/recommended_app_service.py b/api/services/recommended_app_service.py index 3d36fb80af712..def39569ea035 100644 --- a/api/services/recommended_app_service.py +++ b/api/services/recommended_app_service.py @@ -86,6 +86,7 @@ def _fetch_recommended_apps_from_db(cls, language: str) -> dict: 'description': site.description, 'copyright': site.copyright, 'privacy_policy': site.privacy_policy, + 'custom_disclaimer': site.custom_disclaimer, 'category': recommended_app.category, 'position': recommended_app.position, 'is_listed': recommended_app.is_listed diff --git a/api/services/tools_manage_service.py b/api/services/tools_manage_service.py index ec4e89bd1489d..7100d79ee0b9d 100644 --- a/api/services/tools_manage_service.py +++ b/api/services/tools_manage_service.py @@ -177,7 +177,7 @@ def convert_schema_to_tool_bundles(schema: str, extra_info: dict = None) -> list @staticmethod def create_api_tool_provider( user_id: str, tenant_id: str, provider_name: str, icon: dict, credentials: dict, - schema_type: str, schema: str, privacy_policy: str + schema_type: str, schema: str, privacy_policy: str, custom_disclaimer: str ): """ create api tool provider @@ -213,7 +213,8 @@ def create_api_tool_provider( schema_type_str=schema_type, tools_str=json.dumps(jsonable_encoder(tool_bundles)), credentials_str={}, - privacy_policy=privacy_policy + privacy_policy=privacy_policy, + custom_disclaimer=custom_disclaimer ) if 'auth_type' not in credentials: @@ -364,7 +365,7 @@ def get_builtin_tool_provider_credentials( @staticmethod def update_api_tool_provider( user_id: str, tenant_id: str, provider_name: str, original_provider: str, icon: dict, credentials: dict, - schema_type: str, schema: str, privacy_policy: str + schema_type: str, schema: str, privacy_policy: str, custom_disclaimer: str ): """ update api tool provider @@ -394,6 +395,7 @@ def update_api_tool_provider( provider.schema_type_str = ApiProviderSchemaType.OPENAPI.value provider.tools_str = json.dumps(jsonable_encoder(tool_bundles)) provider.privacy_policy = privacy_policy + provider.custom_disclaimer = custom_disclaimer if 'auth_type' not in credentials: raise ValueError('auth_type is required') diff --git a/web/app/components/app/chat/index.tsx b/web/app/components/app/chat/index.tsx index 6187ec684f005..d861ddb2decf9 100644 --- a/web/app/components/app/chat/index.tsx +++ b/web/app/components/app/chat/index.tsx @@ -67,6 +67,7 @@ export type IChatProps = { visionConfig?: VisionSettings supportAnnotation?: boolean allToolIcons?: Record + customDisclaimer?: string } const Chat: FC = ({ @@ -102,6 +103,7 @@ const Chat: FC = ({ supportAnnotation, onChatListChange, allToolIcons, + customDisclaimer, }) => { const { t } = useTranslation() const { notify } = useContext(ToastContext) @@ -358,44 +360,46 @@ const Chat: FC = ({ )} -
- {visionConfig?.enabled && ( - <> -
- = visionConfig.number_limits} - /> -
-
-
- -
- - )} -