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 4.0KB

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