provider_manager.py 39 KB

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