Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

model_load_balancing_service.py 25KB

Introduce Plugins (#13836) Signed-off-by: yihong0618 <zouzou0208@gmail.com> Signed-off-by: -LAN- <laipz8200@outlook.com> Signed-off-by: xhe <xw897002528@gmail.com> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: takatost <takatost@gmail.com> Co-authored-by: kurokobo <kuro664@gmail.com> Co-authored-by: Novice Lee <novicelee@NoviPro.local> Co-authored-by: zxhlyh <jasonapring2015@outlook.com> Co-authored-by: AkaraChen <akarachen@outlook.com> Co-authored-by: Yi <yxiaoisme@gmail.com> Co-authored-by: Joel <iamjoel007@gmail.com> Co-authored-by: JzoNg <jzongcode@gmail.com> Co-authored-by: twwu <twwu@dify.ai> Co-authored-by: Hiroshi Fujita <fujita-h@users.noreply.github.com> Co-authored-by: AkaraChen <85140972+AkaraChen@users.noreply.github.com> Co-authored-by: NFish <douxc512@gmail.com> Co-authored-by: Wu Tianwei <30284043+WTW0313@users.noreply.github.com> Co-authored-by: 非法操作 <hjlarry@163.com> Co-authored-by: Novice <857526207@qq.com> Co-authored-by: Hiroki Nagai <82458324+nagaihiroki-git@users.noreply.github.com> Co-authored-by: Gen Sato <52241300+halogen22@users.noreply.github.com> Co-authored-by: eux <euxuuu@gmail.com> Co-authored-by: huangzhuo1949 <167434202+huangzhuo1949@users.noreply.github.com> Co-authored-by: huangzhuo <huangzhuo1@xiaomi.com> Co-authored-by: lotsik <lotsik@mail.ru> Co-authored-by: crazywoola <100913391+crazywoola@users.noreply.github.com> Co-authored-by: nite-knite <nkCoding@gmail.com> Co-authored-by: Jyong <76649700+JohnJyong@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: gakkiyomi <gakkiyomi@aliyun.com> Co-authored-by: CN-P5 <heibai2006@gmail.com> Co-authored-by: CN-P5 <heibai2006@qq.com> Co-authored-by: Chuehnone <1897025+chuehnone@users.noreply.github.com> Co-authored-by: yihong <zouzou0208@gmail.com> Co-authored-by: Kevin9703 <51311316+Kevin9703@users.noreply.github.com> Co-authored-by: -LAN- <laipz8200@outlook.com> Co-authored-by: Boris Feld <lothiraldan@gmail.com> Co-authored-by: mbo <himabo@gmail.com> Co-authored-by: mabo <mabo@aeyes.ai> Co-authored-by: Warren Chen <warren.chen830@gmail.com> Co-authored-by: JzoNgKVO <27049666+JzoNgKVO@users.noreply.github.com> Co-authored-by: jiandanfeng <chenjh3@wangsu.com> Co-authored-by: zhu-an <70234959+xhdd123321@users.noreply.github.com> Co-authored-by: zhaoqingyu.1075 <zhaoqingyu.1075@bytedance.com> Co-authored-by: 海狸大師 <86974027+yenslife@users.noreply.github.com> Co-authored-by: Xu Song <xusong.vip@gmail.com> Co-authored-by: rayshaw001 <396301947@163.com> Co-authored-by: Ding Jiatong <dingjiatong@gmail.com> Co-authored-by: Bowen Liang <liangbowen@gf.com.cn> Co-authored-by: JasonVV <jasonwangiii@outlook.com> Co-authored-by: le0zh <newlight@qq.com> Co-authored-by: zhuxinliang <zhuxinliang@didiglobal.com> Co-authored-by: k-zaku <zaku99@outlook.jp> Co-authored-by: luckylhb90 <luckylhb90@gmail.com> Co-authored-by: hobo.l <hobo.l@binance.com> Co-authored-by: jiangbo721 <365065261@qq.com> Co-authored-by: 刘江波 <jiangbo721@163.com> Co-authored-by: Shun Miyazawa <34241526+miya@users.noreply.github.com> Co-authored-by: EricPan <30651140+Egfly@users.noreply.github.com> Co-authored-by: crazywoola <427733928@qq.com> Co-authored-by: sino <sino2322@gmail.com> Co-authored-by: Jhvcc <37662342+Jhvcc@users.noreply.github.com> Co-authored-by: lowell <lowell.hu@zkteco.in> Co-authored-by: Boris Polonsky <BorisPolonsky@users.noreply.github.com> Co-authored-by: Ademílson Tonato <ademilsonft@outlook.com> Co-authored-by: Ademílson Tonato <ademilson.tonato@refurbed.com> Co-authored-by: IWAI, Masaharu <iwaim.sub@gmail.com> Co-authored-by: Yueh-Po Peng (Yabi) <94939112+y10ab1@users.noreply.github.com> Co-authored-by: Jason <ggbbddjm@gmail.com> Co-authored-by: Xin Zhang <sjhpzx@gmail.com> Co-authored-by: yjc980121 <3898524+yjc980121@users.noreply.github.com> Co-authored-by: heyszt <36215648+hieheihei@users.noreply.github.com> Co-authored-by: Abdullah AlOsaimi <osaimiacc@gmail.com> Co-authored-by: Abdullah AlOsaimi <189027247+osaimi@users.noreply.github.com> Co-authored-by: Yingchun Lai <laiyingchun@apache.org> Co-authored-by: Hash Brown <hi@xzd.me> Co-authored-by: zuodongxu <192560071+zuodongxu@users.noreply.github.com> Co-authored-by: Masashi Tomooka <tmokmss@users.noreply.github.com> Co-authored-by: aplio <ryo.091219@gmail.com> Co-authored-by: Obada Khalili <54270856+obadakhalili@users.noreply.github.com> Co-authored-by: Nam Vu <zuzoovn@gmail.com> Co-authored-by: Kei YAMAZAKI <1715090+kei-yamazaki@users.noreply.github.com> Co-authored-by: TechnoHouse <13776377+deephbz@users.noreply.github.com> Co-authored-by: Riddhimaan-Senapati <114703025+Riddhimaan-Senapati@users.noreply.github.com> Co-authored-by: MaFee921 <31881301+2284730142@users.noreply.github.com> Co-authored-by: te-chan <t-nakanome@sakura-is.co.jp> Co-authored-by: HQidea <HQidea@users.noreply.github.com> Co-authored-by: Joshbly <36315710+Joshbly@users.noreply.github.com> Co-authored-by: xhe <xw897002528@gmail.com> Co-authored-by: weiwenyan-dev <154779315+weiwenyan-dev@users.noreply.github.com> Co-authored-by: ex_wenyan.wei <ex_wenyan.wei@tcl.com> Co-authored-by: engchina <12236799+engchina@users.noreply.github.com> Co-authored-by: engchina <atjapan2015@gmail.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: 呆萌闷油瓶 <253605712@qq.com> Co-authored-by: Kemal <kemalmeler@outlook.com> Co-authored-by: Lazy_Frog <4590648+lazyFrogLOL@users.noreply.github.com> Co-authored-by: Yi Xiao <54782454+YIXIAO0@users.noreply.github.com> Co-authored-by: Steven sun <98230804+Tuyohai@users.noreply.github.com> Co-authored-by: steven <sunzwj@digitalchina.com> Co-authored-by: Kalo Chin <91766386+fdb02983rhy@users.noreply.github.com> Co-authored-by: Katy Tao <34019945+KatyTao@users.noreply.github.com> Co-authored-by: depy <42985524+h4ckdepy@users.noreply.github.com> Co-authored-by: 胡春东 <gycm520@gmail.com> Co-authored-by: Junjie.M <118170653@qq.com> Co-authored-by: MuYu <mr.muzea@gmail.com> Co-authored-by: Naoki Takashima <39912547+takatea@users.noreply.github.com> Co-authored-by: Summer-Gu <37869445+gubinjie@users.noreply.github.com> Co-authored-by: Fei He <droxer.he@gmail.com> Co-authored-by: ybalbert001 <120714773+ybalbert001@users.noreply.github.com> Co-authored-by: Yuanbo Li <ybalbert@amazon.com> Co-authored-by: douxc <7553076+douxc@users.noreply.github.com> Co-authored-by: liuzhenghua <1090179900@qq.com> Co-authored-by: Wu Jiayang <62842862+Wu-Jiayang@users.noreply.github.com> Co-authored-by: Your Name <you@example.com> Co-authored-by: kimjion <45935338+kimjion@users.noreply.github.com> Co-authored-by: AugNSo <song.tiankai@icloud.com> Co-authored-by: llinvokerl <38915183+llinvokerl@users.noreply.github.com> Co-authored-by: liusurong.lsr <liusurong.lsr@alibaba-inc.com> Co-authored-by: Vasu Negi <vasu-negi@users.noreply.github.com> Co-authored-by: Hundredwz <1808096180@qq.com> Co-authored-by: Xiyuan Chen <52963600+GareArc@users.noreply.github.com>
8 месяцев назад
10 месяцев назад
10 месяцев назад
10 месяцев назад
10 месяцев назад
10 месяцев назад
10 месяцев назад
10 месяцев назад
10 месяцев назад
10 месяцев назад
10 месяцев назад
10 месяцев назад
10 месяцев назад
10 месяцев назад
Introduce Plugins (#13836) Signed-off-by: yihong0618 <zouzou0208@gmail.com> Signed-off-by: -LAN- <laipz8200@outlook.com> Signed-off-by: xhe <xw897002528@gmail.com> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: takatost <takatost@gmail.com> Co-authored-by: kurokobo <kuro664@gmail.com> Co-authored-by: Novice Lee <novicelee@NoviPro.local> Co-authored-by: zxhlyh <jasonapring2015@outlook.com> Co-authored-by: AkaraChen <akarachen@outlook.com> Co-authored-by: Yi <yxiaoisme@gmail.com> Co-authored-by: Joel <iamjoel007@gmail.com> Co-authored-by: JzoNg <jzongcode@gmail.com> Co-authored-by: twwu <twwu@dify.ai> Co-authored-by: Hiroshi Fujita <fujita-h@users.noreply.github.com> Co-authored-by: AkaraChen <85140972+AkaraChen@users.noreply.github.com> Co-authored-by: NFish <douxc512@gmail.com> Co-authored-by: Wu Tianwei <30284043+WTW0313@users.noreply.github.com> Co-authored-by: 非法操作 <hjlarry@163.com> Co-authored-by: Novice <857526207@qq.com> Co-authored-by: Hiroki Nagai <82458324+nagaihiroki-git@users.noreply.github.com> Co-authored-by: Gen Sato <52241300+halogen22@users.noreply.github.com> Co-authored-by: eux <euxuuu@gmail.com> Co-authored-by: huangzhuo1949 <167434202+huangzhuo1949@users.noreply.github.com> Co-authored-by: huangzhuo <huangzhuo1@xiaomi.com> Co-authored-by: lotsik <lotsik@mail.ru> Co-authored-by: crazywoola <100913391+crazywoola@users.noreply.github.com> Co-authored-by: nite-knite <nkCoding@gmail.com> Co-authored-by: Jyong <76649700+JohnJyong@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: gakkiyomi <gakkiyomi@aliyun.com> Co-authored-by: CN-P5 <heibai2006@gmail.com> Co-authored-by: CN-P5 <heibai2006@qq.com> Co-authored-by: Chuehnone <1897025+chuehnone@users.noreply.github.com> Co-authored-by: yihong <zouzou0208@gmail.com> Co-authored-by: Kevin9703 <51311316+Kevin9703@users.noreply.github.com> Co-authored-by: -LAN- <laipz8200@outlook.com> Co-authored-by: Boris Feld <lothiraldan@gmail.com> Co-authored-by: mbo <himabo@gmail.com> Co-authored-by: mabo <mabo@aeyes.ai> Co-authored-by: Warren Chen <warren.chen830@gmail.com> Co-authored-by: JzoNgKVO <27049666+JzoNgKVO@users.noreply.github.com> Co-authored-by: jiandanfeng <chenjh3@wangsu.com> Co-authored-by: zhu-an <70234959+xhdd123321@users.noreply.github.com> Co-authored-by: zhaoqingyu.1075 <zhaoqingyu.1075@bytedance.com> Co-authored-by: 海狸大師 <86974027+yenslife@users.noreply.github.com> Co-authored-by: Xu Song <xusong.vip@gmail.com> Co-authored-by: rayshaw001 <396301947@163.com> Co-authored-by: Ding Jiatong <dingjiatong@gmail.com> Co-authored-by: Bowen Liang <liangbowen@gf.com.cn> Co-authored-by: JasonVV <jasonwangiii@outlook.com> Co-authored-by: le0zh <newlight@qq.com> Co-authored-by: zhuxinliang <zhuxinliang@didiglobal.com> Co-authored-by: k-zaku <zaku99@outlook.jp> Co-authored-by: luckylhb90 <luckylhb90@gmail.com> Co-authored-by: hobo.l <hobo.l@binance.com> Co-authored-by: jiangbo721 <365065261@qq.com> Co-authored-by: 刘江波 <jiangbo721@163.com> Co-authored-by: Shun Miyazawa <34241526+miya@users.noreply.github.com> Co-authored-by: EricPan <30651140+Egfly@users.noreply.github.com> Co-authored-by: crazywoola <427733928@qq.com> Co-authored-by: sino <sino2322@gmail.com> Co-authored-by: Jhvcc <37662342+Jhvcc@users.noreply.github.com> Co-authored-by: lowell <lowell.hu@zkteco.in> Co-authored-by: Boris Polonsky <BorisPolonsky@users.noreply.github.com> Co-authored-by: Ademílson Tonato <ademilsonft@outlook.com> Co-authored-by: Ademílson Tonato <ademilson.tonato@refurbed.com> Co-authored-by: IWAI, Masaharu <iwaim.sub@gmail.com> Co-authored-by: Yueh-Po Peng (Yabi) <94939112+y10ab1@users.noreply.github.com> Co-authored-by: Jason <ggbbddjm@gmail.com> Co-authored-by: Xin Zhang <sjhpzx@gmail.com> Co-authored-by: yjc980121 <3898524+yjc980121@users.noreply.github.com> Co-authored-by: heyszt <36215648+hieheihei@users.noreply.github.com> Co-authored-by: Abdullah AlOsaimi <osaimiacc@gmail.com> Co-authored-by: Abdullah AlOsaimi <189027247+osaimi@users.noreply.github.com> Co-authored-by: Yingchun Lai <laiyingchun@apache.org> Co-authored-by: Hash Brown <hi@xzd.me> Co-authored-by: zuodongxu <192560071+zuodongxu@users.noreply.github.com> Co-authored-by: Masashi Tomooka <tmokmss@users.noreply.github.com> Co-authored-by: aplio <ryo.091219@gmail.com> Co-authored-by: Obada Khalili <54270856+obadakhalili@users.noreply.github.com> Co-authored-by: Nam Vu <zuzoovn@gmail.com> Co-authored-by: Kei YAMAZAKI <1715090+kei-yamazaki@users.noreply.github.com> Co-authored-by: TechnoHouse <13776377+deephbz@users.noreply.github.com> Co-authored-by: Riddhimaan-Senapati <114703025+Riddhimaan-Senapati@users.noreply.github.com> Co-authored-by: MaFee921 <31881301+2284730142@users.noreply.github.com> Co-authored-by: te-chan <t-nakanome@sakura-is.co.jp> Co-authored-by: HQidea <HQidea@users.noreply.github.com> Co-authored-by: Joshbly <36315710+Joshbly@users.noreply.github.com> Co-authored-by: xhe <xw897002528@gmail.com> Co-authored-by: weiwenyan-dev <154779315+weiwenyan-dev@users.noreply.github.com> Co-authored-by: ex_wenyan.wei <ex_wenyan.wei@tcl.com> Co-authored-by: engchina <12236799+engchina@users.noreply.github.com> Co-authored-by: engchina <atjapan2015@gmail.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: 呆萌闷油瓶 <253605712@qq.com> Co-authored-by: Kemal <kemalmeler@outlook.com> Co-authored-by: Lazy_Frog <4590648+lazyFrogLOL@users.noreply.github.com> Co-authored-by: Yi Xiao <54782454+YIXIAO0@users.noreply.github.com> Co-authored-by: Steven sun <98230804+Tuyohai@users.noreply.github.com> Co-authored-by: steven <sunzwj@digitalchina.com> Co-authored-by: Kalo Chin <91766386+fdb02983rhy@users.noreply.github.com> Co-authored-by: Katy Tao <34019945+KatyTao@users.noreply.github.com> Co-authored-by: depy <42985524+h4ckdepy@users.noreply.github.com> Co-authored-by: 胡春东 <gycm520@gmail.com> Co-authored-by: Junjie.M <118170653@qq.com> Co-authored-by: MuYu <mr.muzea@gmail.com> Co-authored-by: Naoki Takashima <39912547+takatea@users.noreply.github.com> Co-authored-by: Summer-Gu <37869445+gubinjie@users.noreply.github.com> Co-authored-by: Fei He <droxer.he@gmail.com> Co-authored-by: ybalbert001 <120714773+ybalbert001@users.noreply.github.com> Co-authored-by: Yuanbo Li <ybalbert@amazon.com> Co-authored-by: douxc <7553076+douxc@users.noreply.github.com> Co-authored-by: liuzhenghua <1090179900@qq.com> Co-authored-by: Wu Jiayang <62842862+Wu-Jiayang@users.noreply.github.com> Co-authored-by: Your Name <you@example.com> Co-authored-by: kimjion <45935338+kimjion@users.noreply.github.com> Co-authored-by: AugNSo <song.tiankai@icloud.com> Co-authored-by: llinvokerl <38915183+llinvokerl@users.noreply.github.com> Co-authored-by: liusurong.lsr <liusurong.lsr@alibaba-inc.com> Co-authored-by: Vasu Negi <vasu-negi@users.noreply.github.com> Co-authored-by: Hundredwz <1808096180@qq.com> Co-authored-by: Xiyuan Chen <52963600+GareArc@users.noreply.github.com>
8 месяцев назад
10 месяцев назад
10 месяцев назад
10 месяцев назад
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620
  1. import json
  2. import logging
  3. from json import JSONDecodeError
  4. from typing import Union
  5. from sqlalchemy import or_, select
  6. from constants import HIDDEN_VALUE
  7. from core.entities.provider_configuration import ProviderConfiguration
  8. from core.helper import encrypter
  9. from core.helper.model_provider_cache import ProviderCredentialsCache, ProviderCredentialsCacheType
  10. from core.model_manager import LBModelManager
  11. from core.model_runtime.entities.model_entities import ModelType
  12. from core.model_runtime.entities.provider_entities import (
  13. ModelCredentialSchema,
  14. ProviderCredentialSchema,
  15. )
  16. from core.model_runtime.model_providers.model_provider_factory import ModelProviderFactory
  17. from core.provider_manager import ProviderManager
  18. from extensions.ext_database import db
  19. from libs.datetime_utils import naive_utc_now
  20. from models.provider import LoadBalancingModelConfig, ProviderCredential, ProviderModelCredential
  21. logger = logging.getLogger(__name__)
  22. class ModelLoadBalancingService:
  23. def __init__(self):
  24. self.provider_manager = ProviderManager()
  25. def enable_model_load_balancing(self, tenant_id: str, provider: str, model: str, model_type: str):
  26. """
  27. enable model load balancing.
  28. :param tenant_id: workspace id
  29. :param provider: provider name
  30. :param model: model name
  31. :param model_type: model type
  32. :return:
  33. """
  34. # Get all provider configurations of the current workspace
  35. provider_configurations = self.provider_manager.get_configurations(tenant_id)
  36. # Get provider configuration
  37. provider_configuration = provider_configurations.get(provider)
  38. if not provider_configuration:
  39. raise ValueError(f"Provider {provider} does not exist.")
  40. # Enable model load balancing
  41. provider_configuration.enable_model_load_balancing(model=model, model_type=ModelType.value_of(model_type))
  42. def disable_model_load_balancing(self, tenant_id: str, provider: str, model: str, model_type: str):
  43. """
  44. disable model load balancing.
  45. :param tenant_id: workspace id
  46. :param provider: provider name
  47. :param model: model name
  48. :param model_type: model type
  49. :return:
  50. """
  51. # Get all provider configurations of the current workspace
  52. provider_configurations = self.provider_manager.get_configurations(tenant_id)
  53. # Get provider configuration
  54. provider_configuration = provider_configurations.get(provider)
  55. if not provider_configuration:
  56. raise ValueError(f"Provider {provider} does not exist.")
  57. # disable model load balancing
  58. provider_configuration.disable_model_load_balancing(model=model, model_type=ModelType.value_of(model_type))
  59. def get_load_balancing_configs(
  60. self, tenant_id: str, provider: str, model: str, model_type: str, config_from: str = ""
  61. ) -> tuple[bool, list[dict]]:
  62. """
  63. Get load balancing configurations.
  64. :param tenant_id: workspace id
  65. :param provider: provider name
  66. :param model: model name
  67. :param model_type: model type
  68. :return:
  69. """
  70. # Get all provider configurations of the current workspace
  71. provider_configurations = self.provider_manager.get_configurations(tenant_id)
  72. # Get provider configuration
  73. provider_configuration = provider_configurations.get(provider)
  74. if not provider_configuration:
  75. raise ValueError(f"Provider {provider} does not exist.")
  76. # Convert model type to ModelType
  77. model_type_enum = ModelType.value_of(model_type)
  78. # Get provider model setting
  79. provider_model_setting = provider_configuration.get_provider_model_setting(
  80. model_type=model_type_enum,
  81. model=model,
  82. )
  83. is_load_balancing_enabled = False
  84. if provider_model_setting and provider_model_setting.load_balancing_enabled:
  85. is_load_balancing_enabled = True
  86. if config_from == "predefined-model":
  87. credential_source_type = "provider"
  88. else:
  89. credential_source_type = "custom_model"
  90. # Get load balancing configurations
  91. load_balancing_configs = (
  92. db.session.query(LoadBalancingModelConfig)
  93. .where(
  94. LoadBalancingModelConfig.tenant_id == tenant_id,
  95. LoadBalancingModelConfig.provider_name == provider_configuration.provider.provider,
  96. LoadBalancingModelConfig.model_type == model_type_enum.to_origin_model_type(),
  97. LoadBalancingModelConfig.model_name == model,
  98. or_(
  99. LoadBalancingModelConfig.credential_source_type == credential_source_type,
  100. LoadBalancingModelConfig.credential_source_type.is_(None),
  101. ),
  102. )
  103. .order_by(LoadBalancingModelConfig.created_at)
  104. .all()
  105. )
  106. if provider_configuration.custom_configuration.provider:
  107. # check if the inherit configuration exists,
  108. # inherit is represented for the provider or model custom credentials
  109. inherit_config_exists = False
  110. for load_balancing_config in load_balancing_configs:
  111. if load_balancing_config.name == "__inherit__":
  112. inherit_config_exists = True
  113. break
  114. if not inherit_config_exists:
  115. # Initialize the inherit configuration
  116. inherit_config = self._init_inherit_config(tenant_id, provider, model, model_type_enum)
  117. # prepend the inherit configuration
  118. load_balancing_configs.insert(0, inherit_config)
  119. else:
  120. # move the inherit configuration to the first
  121. for i, load_balancing_config in enumerate(load_balancing_configs[:]):
  122. if load_balancing_config.name == "__inherit__":
  123. inherit_config = load_balancing_configs.pop(i)
  124. load_balancing_configs.insert(0, inherit_config)
  125. # Get credential form schemas from model credential schema or provider credential schema
  126. credential_schemas = self._get_credential_schema(provider_configuration)
  127. # Get decoding rsa key and cipher for decrypting credentials
  128. decoding_rsa_key, decoding_cipher_rsa = encrypter.get_decrypt_decoding(tenant_id)
  129. # fetch status and ttl for each config
  130. datas = []
  131. for load_balancing_config in load_balancing_configs:
  132. in_cooldown, ttl = LBModelManager.get_config_in_cooldown_and_ttl(
  133. tenant_id=tenant_id,
  134. provider=provider,
  135. model=model,
  136. model_type=model_type_enum,
  137. config_id=load_balancing_config.id,
  138. )
  139. try:
  140. if load_balancing_config.encrypted_config:
  141. credentials: dict[str, object] = json.loads(load_balancing_config.encrypted_config)
  142. else:
  143. credentials = {}
  144. except JSONDecodeError:
  145. credentials = {}
  146. # Get provider credential secret variables
  147. credential_secret_variables = provider_configuration.extract_secret_variables(
  148. credential_schemas.credential_form_schemas
  149. )
  150. # decrypt credentials
  151. for variable in credential_secret_variables:
  152. if variable in credentials:
  153. try:
  154. token_value = credentials.get(variable)
  155. if isinstance(token_value, str):
  156. credentials[variable] = encrypter.decrypt_token_with_decoding(
  157. token_value,
  158. decoding_rsa_key,
  159. decoding_cipher_rsa,
  160. )
  161. except ValueError:
  162. pass
  163. # Obfuscate credentials
  164. credentials = provider_configuration.obfuscated_credentials(
  165. credentials=credentials, credential_form_schemas=credential_schemas.credential_form_schemas
  166. )
  167. datas.append(
  168. {
  169. "id": load_balancing_config.id,
  170. "name": load_balancing_config.name,
  171. "credentials": credentials,
  172. "credential_id": load_balancing_config.credential_id,
  173. "enabled": load_balancing_config.enabled,
  174. "in_cooldown": in_cooldown,
  175. "ttl": ttl,
  176. }
  177. )
  178. return is_load_balancing_enabled, datas
  179. def get_load_balancing_config(
  180. self, tenant_id: str, provider: str, model: str, model_type: str, config_id: str
  181. ) -> dict | None:
  182. """
  183. Get load balancing configuration.
  184. :param tenant_id: workspace id
  185. :param provider: provider name
  186. :param model: model name
  187. :param model_type: model type
  188. :param config_id: load balancing config id
  189. :return:
  190. """
  191. # Get all provider configurations of the current workspace
  192. provider_configurations = self.provider_manager.get_configurations(tenant_id)
  193. # Get provider configuration
  194. provider_configuration = provider_configurations.get(provider)
  195. if not provider_configuration:
  196. raise ValueError(f"Provider {provider} does not exist.")
  197. # Convert model type to ModelType
  198. model_type_enum = ModelType.value_of(model_type)
  199. # Get load balancing configurations
  200. load_balancing_model_config = (
  201. db.session.query(LoadBalancingModelConfig)
  202. .where(
  203. LoadBalancingModelConfig.tenant_id == tenant_id,
  204. LoadBalancingModelConfig.provider_name == provider_configuration.provider.provider,
  205. LoadBalancingModelConfig.model_type == model_type_enum.to_origin_model_type(),
  206. LoadBalancingModelConfig.model_name == model,
  207. LoadBalancingModelConfig.id == config_id,
  208. )
  209. .first()
  210. )
  211. if not load_balancing_model_config:
  212. return None
  213. try:
  214. if load_balancing_model_config.encrypted_config:
  215. credentials = json.loads(load_balancing_model_config.encrypted_config)
  216. else:
  217. credentials = {}
  218. except JSONDecodeError:
  219. credentials = {}
  220. # Get credential form schemas from model credential schema or provider credential schema
  221. credential_schemas = self._get_credential_schema(provider_configuration)
  222. # Obfuscate credentials
  223. credentials = provider_configuration.obfuscated_credentials(
  224. credentials=credentials, credential_form_schemas=credential_schemas.credential_form_schemas
  225. )
  226. return {
  227. "id": load_balancing_model_config.id,
  228. "name": load_balancing_model_config.name,
  229. "credentials": credentials,
  230. "enabled": load_balancing_model_config.enabled,
  231. }
  232. def _init_inherit_config(
  233. self, tenant_id: str, provider: str, model: str, model_type: ModelType
  234. ) -> LoadBalancingModelConfig:
  235. """
  236. Initialize the inherit configuration.
  237. :param tenant_id: workspace id
  238. :param provider: provider name
  239. :param model: model name
  240. :param model_type: model type
  241. :return:
  242. """
  243. # Initialize the inherit configuration
  244. inherit_config = LoadBalancingModelConfig(
  245. tenant_id=tenant_id,
  246. provider_name=provider,
  247. model_type=model_type.to_origin_model_type(),
  248. model_name=model,
  249. name="__inherit__",
  250. )
  251. db.session.add(inherit_config)
  252. db.session.commit()
  253. return inherit_config
  254. def update_load_balancing_configs(
  255. self, tenant_id: str, provider: str, model: str, model_type: str, configs: list[dict], config_from: str
  256. ):
  257. """
  258. Update load balancing configurations.
  259. :param tenant_id: workspace id
  260. :param provider: provider name
  261. :param model: model name
  262. :param model_type: model type
  263. :param configs: load balancing configs
  264. :param config_from: predefined-model or custom-model
  265. :return:
  266. """
  267. # Get all provider configurations of the current workspace
  268. provider_configurations = self.provider_manager.get_configurations(tenant_id)
  269. # Get provider configuration
  270. provider_configuration = provider_configurations.get(provider)
  271. if not provider_configuration:
  272. raise ValueError(f"Provider {provider} does not exist.")
  273. # Convert model type to ModelType
  274. model_type_enum = ModelType.value_of(model_type)
  275. if not isinstance(configs, list):
  276. raise ValueError("Invalid load balancing configs")
  277. current_load_balancing_configs = db.session.scalars(
  278. select(LoadBalancingModelConfig).where(
  279. LoadBalancingModelConfig.tenant_id == tenant_id,
  280. LoadBalancingModelConfig.provider_name == provider_configuration.provider.provider,
  281. LoadBalancingModelConfig.model_type == model_type_enum.to_origin_model_type(),
  282. LoadBalancingModelConfig.model_name == model,
  283. )
  284. ).all()
  285. # id as key, config as value
  286. current_load_balancing_configs_dict = {config.id: config for config in current_load_balancing_configs}
  287. updated_config_ids = set()
  288. for config in configs:
  289. if not isinstance(config, dict):
  290. raise ValueError("Invalid load balancing config")
  291. config_id = config.get("id")
  292. name = config.get("name")
  293. credentials = config.get("credentials")
  294. credential_id = config.get("credential_id")
  295. enabled = config.get("enabled")
  296. credential_record: ProviderCredential | ProviderModelCredential | None = None
  297. if credential_id:
  298. if config_from == "predefined-model":
  299. credential_record = (
  300. db.session.query(ProviderCredential)
  301. .filter_by(
  302. id=credential_id,
  303. tenant_id=tenant_id,
  304. provider_name=provider_configuration.provider.provider,
  305. )
  306. .first()
  307. )
  308. else:
  309. credential_record = (
  310. db.session.query(ProviderModelCredential)
  311. .filter_by(
  312. id=credential_id,
  313. tenant_id=tenant_id,
  314. provider_name=provider_configuration.provider.provider,
  315. model_name=model,
  316. model_type=model_type_enum.to_origin_model_type(),
  317. )
  318. .first()
  319. )
  320. if not credential_record:
  321. raise ValueError(f"Provider credential with id {credential_id} not found")
  322. name = credential_record.credential_name
  323. if not name:
  324. raise ValueError("Invalid load balancing config name")
  325. if enabled is None:
  326. raise ValueError("Invalid load balancing config enabled")
  327. # is config exists
  328. if config_id:
  329. config_id = str(config_id)
  330. if config_id not in current_load_balancing_configs_dict:
  331. raise ValueError(f"Invalid load balancing config id: {config_id}")
  332. updated_config_ids.add(config_id)
  333. load_balancing_config = current_load_balancing_configs_dict[config_id]
  334. if credentials:
  335. if not isinstance(credentials, dict):
  336. raise ValueError("Invalid load balancing config credentials")
  337. # validate custom provider config
  338. credentials = self._custom_credentials_validate(
  339. tenant_id=tenant_id,
  340. provider_configuration=provider_configuration,
  341. model_type=model_type_enum,
  342. model=model,
  343. credentials=credentials,
  344. load_balancing_model_config=load_balancing_config,
  345. validate=False,
  346. )
  347. # update load balancing config
  348. load_balancing_config.encrypted_config = json.dumps(credentials)
  349. load_balancing_config.name = name
  350. load_balancing_config.enabled = enabled
  351. load_balancing_config.updated_at = naive_utc_now()
  352. db.session.commit()
  353. self._clear_credentials_cache(tenant_id, config_id)
  354. else:
  355. # create load balancing config
  356. if name == "__inherit__":
  357. raise ValueError("Invalid load balancing config name")
  358. if credential_id:
  359. credential_source = "provider" if config_from == "predefined-model" else "custom_model"
  360. assert credential_record is not None
  361. load_balancing_model_config = LoadBalancingModelConfig(
  362. tenant_id=tenant_id,
  363. provider_name=provider_configuration.provider.provider,
  364. model_type=model_type_enum.to_origin_model_type(),
  365. model_name=model,
  366. name=credential_record.credential_name,
  367. encrypted_config=credential_record.encrypted_config,
  368. credential_id=credential_id,
  369. credential_source_type=credential_source,
  370. )
  371. else:
  372. if not credentials:
  373. raise ValueError("Invalid load balancing config credentials")
  374. if not isinstance(credentials, dict):
  375. raise ValueError("Invalid load balancing config credentials")
  376. # validate custom provider config
  377. credentials = self._custom_credentials_validate(
  378. tenant_id=tenant_id,
  379. provider_configuration=provider_configuration,
  380. model_type=model_type_enum,
  381. model=model,
  382. credentials=credentials,
  383. validate=False,
  384. )
  385. # create load balancing config
  386. load_balancing_model_config = LoadBalancingModelConfig(
  387. tenant_id=tenant_id,
  388. provider_name=provider_configuration.provider.provider,
  389. model_type=model_type_enum.to_origin_model_type(),
  390. model_name=model,
  391. name=name,
  392. encrypted_config=json.dumps(credentials),
  393. )
  394. db.session.add(load_balancing_model_config)
  395. db.session.commit()
  396. # get deleted config ids
  397. deleted_config_ids = set(current_load_balancing_configs_dict.keys()) - updated_config_ids
  398. for config_id in deleted_config_ids:
  399. db.session.delete(current_load_balancing_configs_dict[config_id])
  400. db.session.commit()
  401. self._clear_credentials_cache(tenant_id, config_id)
  402. def validate_load_balancing_credentials(
  403. self,
  404. tenant_id: str,
  405. provider: str,
  406. model: str,
  407. model_type: str,
  408. credentials: dict,
  409. config_id: str | None = None,
  410. ):
  411. """
  412. Validate load balancing credentials.
  413. :param tenant_id: workspace id
  414. :param provider: provider name
  415. :param model_type: model type
  416. :param model: model name
  417. :param credentials: credentials
  418. :param config_id: load balancing config id
  419. :return:
  420. """
  421. # Get all provider configurations of the current workspace
  422. provider_configurations = self.provider_manager.get_configurations(tenant_id)
  423. # Get provider configuration
  424. provider_configuration = provider_configurations.get(provider)
  425. if not provider_configuration:
  426. raise ValueError(f"Provider {provider} does not exist.")
  427. # Convert model type to ModelType
  428. model_type_enum = ModelType.value_of(model_type)
  429. load_balancing_model_config = None
  430. if config_id:
  431. # Get load balancing config
  432. load_balancing_model_config = (
  433. db.session.query(LoadBalancingModelConfig)
  434. .where(
  435. LoadBalancingModelConfig.tenant_id == tenant_id,
  436. LoadBalancingModelConfig.provider_name == provider,
  437. LoadBalancingModelConfig.model_type == model_type_enum.to_origin_model_type(),
  438. LoadBalancingModelConfig.model_name == model,
  439. LoadBalancingModelConfig.id == config_id,
  440. )
  441. .first()
  442. )
  443. if not load_balancing_model_config:
  444. raise ValueError(f"Load balancing config {config_id} does not exist.")
  445. # Validate custom provider config
  446. self._custom_credentials_validate(
  447. tenant_id=tenant_id,
  448. provider_configuration=provider_configuration,
  449. model_type=model_type_enum,
  450. model=model,
  451. credentials=credentials,
  452. load_balancing_model_config=load_balancing_model_config,
  453. )
  454. def _custom_credentials_validate(
  455. self,
  456. tenant_id: str,
  457. provider_configuration: ProviderConfiguration,
  458. model_type: ModelType,
  459. model: str,
  460. credentials: dict,
  461. load_balancing_model_config: LoadBalancingModelConfig | None = None,
  462. validate: bool = True,
  463. ):
  464. """
  465. Validate custom credentials.
  466. :param tenant_id: workspace id
  467. :param provider_configuration: provider configuration
  468. :param model_type: model type
  469. :param model: model name
  470. :param credentials: credentials
  471. :param load_balancing_model_config: load balancing model config
  472. :param validate: validate credentials
  473. :return:
  474. """
  475. # Get credential form schemas from model credential schema or provider credential schema
  476. credential_schemas = self._get_credential_schema(provider_configuration)
  477. # Get provider credential secret variables
  478. provider_credential_secret_variables = provider_configuration.extract_secret_variables(
  479. credential_schemas.credential_form_schemas
  480. )
  481. if load_balancing_model_config:
  482. try:
  483. # fix origin data
  484. if load_balancing_model_config.encrypted_config:
  485. original_credentials = json.loads(load_balancing_model_config.encrypted_config)
  486. else:
  487. original_credentials = {}
  488. except JSONDecodeError:
  489. original_credentials = {}
  490. # encrypt credentials
  491. for key, value in credentials.items():
  492. if key in provider_credential_secret_variables:
  493. # if send [__HIDDEN__] in secret input, it will be same as original value
  494. if value == HIDDEN_VALUE and key in original_credentials:
  495. credentials[key] = encrypter.decrypt_token(tenant_id, original_credentials[key])
  496. if validate:
  497. model_provider_factory = ModelProviderFactory(tenant_id)
  498. if isinstance(credential_schemas, ModelCredentialSchema):
  499. credentials = model_provider_factory.model_credentials_validate(
  500. provider=provider_configuration.provider.provider,
  501. model_type=model_type,
  502. model=model,
  503. credentials=credentials,
  504. )
  505. else:
  506. credentials = model_provider_factory.provider_credentials_validate(
  507. provider=provider_configuration.provider.provider, credentials=credentials
  508. )
  509. for key, value in credentials.items():
  510. if key in provider_credential_secret_variables:
  511. credentials[key] = encrypter.encrypt_token(tenant_id, value)
  512. return credentials
  513. def _get_credential_schema(
  514. self, provider_configuration: ProviderConfiguration
  515. ) -> Union[ModelCredentialSchema, ProviderCredentialSchema]:
  516. """Get form schemas."""
  517. if provider_configuration.provider.model_credential_schema:
  518. return provider_configuration.provider.model_credential_schema
  519. elif provider_configuration.provider.provider_credential_schema:
  520. return provider_configuration.provider.provider_credential_schema
  521. else:
  522. raise ValueError("No credential schema found")
  523. def _clear_credentials_cache(self, tenant_id: str, config_id: str):
  524. """
  525. Clear credentials cache.
  526. :param tenant_id: workspace id
  527. :param config_id: load balancing config id
  528. :return:
  529. """
  530. provider_model_credentials_cache = ProviderCredentialsCache(
  531. tenant_id=tenant_id, identity_id=config_id, cache_type=ProviderCredentialsCacheType.LOAD_BALANCING_MODEL
  532. )
  533. provider_model_credentials_cache.delete()