provider_manager.py 40 KB

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