Team Ai
Apppublic

Underground-Digital/Workflow-Engine

sourceHugging Faceupdated 2y agoView on Hugging Face
0likes
provider_manager.py926 linesDownload Raw Back to core
1import json2from collections import defaultdict3from json import JSONDecodeError4from typing import Optional5 6from sqlalchemy.exc import IntegrityError7 8from configs import dify_config9from core.entities.model_entities import DefaultModelEntity, DefaultModelProviderEntity10from core.entities.provider_configuration import ProviderConfiguration, ProviderConfigurations, ProviderModelBundle11from core.entities.provider_entities import (12    CustomConfiguration,13    CustomModelConfiguration,14    CustomProviderConfiguration,15    ModelLoadBalancingConfiguration,16    ModelSettings,17    QuotaConfiguration,18    SystemConfiguration,19)20from core.helper import encrypter21from core.helper.model_provider_cache import ProviderCredentialsCache, ProviderCredentialsCacheType22from core.helper.position_helper import is_filtered23from core.model_runtime.entities.model_entities import ModelType24from core.model_runtime.entities.provider_entities import CredentialFormSchema, FormType, ProviderEntity25from core.model_runtime.model_providers import model_provider_factory26from extensions import ext_hosting_provider27from extensions.ext_database import db28from extensions.ext_redis import redis_client29from models.provider import (30    LoadBalancingModelConfig,31    Provider,32    ProviderModel,33    ProviderModelSetting,34    ProviderQuotaType,35    ProviderType,36    TenantDefaultModel,37    TenantPreferredModelProvider,38)39from services.feature_service import FeatureService40 41 42class ProviderManager:43    """44    ProviderManager is a class that manages the model providers includes Hosting and Customize Model Providers.45    """46 47    def __init__(self) -> None:48        self.decoding_rsa_key = None49        self.decoding_cipher_rsa = None50 51    def get_configurations(self, tenant_id: str) -> ProviderConfigurations:52        """53        Get model provider configurations.54 55        Construct ProviderConfiguration objects for each provider56        Including:57        1. Basic information of the provider58        2. Hosting configuration information, including:59          (1. Whether to enable (support) hosting type, if enabled, the following information exists60          (2. List of hosting type provider configurations61              (including quota type, quota limit, current remaining quota, etc.)62          (3. The current hosting type in use (whether there is a quota or not)63              paid quotas > provider free quotas > hosting trial quotas64          (4. Unified credentials for hosting providers65        3. Custom configuration information, including:66          (1. Whether to enable (support) custom type, if enabled, the following information exists67          (2. Custom provider configuration (including credentials)68          (3. List of custom provider model configurations (including credentials)69        4. Hosting/custom preferred provider type.70        Provide methods:71        - Get the current configuration (including credentials)72        - Get the availability and status of the hosting configuration: active available,73          quota_exceeded insufficient quota, unsupported hosting74        - Get the availability of custom configuration75          Custom provider available conditions:76          (1. custom provider credentials available77          (2. at least one custom model credentials available78        - Verify, update, and delete custom provider configuration79        - Verify, update, and delete custom provider model configuration80        - Get the list of available models (optional provider filtering, model type filtering)81          Append custom provider models to the list82        - Get provider instance83        - Switch selection priority84 85        :param tenant_id:86        :return:87        """88        # Get all provider records of the workspace89        provider_name_to_provider_records_dict = self._get_all_providers(tenant_id)90 91        # Initialize trial provider records if not exist92        provider_name_to_provider_records_dict = self._init_trial_provider_records(93            tenant_id, provider_name_to_provider_records_dict94        )95 96        # Get all provider model records of the workspace97        provider_name_to_provider_model_records_dict = self._get_all_provider_models(tenant_id)98 99        # Get all provider entities100        provider_entities = model_provider_factory.get_providers()101 102        # Get All preferred provider types of the workspace103        provider_name_to_preferred_model_provider_records_dict = self._get_all_preferred_model_providers(tenant_id)104 105        # Get All provider model settings106        provider_name_to_provider_model_settings_dict = self._get_all_provider_model_settings(tenant_id)107 108        # Get All load balancing configs109        provider_name_to_provider_load_balancing_model_configs_dict = self._get_all_provider_load_balancing_configs(110            tenant_id111        )112 113        provider_configurations = ProviderConfigurations(tenant_id=tenant_id)114 115        # Construct ProviderConfiguration objects for each provider116        for provider_entity in provider_entities:117            # handle include, exclude118            if is_filtered(119                include_set=dify_config.POSITION_PROVIDER_INCLUDES_SET,120                exclude_set=dify_config.POSITION_PROVIDER_EXCLUDES_SET,121                data=provider_entity,122                name_func=lambda x: x.provider,123            ):124                continue125 126            provider_name = provider_entity.provider127            provider_records = provider_name_to_provider_records_dict.get(provider_entity.provider, [])128            provider_model_records = provider_name_to_provider_model_records_dict.get(provider_entity.provider, [])129 130            # Convert to custom configuration131            custom_configuration = self._to_custom_configuration(132                tenant_id, provider_entity, provider_records, provider_model_records133            )134 135            # Convert to system configuration136            system_configuration = self._to_system_configuration(tenant_id, provider_entity, provider_records)137 138            # Get preferred provider type139            preferred_provider_type_record = provider_name_to_preferred_model_provider_records_dict.get(provider_name)140 141            if preferred_provider_type_record:142                preferred_provider_type = ProviderType.value_of(preferred_provider_type_record.preferred_provider_type)143            elif custom_configuration.provider or custom_configuration.models:144                preferred_provider_type = ProviderType.CUSTOM145            elif system_configuration.enabled:146                preferred_provider_type = ProviderType.SYSTEM147            else:148                preferred_provider_type = ProviderType.CUSTOM149 150            using_provider_type = preferred_provider_type151            has_valid_quota = any(quota_conf.is_valid for quota_conf in system_configuration.quota_configurations)152 153            if preferred_provider_type == ProviderType.SYSTEM:154                if not system_configuration.enabled or not has_valid_quota:155                    using_provider_type = ProviderType.CUSTOM156 157            else:158                if not custom_configuration.provider and not custom_configuration.models:159                    if system_configuration.enabled and has_valid_quota:160                        using_provider_type = ProviderType.SYSTEM161 162            # Get provider load balancing configs163            provider_model_settings = provider_name_to_provider_model_settings_dict.get(provider_name)164 165            # Get provider load balancing configs166            provider_load_balancing_configs = provider_name_to_provider_load_balancing_model_configs_dict.get(167                provider_name168            )169 170            # Convert to model settings171            model_settings = self._to_model_settings(172                provider_entity=provider_entity,173                provider_model_settings=provider_model_settings,174                load_balancing_model_configs=provider_load_balancing_configs,175            )176 177            provider_configuration = ProviderConfiguration(178                tenant_id=tenant_id,179                provider=provider_entity,180                preferred_provider_type=preferred_provider_type,181                using_provider_type=using_provider_type,182                system_configuration=system_configuration,183                custom_configuration=custom_configuration,184                model_settings=model_settings,185            )186 187            provider_configurations[provider_name] = provider_configuration188 189        # Return the encapsulated object190        return provider_configurations191 192    def get_provider_model_bundle(self, tenant_id: str, provider: str, model_type: ModelType) -> ProviderModelBundle:193        """194        Get provider model bundle.195        :param tenant_id: workspace id196        :param provider: provider name197        :param model_type: model type198        :return:199        """200        provider_configurations = self.get_configurations(tenant_id)201 202        # get provider instance203        provider_configuration = provider_configurations.get(provider)204        if not provider_configuration:205            raise ValueError(f"Provider {provider} does not exist.")206 207        provider_instance = provider_configuration.get_provider_instance()208        model_type_instance = provider_instance.get_model_instance(model_type)209 210        return ProviderModelBundle(211            configuration=provider_configuration,212            provider_instance=provider_instance,213            model_type_instance=model_type_instance,214        )215 216    def get_default_model(self, tenant_id: str, model_type: ModelType) -> Optional[DefaultModelEntity]:217        """218        Get default model.219 220        :param tenant_id: workspace id221        :param model_type: model type222        :return:223        """224        # Get the corresponding TenantDefaultModel record225        default_model = (226            db.session.query(TenantDefaultModel)227            .filter(228                TenantDefaultModel.tenant_id == tenant_id,229                TenantDefaultModel.model_type == model_type.to_origin_model_type(),230            )231            .first()232        )233 234        # If it does not exist, get the first available provider model from get_configurations235        # and update the TenantDefaultModel record236        if not default_model:237            # Get provider configurations238            provider_configurations = self.get_configurations(tenant_id)239 240            # get available models from provider_configurations241            available_models = provider_configurations.get_models(model_type=model_type, only_active=True)242 243            if available_models:244                available_model = next(245                    (model for model in available_models if model.model == "gpt-4"), available_models[0]246                )247 248                default_model = TenantDefaultModel(249                    tenant_id=tenant_id,250                    model_type=model_type.to_origin_model_type(),251                    provider_name=available_model.provider.provider,252                    model_name=available_model.model,253                )254                db.session.add(default_model)255                db.session.commit()256 257        if not default_model:258            return None259 260        provider_instance = model_provider_factory.get_provider_instance(default_model.provider_name)261        provider_schema = provider_instance.get_provider_schema()262 263        return DefaultModelEntity(264            model=default_model.model_name,265            model_type=model_type,266            provider=DefaultModelProviderEntity(267                provider=provider_schema.provider,268                label=provider_schema.label,269                icon_small=provider_schema.icon_small,270                icon_large=provider_schema.icon_large,271                supported_model_types=provider_schema.supported_model_types,272            ),273        )274 275    def get_first_provider_first_model(self, tenant_id: str, model_type: ModelType) -> tuple[str, str]:276        """277        Get names of first model and its provider278 279        :param tenant_id: workspace id280        :param model_type: model type281        :return: provider name, model name282        """283        provider_configurations = self.get_configurations(tenant_id)284 285        # get available models from provider_configurations286        all_models = provider_configurations.get_models(model_type=model_type, only_active=False)287 288        return all_models[0].provider.provider, all_models[0].model289 290    def update_default_model_record(291        self, tenant_id: str, model_type: ModelType, provider: str, model: str292    ) -> TenantDefaultModel:293        """294        Update default model record.295 296        :param tenant_id: workspace id297        :param model_type: model type298        :param provider: provider name299        :param model: model name300        :return:301        """302        provider_configurations = self.get_configurations(tenant_id)303        if provider not in provider_configurations:304            raise ValueError(f"Provider {provider} does not exist.")305 306        # get available models from provider_configurations307        available_models = provider_configurations.get_models(model_type=model_type, only_active=True)308 309        # check if the model is exist in available models310        model_names = [model.model for model in available_models]311        if model not in model_names:312            raise ValueError(f"Model {model} does not exist.")313 314        # Get the list of available models from get_configurations and check if it is LLM315        default_model = (316            db.session.query(TenantDefaultModel)317            .filter(318                TenantDefaultModel.tenant_id == tenant_id,319                TenantDefaultModel.model_type == model_type.to_origin_model_type(),320            )321            .first()322        )323 324        # create or update TenantDefaultModel record325        if default_model:326            # update default model327            default_model.provider_name = provider328            default_model.model_name = model329            db.session.commit()330        else:331            # create default model332            default_model = TenantDefaultModel(333                tenant_id=tenant_id,334                model_type=model_type.value,335                provider_name=provider,336                model_name=model,337            )338            db.session.add(default_model)339            db.session.commit()340 341        return default_model342 343    @staticmethod344    def _get_all_providers(tenant_id: str) -> dict[str, list[Provider]]:345        """346        Get all provider records of the workspace.347 348        :param tenant_id: workspace id349        :return:350        """351        providers = db.session.query(Provider).filter(Provider.tenant_id == tenant_id, Provider.is_valid == True).all()352 353        provider_name_to_provider_records_dict = defaultdict(list)354        for provider in providers:355            provider_name_to_provider_records_dict[provider.provider_name].append(provider)356 357        return provider_name_to_provider_records_dict358 359    @staticmethod360    def _get_all_provider_models(tenant_id: str) -> dict[str, list[ProviderModel]]:361        """362        Get all provider model records of the workspace.363 364        :param tenant_id: workspace id365        :return:366        """367        # Get all provider model records of the workspace368        provider_models = (369            db.session.query(ProviderModel)370            .filter(ProviderModel.tenant_id == tenant_id, ProviderModel.is_valid == True)371            .all()372        )373 374        provider_name_to_provider_model_records_dict = defaultdict(list)375        for provider_model in provider_models:376            provider_name_to_provider_model_records_dict[provider_model.provider_name].append(provider_model)377 378        return provider_name_to_provider_model_records_dict379 380    @staticmethod381    def _get_all_preferred_model_providers(tenant_id: str) -> dict[str, TenantPreferredModelProvider]:382        """383        Get All preferred provider types of the workspace.384 385        :param tenant_id: workspace id386        :return:387        """388        preferred_provider_types = (389            db.session.query(TenantPreferredModelProvider)390            .filter(TenantPreferredModelProvider.tenant_id == tenant_id)391            .all()392        )393 394        provider_name_to_preferred_provider_type_records_dict = {395            preferred_provider_type.provider_name: preferred_provider_type396            for preferred_provider_type in preferred_provider_types397        }398 399        return provider_name_to_preferred_provider_type_records_dict400 401    @staticmethod402    def _get_all_provider_model_settings(tenant_id: str) -> dict[str, list[ProviderModelSetting]]:403        """404        Get All provider model settings of the workspace.405 406        :param tenant_id: workspace id407        :return:408        """409        provider_model_settings = (410            db.session.query(ProviderModelSetting).filter(ProviderModelSetting.tenant_id == tenant_id).all()411        )412 413        provider_name_to_provider_model_settings_dict = defaultdict(list)414        for provider_model_setting in provider_model_settings:415            (416                provider_name_to_provider_model_settings_dict[provider_model_setting.provider_name].append(417                    provider_model_setting418                )419            )420 421        return provider_name_to_provider_model_settings_dict422 423    @staticmethod424    def _get_all_provider_load_balancing_configs(tenant_id: str) -> dict[str, list[LoadBalancingModelConfig]]:425        """426        Get All provider load balancing configs of the workspace.427 428        :param tenant_id: workspace id429        :return:430        """431        cache_key = f"tenant:{tenant_id}:model_load_balancing_enabled"432        cache_result = redis_client.get(cache_key)433        if cache_result is None:434            model_load_balancing_enabled = FeatureService.get_features(tenant_id).model_load_balancing_enabled435            redis_client.setex(cache_key, 120, str(model_load_balancing_enabled))436        else:437            cache_result = cache_result.decode("utf-8")438            model_load_balancing_enabled = cache_result == "True"439 440        if not model_load_balancing_enabled:441            return {}442 443        provider_load_balancing_configs = (444            db.session.query(LoadBalancingModelConfig).filter(LoadBalancingModelConfig.tenant_id == tenant_id).all()445        )446 447        provider_name_to_provider_load_balancing_model_configs_dict = defaultdict(list)448        for provider_load_balancing_config in provider_load_balancing_configs:449            (450                provider_name_to_provider_load_balancing_model_configs_dict[451                    provider_load_balancing_config.provider_name452                ].append(provider_load_balancing_config)453            )454 455        return provider_name_to_provider_load_balancing_model_configs_dict456 457    @staticmethod458    def _init_trial_provider_records(459        tenant_id: str, provider_name_to_provider_records_dict: dict[str, list]460    ) -> dict[str, list]:461        """462        Initialize trial provider records if not exists.463 464        :param tenant_id: workspace id465        :param provider_name_to_provider_records_dict: provider name to provider records dict466        :return:467        """468        # Get hosting configuration469        hosting_configuration = ext_hosting_provider.hosting_configuration470 471        for provider_name, configuration in hosting_configuration.provider_map.items():472            if not configuration.enabled:473                continue474 475            provider_records = provider_name_to_provider_records_dict.get(provider_name)476            if not provider_records:477                provider_records = []478 479            provider_quota_to_provider_record_dict = {}480            for provider_record in provider_records:481                if provider_record.provider_type != ProviderType.SYSTEM.value:482                    continue483 484                provider_quota_to_provider_record_dict[ProviderQuotaType.value_of(provider_record.quota_type)] = (485                    provider_record486                )487 488            for quota in configuration.quotas:489                if quota.quota_type == ProviderQuotaType.TRIAL:490                    # Init trial provider records if not exists491                    if ProviderQuotaType.TRIAL not in provider_quota_to_provider_record_dict:492                        try:493                            provider_record = Provider(494                                tenant_id=tenant_id,495                                provider_name=provider_name,496                                provider_type=ProviderType.SYSTEM.value,497                                quota_type=ProviderQuotaType.TRIAL.value,498                                quota_limit=quota.quota_limit,499                                quota_used=0,500                                is_valid=True,501                            )502                            db.session.add(provider_record)503                            db.session.commit()504                        except IntegrityError:505                            db.session.rollback()506                            provider_record = (507                                db.session.query(Provider)508                                .filter(509                                    Provider.tenant_id == tenant_id,510                                    Provider.provider_name == provider_name,511                                    Provider.provider_type == ProviderType.SYSTEM.value,512                                    Provider.quota_type == ProviderQuotaType.TRIAL.value,513                                )514                                .first()515                            )516 517                            if provider_record and not provider_record.is_valid:518                                provider_record.is_valid = True519                                db.session.commit()520 521                        provider_name_to_provider_records_dict[provider_name].append(provider_record)522 523        return provider_name_to_provider_records_dict524 525    def _to_custom_configuration(526        self,527        tenant_id: str,528        provider_entity: ProviderEntity,529        provider_records: list[Provider],530        provider_model_records: list[ProviderModel],531    ) -> CustomConfiguration:532        """533        Convert to custom configuration.534 535        :param tenant_id: workspace id536        :param provider_entity: provider entity537        :param provider_records: provider records538        :param provider_model_records: provider model records539        :return:540        """541        # Get provider credential secret variables542        provider_credential_secret_variables = self._extract_secret_variables(543            provider_entity.provider_credential_schema.credential_form_schemas544            if provider_entity.provider_credential_schema545            else []546        )547 548        # Get custom provider record549        custom_provider_record = None550        for provider_record in provider_records:551            if provider_record.provider_type == ProviderType.SYSTEM.value:552                continue553 554            if not provider_record.encrypted_config:555                continue556 557            custom_provider_record = provider_record558 559        # Get custom provider credentials560        custom_provider_configuration = None561        if custom_provider_record:562            provider_credentials_cache = ProviderCredentialsCache(563                tenant_id=tenant_id,564                identity_id=custom_provider_record.id,565                cache_type=ProviderCredentialsCacheType.PROVIDER,566            )567 568            # Get cached provider credentials569            cached_provider_credentials = provider_credentials_cache.get()570 571            if not cached_provider_credentials:572                try:573                    # fix origin data574                    if (575                        custom_provider_record.encrypted_config576                        and not custom_provider_record.encrypted_config.startswith("{")577                    ):578                        provider_credentials = {"openai_api_key": custom_provider_record.encrypted_config}579                    else:580                        provider_credentials = json.loads(custom_provider_record.encrypted_config)581                except JSONDecodeError:582                    provider_credentials = {}583 584                # Get decoding rsa key and cipher for decrypting credentials585                if self.decoding_rsa_key is None or self.decoding_cipher_rsa is None:586                    self.decoding_rsa_key, self.decoding_cipher_rsa = encrypter.get_decrypt_decoding(tenant_id)587 588                for variable in provider_credential_secret_variables:589                    if variable in provider_credentials:590                        try:591                            provider_credentials[variable] = encrypter.decrypt_token_with_decoding(592                                provider_credentials.get(variable), self.decoding_rsa_key, self.decoding_cipher_rsa593                            )594                        except ValueError:595                            pass596 597                # cache provider credentials598                provider_credentials_cache.set(credentials=provider_credentials)599            else:600                provider_credentials = cached_provider_credentials601 602            custom_provider_configuration = CustomProviderConfiguration(credentials=provider_credentials)603 604        # Get provider model credential secret variables605        model_credential_secret_variables = self._extract_secret_variables(606            provider_entity.model_credential_schema.credential_form_schemas607            if provider_entity.model_credential_schema608            else []609        )610 611        # Get custom provider model credentials612        custom_model_configurations = []613        for provider_model_record in provider_model_records:614            if not provider_model_record.encrypted_config:615                continue616 617            provider_model_credentials_cache = ProviderCredentialsCache(618                tenant_id=tenant_id, identity_id=provider_model_record.id, cache_type=ProviderCredentialsCacheType.MODEL619            )620 621            # Get cached provider model credentials622            cached_provider_model_credentials = provider_model_credentials_cache.get()623 624            if not cached_provider_model_credentials:625                try:626                    provider_model_credentials = json.loads(provider_model_record.encrypted_config)627                except JSONDecodeError:628                    continue629 630                # Get decoding rsa key and cipher for decrypting credentials631                if self.decoding_rsa_key is None or self.decoding_cipher_rsa is None:632                    self.decoding_rsa_key, self.decoding_cipher_rsa = encrypter.get_decrypt_decoding(tenant_id)633 634                for variable in model_credential_secret_variables:635                    if variable in provider_model_credentials:636                        try:637                            provider_model_credentials[variable] = encrypter.decrypt_token_with_decoding(638                                provider_model_credentials.get(variable),639                                self.decoding_rsa_key,640                                self.decoding_cipher_rsa,641                            )642                        except ValueError:643                            pass644 645                # cache provider model credentials646                provider_model_credentials_cache.set(credentials=provider_model_credentials)647            else:648                provider_model_credentials = cached_provider_model_credentials649 650            custom_model_configurations.append(651                CustomModelConfiguration(652                    model=provider_model_record.model_name,653                    model_type=ModelType.value_of(provider_model_record.model_type),654                    credentials=provider_model_credentials,655                )656            )657 658        return CustomConfiguration(provider=custom_provider_configuration, models=custom_model_configurations)659 660    def _to_system_configuration(661        self, tenant_id: str, provider_entity: ProviderEntity, provider_records: list[Provider]662    ) -> SystemConfiguration:663        """664        Convert to system configuration.665 666        :param tenant_id: workspace id667        :param provider_entity: provider entity668        :param provider_records: provider records669        :return:670        """671        # Get hosting configuration672        hosting_configuration = ext_hosting_provider.hosting_configuration673 674        if (675            provider_entity.provider not in hosting_configuration.provider_map676            or not hosting_configuration.provider_map.get(provider_entity.provider).enabled677        ):678            return SystemConfiguration(enabled=False)679 680        provider_hosting_configuration = hosting_configuration.provider_map.get(provider_entity.provider)681 682        # Convert provider_records to dict683        quota_type_to_provider_records_dict = {}684        for provider_record in provider_records:685            if provider_record.provider_type != ProviderType.SYSTEM.value:686                continue687 688            quota_type_to_provider_records_dict[ProviderQuotaType.value_of(provider_record.quota_type)] = (689                provider_record690            )691 692        quota_configurations = []693        for provider_quota in provider_hosting_configuration.quotas:694            if provider_quota.quota_type not in quota_type_to_provider_records_dict:695                if provider_quota.quota_type == ProviderQuotaType.FREE:696                    quota_configuration = QuotaConfiguration(697                        quota_type=provider_quota.quota_type,698                        quota_unit=provider_hosting_configuration.quota_unit,699                        quota_used=0,700                        quota_limit=0,701                        is_valid=False,702                        restrict_models=provider_quota.restrict_models,703                    )704                else:705                    continue706            else:707                provider_record = quota_type_to_provider_records_dict[provider_quota.quota_type]708 709                quota_configuration = QuotaConfiguration(710                    quota_type=provider_quota.quota_type,711                    quota_unit=provider_hosting_configuration.quota_unit,712                    quota_used=provider_record.quota_used,713                    quota_limit=provider_record.quota_limit,714                    is_valid=provider_record.quota_limit > provider_record.quota_used715                    or provider_record.quota_limit == -1,716                    restrict_models=provider_quota.restrict_models,717                )718 719            quota_configurations.append(quota_configuration)720 721        if len(quota_configurations) == 0:722            return SystemConfiguration(enabled=False)723 724        current_quota_type = self._choice_current_using_quota_type(quota_configurations)725 726        current_using_credentials = provider_hosting_configuration.credentials727        if current_quota_type == ProviderQuotaType.FREE:728            provider_record = quota_type_to_provider_records_dict.get(current_quota_type)729 730            if provider_record:731                provider_credentials_cache = ProviderCredentialsCache(732                    tenant_id=tenant_id,733                    identity_id=provider_record.id,734                    cache_type=ProviderCredentialsCacheType.PROVIDER,735                )736 737                # Get cached provider credentials738                cached_provider_credentials = provider_credentials_cache.get()739 740                if not cached_provider_credentials:741                    try:742                        provider_credentials = json.loads(provider_record.encrypted_config)743                    except JSONDecodeError:744                        provider_credentials = {}745 746                    # Get provider credential secret variables747                    provider_credential_secret_variables = self._extract_secret_variables(748                        provider_entity.provider_credential_schema.credential_form_schemas749                        if provider_entity.provider_credential_schema750                        else []751                    )752 753                    # Get decoding rsa key and cipher for decrypting credentials754                    if self.decoding_rsa_key is None or self.decoding_cipher_rsa is None:755                        self.decoding_rsa_key, self.decoding_cipher_rsa = encrypter.get_decrypt_decoding(tenant_id)756 757                    for variable in provider_credential_secret_variables:758                        if variable in provider_credentials:759                            try:760                                provider_credentials[variable] = encrypter.decrypt_token_with_decoding(761                                    provider_credentials.get(variable), self.decoding_rsa_key, self.decoding_cipher_rsa762                                )763                            except ValueError:764                                pass765 766                    current_using_credentials = provider_credentials767 768                    # cache provider credentials769                    provider_credentials_cache.set(credentials=current_using_credentials)770                else:771                    current_using_credentials = cached_provider_credentials772            else:773                current_using_credentials = {}774                quota_configurations = []775 776        return SystemConfiguration(777            enabled=True,778            current_quota_type=current_quota_type,779            quota_configurations=quota_configurations,780            credentials=current_using_credentials,781        )782 783    @staticmethod784    def _choice_current_using_quota_type(quota_configurations: list[QuotaConfiguration]) -> ProviderQuotaType:785        """786        Choice current using quota type.787        paid quotas > provider free quotas > hosting trial quotas788        If there is still quota for the corresponding quota type according to the sorting,789 790        :param quota_configurations:791        :return:792        """793        # convert to dict794        quota_type_to_quota_configuration_dict = {795            quota_configuration.quota_type: quota_configuration for quota_configuration in quota_configurations796        }797 798        last_quota_configuration = None799        for quota_type in [ProviderQuotaType.PAID, ProviderQuotaType.FREE, ProviderQuotaType.TRIAL]:800            if quota_type in quota_type_to_quota_configuration_dict:801                last_quota_configuration = quota_type_to_quota_configuration_dict[quota_type]802                if last_quota_configuration.is_valid:803                    return quota_type804 805        if last_quota_configuration:806            return last_quota_configuration.quota_type807 808        raise ValueError("No quota type available")809 810    @staticmethod811    def _extract_secret_variables(credential_form_schemas: list[CredentialFormSchema]) -> list[str]:812        """813        Extract secret input form variables.814 815        :param credential_form_schemas:816        :return:817        """818        secret_input_form_variables = []819        for credential_form_schema in credential_form_schemas:820            if credential_form_schema.type == FormType.SECRET_INPUT:821                secret_input_form_variables.append(credential_form_schema.variable)822 823        return secret_input_form_variables824 825    def _to_model_settings(826        self,827        provider_entity: ProviderEntity,828        provider_model_settings: Optional[list[ProviderModelSetting]] = None,829        load_balancing_model_configs: Optional[list[LoadBalancingModelConfig]] = None,830    ) -> list[ModelSettings]:831        """832        Convert to model settings.833        :param provider_entity: provider entity834        :param provider_model_settings: provider model settings include enabled, load balancing enabled835        :param load_balancing_model_configs: load balancing model configs836        :return:837        """838        # Get provider model credential secret variables839        model_credential_secret_variables = self._extract_secret_variables(840            provider_entity.model_credential_schema.credential_form_schemas841            if provider_entity.model_credential_schema842            else []843        )844 845        model_settings = []846        if not provider_model_settings:847            return model_settings848 849        for provider_model_setting in provider_model_settings:850            load_balancing_configs = []851            if provider_model_setting.load_balancing_enabled and load_balancing_model_configs:852                for load_balancing_model_config in load_balancing_model_configs:853                    if (854                        load_balancing_model_config.model_name == provider_model_setting.model_name855                        and load_balancing_model_config.model_type == provider_model_setting.model_type856                    ):857                        if not load_balancing_model_config.enabled:858                            continue859 860                        if not load_balancing_model_config.encrypted_config:861                            if load_balancing_model_config.name == "__inherit__":862                                load_balancing_configs.append(863                                    ModelLoadBalancingConfiguration(864                                        id=load_balancing_model_config.id,865                                        name=load_balancing_model_config.name,866                                        credentials={},867                                    )868                                )869                            continue870 871                        provider_model_credentials_cache = ProviderCredentialsCache(872                            tenant_id=load_balancing_model_config.tenant_id,873                            identity_id=load_balancing_model_config.id,874                            cache_type=ProviderCredentialsCacheType.LOAD_BALANCING_MODEL,875                        )876 877                        # Get cached provider model credentials878                        cached_provider_model_credentials = provider_model_credentials_cache.get()879 880                        if not cached_provider_model_credentials:881                            try:882                                provider_model_credentials = json.loads(load_balancing_model_config.encrypted_config)883                            except JSONDecodeError:884                                continue885 886                            # Get decoding rsa key and cipher for decrypting credentials887                            if self.decoding_rsa_key is None or self.decoding_cipher_rsa is None:888                                self.decoding_rsa_key, self.decoding_cipher_rsa = encrypter.get_decrypt_decoding(889                                    load_balancing_model_config.tenant_id890                                )891 892                            for variable in model_credential_secret_variables:893                                if variable in provider_model_credentials:894                                    try:895                                        provider_model_credentials[variable] = encrypter.decrypt_token_with_decoding(896                                            provider_model_credentials.get(variable),897                                            self.decoding_rsa_key,898                                            self.decoding_cipher_rsa,899                                        )900                                    except ValueError:901                                        pass902 903                            # cache provider model credentials904                            provider_model_credentials_cache.set(credentials=provider_model_credentials)905                        else:906                            provider_model_credentials = cached_provider_model_credentials907 908                        load_balancing_configs.append(909                            ModelLoadBalancingConfiguration(910                                id=load_balancing_model_config.id,911                                name=load_balancing_model_config.name,912                                credentials=provider_model_credentials,913                            )914                        )915 916            model_settings.append(917                ModelSettings(918                    model=provider_model_setting.model_name,919                    model_type=ModelType.value_of(provider_model_setting.model_type),920                    enabled=provider_model_setting.enabled,921                    load_balancing_configs=load_balancing_configs if len(load_balancing_configs) > 1 else [],922                )923            )924 925        return model_settings926