Quellcode durchsuchen

fix: free quota type apply button missing (#2069)

Co-authored-by: StyleZhang <jasonapring2015@outlook.com>
takatost vor 1 Jahr
Ursprung
Commit
8799c888e3

+ 0 - 4
.github/workflows/api-model-runtime-tests.yml

@@ -4,10 +4,6 @@ on:
   pull_request:
     branches:
       - main
-  push:
-    branches:
-      - deploy/dev
-      - feat/model-runtime
 
 jobs:
   test:

+ 0 - 3
.github/workflows/style.yml

@@ -4,9 +4,6 @@ on:
   pull_request:
     branches:
       - main
-  push:
-    branches:
-      - deploy/dev
 
 concurrency:
   group: dep-${{ github.head_ref || github.run_id }}

+ 2 - 2
api/.env.example

@@ -102,10 +102,10 @@ NOTION_CLIENT_ID=you-client-id
 NOTION_INTERNAL_SECRET=you-internal-secret
 
 # Hosted Model Credentials
-HOSTED_OPENAI_ENABLED=false
 HOSTED_OPENAI_API_KEY=
 HOSTED_OPENAI_API_BASE=
 HOSTED_OPENAI_API_ORGANIZATION=
+HOSTED_OPENAI_TRIAL_ENABLED=false
 HOSTED_OPENAI_QUOTA_LIMIT=200
 HOSTED_OPENAI_PAID_ENABLED=false
 
@@ -114,9 +114,9 @@ HOSTED_AZURE_OPENAI_API_KEY=
 HOSTED_AZURE_OPENAI_API_BASE=
 HOSTED_AZURE_OPENAI_QUOTA_LIMIT=200
 
-HOSTED_ANTHROPIC_ENABLED=false
 HOSTED_ANTHROPIC_API_BASE=
 HOSTED_ANTHROPIC_API_KEY=
+HOSTED_ANTHROPIC_TRIAL_ENABLED=false
 HOSTED_ANTHROPIC_QUOTA_LIMIT=600000
 HOSTED_ANTHROPIC_PAID_ENABLED=false
 

+ 24 - 5
api/config.py

@@ -39,13 +39,19 @@ DEFAULTS = {
     'CELERY_BACKEND': 'database',
     'LOG_LEVEL': 'INFO',
     'HOSTED_OPENAI_QUOTA_LIMIT': 200,
-    'HOSTED_OPENAI_ENABLED': 'False',
+    'HOSTED_OPENAI_TRIAL_ENABLED': 'False',
     'HOSTED_OPENAI_PAID_ENABLED': 'False',
+    'HOSTED_OPENAI_PAID_INCREASE_QUOTA': 1,
+    'HOSTED_OPENAI_PAID_MIN_QUANTITY': 1,
+    'HOSTED_OPENAI_PAID_MAX_QUANTITY': 1,
     'HOSTED_AZURE_OPENAI_ENABLED': 'False',
     'HOSTED_AZURE_OPENAI_QUOTA_LIMIT': 200,
     'HOSTED_ANTHROPIC_QUOTA_LIMIT': 600000,
-    'HOSTED_ANTHROPIC_ENABLED': 'False',
+    'HOSTED_ANTHROPIC_TRIAL_ENABLED': 'False',
     'HOSTED_ANTHROPIC_PAID_ENABLED': 'False',
+    'HOSTED_ANTHROPIC_PAID_INCREASE_QUOTA': 1,
+    'HOSTED_ANTHROPIC_PAID_MIN_QUANTITY': 1,
+    'HOSTED_ANTHROPIC_PAID_MAX_QUANTITY': 1,
     'HOSTED_MODERATION_ENABLED': 'False',
     'HOSTED_MODERATION_PROVIDERS': '',
     'CLEAN_DAY_SETTING': 30,
@@ -66,7 +72,8 @@ def get_env(key):
 
 
 def get_bool_env(key):
-    return get_env(key).lower() == 'true'
+    value = get_env(key)
+    return value.lower() == 'true' if value is not None else False
 
 
 def get_cors_allow_origins(env, default):
@@ -260,23 +267,35 @@ class Config:
         # ------------------------
         # Platform Configurations.
         # ------------------------
-        self.HOSTED_OPENAI_ENABLED = get_bool_env('HOSTED_OPENAI_ENABLED')
         self.HOSTED_OPENAI_API_KEY = get_env('HOSTED_OPENAI_API_KEY')
         self.HOSTED_OPENAI_API_BASE = get_env('HOSTED_OPENAI_API_BASE')
         self.HOSTED_OPENAI_API_ORGANIZATION = get_env('HOSTED_OPENAI_API_ORGANIZATION')
+        self.HOSTED_OPENAI_TRIAL_ENABLED = get_bool_env('HOSTED_OPENAI_TRIAL_ENABLED')
         self.HOSTED_OPENAI_QUOTA_LIMIT = int(get_env('HOSTED_OPENAI_QUOTA_LIMIT'))
         self.HOSTED_OPENAI_PAID_ENABLED = get_bool_env('HOSTED_OPENAI_PAID_ENABLED')
+        self.HOSTED_OPENAI_PAID_STRIPE_PRICE_ID = get_env('HOSTED_OPENAI_PAID_STRIPE_PRICE_ID')
+        self.HOSTED_OPENAI_PAID_INCREASE_QUOTA = int(get_env('HOSTED_OPENAI_PAID_INCREASE_QUOTA'))
+        self.HOSTED_OPENAI_PAID_MIN_QUANTITY = int(get_env('HOSTED_OPENAI_PAID_MIN_QUANTITY'))
+        self.HOSTED_OPENAI_PAID_MAX_QUANTITY = int(get_env('HOSTED_OPENAI_PAID_MAX_QUANTITY'))
 
         self.HOSTED_AZURE_OPENAI_ENABLED = get_bool_env('HOSTED_AZURE_OPENAI_ENABLED')
         self.HOSTED_AZURE_OPENAI_API_KEY = get_env('HOSTED_AZURE_OPENAI_API_KEY')
         self.HOSTED_AZURE_OPENAI_API_BASE = get_env('HOSTED_AZURE_OPENAI_API_BASE')
         self.HOSTED_AZURE_OPENAI_QUOTA_LIMIT = int(get_env('HOSTED_AZURE_OPENAI_QUOTA_LIMIT'))
 
-        self.HOSTED_ANTHROPIC_ENABLED = get_bool_env('HOSTED_ANTHROPIC_ENABLED')
         self.HOSTED_ANTHROPIC_API_BASE = get_env('HOSTED_ANTHROPIC_API_BASE')
         self.HOSTED_ANTHROPIC_API_KEY = get_env('HOSTED_ANTHROPIC_API_KEY')
+        self.HOSTED_ANTHROPIC_TRIAL_ENABLED = get_bool_env('HOSTED_ANTHROPIC_TRIAL_ENABLED')
         self.HOSTED_ANTHROPIC_QUOTA_LIMIT = int(get_env('HOSTED_ANTHROPIC_QUOTA_LIMIT'))
         self.HOSTED_ANTHROPIC_PAID_ENABLED = get_bool_env('HOSTED_ANTHROPIC_PAID_ENABLED')
+        self.HOSTED_ANTHROPIC_PAID_STRIPE_PRICE_ID = get_env('HOSTED_ANTHROPIC_PAID_STRIPE_PRICE_ID')
+        self.HOSTED_ANTHROPIC_PAID_INCREASE_QUOTA = int(get_env('HOSTED_ANTHROPIC_PAID_INCREASE_QUOTA'))
+        self.HOSTED_ANTHROPIC_PAID_MIN_QUANTITY = int(get_env('HOSTED_ANTHROPIC_PAID_MIN_QUANTITY'))
+        self.HOSTED_ANTHROPIC_PAID_MAX_QUANTITY = int(get_env('HOSTED_ANTHROPIC_PAID_MAX_QUANTITY'))
+
+        self.HOSTED_MINIMAX_ENABLED = get_bool_env('HOSTED_MINIMAX_ENABLED')
+        self.HOSTED_SPARK_ENABLED = get_bool_env('HOSTED_SPARK_ENABLED')
+        self.HOSTED_ZHIPUAI_ENABLED = get_bool_env('HOSTED_ZHIPUAI_ENABLED')
 
         self.HOSTED_MODERATION_ENABLED = get_bool_env('HOSTED_MODERATION_ENABLED')
         self.HOSTED_MODERATION_PROVIDERS = get_env('HOSTED_MODERATION_PROVIDERS')

+ 98 - 97
api/core/hosting_configuration.py

@@ -1,9 +1,8 @@
-import os
 from typing import Optional
 
 from core.entities.provider_entities import QuotaUnit, RestrictModel
 from core.model_runtime.entities.model_entities import ModelType
-from flask import Flask
+from flask import Flask, Config
 from models.provider import ProviderQuotaType
 from pydantic import BaseModel
 
@@ -48,46 +47,47 @@ class HostingConfiguration:
     moderation_config: HostedModerationConfig = None
 
     def init_app(self, app: Flask) -> None:
-        if app.config.get('EDITION') != 'CLOUD':
+        config = app.config
+
+        if config.get('EDITION') != 'CLOUD':
             return
 
-        self.provider_map["azure_openai"] = self.init_azure_openai()
-        self.provider_map["openai"] = self.init_openai()
-        self.provider_map["anthropic"] = self.init_anthropic()
-        self.provider_map["minimax"] = self.init_minimax()
-        self.provider_map["spark"] = self.init_spark()
-        self.provider_map["zhipuai"] = self.init_zhipuai()
+        self.provider_map["azure_openai"] = self.init_azure_openai(config)
+        self.provider_map["openai"] = self.init_openai(config)
+        self.provider_map["anthropic"] = self.init_anthropic(config)
+        self.provider_map["minimax"] = self.init_minimax(config)
+        self.provider_map["spark"] = self.init_spark(config)
+        self.provider_map["zhipuai"] = self.init_zhipuai(config)
 
-        self.moderation_config = self.init_moderation_config()
+        self.moderation_config = self.init_moderation_config(config)
 
-    def init_azure_openai(self) -> HostingProvider:
+    def init_azure_openai(self, app_config: Config) -> HostingProvider:
         quota_unit = QuotaUnit.TIMES
-        if os.environ.get("HOSTED_AZURE_OPENAI_ENABLED") and os.environ.get("HOSTED_AZURE_OPENAI_ENABLED").lower() == 'true':
+        if app_config.get("HOSTED_AZURE_OPENAI_ENABLED"):
             credentials = {
-                "openai_api_key": os.environ.get("HOSTED_AZURE_OPENAI_API_KEY"),
-                "openai_api_base": os.environ.get("HOSTED_AZURE_OPENAI_API_BASE"),
+                "openai_api_key": app_config.get("HOSTED_AZURE_OPENAI_API_KEY"),
+                "openai_api_base": app_config.get("HOSTED_AZURE_OPENAI_API_BASE"),
                 "base_model_name": "gpt-35-turbo"
             }
 
             quotas = []
-            hosted_quota_limit = int(os.environ.get("HOSTED_AZURE_OPENAI_QUOTA_LIMIT", "1000"))
-            if hosted_quota_limit != -1 or hosted_quota_limit > 0:
-                trial_quota = TrialHostingQuota(
-                    quota_limit=hosted_quota_limit,
-                    restrict_models=[
-                        RestrictModel(model="gpt-4", base_model_name="gpt-4", model_type=ModelType.LLM),
-                        RestrictModel(model="gpt-4-32k", base_model_name="gpt-4-32k", model_type=ModelType.LLM),
-                        RestrictModel(model="gpt-4-1106-preview", base_model_name="gpt-4-1106-preview", model_type=ModelType.LLM),
-                        RestrictModel(model="gpt-4-vision-preview", base_model_name="gpt-4-vision-preview", model_type=ModelType.LLM),
-                        RestrictModel(model="gpt-35-turbo", base_model_name="gpt-35-turbo", model_type=ModelType.LLM),
-                        RestrictModel(model="gpt-35-turbo-1106", base_model_name="gpt-35-turbo-1106", model_type=ModelType.LLM),
-                        RestrictModel(model="gpt-35-turbo-instruct", base_model_name="gpt-35-turbo-instruct", model_type=ModelType.LLM),
-                        RestrictModel(model="gpt-35-turbo-16k", base_model_name="gpt-35-turbo-16k", model_type=ModelType.LLM),
-                        RestrictModel(model="text-davinci-003", base_model_name="text-davinci-003", model_type=ModelType.LLM),
-                        RestrictModel(model="text-embedding-ada-002", base_model_name="text-embedding-ada-002", model_type=ModelType.TEXT_EMBEDDING),
-                    ]
-                )
-                quotas.append(trial_quota)
+            hosted_quota_limit = int(app_config.get("HOSTED_AZURE_OPENAI_QUOTA_LIMIT", "1000"))
+            trial_quota = TrialHostingQuota(
+                quota_limit=hosted_quota_limit,
+                restrict_models=[
+                    RestrictModel(model="gpt-4", base_model_name="gpt-4", model_type=ModelType.LLM),
+                    RestrictModel(model="gpt-4-32k", base_model_name="gpt-4-32k", model_type=ModelType.LLM),
+                    RestrictModel(model="gpt-4-1106-preview", base_model_name="gpt-4-1106-preview", model_type=ModelType.LLM),
+                    RestrictModel(model="gpt-4-vision-preview", base_model_name="gpt-4-vision-preview", model_type=ModelType.LLM),
+                    RestrictModel(model="gpt-35-turbo", base_model_name="gpt-35-turbo", model_type=ModelType.LLM),
+                    RestrictModel(model="gpt-35-turbo-1106", base_model_name="gpt-35-turbo-1106", model_type=ModelType.LLM),
+                    RestrictModel(model="gpt-35-turbo-instruct", base_model_name="gpt-35-turbo-instruct", model_type=ModelType.LLM),
+                    RestrictModel(model="gpt-35-turbo-16k", base_model_name="gpt-35-turbo-16k", model_type=ModelType.LLM),
+                    RestrictModel(model="text-davinci-003", base_model_name="text-davinci-003", model_type=ModelType.LLM),
+                    RestrictModel(model="text-embedding-ada-002", base_model_name="text-embedding-ada-002", model_type=ModelType.TEXT_EMBEDDING),
+                ]
+            )
+            quotas.append(trial_quota)
 
             return HostingProvider(
                 enabled=True,
@@ -101,43 +101,44 @@ class HostingConfiguration:
             quota_unit=quota_unit,
         )
 
-    def init_openai(self) -> HostingProvider:
+    def init_openai(self, app_config: Config) -> HostingProvider:
         quota_unit = QuotaUnit.TIMES
-        if os.environ.get("HOSTED_OPENAI_ENABLED") and os.environ.get("HOSTED_OPENAI_ENABLED").lower() == 'true':
+        quotas = []
+
+        if app_config.get("HOSTED_OPENAI_TRIAL_ENABLED"):
+            hosted_quota_limit = int(app_config.get("HOSTED_OPENAI_QUOTA_LIMIT", "200"))
+            trial_quota = TrialHostingQuota(
+                quota_limit=hosted_quota_limit,
+                restrict_models=[
+                    RestrictModel(model="gpt-3.5-turbo", model_type=ModelType.LLM),
+                    RestrictModel(model="gpt-3.5-turbo-1106", model_type=ModelType.LLM),
+                    RestrictModel(model="gpt-3.5-turbo-instruct", model_type=ModelType.LLM),
+                    RestrictModel(model="gpt-3.5-turbo-16k", model_type=ModelType.LLM),
+                    RestrictModel(model="text-davinci-003", model_type=ModelType.LLM),
+                    RestrictModel(model="whisper-1", model_type=ModelType.SPEECH2TEXT),
+                ]
+            )
+            quotas.append(trial_quota)
+
+        if app_config.get("HOSTED_OPENAI_PAID_ENABLED"):
+            paid_quota = PaidHostingQuota(
+                stripe_price_id=app_config.get("HOSTED_OPENAI_PAID_STRIPE_PRICE_ID"),
+                increase_quota=int(app_config.get("HOSTED_OPENAI_PAID_INCREASE_QUOTA", "1")),
+                min_quantity=int(app_config.get("HOSTED_OPENAI_PAID_MIN_QUANTITY", "1")),
+                max_quantity=int(app_config.get("HOSTED_OPENAI_PAID_MAX_QUANTITY", "1"))
+            )
+            quotas.append(paid_quota)
+
+        if len(quotas) > 0:
             credentials = {
-                "openai_api_key": os.environ.get("HOSTED_OPENAI_API_KEY"),
+                "openai_api_key": app_config.get("HOSTED_OPENAI_API_KEY"),
             }
 
-            if os.environ.get("HOSTED_OPENAI_API_BASE"):
-                credentials["openai_api_base"] = os.environ.get("HOSTED_OPENAI_API_BASE")
-
-            if os.environ.get("HOSTED_OPENAI_API_ORGANIZATION"):
-                credentials["openai_organization"] = os.environ.get("HOSTED_OPENAI_API_ORGANIZATION")
+            if app_config.get("HOSTED_OPENAI_API_BASE"):
+                credentials["openai_api_base"] = app_config.get("HOSTED_OPENAI_API_BASE")
 
-            quotas = []
-            hosted_quota_limit = int(os.environ.get("HOSTED_OPENAI_QUOTA_LIMIT", "200"))
-            if hosted_quota_limit != -1 or hosted_quota_limit > 0:
-                trial_quota = TrialHostingQuota(
-                    quota_limit=hosted_quota_limit,
-                    restrict_models=[
-                        RestrictModel(model="gpt-3.5-turbo", model_type=ModelType.LLM),
-                        RestrictModel(model="gpt-3.5-turbo-1106", model_type=ModelType.LLM),
-                        RestrictModel(model="gpt-3.5-turbo-instruct", model_type=ModelType.LLM),
-                        RestrictModel(model="gpt-3.5-turbo-16k", model_type=ModelType.LLM),
-                        RestrictModel(model="text-davinci-003", model_type=ModelType.LLM),
-                    ]
-                )
-                quotas.append(trial_quota)
-
-            if os.environ.get("HOSTED_OPENAI_PAID_ENABLED") and os.environ.get(
-                    "HOSTED_OPENAI_PAID_ENABLED").lower() == 'true':
-                paid_quota = PaidHostingQuota(
-                    stripe_price_id=os.environ.get("HOSTED_OPENAI_PAID_STRIPE_PRICE_ID"),
-                    increase_quota=int(os.environ.get("HOSTED_OPENAI_PAID_INCREASE_QUOTA", "1")),
-                    min_quantity=int(os.environ.get("HOSTED_OPENAI_PAID_MIN_QUANTITY", "1")),
-                    max_quantity=int(os.environ.get("HOSTED_OPENAI_PAID_MAX_QUANTITY", "1"))
-                )
-                quotas.append(paid_quota)
+            if app_config.get("HOSTED_OPENAI_API_ORGANIZATION"):
+                credentials["openai_organization"] = app_config.get("HOSTED_OPENAI_API_ORGANIZATION")
 
             return HostingProvider(
                 enabled=True,
@@ -151,33 +152,33 @@ class HostingConfiguration:
             quota_unit=quota_unit,
         )
 
-    def init_anthropic(self) -> HostingProvider:
+    def init_anthropic(self, app_config: Config) -> HostingProvider:
         quota_unit = QuotaUnit.TOKENS
-        if os.environ.get("HOSTED_ANTHROPIC_ENABLED") and os.environ.get("HOSTED_ANTHROPIC_ENABLED").lower() == 'true':
+        quotas = []
+
+        if app_config.get("HOSTED_ANTHROPIC_TRIAL_ENABLED"):
+            hosted_quota_limit = int(app_config.get("HOSTED_ANTHROPIC_QUOTA_LIMIT", "0"))
+            trial_quota = TrialHostingQuota(
+                quota_limit=hosted_quota_limit
+            )
+            quotas.append(trial_quota)
+
+        if app_config.get("HOSTED_ANTHROPIC_PAID_ENABLED"):
+            paid_quota = PaidHostingQuota(
+                stripe_price_id=app_config.get("HOSTED_ANTHROPIC_PAID_STRIPE_PRICE_ID"),
+                increase_quota=int(app_config.get("HOSTED_ANTHROPIC_PAID_INCREASE_QUOTA", "1000000")),
+                min_quantity=int(app_config.get("HOSTED_ANTHROPIC_PAID_MIN_QUANTITY", "20")),
+                max_quantity=int(app_config.get("HOSTED_ANTHROPIC_PAID_MAX_QUANTITY", "100"))
+            )
+            quotas.append(paid_quota)
+
+        if len(quotas) > 0:
             credentials = {
-                "anthropic_api_key": os.environ.get("HOSTED_ANTHROPIC_API_KEY"),
+                "anthropic_api_key": app_config.get("HOSTED_ANTHROPIC_API_KEY"),
             }
 
-            if os.environ.get("HOSTED_ANTHROPIC_API_BASE"):
-                credentials["anthropic_api_url"] = os.environ.get("HOSTED_ANTHROPIC_API_BASE")
-
-            quotas = []
-            hosted_quota_limit = int(os.environ.get("HOSTED_ANTHROPIC_QUOTA_LIMIT", "0"))
-            if hosted_quota_limit != -1 or hosted_quota_limit > 0:
-                trial_quota = TrialHostingQuota(
-                    quota_limit=hosted_quota_limit
-                )
-                quotas.append(trial_quota)
-
-            if os.environ.get("HOSTED_ANTHROPIC_PAID_ENABLED") and os.environ.get(
-                    "HOSTED_ANTHROPIC_PAID_ENABLED").lower() == 'true':
-                paid_quota = PaidHostingQuota(
-                    stripe_price_id=os.environ.get("HOSTED_ANTHROPIC_PAID_STRIPE_PRICE_ID"),
-                    increase_quota=int(os.environ.get("HOSTED_ANTHROPIC_PAID_INCREASE_QUOTA", "1000000")),
-                    min_quantity=int(os.environ.get("HOSTED_ANTHROPIC_PAID_MIN_QUANTITY", "20")),
-                    max_quantity=int(os.environ.get("HOSTED_ANTHROPIC_PAID_MAX_QUANTITY", "100"))
-                )
-                quotas.append(paid_quota)
+            if app_config.get("HOSTED_ANTHROPIC_API_BASE"):
+                credentials["anthropic_api_url"] = app_config.get("HOSTED_ANTHROPIC_API_BASE")
 
             return HostingProvider(
                 enabled=True,
@@ -191,9 +192,9 @@ class HostingConfiguration:
             quota_unit=quota_unit,
         )
 
-    def init_minimax(self) -> HostingProvider:
+    def init_minimax(self, app_config: Config) -> HostingProvider:
         quota_unit = QuotaUnit.TOKENS
-        if os.environ.get("HOSTED_MINIMAX_ENABLED") and os.environ.get("HOSTED_MINIMAX_ENABLED").lower() == 'true':
+        if app_config.get("HOSTED_MINIMAX_ENABLED"):
             quotas = [FreeHostingQuota()]
 
             return HostingProvider(
@@ -208,9 +209,9 @@ class HostingConfiguration:
             quota_unit=quota_unit,
         )
 
-    def init_spark(self) -> HostingProvider:
+    def init_spark(self, app_config: Config) -> HostingProvider:
         quota_unit = QuotaUnit.TOKENS
-        if os.environ.get("HOSTED_SPARK_ENABLED") and os.environ.get("HOSTED_SPARK_ENABLED").lower() == 'true':
+        if app_config.get("HOSTED_SPARK_ENABLED"):
             quotas = [FreeHostingQuota()]
 
             return HostingProvider(
@@ -225,9 +226,9 @@ class HostingConfiguration:
             quota_unit=quota_unit,
         )
 
-    def init_zhipuai(self) -> HostingProvider:
+    def init_zhipuai(self, app_config: Config) -> HostingProvider:
         quota_unit = QuotaUnit.TOKENS
-        if os.environ.get("HOSTED_ZHIPUAI_ENABLED") and os.environ.get("HOSTED_ZHIPUAI_ENABLED").lower() == 'true':
+        if app_config.get("HOSTED_ZHIPUAI_ENABLED"):
             quotas = [FreeHostingQuota()]
 
             return HostingProvider(
@@ -242,12 +243,12 @@ class HostingConfiguration:
             quota_unit=quota_unit,
         )
 
-    def init_moderation_config(self) -> HostedModerationConfig:
-        if os.environ.get("HOSTED_MODERATION_ENABLED") and os.environ.get("HOSTED_MODERATION_ENABLED").lower() == 'true' \
-                and os.environ.get("HOSTED_MODERATION_PROVIDERS"):
+    def init_moderation_config(self, app_config: Config) -> HostedModerationConfig:
+        if app_config.get("HOSTED_MODERATION_ENABLED") \
+                and app_config.get("HOSTED_MODERATION_PROVIDERS"):
             return HostedModerationConfig(
                 enabled=True,
-                providers=os.environ.get("HOSTED_MODERATION_PROVIDERS").split(',')
+                providers=app_config.get("HOSTED_MODERATION_PROVIDERS").split(',')
             )
 
         return HostedModerationConfig(

+ 23 - 12
api/core/provider_manager.py

@@ -597,18 +597,28 @@ class ProviderManager:
         quota_configurations = []
         for provider_quota in provider_hosting_configuration.quotas:
             if provider_quota.quota_type not in quota_type_to_provider_records_dict:
-                continue
-
-            provider_record = quota_type_to_provider_records_dict[provider_quota.quota_type]
-
-            quota_configuration = QuotaConfiguration(
-                quota_type=provider_quota.quota_type,
-                quota_unit=provider_hosting_configuration.quota_unit,
-                quota_used=provider_record.quota_used,
-                quota_limit=provider_record.quota_limit,
-                is_valid=provider_record.quota_limit > provider_record.quota_used or provider_record.quota_limit == -1,
-                restrict_models=provider_quota.restrict_models
-            )
+                if provider_quota.quota_type == ProviderQuotaType.FREE:
+                    quota_configuration = QuotaConfiguration(
+                        quota_type=provider_quota.quota_type,
+                        quota_unit=provider_hosting_configuration.quota_unit,
+                        quota_used=0,
+                        quota_limit=0,
+                        is_valid=False,
+                        restrict_models=provider_quota.restrict_models
+                    )
+                else:
+                    continue
+            else:
+                provider_record = quota_type_to_provider_records_dict[provider_quota.quota_type]
+
+                quota_configuration = QuotaConfiguration(
+                    quota_type=provider_quota.quota_type,
+                    quota_unit=provider_hosting_configuration.quota_unit,
+                    quota_used=provider_record.quota_used,
+                    quota_limit=provider_record.quota_limit,
+                    is_valid=provider_record.quota_limit > provider_record.quota_used or provider_record.quota_limit == -1,
+                    restrict_models=provider_quota.restrict_models
+                )
 
             quota_configurations.append(quota_configuration)
 
@@ -670,6 +680,7 @@ class ProviderManager:
                     current_using_credentials = cached_provider_credentials
             else:
                 current_using_credentials = {}
+                quota_configurations = []
 
         return SystemConfiguration(
             enabled=True,

+ 6 - 2
api/events/event_handlers/deduct_quota_when_messaeg_created.py

@@ -23,12 +23,16 @@ def handle(sender, **kwargs):
     for quota_configuration in system_configuration.quota_configurations:
         if quota_configuration.quota_type == system_configuration.current_quota_type:
             quota_unit = quota_configuration.quota_unit
+
+            if quota_configuration.quota_limit == -1:
+                return
+
             break
 
     used_quota = None
     if quota_unit:
-        if quota_unit == QuotaUnit.TOKENS.value:
-            used_quota = message.message_tokens + message.prompt_tokens
+        if quota_unit == QuotaUnit.TOKENS:
+            used_quota = message.message_tokens + message.answer_tokens
         else:
             used_quota = 1
 

+ 7 - 1
web/app/components/header/account-setting/model-provider-page/index.tsx

@@ -38,7 +38,13 @@ const ModelProviderPage = () => {
     const notConfigedProviders: ModelProvider[] = []
 
     providers.forEach((provider) => {
-      if (provider.custom_configuration.status === CustomConfigurationStatusEnum.active || provider.system_configuration.enabled === true)
+      if (
+        provider.custom_configuration.status === CustomConfigurationStatusEnum.active
+        || (
+          provider.system_configuration.enabled === true
+          && provider.system_configuration.quota_configurations.find(item => item.quota_type === provider.system_configuration.current_quota_type)
+        )
+      )
         configedProviders.push(provider)
       else
         notConfigedProviders.push(provider)

+ 3 - 1
web/app/components/header/account-setting/model-provider-page/provider-added-card/index.tsx

@@ -9,6 +9,8 @@ import type {
 import { ConfigurateMethodEnum } from '../declarations'
 import {
   DEFAULT_BACKGROUND_COLOR,
+  MODEL_PROVIDER_QUOTA_GET_FREE,
+  MODEL_PROVIDER_QUOTA_GET_PAID,
   modelTypeFormat,
 } from '../utils'
 import ProviderIcon from '../provider-icon'
@@ -41,7 +43,7 @@ const ProviderAddedCard: FC<ProviderAddedCardProps> = ({
   const configurateMethods = provider.configurate_methods.filter(method => method !== ConfigurateMethodEnum.fetchFromRemote)
   const systemConfig = provider.system_configuration
   const hasModelList = fetched && !!modelList.length
-  const showQuota = systemConfig.enabled && ['minimax', 'spark', 'zhipuai', 'anthropic', 'openai'].includes(provider.provider) && !IS_CE_EDITION
+  const showQuota = systemConfig.enabled && [...MODEL_PROVIDER_QUOTA_GET_FREE, ...MODEL_PROVIDER_QUOTA_GET_PAID].includes(provider.provider) && !IS_CE_EDITION
 
   const getModelList = async (providerName: string) => {
     if (loading)

+ 6 - 2
web/app/components/header/account-setting/model-provider-page/provider-added-card/quota-panel.tsx

@@ -11,6 +11,10 @@ import {
   useFreeQuota,
   useUpdateModelProviders,
 } from '../hooks'
+import {
+  MODEL_PROVIDER_QUOTA_GET_FREE,
+  MODEL_PROVIDER_QUOTA_GET_PAID,
+} from '../utils'
 import PriorityUseTip from './priority-use-tip'
 import { InfoCircle } from '@/app/components/base/icons/src/vender/line/general'
 import Button from '@/app/components/base/button'
@@ -34,7 +38,7 @@ const QuotaPanel: FC<QuotaPanelProps> = ({
   const priorityUseType = provider.preferred_provider_type
   const systemConfig = provider.system_configuration
   const currentQuota = systemConfig.enabled && systemConfig.quota_configurations.find(item => item.quota_type === systemConfig.current_quota_type)
-  const openaiOrAnthropic = ['openai', 'anthropic'].includes(provider.provider)
+  const openaiOrAnthropic = MODEL_PROVIDER_QUOTA_GET_PAID.includes(provider.provider)
 
   return (
     <div className='group relative shrink-0 min-w-[112px] px-3 py-2 rounded-lg bg-white/[0.3] border-[0.5px] border-black/5'>
@@ -72,7 +76,7 @@ const QuotaPanel: FC<QuotaPanelProps> = ({
         )
       }
       {
-        !currentQuota && ['minimax', 'spark', 'zhipuai'].includes(provider.provider) && (
+        !currentQuota && MODEL_PROVIDER_QUOTA_GET_FREE.includes(provider.provider) && (
           <Button
             className='h-6 bg-white text-xs font-medium rounded-md'
             onClick={() => handleFreeQuota(provider.provider)}

+ 2 - 1
web/app/components/header/account-setting/model-provider-page/provider-card/index.tsx

@@ -7,6 +7,7 @@ import type {
 import { ConfigurateMethodEnum } from '../declarations'
 import {
   DEFAULT_BACKGROUND_COLOR,
+  MODEL_PROVIDER_QUOTA_GET_FREE,
   modelTypeFormat,
 } from '../utils'
 import {
@@ -55,7 +56,7 @@ const ProviderCard: FC<ProviderCardProps> = ({
   }
   const handleFreeQuota = useFreeQuota(handleFreeQuotaSuccess)
   const configurateMethods = provider.configurate_methods.filter(method => method !== ConfigurateMethodEnum.fetchFromRemote)
-  const canGetFreeQuota = ['mininmax', 'spark', 'zhipuai'].includes(provider.provider) && !IS_CE_EDITION
+  const canGetFreeQuota = MODEL_PROVIDER_QUOTA_GET_FREE.includes(provider.provider) && !IS_CE_EDITION && provider.system_configuration.enabled
 
   return (
     <div

+ 3 - 0
web/app/components/header/account-setting/model-provider-page/utils.ts

@@ -23,6 +23,9 @@ export const languageMaps = {
   'zh-Hans': 'zh_Hans'
 }
 
+export const MODEL_PROVIDER_QUOTA_GET_FREE = ['minimax', 'spark', 'zhipuai']
+export const MODEL_PROVIDER_QUOTA_GET_PAID = ['anthropic', 'openai']
+
 export const DEFAULT_BACKGROUND_COLOR = '#F3F4F6'
 
 export const isNullOrUndefined = (value: any) => {