provider_manager.py 38 KB

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