provider_manager.py 32 KB

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