provider_manager.py 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746
  1. import json
  2. from collections import defaultdict
  3. from json import JSONDecodeError
  4. from typing import Optional
  5. from core.entities.model_entities import DefaultModelEntity, DefaultModelProviderEntity
  6. from core.entities.provider_configuration import ProviderConfiguration, ProviderConfigurations, ProviderModelBundle
  7. from core.entities.provider_entities import (CustomConfiguration, CustomModelConfiguration, CustomProviderConfiguration,
  8. QuotaConfiguration, SystemConfiguration)
  9. from core.helper import encrypter
  10. from core.helper.model_provider_cache import ProviderCredentialsCache, ProviderCredentialsCacheType
  11. from core.model_runtime.entities.model_entities import ModelType
  12. from core.model_runtime.entities.provider_entities import (ConfigurateMethod, CredentialFormSchema, FormType,
  13. ProviderEntity)
  14. from core.model_runtime.model_providers import model_provider_factory
  15. from extensions import ext_hosting_provider
  16. from extensions.ext_database import db
  17. from models.provider import (Provider, ProviderModel, ProviderQuotaType, ProviderType, TenantDefaultModel,
  18. TenantPreferredModelProvider)
  19. from sqlalchemy.exc import IntegrityError
  20. class ProviderManager:
  21. """
  22. ProviderManager is a class that manages the model providers includes Hosting and Customize Model Providers.
  23. """
  24. def __init__(self) -> None:
  25. self.decoding_rsa_key = None
  26. self.decoding_cipher_rsa = None
  27. def get_configurations(self, tenant_id: str) -> ProviderConfigurations:
  28. """
  29. Get model provider configurations.
  30. Construct ProviderConfiguration objects for each provider
  31. Including:
  32. 1. Basic information of the provider
  33. 2. Hosting configuration information, including:
  34. (1. Whether to enable (support) hosting type, if enabled, the following information exists
  35. (2. List of hosting type provider configurations
  36. (including quota type, quota limit, current remaining quota, etc.)
  37. (3. The current hosting type in use (whether there is a quota or not)
  38. paid quotas > provider free quotas > hosting trial quotas
  39. (4. Unified credentials for hosting providers
  40. 3. Custom configuration information, including:
  41. (1. Whether to enable (support) custom type, if enabled, the following information exists
  42. (2. Custom provider configuration (including credentials)
  43. (3. List of custom provider model configurations (including credentials)
  44. 4. Hosting/custom preferred provider type.
  45. Provide methods:
  46. - Get the current configuration (including credentials)
  47. - Get the availability and status of the hosting configuration: active available,
  48. quota_exceeded insufficient quota, unsupported hosting
  49. - Get the availability of custom configuration
  50. Custom provider available conditions:
  51. (1. custom provider credentials available
  52. (2. at least one custom model credentials available
  53. - Verify, update, and delete custom provider configuration
  54. - Verify, update, and delete custom provider model configuration
  55. - Get the list of available models (optional provider filtering, model type filtering)
  56. Append custom provider models to the list
  57. - Get provider instance
  58. - Switch selection priority
  59. :param tenant_id:
  60. :return:
  61. """
  62. # Get all provider records of the workspace
  63. provider_name_to_provider_records_dict = self._get_all_providers(tenant_id)
  64. # Initialize trial provider records if not exist
  65. provider_name_to_provider_records_dict = self._init_trial_provider_records(
  66. tenant_id,
  67. provider_name_to_provider_records_dict
  68. )
  69. # Get all provider model records of the workspace
  70. provider_name_to_provider_model_records_dict = self._get_all_provider_models(tenant_id)
  71. # Get all provider entities
  72. provider_entities = model_provider_factory.get_providers()
  73. # Get All preferred provider types of the workspace
  74. provider_name_to_preferred_model_provider_records_dict = self._get_all_preferred_model_providers(tenant_id)
  75. provider_configurations = ProviderConfigurations(
  76. tenant_id=tenant_id
  77. )
  78. # Construct ProviderConfiguration objects for each provider
  79. for provider_entity in provider_entities:
  80. provider_name = provider_entity.provider
  81. provider_records = provider_name_to_provider_records_dict.get(provider_entity.provider)
  82. if not provider_records:
  83. provider_records = []
  84. provider_model_records = provider_name_to_provider_model_records_dict.get(provider_entity.provider)
  85. if not provider_model_records:
  86. provider_model_records = []
  87. # Convert to custom configuration
  88. custom_configuration = self._to_custom_configuration(
  89. tenant_id,
  90. provider_entity,
  91. provider_records,
  92. provider_model_records
  93. )
  94. # Convert to system configuration
  95. system_configuration = self._to_system_configuration(
  96. tenant_id,
  97. provider_entity,
  98. provider_records
  99. )
  100. # Get preferred provider type
  101. preferred_provider_type_record = provider_name_to_preferred_model_provider_records_dict.get(provider_name)
  102. if preferred_provider_type_record:
  103. preferred_provider_type = ProviderType.value_of(preferred_provider_type_record.preferred_provider_type)
  104. else:
  105. if custom_configuration.provider or custom_configuration.models:
  106. preferred_provider_type = ProviderType.CUSTOM
  107. elif system_configuration.enabled:
  108. preferred_provider_type = ProviderType.SYSTEM
  109. else:
  110. preferred_provider_type = ProviderType.CUSTOM
  111. using_provider_type = preferred_provider_type
  112. if preferred_provider_type == ProviderType.SYSTEM:
  113. if not system_configuration.enabled:
  114. using_provider_type = ProviderType.CUSTOM
  115. has_valid_quota = False
  116. for quota_configuration in system_configuration.quota_configurations:
  117. if quota_configuration.is_valid:
  118. has_valid_quota = True
  119. break
  120. if not has_valid_quota:
  121. using_provider_type = ProviderType.CUSTOM
  122. else:
  123. if not custom_configuration.provider and not custom_configuration.models:
  124. if system_configuration.enabled:
  125. has_valid_quota = False
  126. for quota_configuration in system_configuration.quota_configurations:
  127. if quota_configuration.is_valid:
  128. has_valid_quota = True
  129. break
  130. if has_valid_quota:
  131. using_provider_type = ProviderType.SYSTEM
  132. provider_configuration = ProviderConfiguration(
  133. tenant_id=tenant_id,
  134. provider=provider_entity,
  135. preferred_provider_type=preferred_provider_type,
  136. using_provider_type=using_provider_type,
  137. system_configuration=system_configuration,
  138. custom_configuration=custom_configuration
  139. )
  140. provider_configurations[provider_name] = provider_configuration
  141. # Return the encapsulated object
  142. return provider_configurations
  143. def get_provider_model_bundle(self, tenant_id: str, provider: str, model_type: ModelType) -> ProviderModelBundle:
  144. """
  145. Get provider model bundle.
  146. :param tenant_id: workspace id
  147. :param provider: provider name
  148. :param model_type: model type
  149. :return:
  150. """
  151. provider_configurations = self.get_configurations(tenant_id)
  152. # get provider instance
  153. provider_configuration = provider_configurations.get(provider)
  154. if not provider_configuration:
  155. raise ValueError(f"Provider {provider} does not exist.")
  156. provider_instance = provider_configuration.get_provider_instance()
  157. model_type_instance = provider_instance.get_model_instance(model_type)
  158. return ProviderModelBundle(
  159. configuration=provider_configuration,
  160. provider_instance=provider_instance,
  161. model_type_instance=model_type_instance
  162. )
  163. def get_default_model(self, tenant_id: str, model_type: ModelType) -> Optional[DefaultModelEntity]:
  164. """
  165. Get default model.
  166. :param tenant_id: workspace id
  167. :param model_type: model type
  168. :return:
  169. """
  170. # Get the corresponding TenantDefaultModel record
  171. default_model = db.session.query(TenantDefaultModel) \
  172. .filter(
  173. TenantDefaultModel.tenant_id == tenant_id,
  174. TenantDefaultModel.model_type == model_type.to_origin_model_type()
  175. ).first()
  176. # If it does not exist, get the first available provider model from get_configurations
  177. # and update the TenantDefaultModel record
  178. if not default_model:
  179. # Get provider configurations
  180. provider_configurations = self.get_configurations(tenant_id)
  181. # get available models from provider_configurations
  182. available_models = provider_configurations.get_models(
  183. model_type=model_type,
  184. only_active=True
  185. )
  186. if available_models:
  187. found = False
  188. for available_model in available_models:
  189. if available_model.model == "gpt-3.5-turbo-1106":
  190. default_model = TenantDefaultModel(
  191. tenant_id=tenant_id,
  192. model_type=model_type.to_origin_model_type(),
  193. provider_name=available_model.provider.provider,
  194. model_name=available_model.model
  195. )
  196. db.session.add(default_model)
  197. db.session.commit()
  198. found = True
  199. break
  200. if not found:
  201. available_model = available_models[0]
  202. default_model = TenantDefaultModel(
  203. tenant_id=tenant_id,
  204. model_type=model_type.to_origin_model_type(),
  205. provider_name=available_model.provider.provider,
  206. model_name=available_model.model
  207. )
  208. db.session.add(default_model)
  209. db.session.commit()
  210. if not default_model:
  211. return None
  212. provider_instance = model_provider_factory.get_provider_instance(default_model.provider_name)
  213. provider_schema = provider_instance.get_provider_schema()
  214. return DefaultModelEntity(
  215. model=default_model.model_name,
  216. model_type=model_type,
  217. provider=DefaultModelProviderEntity(
  218. provider=provider_schema.provider,
  219. label=provider_schema.label,
  220. icon_small=provider_schema.icon_small,
  221. icon_large=provider_schema.icon_large,
  222. supported_model_types=provider_schema.supported_model_types
  223. )
  224. )
  225. def update_default_model_record(self, tenant_id: str, model_type: ModelType, provider: str, model: str) \
  226. -> TenantDefaultModel:
  227. """
  228. Update default model record.
  229. :param tenant_id: workspace id
  230. :param model_type: model type
  231. :param provider: provider name
  232. :param model: model name
  233. :return:
  234. """
  235. provider_configurations = self.get_configurations(tenant_id)
  236. if provider not in provider_configurations:
  237. raise ValueError(f"Provider {provider} does not exist.")
  238. # get available models from provider_configurations
  239. available_models = provider_configurations.get_models(
  240. model_type=model_type,
  241. only_active=True
  242. )
  243. # check if the model is exist in available models
  244. model_names = [model.model for model in available_models]
  245. if model not in model_names:
  246. raise ValueError(f"Model {model} does not exist.")
  247. # Get the list of available models from get_configurations and check if it is LLM
  248. default_model = db.session.query(TenantDefaultModel) \
  249. .filter(
  250. TenantDefaultModel.tenant_id == tenant_id,
  251. TenantDefaultModel.model_type == model_type.to_origin_model_type()
  252. ).first()
  253. # create or update TenantDefaultModel record
  254. if default_model:
  255. # update default model
  256. default_model.provider_name = provider
  257. default_model.model_name = model
  258. db.session.commit()
  259. else:
  260. # create default model
  261. default_model = TenantDefaultModel(
  262. tenant_id=tenant_id,
  263. model_type=model_type.value,
  264. provider_name=provider,
  265. model_name=model,
  266. )
  267. db.session.add(default_model)
  268. db.session.commit()
  269. return default_model
  270. def _get_all_providers(self, tenant_id: str) -> dict[str, list[Provider]]:
  271. """
  272. Get all provider records of the workspace.
  273. :param tenant_id: workspace id
  274. :return:
  275. """
  276. providers = db.session.query(Provider) \
  277. .filter(
  278. Provider.tenant_id == tenant_id,
  279. Provider.is_valid == True
  280. ).all()
  281. provider_name_to_provider_records_dict = defaultdict(list)
  282. for provider in providers:
  283. provider_name_to_provider_records_dict[provider.provider_name].append(provider)
  284. return provider_name_to_provider_records_dict
  285. def _get_all_provider_models(self, tenant_id: str) -> dict[str, list[ProviderModel]]:
  286. """
  287. Get all provider model records of the workspace.
  288. :param tenant_id: workspace id
  289. :return:
  290. """
  291. # Get all provider model records of the workspace
  292. provider_models = db.session.query(ProviderModel) \
  293. .filter(
  294. ProviderModel.tenant_id == tenant_id,
  295. ProviderModel.is_valid == True
  296. ).all()
  297. provider_name_to_provider_model_records_dict = defaultdict(list)
  298. for provider_model in provider_models:
  299. provider_name_to_provider_model_records_dict[provider_model.provider_name].append(provider_model)
  300. return provider_name_to_provider_model_records_dict
  301. def _get_all_preferred_model_providers(self, tenant_id: str) -> dict[str, TenantPreferredModelProvider]:
  302. """
  303. Get All preferred provider types of the workspace.
  304. :param tenant_id:
  305. :return:
  306. """
  307. preferred_provider_types = db.session.query(TenantPreferredModelProvider) \
  308. .filter(
  309. TenantPreferredModelProvider.tenant_id == tenant_id
  310. ).all()
  311. provider_name_to_preferred_provider_type_records_dict = {
  312. preferred_provider_type.provider_name: preferred_provider_type
  313. for preferred_provider_type in preferred_provider_types
  314. }
  315. return provider_name_to_preferred_provider_type_records_dict
  316. def _init_trial_provider_records(self, tenant_id: str,
  317. provider_name_to_provider_records_dict: dict[str, list]) -> dict[str, list]:
  318. """
  319. Initialize trial provider records if not exists.
  320. :param tenant_id: workspace id
  321. :param provider_name_to_provider_records_dict: provider name to provider records dict
  322. :return:
  323. """
  324. # Get hosting configuration
  325. hosting_configuration = ext_hosting_provider.hosting_configuration
  326. for provider_name, configuration in hosting_configuration.provider_map.items():
  327. if not configuration.enabled:
  328. continue
  329. provider_records = provider_name_to_provider_records_dict.get(provider_name)
  330. if not provider_records:
  331. provider_records = []
  332. provider_quota_to_provider_record_dict = dict()
  333. for provider_record in provider_records:
  334. if provider_record.provider_type != ProviderType.SYSTEM.value:
  335. continue
  336. provider_quota_to_provider_record_dict[ProviderQuotaType.value_of(provider_record.quota_type)] \
  337. = provider_record
  338. for quota in configuration.quotas:
  339. if quota.quota_type == ProviderQuotaType.TRIAL:
  340. # Init trial provider records if not exists
  341. if ProviderQuotaType.TRIAL not in provider_quota_to_provider_record_dict:
  342. try:
  343. provider_record = Provider(
  344. tenant_id=tenant_id,
  345. provider_name=provider_name,
  346. provider_type=ProviderType.SYSTEM.value,
  347. quota_type=ProviderQuotaType.TRIAL.value,
  348. quota_limit=quota.quota_limit,
  349. quota_used=0,
  350. is_valid=True
  351. )
  352. db.session.add(provider_record)
  353. db.session.commit()
  354. except IntegrityError:
  355. db.session.rollback()
  356. provider_record = db.session.query(Provider) \
  357. .filter(
  358. Provider.tenant_id == tenant_id,
  359. Provider.provider_name == provider_name,
  360. Provider.provider_type == ProviderType.SYSTEM.value,
  361. Provider.quota_type == ProviderQuotaType.TRIAL.value
  362. ).first()
  363. if provider_record and not provider_record.is_valid:
  364. provider_record.is_valid = True
  365. db.session.commit()
  366. provider_name_to_provider_records_dict[provider_name].append(provider_record)
  367. return provider_name_to_provider_records_dict
  368. def _to_custom_configuration(self,
  369. tenant_id: str,
  370. provider_entity: ProviderEntity,
  371. provider_records: list[Provider],
  372. provider_model_records: list[ProviderModel]) -> CustomConfiguration:
  373. """
  374. Convert to custom configuration.
  375. :param tenant_id: workspace id
  376. :param provider_entity: provider entity
  377. :param provider_records: provider records
  378. :param provider_model_records: provider model records
  379. :return:
  380. """
  381. # Get provider credential secret variables
  382. provider_credential_secret_variables = self._extract_secret_variables(
  383. provider_entity.provider_credential_schema.credential_form_schemas
  384. if provider_entity.provider_credential_schema else []
  385. )
  386. # Get custom provider record
  387. custom_provider_record = None
  388. for provider_record in provider_records:
  389. if provider_record.provider_type == ProviderType.SYSTEM.value:
  390. continue
  391. if not provider_record.encrypted_config:
  392. continue
  393. custom_provider_record = provider_record
  394. # Get custom provider credentials
  395. custom_provider_configuration = None
  396. if custom_provider_record:
  397. provider_credentials_cache = ProviderCredentialsCache(
  398. tenant_id=tenant_id,
  399. identity_id=custom_provider_record.id,
  400. cache_type=ProviderCredentialsCacheType.PROVIDER
  401. )
  402. # Get cached provider credentials
  403. cached_provider_credentials = provider_credentials_cache.get()
  404. if not cached_provider_credentials:
  405. try:
  406. # fix origin data
  407. if (custom_provider_record.encrypted_config
  408. and not custom_provider_record.encrypted_config.startswith("{")):
  409. provider_credentials = {
  410. "openai_api_key": custom_provider_record.encrypted_config
  411. }
  412. else:
  413. provider_credentials = json.loads(custom_provider_record.encrypted_config)
  414. except JSONDecodeError:
  415. provider_credentials = {}
  416. # Get decoding rsa key and cipher for decrypting credentials
  417. if self.decoding_rsa_key is None or self.decoding_cipher_rsa is None:
  418. self.decoding_rsa_key, self.decoding_cipher_rsa = encrypter.get_decrypt_decoding(tenant_id)
  419. for variable in provider_credential_secret_variables:
  420. if variable in provider_credentials:
  421. try:
  422. provider_credentials[variable] = encrypter.decrypt_token_with_decoding(
  423. provider_credentials.get(variable),
  424. self.decoding_rsa_key,
  425. self.decoding_cipher_rsa
  426. )
  427. except ValueError:
  428. pass
  429. # cache provider credentials
  430. provider_credentials_cache.set(
  431. credentials=provider_credentials
  432. )
  433. else:
  434. provider_credentials = cached_provider_credentials
  435. custom_provider_configuration = CustomProviderConfiguration(
  436. credentials=provider_credentials
  437. )
  438. # Get provider model credential secret variables
  439. model_credential_secret_variables = self._extract_secret_variables(
  440. provider_entity.model_credential_schema.credential_form_schemas
  441. if provider_entity.model_credential_schema else []
  442. )
  443. # Get custom provider model credentials
  444. custom_model_configurations = []
  445. for provider_model_record in provider_model_records:
  446. if not provider_model_record.encrypted_config:
  447. continue
  448. provider_model_credentials_cache = ProviderCredentialsCache(
  449. tenant_id=tenant_id,
  450. identity_id=provider_model_record.id,
  451. cache_type=ProviderCredentialsCacheType.MODEL
  452. )
  453. # Get cached provider model credentials
  454. cached_provider_model_credentials = provider_model_credentials_cache.get()
  455. if not cached_provider_model_credentials:
  456. try:
  457. provider_model_credentials = json.loads(provider_model_record.encrypted_config)
  458. except JSONDecodeError:
  459. continue
  460. # Get decoding rsa key and cipher for decrypting credentials
  461. if self.decoding_rsa_key is None or self.decoding_cipher_rsa is None:
  462. self.decoding_rsa_key, self.decoding_cipher_rsa = encrypter.get_decrypt_decoding(tenant_id)
  463. for variable in model_credential_secret_variables:
  464. if variable in provider_model_credentials:
  465. try:
  466. provider_model_credentials[variable] = encrypter.decrypt_token_with_decoding(
  467. provider_model_credentials.get(variable),
  468. self.decoding_rsa_key,
  469. self.decoding_cipher_rsa
  470. )
  471. except ValueError:
  472. pass
  473. # cache provider model credentials
  474. provider_model_credentials_cache.set(
  475. credentials=provider_model_credentials
  476. )
  477. else:
  478. provider_model_credentials = cached_provider_model_credentials
  479. custom_model_configurations.append(
  480. CustomModelConfiguration(
  481. model=provider_model_record.model_name,
  482. model_type=ModelType.value_of(provider_model_record.model_type),
  483. credentials=provider_model_credentials
  484. )
  485. )
  486. return CustomConfiguration(
  487. provider=custom_provider_configuration,
  488. models=custom_model_configurations
  489. )
  490. def _to_system_configuration(self,
  491. tenant_id: str,
  492. provider_entity: ProviderEntity,
  493. provider_records: list[Provider]) -> SystemConfiguration:
  494. """
  495. Convert to system configuration.
  496. :param tenant_id: workspace id
  497. :param provider_entity: provider entity
  498. :param provider_records: provider records
  499. :return:
  500. """
  501. # Get hosting configuration
  502. hosting_configuration = ext_hosting_provider.hosting_configuration
  503. if provider_entity.provider not in hosting_configuration.provider_map \
  504. or not hosting_configuration.provider_map.get(provider_entity.provider).enabled:
  505. return SystemConfiguration(
  506. enabled=False
  507. )
  508. provider_hosting_configuration = hosting_configuration.provider_map.get(provider_entity.provider)
  509. # Convert provider_records to dict
  510. quota_type_to_provider_records_dict = dict()
  511. for provider_record in provider_records:
  512. if provider_record.provider_type != ProviderType.SYSTEM.value:
  513. continue
  514. quota_type_to_provider_records_dict[ProviderQuotaType.value_of(provider_record.quota_type)] \
  515. = provider_record
  516. quota_configurations = []
  517. for provider_quota in provider_hosting_configuration.quotas:
  518. if provider_quota.quota_type not in quota_type_to_provider_records_dict:
  519. if provider_quota.quota_type == ProviderQuotaType.FREE:
  520. quota_configuration = QuotaConfiguration(
  521. quota_type=provider_quota.quota_type,
  522. quota_unit=provider_hosting_configuration.quota_unit,
  523. quota_used=0,
  524. quota_limit=0,
  525. is_valid=False,
  526. restrict_models=provider_quota.restrict_models
  527. )
  528. else:
  529. continue
  530. else:
  531. provider_record = quota_type_to_provider_records_dict[provider_quota.quota_type]
  532. quota_configuration = QuotaConfiguration(
  533. quota_type=provider_quota.quota_type,
  534. quota_unit=provider_hosting_configuration.quota_unit,
  535. quota_used=provider_record.quota_used,
  536. quota_limit=provider_record.quota_limit,
  537. is_valid=provider_record.quota_limit > provider_record.quota_used or provider_record.quota_limit == -1,
  538. restrict_models=provider_quota.restrict_models
  539. )
  540. quota_configurations.append(quota_configuration)
  541. if len(quota_configurations) == 0:
  542. return SystemConfiguration(
  543. enabled=False
  544. )
  545. current_quota_type = self._choice_current_using_quota_type(quota_configurations)
  546. current_using_credentials = provider_hosting_configuration.credentials
  547. if current_quota_type == ProviderQuotaType.FREE:
  548. provider_record = quota_type_to_provider_records_dict.get(current_quota_type)
  549. if provider_record:
  550. provider_credentials_cache = ProviderCredentialsCache(
  551. tenant_id=tenant_id,
  552. identity_id=provider_record.id,
  553. cache_type=ProviderCredentialsCacheType.PROVIDER
  554. )
  555. # Get cached provider credentials
  556. cached_provider_credentials = provider_credentials_cache.get()
  557. if not cached_provider_credentials:
  558. try:
  559. provider_credentials = json.loads(provider_record.encrypted_config)
  560. except JSONDecodeError:
  561. provider_credentials = {}
  562. # Get provider credential secret variables
  563. provider_credential_secret_variables = self._extract_secret_variables(
  564. provider_entity.provider_credential_schema.credential_form_schemas
  565. if provider_entity.provider_credential_schema else []
  566. )
  567. # Get decoding rsa key and cipher for decrypting credentials
  568. if self.decoding_rsa_key is None or self.decoding_cipher_rsa is None:
  569. self.decoding_rsa_key, self.decoding_cipher_rsa = encrypter.get_decrypt_decoding(tenant_id)
  570. for variable in provider_credential_secret_variables:
  571. if variable in provider_credentials:
  572. try:
  573. provider_credentials[variable] = encrypter.decrypt_token_with_decoding(
  574. provider_credentials.get(variable),
  575. self.decoding_rsa_key,
  576. self.decoding_cipher_rsa
  577. )
  578. except ValueError:
  579. pass
  580. current_using_credentials = provider_credentials
  581. # cache provider credentials
  582. provider_credentials_cache.set(
  583. credentials=current_using_credentials
  584. )
  585. else:
  586. current_using_credentials = cached_provider_credentials
  587. else:
  588. current_using_credentials = {}
  589. quota_configurations = []
  590. return SystemConfiguration(
  591. enabled=True,
  592. current_quota_type=current_quota_type,
  593. quota_configurations=quota_configurations,
  594. credentials=current_using_credentials
  595. )
  596. def _choice_current_using_quota_type(self, quota_configurations: list[QuotaConfiguration]) -> ProviderQuotaType:
  597. """
  598. Choice current using quota type.
  599. paid quotas > provider free quotas > hosting trial quotas
  600. If there is still quota for the corresponding quota type according to the sorting,
  601. :param quota_configurations:
  602. :return:
  603. """
  604. # convert to dict
  605. quota_type_to_quota_configuration_dict = {
  606. quota_configuration.quota_type: quota_configuration
  607. for quota_configuration in quota_configurations
  608. }
  609. last_quota_configuration = None
  610. for quota_type in [ProviderQuotaType.PAID, ProviderQuotaType.FREE, ProviderQuotaType.TRIAL]:
  611. if quota_type in quota_type_to_quota_configuration_dict:
  612. last_quota_configuration = quota_type_to_quota_configuration_dict[quota_type]
  613. if last_quota_configuration.is_valid:
  614. return quota_type
  615. if last_quota_configuration:
  616. return last_quota_configuration.quota_type
  617. raise ValueError('No quota type available')
  618. def _extract_secret_variables(self, credential_form_schemas: list[CredentialFormSchema]) -> list[str]:
  619. """
  620. Extract secret input form variables.
  621. :param credential_form_schemas:
  622. :return:
  623. """
  624. secret_input_form_variables = []
  625. for credential_form_schema in credential_form_schemas:
  626. if credential_form_schema.type == FormType.SECRET_INPUT:
  627. secret_input_form_variables.append(credential_form_schema.variable)
  628. return secret_input_form_variables