app_config.py 3.3 KB

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