models.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. import logging
  2. from flask_login import current_user
  3. from flask_restful import Resource, reqparse
  4. from werkzeug.exceptions import Forbidden
  5. from controllers.console import api
  6. from controllers.console.setup import setup_required
  7. from controllers.console.wraps import account_initialization_required
  8. from core.model_runtime.entities.model_entities import ModelType
  9. from core.model_runtime.errors.validate import CredentialsValidateFailedError
  10. from core.model_runtime.utils.encoders import jsonable_encoder
  11. from libs.login import login_required
  12. from models.account import TenantAccountRole
  13. from services.model_load_balancing_service import ModelLoadBalancingService
  14. from services.model_provider_service import ModelProviderService
  15. class DefaultModelApi(Resource):
  16. @setup_required
  17. @login_required
  18. @account_initialization_required
  19. def get(self):
  20. parser = reqparse.RequestParser()
  21. parser.add_argument('model_type', type=str, required=True, nullable=False,
  22. choices=[mt.value for mt in ModelType], location='args')
  23. args = parser.parse_args()
  24. tenant_id = current_user.current_tenant_id
  25. model_provider_service = ModelProviderService()
  26. default_model_entity = model_provider_service.get_default_model_of_model_type(
  27. tenant_id=tenant_id,
  28. model_type=args['model_type']
  29. )
  30. return jsonable_encoder({
  31. "data": default_model_entity
  32. })
  33. @setup_required
  34. @login_required
  35. @account_initialization_required
  36. def post(self):
  37. parser = reqparse.RequestParser()
  38. parser.add_argument('model_settings', type=list, required=True, nullable=False, location='json')
  39. args = parser.parse_args()
  40. tenant_id = current_user.current_tenant_id
  41. model_provider_service = ModelProviderService()
  42. model_settings = args['model_settings']
  43. for model_setting in model_settings:
  44. if 'model_type' not in model_setting or model_setting['model_type'] not in [mt.value for mt in ModelType]:
  45. raise ValueError('invalid model type')
  46. if 'provider' not in model_setting:
  47. continue
  48. if 'model' not in model_setting:
  49. raise ValueError('invalid model')
  50. try:
  51. model_provider_service.update_default_model_of_model_type(
  52. tenant_id=tenant_id,
  53. model_type=model_setting['model_type'],
  54. provider=model_setting['provider'],
  55. model=model_setting['model']
  56. )
  57. except Exception:
  58. logging.warning(f"{model_setting['model_type']} save error")
  59. return {'result': 'success'}
  60. class ModelProviderModelApi(Resource):
  61. @setup_required
  62. @login_required
  63. @account_initialization_required
  64. def get(self, provider):
  65. tenant_id = current_user.current_tenant_id
  66. model_provider_service = ModelProviderService()
  67. models = model_provider_service.get_models_by_provider(
  68. tenant_id=tenant_id,
  69. provider=provider
  70. )
  71. return jsonable_encoder({
  72. "data": models
  73. })
  74. @setup_required
  75. @login_required
  76. @account_initialization_required
  77. def post(self, provider: str):
  78. if not TenantAccountRole.is_privileged_role(current_user.current_tenant.current_role):
  79. raise Forbidden()
  80. tenant_id = current_user.current_tenant_id
  81. parser = reqparse.RequestParser()
  82. parser.add_argument('model', type=str, required=True, nullable=False, location='json')
  83. parser.add_argument('model_type', type=str, required=True, nullable=False,
  84. choices=[mt.value for mt in ModelType], location='json')
  85. parser.add_argument('credentials', type=dict, required=False, nullable=True, location='json')
  86. parser.add_argument('load_balancing', type=dict, required=False, nullable=True, location='json')
  87. parser.add_argument('config_from', type=str, required=False, nullable=True, location='json')
  88. args = parser.parse_args()
  89. model_load_balancing_service = ModelLoadBalancingService()
  90. if ('load_balancing' in args and args['load_balancing'] and
  91. 'enabled' in args['load_balancing'] and args['load_balancing']['enabled']):
  92. if 'configs' not in args['load_balancing']:
  93. raise ValueError('invalid load balancing configs')
  94. # save load balancing configs
  95. model_load_balancing_service.update_load_balancing_configs(
  96. tenant_id=tenant_id,
  97. provider=provider,
  98. model=args['model'],
  99. model_type=args['model_type'],
  100. configs=args['load_balancing']['configs']
  101. )
  102. # enable load balancing
  103. model_load_balancing_service.enable_model_load_balancing(
  104. tenant_id=tenant_id,
  105. provider=provider,
  106. model=args['model'],
  107. model_type=args['model_type']
  108. )
  109. else:
  110. # disable load balancing
  111. model_load_balancing_service.disable_model_load_balancing(
  112. tenant_id=tenant_id,
  113. provider=provider,
  114. model=args['model'],
  115. model_type=args['model_type']
  116. )
  117. if args.get('config_from', '') != 'predefined-model':
  118. model_provider_service = ModelProviderService()
  119. try:
  120. model_provider_service.save_model_credentials(
  121. tenant_id=tenant_id,
  122. provider=provider,
  123. model=args['model'],
  124. model_type=args['model_type'],
  125. credentials=args['credentials']
  126. )
  127. except CredentialsValidateFailedError as ex:
  128. raise ValueError(str(ex))
  129. return {'result': 'success'}, 200
  130. @setup_required
  131. @login_required
  132. @account_initialization_required
  133. def delete(self, provider: str):
  134. if not TenantAccountRole.is_privileged_role(current_user.current_tenant.current_role):
  135. raise Forbidden()
  136. tenant_id = current_user.current_tenant_id
  137. parser = reqparse.RequestParser()
  138. parser.add_argument('model', type=str, required=True, nullable=False, location='json')
  139. parser.add_argument('model_type', type=str, required=True, nullable=False,
  140. choices=[mt.value for mt in ModelType], location='json')
  141. args = parser.parse_args()
  142. model_provider_service = ModelProviderService()
  143. model_provider_service.remove_model_credentials(
  144. tenant_id=tenant_id,
  145. provider=provider,
  146. model=args['model'],
  147. model_type=args['model_type']
  148. )
  149. return {'result': 'success'}, 204
  150. class ModelProviderModelCredentialApi(Resource):
  151. @setup_required
  152. @login_required
  153. @account_initialization_required
  154. def get(self, provider: str):
  155. tenant_id = current_user.current_tenant_id
  156. parser = reqparse.RequestParser()
  157. parser.add_argument('model', type=str, required=True, nullable=False, location='args')
  158. parser.add_argument('model_type', type=str, required=True, nullable=False,
  159. choices=[mt.value for mt in ModelType], location='args')
  160. args = parser.parse_args()
  161. model_provider_service = ModelProviderService()
  162. credentials = model_provider_service.get_model_credentials(
  163. tenant_id=tenant_id,
  164. provider=provider,
  165. model_type=args['model_type'],
  166. model=args['model']
  167. )
  168. model_load_balancing_service = ModelLoadBalancingService()
  169. is_load_balancing_enabled, load_balancing_configs = model_load_balancing_service.get_load_balancing_configs(
  170. tenant_id=tenant_id,
  171. provider=provider,
  172. model=args['model'],
  173. model_type=args['model_type']
  174. )
  175. return {
  176. "credentials": credentials,
  177. "load_balancing": {
  178. "enabled": is_load_balancing_enabled,
  179. "configs": load_balancing_configs
  180. }
  181. }
  182. class ModelProviderModelEnableApi(Resource):
  183. @setup_required
  184. @login_required
  185. @account_initialization_required
  186. def patch(self, provider: str):
  187. tenant_id = current_user.current_tenant_id
  188. parser = reqparse.RequestParser()
  189. parser.add_argument('model', type=str, required=True, nullable=False, location='json')
  190. parser.add_argument('model_type', type=str, required=True, nullable=False,
  191. choices=[mt.value for mt in ModelType], location='json')
  192. args = parser.parse_args()
  193. model_provider_service = ModelProviderService()
  194. model_provider_service.enable_model(
  195. tenant_id=tenant_id,
  196. provider=provider,
  197. model=args['model'],
  198. model_type=args['model_type']
  199. )
  200. return {'result': 'success'}
  201. class ModelProviderModelDisableApi(Resource):
  202. @setup_required
  203. @login_required
  204. @account_initialization_required
  205. def patch(self, provider: str):
  206. tenant_id = current_user.current_tenant_id
  207. parser = reqparse.RequestParser()
  208. parser.add_argument('model', type=str, required=True, nullable=False, location='json')
  209. parser.add_argument('model_type', type=str, required=True, nullable=False,
  210. choices=[mt.value for mt in ModelType], location='json')
  211. args = parser.parse_args()
  212. model_provider_service = ModelProviderService()
  213. model_provider_service.disable_model(
  214. tenant_id=tenant_id,
  215. provider=provider,
  216. model=args['model'],
  217. model_type=args['model_type']
  218. )
  219. return {'result': 'success'}
  220. class ModelProviderModelValidateApi(Resource):
  221. @setup_required
  222. @login_required
  223. @account_initialization_required
  224. def post(self, provider: str):
  225. tenant_id = current_user.current_tenant_id
  226. parser = reqparse.RequestParser()
  227. parser.add_argument('model', type=str, required=True, nullable=False, location='json')
  228. parser.add_argument('model_type', type=str, required=True, nullable=False,
  229. choices=[mt.value for mt in ModelType], location='json')
  230. parser.add_argument('credentials', type=dict, required=True, nullable=False, location='json')
  231. args = parser.parse_args()
  232. model_provider_service = ModelProviderService()
  233. result = True
  234. error = None
  235. try:
  236. model_provider_service.model_credentials_validate(
  237. tenant_id=tenant_id,
  238. provider=provider,
  239. model=args['model'],
  240. model_type=args['model_type'],
  241. credentials=args['credentials']
  242. )
  243. except CredentialsValidateFailedError as ex:
  244. result = False
  245. error = str(ex)
  246. response = {'result': 'success' if result else 'error'}
  247. if not result:
  248. response['error'] = error
  249. return response
  250. class ModelProviderModelParameterRuleApi(Resource):
  251. @setup_required
  252. @login_required
  253. @account_initialization_required
  254. def get(self, provider: str):
  255. parser = reqparse.RequestParser()
  256. parser.add_argument('model', type=str, required=True, nullable=False, location='args')
  257. args = parser.parse_args()
  258. tenant_id = current_user.current_tenant_id
  259. model_provider_service = ModelProviderService()
  260. parameter_rules = model_provider_service.get_model_parameter_rules(
  261. tenant_id=tenant_id,
  262. provider=provider,
  263. model=args['model']
  264. )
  265. return jsonable_encoder({
  266. "data": parameter_rules
  267. })
  268. class ModelProviderAvailableModelApi(Resource):
  269. @setup_required
  270. @login_required
  271. @account_initialization_required
  272. def get(self, model_type):
  273. tenant_id = current_user.current_tenant_id
  274. model_provider_service = ModelProviderService()
  275. models = model_provider_service.get_models_by_model_type(
  276. tenant_id=tenant_id,
  277. model_type=model_type
  278. )
  279. return jsonable_encoder({
  280. "data": models
  281. })
  282. api.add_resource(ModelProviderModelApi, '/workspaces/current/model-providers/<string:provider>/models')
  283. api.add_resource(ModelProviderModelEnableApi, '/workspaces/current/model-providers/<string:provider>/models/enable',
  284. endpoint='model-provider-model-enable')
  285. api.add_resource(ModelProviderModelDisableApi, '/workspaces/current/model-providers/<string:provider>/models/disable',
  286. endpoint='model-provider-model-disable')
  287. api.add_resource(ModelProviderModelCredentialApi,
  288. '/workspaces/current/model-providers/<string:provider>/models/credentials')
  289. api.add_resource(ModelProviderModelValidateApi,
  290. '/workspaces/current/model-providers/<string:provider>/models/credentials/validate')
  291. api.add_resource(ModelProviderModelParameterRuleApi,
  292. '/workspaces/current/model-providers/<string:provider>/models/parameter-rules')
  293. api.add_resource(ModelProviderAvailableModelApi, '/workspaces/current/models/model-types/<string:model_type>')
  294. api.add_resource(DefaultModelApi, '/workspaces/current/default-model')