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

model_load_balancing_service.py 25KB

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 месяцев назад
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 месяцев назад
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608
  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, ProviderCredential, ProviderModelCredential
  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), # ty: ignore [invalid-argument-type]
  147. decoding_rsa_key,
  148. decoding_cipher_rsa,
  149. )
  150. except ValueError:
  151. pass
  152. # Obfuscate credentials
  153. credentials = provider_configuration.obfuscated_credentials(
  154. credentials=credentials, credential_form_schemas=credential_schemas.credential_form_schemas
  155. )
  156. datas.append(
  157. {
  158. "id": load_balancing_config.id,
  159. "name": load_balancing_config.name,
  160. "credentials": credentials,
  161. "credential_id": load_balancing_config.credential_id,
  162. "enabled": load_balancing_config.enabled,
  163. "in_cooldown": in_cooldown,
  164. "ttl": ttl,
  165. }
  166. )
  167. return is_load_balancing_enabled, datas
  168. def get_load_balancing_config(
  169. self, tenant_id: str, provider: str, model: str, model_type: str, config_id: str
  170. ) -> Optional[dict]:
  171. """
  172. Get load balancing configuration.
  173. :param tenant_id: workspace id
  174. :param provider: provider name
  175. :param model: model name
  176. :param model_type: model type
  177. :param config_id: load balancing config id
  178. :return:
  179. """
  180. # Get all provider configurations of the current workspace
  181. provider_configurations = self.provider_manager.get_configurations(tenant_id)
  182. # Get provider configuration
  183. provider_configuration = provider_configurations.get(provider)
  184. if not provider_configuration:
  185. raise ValueError(f"Provider {provider} does not exist.")
  186. # Convert model type to ModelType
  187. model_type_enum = ModelType.value_of(model_type)
  188. # Get load balancing configurations
  189. load_balancing_model_config = (
  190. db.session.query(LoadBalancingModelConfig)
  191. .where(
  192. LoadBalancingModelConfig.tenant_id == tenant_id,
  193. LoadBalancingModelConfig.provider_name == provider_configuration.provider.provider,
  194. LoadBalancingModelConfig.model_type == model_type_enum.to_origin_model_type(),
  195. LoadBalancingModelConfig.model_name == model,
  196. LoadBalancingModelConfig.id == config_id,
  197. )
  198. .first()
  199. )
  200. if not load_balancing_model_config:
  201. return None
  202. try:
  203. if load_balancing_model_config.encrypted_config:
  204. credentials = json.loads(load_balancing_model_config.encrypted_config)
  205. else:
  206. credentials = {}
  207. except JSONDecodeError:
  208. credentials = {}
  209. # Get credential form schemas from model credential schema or provider credential schema
  210. credential_schemas = self._get_credential_schema(provider_configuration)
  211. # Obfuscate credentials
  212. credentials = provider_configuration.obfuscated_credentials(
  213. credentials=credentials, credential_form_schemas=credential_schemas.credential_form_schemas
  214. )
  215. return {
  216. "id": load_balancing_model_config.id,
  217. "name": load_balancing_model_config.name,
  218. "credentials": credentials,
  219. "enabled": load_balancing_model_config.enabled,
  220. }
  221. def _init_inherit_config(
  222. self, tenant_id: str, provider: str, model: str, model_type: ModelType
  223. ) -> LoadBalancingModelConfig:
  224. """
  225. Initialize the inherit configuration.
  226. :param tenant_id: workspace id
  227. :param provider: provider name
  228. :param model: model name
  229. :param model_type: model type
  230. :return:
  231. """
  232. # Initialize the inherit configuration
  233. inherit_config = LoadBalancingModelConfig(
  234. tenant_id=tenant_id,
  235. provider_name=provider,
  236. model_type=model_type.to_origin_model_type(),
  237. model_name=model,
  238. name="__inherit__",
  239. )
  240. db.session.add(inherit_config)
  241. db.session.commit()
  242. return inherit_config
  243. def update_load_balancing_configs(
  244. self, tenant_id: str, provider: str, model: str, model_type: str, configs: list[dict], config_from: str
  245. ) -> None:
  246. """
  247. Update load balancing configurations.
  248. :param tenant_id: workspace id
  249. :param provider: provider name
  250. :param model: model name
  251. :param model_type: model type
  252. :param configs: load balancing configs
  253. :param config_from: predefined-model or custom-model
  254. :return:
  255. """
  256. # Get all provider configurations of the current workspace
  257. provider_configurations = self.provider_manager.get_configurations(tenant_id)
  258. # Get provider configuration
  259. provider_configuration = provider_configurations.get(provider)
  260. if not provider_configuration:
  261. raise ValueError(f"Provider {provider} does not exist.")
  262. # Convert model type to ModelType
  263. model_type_enum = ModelType.value_of(model_type)
  264. if not isinstance(configs, list):
  265. raise ValueError("Invalid load balancing configs")
  266. current_load_balancing_configs = (
  267. db.session.query(LoadBalancingModelConfig)
  268. .where(
  269. LoadBalancingModelConfig.tenant_id == tenant_id,
  270. LoadBalancingModelConfig.provider_name == provider_configuration.provider.provider,
  271. LoadBalancingModelConfig.model_type == model_type_enum.to_origin_model_type(),
  272. LoadBalancingModelConfig.model_name == model,
  273. )
  274. .all()
  275. )
  276. # id as key, config as value
  277. current_load_balancing_configs_dict = {config.id: config for config in current_load_balancing_configs}
  278. updated_config_ids = set()
  279. for config in configs:
  280. if not isinstance(config, dict):
  281. raise ValueError("Invalid load balancing config")
  282. config_id = config.get("id")
  283. name = config.get("name")
  284. credentials = config.get("credentials")
  285. credential_id = config.get("credential_id")
  286. enabled = config.get("enabled")
  287. if credential_id:
  288. credential_record: ProviderCredential | ProviderModelCredential | None = None
  289. if config_from == "predefined-model":
  290. credential_record = (
  291. db.session.query(ProviderCredential)
  292. .filter_by(
  293. id=credential_id,
  294. tenant_id=tenant_id,
  295. provider_name=provider_configuration.provider.provider,
  296. )
  297. .first()
  298. )
  299. else:
  300. credential_record = (
  301. db.session.query(ProviderModelCredential)
  302. .filter_by(
  303. id=credential_id,
  304. tenant_id=tenant_id,
  305. provider_name=provider_configuration.provider.provider,
  306. model_name=model,
  307. model_type=model_type_enum.to_origin_model_type(),
  308. )
  309. .first()
  310. )
  311. if not credential_record:
  312. raise ValueError(f"Provider credential with id {credential_id} not found")
  313. name = credential_record.credential_name
  314. if not name:
  315. raise ValueError("Invalid load balancing config name")
  316. if enabled is None:
  317. raise ValueError("Invalid load balancing config enabled")
  318. # is config exists
  319. if config_id:
  320. config_id = str(config_id)
  321. if config_id not in current_load_balancing_configs_dict:
  322. raise ValueError(f"Invalid load balancing config id: {config_id}")
  323. updated_config_ids.add(config_id)
  324. load_balancing_config = current_load_balancing_configs_dict[config_id]
  325. if credentials:
  326. if not isinstance(credentials, dict):
  327. raise ValueError("Invalid load balancing config credentials")
  328. # validate custom provider config
  329. credentials = self._custom_credentials_validate(
  330. tenant_id=tenant_id,
  331. provider_configuration=provider_configuration,
  332. model_type=model_type_enum,
  333. model=model,
  334. credentials=credentials,
  335. load_balancing_model_config=load_balancing_config,
  336. validate=False,
  337. )
  338. # update load balancing config
  339. load_balancing_config.encrypted_config = json.dumps(credentials)
  340. load_balancing_config.name = name
  341. load_balancing_config.enabled = enabled
  342. load_balancing_config.updated_at = naive_utc_now()
  343. db.session.commit()
  344. self._clear_credentials_cache(tenant_id, config_id)
  345. else:
  346. # create load balancing config
  347. if name in {"__inherit__", "__delete__"}:
  348. raise ValueError("Invalid load balancing config name")
  349. if credential_id:
  350. credential_source = "provider" if config_from == "predefined-model" else "custom_model"
  351. assert credential_record is not None
  352. load_balancing_model_config = LoadBalancingModelConfig(
  353. tenant_id=tenant_id,
  354. provider_name=provider_configuration.provider.provider,
  355. model_type=model_type_enum.to_origin_model_type(),
  356. model_name=model,
  357. name=credential_record.credential_name,
  358. encrypted_config=credential_record.encrypted_config,
  359. credential_id=credential_id,
  360. credential_source_type=credential_source,
  361. )
  362. else:
  363. if not credentials:
  364. raise ValueError("Invalid load balancing config credentials")
  365. if not isinstance(credentials, dict):
  366. raise ValueError("Invalid load balancing config credentials")
  367. # validate custom provider config
  368. credentials = self._custom_credentials_validate(
  369. tenant_id=tenant_id,
  370. provider_configuration=provider_configuration,
  371. model_type=model_type_enum,
  372. model=model,
  373. credentials=credentials,
  374. validate=False,
  375. )
  376. # create load balancing config
  377. load_balancing_model_config = LoadBalancingModelConfig(
  378. tenant_id=tenant_id,
  379. provider_name=provider_configuration.provider.provider,
  380. model_type=model_type_enum.to_origin_model_type(),
  381. model_name=model,
  382. name=name,
  383. encrypted_config=json.dumps(credentials),
  384. )
  385. db.session.add(load_balancing_model_config)
  386. db.session.commit()
  387. # get deleted config ids
  388. deleted_config_ids = set(current_load_balancing_configs_dict.keys()) - updated_config_ids
  389. for config_id in deleted_config_ids:
  390. db.session.delete(current_load_balancing_configs_dict[config_id])
  391. db.session.commit()
  392. self._clear_credentials_cache(tenant_id, config_id)
  393. def validate_load_balancing_credentials(
  394. self,
  395. tenant_id: str,
  396. provider: str,
  397. model: str,
  398. model_type: str,
  399. credentials: dict,
  400. config_id: Optional[str] = None,
  401. ) -> None:
  402. """
  403. Validate load balancing credentials.
  404. :param tenant_id: workspace id
  405. :param provider: provider name
  406. :param model_type: model type
  407. :param model: model name
  408. :param credentials: credentials
  409. :param config_id: load balancing config id
  410. :return:
  411. """
  412. # Get all provider configurations of the current workspace
  413. provider_configurations = self.provider_manager.get_configurations(tenant_id)
  414. # Get provider configuration
  415. provider_configuration = provider_configurations.get(provider)
  416. if not provider_configuration:
  417. raise ValueError(f"Provider {provider} does not exist.")
  418. # Convert model type to ModelType
  419. model_type_enum = ModelType.value_of(model_type)
  420. load_balancing_model_config = None
  421. if config_id:
  422. # Get load balancing config
  423. load_balancing_model_config = (
  424. db.session.query(LoadBalancingModelConfig)
  425. .where(
  426. LoadBalancingModelConfig.tenant_id == tenant_id,
  427. LoadBalancingModelConfig.provider_name == provider,
  428. LoadBalancingModelConfig.model_type == model_type_enum.to_origin_model_type(),
  429. LoadBalancingModelConfig.model_name == model,
  430. LoadBalancingModelConfig.id == config_id,
  431. )
  432. .first()
  433. )
  434. if not load_balancing_model_config:
  435. raise ValueError(f"Load balancing config {config_id} does not exist.")
  436. # Validate custom provider config
  437. self._custom_credentials_validate(
  438. tenant_id=tenant_id,
  439. provider_configuration=provider_configuration,
  440. model_type=model_type_enum,
  441. model=model,
  442. credentials=credentials,
  443. load_balancing_model_config=load_balancing_model_config,
  444. )
  445. def _custom_credentials_validate(
  446. self,
  447. tenant_id: str,
  448. provider_configuration: ProviderConfiguration,
  449. model_type: ModelType,
  450. model: str,
  451. credentials: dict,
  452. load_balancing_model_config: Optional[LoadBalancingModelConfig] = None,
  453. validate: bool = True,
  454. ) -> dict:
  455. """
  456. Validate custom credentials.
  457. :param tenant_id: workspace id
  458. :param provider_configuration: provider configuration
  459. :param model_type: model type
  460. :param model: model name
  461. :param credentials: credentials
  462. :param load_balancing_model_config: load balancing model config
  463. :param validate: validate credentials
  464. :return:
  465. """
  466. # Get credential form schemas from model credential schema or provider credential schema
  467. credential_schemas = self._get_credential_schema(provider_configuration)
  468. # Get provider credential secret variables
  469. provider_credential_secret_variables = provider_configuration.extract_secret_variables(
  470. credential_schemas.credential_form_schemas
  471. )
  472. if load_balancing_model_config:
  473. try:
  474. # fix origin data
  475. if load_balancing_model_config.encrypted_config:
  476. original_credentials = json.loads(load_balancing_model_config.encrypted_config)
  477. else:
  478. original_credentials = {}
  479. except JSONDecodeError:
  480. original_credentials = {}
  481. # encrypt credentials
  482. for key, value in credentials.items():
  483. if key in provider_credential_secret_variables:
  484. # if send [__HIDDEN__] in secret input, it will be same as original value
  485. if value == HIDDEN_VALUE and key in original_credentials:
  486. credentials[key] = encrypter.decrypt_token(tenant_id, original_credentials[key])
  487. if validate:
  488. model_provider_factory = ModelProviderFactory(tenant_id)
  489. if isinstance(credential_schemas, ModelCredentialSchema):
  490. credentials = model_provider_factory.model_credentials_validate(
  491. provider=provider_configuration.provider.provider,
  492. model_type=model_type,
  493. model=model,
  494. credentials=credentials,
  495. )
  496. else:
  497. credentials = model_provider_factory.provider_credentials_validate(
  498. provider=provider_configuration.provider.provider, credentials=credentials
  499. )
  500. for key, value in credentials.items():
  501. if key in provider_credential_secret_variables:
  502. credentials[key] = encrypter.encrypt_token(tenant_id, value)
  503. return credentials
  504. def _get_credential_schema(
  505. self, provider_configuration: ProviderConfiguration
  506. ) -> Union[ModelCredentialSchema, ProviderCredentialSchema]:
  507. """Get form schemas."""
  508. if provider_configuration.provider.model_credential_schema:
  509. return provider_configuration.provider.model_credential_schema
  510. elif provider_configuration.provider.provider_credential_schema:
  511. return provider_configuration.provider.provider_credential_schema
  512. else:
  513. raise ValueError("No credential schema found")
  514. def _clear_credentials_cache(self, tenant_id: str, config_id: str) -> None:
  515. """
  516. Clear credentials cache.
  517. :param tenant_id: workspace id
  518. :param config_id: load balancing config id
  519. :return:
  520. """
  521. provider_model_credentials_cache = ProviderCredentialsCache(
  522. tenant_id=tenant_id, identity_id=config_id, cache_type=ProviderCredentialsCacheType.LOAD_BALANCING_MODEL
  523. )
  524. provider_model_credentials_cache.delete()