You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

model_load_balancing_service.py 23KB

преди 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 месеца
преди 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 месеца
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571
  1. import json
  2. import logging
  3. from json import JSONDecodeError
  4. from typing import Optional, Union
  5. from constants import HIDDEN_VALUE
  6. from core.entities.provider_configuration import ProviderConfiguration
  7. from core.helper import encrypter
  8. from core.helper.model_provider_cache import ProviderCredentialsCache, ProviderCredentialsCacheType
  9. from core.model_manager import LBModelManager
  10. from core.model_runtime.entities.model_entities import ModelType
  11. from core.model_runtime.entities.provider_entities import (
  12. ModelCredentialSchema,
  13. ProviderCredentialSchema,
  14. )
  15. from core.model_runtime.model_providers.model_provider_factory import ModelProviderFactory
  16. from core.provider_manager import ProviderManager
  17. from extensions.ext_database import db
  18. from libs.datetime_utils import naive_utc_now
  19. from models.provider import LoadBalancingModelConfig
  20. logger = logging.getLogger(__name__)
  21. class ModelLoadBalancingService:
  22. def __init__(self) -> None:
  23. self.provider_manager = ProviderManager()
  24. def enable_model_load_balancing(self, tenant_id: str, provider: str, model: str, model_type: str) -> None:
  25. """
  26. enable model load balancing.
  27. :param tenant_id: workspace id
  28. :param provider: provider name
  29. :param model: model name
  30. :param model_type: model type
  31. :return:
  32. """
  33. # Get all provider configurations of the current workspace
  34. provider_configurations = self.provider_manager.get_configurations(tenant_id)
  35. # Get provider configuration
  36. provider_configuration = provider_configurations.get(provider)
  37. if not provider_configuration:
  38. raise ValueError(f"Provider {provider} does not exist.")
  39. # Enable model load balancing
  40. provider_configuration.enable_model_load_balancing(model=model, model_type=ModelType.value_of(model_type))
  41. def disable_model_load_balancing(self, tenant_id: str, provider: str, model: str, model_type: str) -> None:
  42. """
  43. disable model load balancing.
  44. :param tenant_id: workspace id
  45. :param provider: provider name
  46. :param model: model name
  47. :param model_type: model type
  48. :return:
  49. """
  50. # Get all provider configurations of the current workspace
  51. provider_configurations = self.provider_manager.get_configurations(tenant_id)
  52. # Get provider configuration
  53. provider_configuration = provider_configurations.get(provider)
  54. if not provider_configuration:
  55. raise ValueError(f"Provider {provider} does not exist.")
  56. # disable model load balancing
  57. provider_configuration.disable_model_load_balancing(model=model, model_type=ModelType.value_of(model_type))
  58. def get_load_balancing_configs(
  59. self, tenant_id: str, provider: str, model: str, model_type: str
  60. ) -> tuple[bool, list[dict]]:
  61. """
  62. Get load balancing configurations.
  63. :param tenant_id: workspace id
  64. :param provider: provider name
  65. :param model: model name
  66. :param model_type: model type
  67. :return:
  68. """
  69. # Get all provider configurations of the current workspace
  70. provider_configurations = self.provider_manager.get_configurations(tenant_id)
  71. # Get provider configuration
  72. provider_configuration = provider_configurations.get(provider)
  73. if not provider_configuration:
  74. raise ValueError(f"Provider {provider} does not exist.")
  75. # Convert model type to ModelType
  76. model_type_enum = ModelType.value_of(model_type)
  77. # Get provider model setting
  78. provider_model_setting = provider_configuration.get_provider_model_setting(
  79. model_type=model_type_enum,
  80. model=model,
  81. )
  82. is_load_balancing_enabled = False
  83. if provider_model_setting and provider_model_setting.load_balancing_enabled:
  84. is_load_balancing_enabled = True
  85. # Get load balancing configurations
  86. load_balancing_configs = (
  87. db.session.query(LoadBalancingModelConfig)
  88. .where(
  89. LoadBalancingModelConfig.tenant_id == tenant_id,
  90. LoadBalancingModelConfig.provider_name == provider_configuration.provider.provider,
  91. LoadBalancingModelConfig.model_type == model_type_enum.to_origin_model_type(),
  92. LoadBalancingModelConfig.model_name == model,
  93. )
  94. .order_by(LoadBalancingModelConfig.created_at)
  95. .all()
  96. )
  97. if provider_configuration.custom_configuration.provider:
  98. # check if the inherit configuration exists,
  99. # inherit is represented for the provider or model custom credentials
  100. inherit_config_exists = False
  101. for load_balancing_config in load_balancing_configs:
  102. if load_balancing_config.name == "__inherit__":
  103. inherit_config_exists = True
  104. break
  105. if not inherit_config_exists:
  106. # Initialize the inherit configuration
  107. inherit_config = self._init_inherit_config(tenant_id, provider, model, model_type_enum)
  108. # prepend the inherit configuration
  109. load_balancing_configs.insert(0, inherit_config)
  110. else:
  111. # move the inherit configuration to the first
  112. for i, load_balancing_config in enumerate(load_balancing_configs[:]):
  113. if load_balancing_config.name == "__inherit__":
  114. inherit_config = load_balancing_configs.pop(i)
  115. load_balancing_configs.insert(0, inherit_config)
  116. # Get credential form schemas from model credential schema or provider credential schema
  117. credential_schemas = self._get_credential_schema(provider_configuration)
  118. # Get decoding rsa key and cipher for decrypting credentials
  119. decoding_rsa_key, decoding_cipher_rsa = encrypter.get_decrypt_decoding(tenant_id)
  120. # fetch status and ttl for each config
  121. datas = []
  122. for load_balancing_config in load_balancing_configs:
  123. in_cooldown, ttl = LBModelManager.get_config_in_cooldown_and_ttl(
  124. tenant_id=tenant_id,
  125. provider=provider,
  126. model=model,
  127. model_type=model_type_enum,
  128. config_id=load_balancing_config.id,
  129. )
  130. try:
  131. if load_balancing_config.encrypted_config:
  132. credentials = json.loads(load_balancing_config.encrypted_config)
  133. else:
  134. credentials = {}
  135. except JSONDecodeError:
  136. credentials = {}
  137. # Get provider credential secret variables
  138. credential_secret_variables = provider_configuration.extract_secret_variables(
  139. credential_schemas.credential_form_schemas
  140. )
  141. # decrypt credentials
  142. for variable in credential_secret_variables:
  143. if variable in credentials:
  144. try:
  145. credentials[variable] = encrypter.decrypt_token_with_decoding(
  146. credentials.get(variable), decoding_rsa_key, decoding_cipher_rsa
  147. )
  148. except ValueError:
  149. pass
  150. # Obfuscate credentials
  151. credentials = provider_configuration.obfuscated_credentials(
  152. credentials=credentials, credential_form_schemas=credential_schemas.credential_form_schemas
  153. )
  154. datas.append(
  155. {
  156. "id": load_balancing_config.id,
  157. "name": load_balancing_config.name,
  158. "credentials": credentials,
  159. "enabled": load_balancing_config.enabled,
  160. "in_cooldown": in_cooldown,
  161. "ttl": ttl,
  162. }
  163. )
  164. return is_load_balancing_enabled, datas
  165. def get_load_balancing_config(
  166. self, tenant_id: str, provider: str, model: str, model_type: str, config_id: str
  167. ) -> Optional[dict]:
  168. """
  169. Get load balancing configuration.
  170. :param tenant_id: workspace id
  171. :param provider: provider name
  172. :param model: model name
  173. :param model_type: model type
  174. :param config_id: load balancing config id
  175. :return:
  176. """
  177. # Get all provider configurations of the current workspace
  178. provider_configurations = self.provider_manager.get_configurations(tenant_id)
  179. # Get provider configuration
  180. provider_configuration = provider_configurations.get(provider)
  181. if not provider_configuration:
  182. raise ValueError(f"Provider {provider} does not exist.")
  183. # Convert model type to ModelType
  184. model_type_enum = ModelType.value_of(model_type)
  185. # Get load balancing configurations
  186. load_balancing_model_config = (
  187. db.session.query(LoadBalancingModelConfig)
  188. .where(
  189. LoadBalancingModelConfig.tenant_id == tenant_id,
  190. LoadBalancingModelConfig.provider_name == provider_configuration.provider.provider,
  191. LoadBalancingModelConfig.model_type == model_type_enum.to_origin_model_type(),
  192. LoadBalancingModelConfig.model_name == model,
  193. LoadBalancingModelConfig.id == config_id,
  194. )
  195. .first()
  196. )
  197. if not load_balancing_model_config:
  198. return None
  199. try:
  200. if load_balancing_model_config.encrypted_config:
  201. credentials = json.loads(load_balancing_model_config.encrypted_config)
  202. else:
  203. credentials = {}
  204. except JSONDecodeError:
  205. credentials = {}
  206. # Get credential form schemas from model credential schema or provider credential schema
  207. credential_schemas = self._get_credential_schema(provider_configuration)
  208. # Obfuscate credentials
  209. credentials = provider_configuration.obfuscated_credentials(
  210. credentials=credentials, credential_form_schemas=credential_schemas.credential_form_schemas
  211. )
  212. return {
  213. "id": load_balancing_model_config.id,
  214. "name": load_balancing_model_config.name,
  215. "credentials": credentials,
  216. "enabled": load_balancing_model_config.enabled,
  217. }
  218. def _init_inherit_config(
  219. self, tenant_id: str, provider: str, model: str, model_type: ModelType
  220. ) -> LoadBalancingModelConfig:
  221. """
  222. Initialize the inherit configuration.
  223. :param tenant_id: workspace id
  224. :param provider: provider name
  225. :param model: model name
  226. :param model_type: model type
  227. :return:
  228. """
  229. # Initialize the inherit configuration
  230. inherit_config = LoadBalancingModelConfig(
  231. tenant_id=tenant_id,
  232. provider_name=provider,
  233. model_type=model_type.to_origin_model_type(),
  234. model_name=model,
  235. name="__inherit__",
  236. )
  237. db.session.add(inherit_config)
  238. db.session.commit()
  239. return inherit_config
  240. def update_load_balancing_configs(
  241. self, tenant_id: str, provider: str, model: str, model_type: str, configs: list[dict]
  242. ) -> None:
  243. """
  244. Update load balancing configurations.
  245. :param tenant_id: workspace id
  246. :param provider: provider name
  247. :param model: model name
  248. :param model_type: model type
  249. :param configs: load balancing configs
  250. :return:
  251. """
  252. # Get all provider configurations of the current workspace
  253. provider_configurations = self.provider_manager.get_configurations(tenant_id)
  254. # Get provider configuration
  255. provider_configuration = provider_configurations.get(provider)
  256. if not provider_configuration:
  257. raise ValueError(f"Provider {provider} does not exist.")
  258. # Convert model type to ModelType
  259. model_type_enum = ModelType.value_of(model_type)
  260. if not isinstance(configs, list):
  261. raise ValueError("Invalid load balancing configs")
  262. current_load_balancing_configs = (
  263. db.session.query(LoadBalancingModelConfig)
  264. .where(
  265. LoadBalancingModelConfig.tenant_id == tenant_id,
  266. LoadBalancingModelConfig.provider_name == provider_configuration.provider.provider,
  267. LoadBalancingModelConfig.model_type == model_type_enum.to_origin_model_type(),
  268. LoadBalancingModelConfig.model_name == model,
  269. )
  270. .all()
  271. )
  272. # id as key, config as value
  273. current_load_balancing_configs_dict = {config.id: config for config in current_load_balancing_configs}
  274. updated_config_ids = set()
  275. for config in configs:
  276. if not isinstance(config, dict):
  277. raise ValueError("Invalid load balancing config")
  278. config_id = config.get("id")
  279. name = config.get("name")
  280. credentials = config.get("credentials")
  281. enabled = config.get("enabled")
  282. if not name:
  283. raise ValueError("Invalid load balancing config name")
  284. if enabled is None:
  285. raise ValueError("Invalid load balancing config enabled")
  286. # is config exists
  287. if config_id:
  288. config_id = str(config_id)
  289. if config_id not in current_load_balancing_configs_dict:
  290. raise ValueError(f"Invalid load balancing config id: {config_id}")
  291. updated_config_ids.add(config_id)
  292. load_balancing_config = current_load_balancing_configs_dict[config_id]
  293. # check duplicate name
  294. for current_load_balancing_config in current_load_balancing_configs:
  295. if current_load_balancing_config.id != config_id and current_load_balancing_config.name == name:
  296. raise ValueError(f"Load balancing config name {name} already exists")
  297. if credentials:
  298. if not isinstance(credentials, dict):
  299. raise ValueError("Invalid load balancing config credentials")
  300. # validate custom provider config
  301. credentials = self._custom_credentials_validate(
  302. tenant_id=tenant_id,
  303. provider_configuration=provider_configuration,
  304. model_type=model_type_enum,
  305. model=model,
  306. credentials=credentials,
  307. load_balancing_model_config=load_balancing_config,
  308. validate=False,
  309. )
  310. # update load balancing config
  311. load_balancing_config.encrypted_config = json.dumps(credentials)
  312. load_balancing_config.name = name
  313. load_balancing_config.enabled = enabled
  314. load_balancing_config.updated_at = naive_utc_now()
  315. db.session.commit()
  316. self._clear_credentials_cache(tenant_id, config_id)
  317. else:
  318. # create load balancing config
  319. if name == "__inherit__":
  320. raise ValueError("Invalid load balancing config name")
  321. # check duplicate name
  322. for current_load_balancing_config in current_load_balancing_configs:
  323. if current_load_balancing_config.name == name:
  324. raise ValueError(f"Load balancing config name {name} already exists")
  325. if not credentials:
  326. raise ValueError("Invalid load balancing config credentials")
  327. if not isinstance(credentials, dict):
  328. raise ValueError("Invalid load balancing config credentials")
  329. # validate custom provider config
  330. credentials = self._custom_credentials_validate(
  331. tenant_id=tenant_id,
  332. provider_configuration=provider_configuration,
  333. model_type=model_type_enum,
  334. model=model,
  335. credentials=credentials,
  336. validate=False,
  337. )
  338. # create load balancing config
  339. load_balancing_model_config = LoadBalancingModelConfig(
  340. tenant_id=tenant_id,
  341. provider_name=provider_configuration.provider.provider,
  342. model_type=model_type_enum.to_origin_model_type(),
  343. model_name=model,
  344. name=name,
  345. encrypted_config=json.dumps(credentials),
  346. )
  347. db.session.add(load_balancing_model_config)
  348. db.session.commit()
  349. # get deleted config ids
  350. deleted_config_ids = set(current_load_balancing_configs_dict.keys()) - updated_config_ids
  351. for config_id in deleted_config_ids:
  352. db.session.delete(current_load_balancing_configs_dict[config_id])
  353. db.session.commit()
  354. self._clear_credentials_cache(tenant_id, config_id)
  355. def validate_load_balancing_credentials(
  356. self,
  357. tenant_id: str,
  358. provider: str,
  359. model: str,
  360. model_type: str,
  361. credentials: dict,
  362. config_id: Optional[str] = None,
  363. ) -> None:
  364. """
  365. Validate load balancing credentials.
  366. :param tenant_id: workspace id
  367. :param provider: provider name
  368. :param model_type: model type
  369. :param model: model name
  370. :param credentials: credentials
  371. :param config_id: load balancing config id
  372. :return:
  373. """
  374. # Get all provider configurations of the current workspace
  375. provider_configurations = self.provider_manager.get_configurations(tenant_id)
  376. # Get provider configuration
  377. provider_configuration = provider_configurations.get(provider)
  378. if not provider_configuration:
  379. raise ValueError(f"Provider {provider} does not exist.")
  380. # Convert model type to ModelType
  381. model_type_enum = ModelType.value_of(model_type)
  382. load_balancing_model_config = None
  383. if config_id:
  384. # Get load balancing config
  385. load_balancing_model_config = (
  386. db.session.query(LoadBalancingModelConfig)
  387. .where(
  388. LoadBalancingModelConfig.tenant_id == tenant_id,
  389. LoadBalancingModelConfig.provider_name == provider,
  390. LoadBalancingModelConfig.model_type == model_type_enum.to_origin_model_type(),
  391. LoadBalancingModelConfig.model_name == model,
  392. LoadBalancingModelConfig.id == config_id,
  393. )
  394. .first()
  395. )
  396. if not load_balancing_model_config:
  397. raise ValueError(f"Load balancing config {config_id} does not exist.")
  398. # Validate custom provider config
  399. self._custom_credentials_validate(
  400. tenant_id=tenant_id,
  401. provider_configuration=provider_configuration,
  402. model_type=model_type_enum,
  403. model=model,
  404. credentials=credentials,
  405. load_balancing_model_config=load_balancing_model_config,
  406. )
  407. def _custom_credentials_validate(
  408. self,
  409. tenant_id: str,
  410. provider_configuration: ProviderConfiguration,
  411. model_type: ModelType,
  412. model: str,
  413. credentials: dict,
  414. load_balancing_model_config: Optional[LoadBalancingModelConfig] = None,
  415. validate: bool = True,
  416. ) -> dict:
  417. """
  418. Validate custom credentials.
  419. :param tenant_id: workspace id
  420. :param provider_configuration: provider configuration
  421. :param model_type: model type
  422. :param model: model name
  423. :param credentials: credentials
  424. :param load_balancing_model_config: load balancing model config
  425. :param validate: validate credentials
  426. :return:
  427. """
  428. # Get credential form schemas from model credential schema or provider credential schema
  429. credential_schemas = self._get_credential_schema(provider_configuration)
  430. # Get provider credential secret variables
  431. provider_credential_secret_variables = provider_configuration.extract_secret_variables(
  432. credential_schemas.credential_form_schemas
  433. )
  434. if load_balancing_model_config:
  435. try:
  436. # fix origin data
  437. if load_balancing_model_config.encrypted_config:
  438. original_credentials = json.loads(load_balancing_model_config.encrypted_config)
  439. else:
  440. original_credentials = {}
  441. except JSONDecodeError:
  442. original_credentials = {}
  443. # encrypt credentials
  444. for key, value in credentials.items():
  445. if key in provider_credential_secret_variables:
  446. # if send [__HIDDEN__] in secret input, it will be same as original value
  447. if value == HIDDEN_VALUE and key in original_credentials:
  448. credentials[key] = encrypter.decrypt_token(tenant_id, original_credentials[key])
  449. if validate:
  450. model_provider_factory = ModelProviderFactory(tenant_id)
  451. if isinstance(credential_schemas, ModelCredentialSchema):
  452. credentials = model_provider_factory.model_credentials_validate(
  453. provider=provider_configuration.provider.provider,
  454. model_type=model_type,
  455. model=model,
  456. credentials=credentials,
  457. )
  458. else:
  459. credentials = model_provider_factory.provider_credentials_validate(
  460. provider=provider_configuration.provider.provider, credentials=credentials
  461. )
  462. for key, value in credentials.items():
  463. if key in provider_credential_secret_variables:
  464. credentials[key] = encrypter.encrypt_token(tenant_id, value)
  465. return credentials
  466. def _get_credential_schema(
  467. self, provider_configuration: ProviderConfiguration
  468. ) -> Union[ModelCredentialSchema, ProviderCredentialSchema]:
  469. """Get form schemas."""
  470. if provider_configuration.provider.model_credential_schema:
  471. return provider_configuration.provider.model_credential_schema
  472. elif provider_configuration.provider.provider_credential_schema:
  473. return provider_configuration.provider.provider_credential_schema
  474. else:
  475. raise ValueError("No credential schema found")
  476. def _clear_credentials_cache(self, tenant_id: str, config_id: str) -> None:
  477. """
  478. Clear credentials cache.
  479. :param tenant_id: workspace id
  480. :param config_id: load balancing config id
  481. :return:
  482. """
  483. provider_model_credentials_cache = ProviderCredentialsCache(
  484. tenant_id=tenant_id, identity_id=config_id, cache_type=ProviderCredentialsCacheType.LOAD_BALANCING_MODEL
  485. )
  486. provider_model_credentials_cache.delete()