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.

app_config.py 3.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. import logging
  2. from typing import Any
  3. from pydantic.fields import FieldInfo
  4. from pydantic_settings import BaseSettings, PydanticBaseSettingsSource, SettingsConfigDict
  5. from .deploy import DeploymentConfig
  6. from .enterprise import EnterpriseFeatureConfig
  7. from .extra import ExtraServiceConfig
  8. from .feature import FeatureConfig
  9. from .middleware import MiddlewareConfig
  10. from .observability import ObservabilityConfig
  11. from .packaging import PackagingInfo
  12. from .remote_settings_sources import RemoteSettingsSource, RemoteSettingsSourceConfig, RemoteSettingsSourceName
  13. from .remote_settings_sources.apollo import ApolloSettingsSource
  14. from .remote_settings_sources.nacos import NacosSettingsSource
  15. logger = logging.getLogger(__name__)
  16. class RemoteSettingsSourceFactory(PydanticBaseSettingsSource):
  17. def __init__(self, settings_cls: type[BaseSettings]):
  18. super().__init__(settings_cls)
  19. def get_field_value(self, field: FieldInfo, field_name: str) -> tuple[Any, str, bool]:
  20. raise NotImplementedError
  21. def __call__(self) -> dict[str, Any]:
  22. current_state = self.current_state
  23. remote_source_name = current_state.get("REMOTE_SETTINGS_SOURCE_NAME")
  24. if not remote_source_name:
  25. return {}
  26. remote_source: RemoteSettingsSource | None = None
  27. match remote_source_name:
  28. case RemoteSettingsSourceName.APOLLO:
  29. remote_source = ApolloSettingsSource(current_state)
  30. case RemoteSettingsSourceName.NACOS:
  31. remote_source = NacosSettingsSource(current_state)
  32. case _:
  33. logger.warning(f"Unsupported remote source: {remote_source_name}")
  34. return {}
  35. d: dict[str, Any] = {}
  36. for field_name, field in self.settings_cls.model_fields.items():
  37. field_value, field_key, value_is_complex = remote_source.get_field_value(field, field_name)
  38. field_value = remote_source.prepare_field_value(field_name, field, field_value, value_is_complex)
  39. if field_value is not None:
  40. d[field_key] = field_value
  41. return d
  42. class DifyConfig(
  43. # Packaging info
  44. PackagingInfo,
  45. # Deployment configs
  46. DeploymentConfig,
  47. # Feature configs
  48. FeatureConfig,
  49. # Middleware configs
  50. MiddlewareConfig,
  51. # Extra service configs
  52. ExtraServiceConfig,
  53. # Observability configs
  54. ObservabilityConfig,
  55. # Remote source configs
  56. RemoteSettingsSourceConfig,
  57. # Enterprise feature configs
  58. # **Before using, please contact business@dify.ai by email to inquire about licensing matters.**
  59. EnterpriseFeatureConfig,
  60. ):
  61. model_config = SettingsConfigDict(
  62. # read from dotenv format config file
  63. env_file=".env",
  64. env_file_encoding="utf-8",
  65. # ignore extra attributes
  66. extra="ignore",
  67. )
  68. # Before adding any config,
  69. # please consider to arrange it in the proper config group of existed or added
  70. # for better readability and maintainability.
  71. # Thanks for your concentration and consideration.
  72. @classmethod
  73. def settings_customise_sources(
  74. cls,
  75. settings_cls: type[BaseSettings],
  76. init_settings: PydanticBaseSettingsSource,
  77. env_settings: PydanticBaseSettingsSource,
  78. dotenv_settings: PydanticBaseSettingsSource,
  79. file_secret_settings: PydanticBaseSettingsSource,
  80. ) -> tuple[PydanticBaseSettingsSource, ...]:
  81. return (
  82. init_settings,
  83. env_settings,
  84. RemoteSettingsSourceFactory(settings_cls),
  85. dotenv_settings,
  86. file_secret_settings,
  87. )