provider_service.py 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503
  1. import datetime
  2. import json
  3. from collections import defaultdict
  4. from typing import Optional
  5. from core.model_providers.model_factory import ModelFactory
  6. from extensions.ext_database import db
  7. from core.model_providers.model_provider_factory import ModelProviderFactory
  8. from core.model_providers.models.entity.model_params import ModelType, ModelKwargsRules
  9. from models.provider import Provider, ProviderModel, TenantPreferredModelProvider, ProviderType, ProviderQuotaType, \
  10. TenantDefaultModel
  11. class ProviderService:
  12. def get_provider_list(self, tenant_id: str):
  13. """
  14. get provider list of tenant.
  15. :param tenant_id:
  16. :return:
  17. """
  18. # get rules for all providers
  19. model_provider_rules = ModelProviderFactory.get_provider_rules()
  20. model_provider_names = [model_provider_name for model_provider_name, _ in model_provider_rules.items()]
  21. configurable_model_provider_names = [
  22. model_provider_name
  23. for model_provider_name, model_provider_rules in model_provider_rules.items()
  24. if 'custom' in model_provider_rules['support_provider_types']
  25. and model_provider_rules['model_flexibility'] == 'configurable'
  26. ]
  27. # get all providers for the tenant
  28. providers = db.session.query(Provider) \
  29. .filter(
  30. Provider.tenant_id == tenant_id,
  31. Provider.provider_name.in_(model_provider_names),
  32. Provider.is_valid == True
  33. ).order_by(Provider.created_at.desc()).all()
  34. provider_name_to_provider_dict = defaultdict(list)
  35. for provider in providers:
  36. provider_name_to_provider_dict[provider.provider_name].append(provider)
  37. # get all configurable provider models for the tenant
  38. provider_models = db.session.query(ProviderModel) \
  39. .filter(
  40. ProviderModel.tenant_id == tenant_id,
  41. ProviderModel.provider_name.in_(configurable_model_provider_names),
  42. ProviderModel.is_valid == True
  43. ).order_by(ProviderModel.created_at.desc()).all()
  44. provider_name_to_provider_model_dict = defaultdict(list)
  45. for provider_model in provider_models:
  46. provider_name_to_provider_model_dict[provider_model.provider_name].append(provider_model)
  47. # get all preferred provider type for the tenant
  48. preferred_provider_types = db.session.query(TenantPreferredModelProvider) \
  49. .filter(
  50. TenantPreferredModelProvider.tenant_id == tenant_id,
  51. TenantPreferredModelProvider.provider_name.in_(model_provider_names)
  52. ).all()
  53. provider_name_to_preferred_provider_type_dict = {preferred_provider_type.provider_name: preferred_provider_type
  54. for preferred_provider_type in preferred_provider_types}
  55. providers_list = {}
  56. for model_provider_name, model_provider_rule in model_provider_rules.items():
  57. # get preferred provider type
  58. preferred_model_provider = provider_name_to_preferred_provider_type_dict.get(model_provider_name)
  59. preferred_provider_type = ModelProviderFactory.get_preferred_type_by_preferred_model_provider(
  60. tenant_id,
  61. model_provider_name,
  62. preferred_model_provider
  63. )
  64. provider_config_dict = {
  65. "preferred_provider_type": preferred_provider_type,
  66. "model_flexibility": model_provider_rule['model_flexibility'],
  67. }
  68. provider_parameter_dict = {}
  69. if ProviderType.SYSTEM.value in model_provider_rule['support_provider_types']:
  70. for quota_type_enum in ProviderQuotaType:
  71. quota_type = quota_type_enum.value
  72. if quota_type in model_provider_rule['system_config']['supported_quota_types']:
  73. key = ProviderType.SYSTEM.value + ':' + quota_type
  74. provider_parameter_dict[key] = {
  75. "provider_name": model_provider_name,
  76. "provider_type": ProviderType.SYSTEM.value,
  77. "config": None,
  78. "is_valid": False, # need update
  79. "quota_type": quota_type,
  80. "quota_unit": model_provider_rule['system_config']['quota_unit'], # need update
  81. "quota_limit": 0 if quota_type != ProviderQuotaType.TRIAL.value else
  82. model_provider_rule['system_config']['quota_limit'], # need update
  83. "quota_used": 0, # need update
  84. "last_used": None # need update
  85. }
  86. if ProviderType.CUSTOM.value in model_provider_rule['support_provider_types']:
  87. provider_parameter_dict[ProviderType.CUSTOM.value] = {
  88. "provider_name": model_provider_name,
  89. "provider_type": ProviderType.CUSTOM.value,
  90. "config": None, # need update
  91. "models": [], # need update
  92. "is_valid": False,
  93. "last_used": None # need update
  94. }
  95. model_provider_class = ModelProviderFactory.get_model_provider_class(model_provider_name)
  96. current_providers = provider_name_to_provider_dict[model_provider_name]
  97. for provider in current_providers:
  98. if provider.provider_type == ProviderType.SYSTEM.value:
  99. quota_type = provider.quota_type
  100. key = f'{ProviderType.SYSTEM.value}:{quota_type}'
  101. if key in provider_parameter_dict:
  102. provider_parameter_dict[key]['is_valid'] = provider.is_valid
  103. provider_parameter_dict[key]['quota_used'] = provider.quota_used
  104. provider_parameter_dict[key]['quota_limit'] = provider.quota_limit
  105. provider_parameter_dict[key]['last_used'] = provider.last_used
  106. elif provider.provider_type == ProviderType.CUSTOM.value \
  107. and ProviderType.CUSTOM.value in provider_parameter_dict:
  108. # if custom
  109. key = ProviderType.CUSTOM.value
  110. provider_parameter_dict[key]['last_used'] = provider.last_used
  111. provider_parameter_dict[key]['is_valid'] = provider.is_valid
  112. if model_provider_rule['model_flexibility'] == 'fixed':
  113. provider_parameter_dict[key]['config'] = model_provider_class(provider=provider) \
  114. .get_provider_credentials(obfuscated=True)
  115. else:
  116. models = []
  117. provider_models = provider_name_to_provider_model_dict[model_provider_name]
  118. for provider_model in provider_models:
  119. models.append({
  120. "model_name": provider_model.model_name,
  121. "model_type": provider_model.model_type,
  122. "config": model_provider_class(provider=provider) \
  123. .get_model_credentials(provider_model.model_name,
  124. ModelType.value_of(provider_model.model_type),
  125. obfuscated=True),
  126. "is_valid": provider_model.is_valid
  127. })
  128. provider_parameter_dict[key]['models'] = models
  129. provider_config_dict['providers'] = list(provider_parameter_dict.values())
  130. providers_list[model_provider_name] = provider_config_dict
  131. return providers_list
  132. def custom_provider_config_validate(self, provider_name: str, config: dict) -> None:
  133. """
  134. validate custom provider config.
  135. :param provider_name:
  136. :param config:
  137. :return:
  138. :raises CredentialsValidateFailedError: When the config credential verification fails.
  139. """
  140. # get model provider rules
  141. model_provider_rules = ModelProviderFactory.get_provider_rule(provider_name)
  142. if model_provider_rules['model_flexibility'] != 'fixed':
  143. raise ValueError('Only support fixed model provider')
  144. # only support provider type CUSTOM
  145. if ProviderType.CUSTOM.value not in model_provider_rules['support_provider_types']:
  146. raise ValueError('Only support provider type CUSTOM')
  147. # validate provider config
  148. model_provider_class = ModelProviderFactory.get_model_provider_class(provider_name)
  149. model_provider_class.is_provider_credentials_valid_or_raise(config)
  150. def save_custom_provider_config(self, tenant_id: str, provider_name: str, config: dict) -> None:
  151. """
  152. save custom provider config.
  153. :param tenant_id:
  154. :param provider_name:
  155. :param config:
  156. :return:
  157. """
  158. # validate custom provider config
  159. self.custom_provider_config_validate(provider_name, config)
  160. # get provider
  161. provider = db.session.query(Provider) \
  162. .filter(
  163. Provider.tenant_id == tenant_id,
  164. Provider.provider_name == provider_name,
  165. Provider.provider_type == ProviderType.CUSTOM.value
  166. ).first()
  167. model_provider_class = ModelProviderFactory.get_model_provider_class(provider_name)
  168. encrypted_config = model_provider_class.encrypt_provider_credentials(tenant_id, config)
  169. # save provider
  170. if provider:
  171. provider.encrypted_config = json.dumps(encrypted_config)
  172. provider.is_valid = True
  173. provider.updated_at = datetime.datetime.utcnow()
  174. db.session.commit()
  175. else:
  176. provider = Provider(
  177. tenant_id=tenant_id,
  178. provider_name=provider_name,
  179. provider_type=ProviderType.CUSTOM.value,
  180. encrypted_config=json.dumps(encrypted_config),
  181. is_valid=True
  182. )
  183. db.session.add(provider)
  184. db.session.commit()
  185. def delete_custom_provider(self, tenant_id: str, provider_name: str) -> None:
  186. """
  187. delete custom provider.
  188. :param tenant_id:
  189. :param provider_name:
  190. :return:
  191. """
  192. # get provider
  193. provider = db.session.query(Provider) \
  194. .filter(
  195. Provider.tenant_id == tenant_id,
  196. Provider.provider_name == provider_name,
  197. Provider.provider_type == ProviderType.CUSTOM.value
  198. ).first()
  199. if provider:
  200. try:
  201. self.switch_preferred_provider(tenant_id, provider_name, ProviderType.SYSTEM.value)
  202. except ValueError:
  203. pass
  204. db.session.delete(provider)
  205. db.session.commit()
  206. def custom_provider_model_config_validate(self,
  207. provider_name: str,
  208. model_name: str,
  209. model_type: str,
  210. config: dict) -> None:
  211. """
  212. validate custom provider model config.
  213. :param provider_name:
  214. :param model_name:
  215. :param model_type:
  216. :param config:
  217. :return:
  218. :raises CredentialsValidateFailedError: When the config credential verification fails.
  219. """
  220. # get model provider rules
  221. model_provider_rules = ModelProviderFactory.get_provider_rule(provider_name)
  222. if model_provider_rules['model_flexibility'] != 'configurable':
  223. raise ValueError('Only support configurable model provider')
  224. # only support provider type CUSTOM
  225. if ProviderType.CUSTOM.value not in model_provider_rules['support_provider_types']:
  226. raise ValueError('Only support provider type CUSTOM')
  227. # validate provider model config
  228. model_type = ModelType.value_of(model_type)
  229. model_provider_class = ModelProviderFactory.get_model_provider_class(provider_name)
  230. model_provider_class.is_model_credentials_valid_or_raise(model_name, model_type, config)
  231. def add_or_save_custom_provider_model_config(self,
  232. tenant_id: str,
  233. provider_name: str,
  234. model_name: str,
  235. model_type: str,
  236. config: dict) -> None:
  237. """
  238. Add or save custom provider model config.
  239. :param tenant_id:
  240. :param provider_name:
  241. :param model_name:
  242. :param model_type:
  243. :param config:
  244. :return:
  245. """
  246. # validate custom provider model config
  247. self.custom_provider_model_config_validate(provider_name, model_name, model_type, config)
  248. # get provider
  249. provider = db.session.query(Provider) \
  250. .filter(
  251. Provider.tenant_id == tenant_id,
  252. Provider.provider_name == provider_name,
  253. Provider.provider_type == ProviderType.CUSTOM.value
  254. ).first()
  255. if not provider:
  256. provider = Provider(
  257. tenant_id=tenant_id,
  258. provider_name=provider_name,
  259. provider_type=ProviderType.CUSTOM.value,
  260. is_valid=True
  261. )
  262. db.session.add(provider)
  263. db.session.commit()
  264. elif not provider.is_valid:
  265. provider.is_valid = True
  266. provider.encrypted_config = None
  267. db.session.commit()
  268. model_provider_class = ModelProviderFactory.get_model_provider_class(provider_name)
  269. encrypted_config = model_provider_class.encrypt_model_credentials(
  270. tenant_id,
  271. model_name,
  272. ModelType.value_of(model_type),
  273. config
  274. )
  275. # get provider model
  276. provider_model = db.session.query(ProviderModel) \
  277. .filter(
  278. ProviderModel.tenant_id == tenant_id,
  279. ProviderModel.provider_name == provider_name,
  280. ProviderModel.model_name == model_name,
  281. ProviderModel.model_type == model_type
  282. ).first()
  283. if provider_model:
  284. provider_model.encrypted_config = json.dumps(encrypted_config)
  285. provider_model.is_valid = True
  286. db.session.commit()
  287. else:
  288. provider_model = ProviderModel(
  289. tenant_id=tenant_id,
  290. provider_name=provider_name,
  291. model_name=model_name,
  292. model_type=model_type,
  293. encrypted_config=json.dumps(encrypted_config),
  294. is_valid=True
  295. )
  296. db.session.add(provider_model)
  297. db.session.commit()
  298. def delete_custom_provider_model(self,
  299. tenant_id: str,
  300. provider_name: str,
  301. model_name: str,
  302. model_type: str) -> None:
  303. """
  304. delete custom provider model.
  305. :param tenant_id:
  306. :param provider_name:
  307. :param model_name:
  308. :param model_type:
  309. :return:
  310. """
  311. # get provider model
  312. provider_model = db.session.query(ProviderModel) \
  313. .filter(
  314. ProviderModel.tenant_id == tenant_id,
  315. ProviderModel.provider_name == provider_name,
  316. ProviderModel.model_name == model_name,
  317. ProviderModel.model_type == model_type
  318. ).first()
  319. if provider_model:
  320. db.session.delete(provider_model)
  321. db.session.commit()
  322. def switch_preferred_provider(self, tenant_id: str, provider_name: str, preferred_provider_type: str) -> None:
  323. """
  324. switch preferred provider.
  325. :param tenant_id:
  326. :param provider_name:
  327. :param preferred_provider_type:
  328. :return:
  329. """
  330. provider_type = ProviderType.value_of(preferred_provider_type)
  331. if not provider_type:
  332. raise ValueError(f'Invalid preferred provider type: {preferred_provider_type}')
  333. model_provider_rules = ModelProviderFactory.get_provider_rule(provider_name)
  334. if preferred_provider_type not in model_provider_rules['support_provider_types']:
  335. raise ValueError(f'Not support provider type: {preferred_provider_type}')
  336. model_provider = ModelProviderFactory.get_model_provider_class(provider_name)
  337. if not model_provider.is_provider_type_system_supported():
  338. return
  339. # get preferred provider
  340. preferred_model_provider = db.session.query(TenantPreferredModelProvider) \
  341. .filter(
  342. TenantPreferredModelProvider.tenant_id == tenant_id,
  343. TenantPreferredModelProvider.provider_name == provider_name
  344. ).first()
  345. if preferred_model_provider:
  346. preferred_model_provider.preferred_provider_type = preferred_provider_type
  347. else:
  348. preferred_model_provider = TenantPreferredModelProvider(
  349. tenant_id=tenant_id,
  350. provider_name=provider_name,
  351. preferred_provider_type=preferred_provider_type
  352. )
  353. db.session.add(preferred_model_provider)
  354. db.session.commit()
  355. def get_default_model_of_model_type(self, tenant_id: str, model_type: str) -> Optional[TenantDefaultModel]:
  356. """
  357. get default model of model type.
  358. :param tenant_id:
  359. :param model_type:
  360. :return:
  361. """
  362. return ModelFactory.get_default_model(tenant_id, ModelType.value_of(model_type))
  363. def update_default_model_of_model_type(self,
  364. tenant_id: str,
  365. model_type: str,
  366. provider_name: str,
  367. model_name: str) -> TenantDefaultModel:
  368. """
  369. update default model of model type.
  370. :param tenant_id:
  371. :param model_type:
  372. :param provider_name:
  373. :param model_name:
  374. :return:
  375. """
  376. return ModelFactory.update_default_model(tenant_id, ModelType.value_of(model_type), provider_name, model_name)
  377. def get_valid_model_list(self, tenant_id: str, model_type: str) -> list:
  378. """
  379. get valid model list.
  380. :param tenant_id:
  381. :param model_type:
  382. :return:
  383. """
  384. valid_model_list = []
  385. # get model provider rules
  386. model_provider_rules = ModelProviderFactory.get_provider_rules()
  387. for model_provider_name, model_provider_rule in model_provider_rules.items():
  388. model_provider = ModelProviderFactory.get_preferred_model_provider(tenant_id, model_provider_name)
  389. if not model_provider:
  390. continue
  391. model_list = model_provider.get_supported_model_list(ModelType.value_of(model_type))
  392. provider = model_provider.provider
  393. for model in model_list:
  394. valid_model_dict = {
  395. "model_name": model['id'],
  396. "model_type": model_type,
  397. "model_provider": {
  398. "provider_name": provider.provider_name,
  399. "provider_type": provider.provider_type
  400. },
  401. 'features': []
  402. }
  403. if 'features' in model:
  404. valid_model_dict['features'] = model['features']
  405. if provider.provider_type == ProviderType.SYSTEM.value:
  406. valid_model_dict['model_provider']['quota_type'] = provider.quota_type
  407. valid_model_dict['model_provider']['quota_unit'] = model_provider_rule['system_config']['quota_unit']
  408. valid_model_dict['model_provider']['quota_limit'] = provider.quota_limit
  409. valid_model_dict['model_provider']['quota_used'] = provider.quota_used
  410. valid_model_list.append(valid_model_dict)
  411. return valid_model_list
  412. def get_model_parameter_rules(self, tenant_id: str, model_provider_name: str, model_name: str, model_type: str) \
  413. -> ModelKwargsRules:
  414. """
  415. get model parameter rules.
  416. It depends on preferred provider in use.
  417. :param tenant_id:
  418. :param model_provider_name:
  419. :param model_name:
  420. :param model_type:
  421. :return:
  422. """
  423. # get model provider
  424. model_provider = ModelProviderFactory.get_preferred_model_provider(tenant_id, model_provider_name)
  425. if not model_provider:
  426. # get empty model provider
  427. return ModelKwargsRules()
  428. # get model parameter rules
  429. return model_provider.get_model_parameter_rules(model_name, ModelType.value_of(model_type))