models.py 13 KB

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