provider_service.py 22 KB

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