| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226 | from typing import Any, Optionalfrom urllib.parse import quote_plusfrom pydantic import Field, NonNegativeInt, PositiveFloat, PositiveInt, computed_fieldfrom pydantic_settings import BaseSettingsfrom configs.middleware.cache.redis_config import RedisConfigfrom configs.middleware.storage.aliyun_oss_storage_config import AliyunOSSStorageConfigfrom configs.middleware.storage.amazon_s3_storage_config import S3StorageConfigfrom configs.middleware.storage.azure_blob_storage_config import AzureBlobStorageConfigfrom configs.middleware.storage.google_cloud_storage_config import GoogleCloudStorageConfigfrom configs.middleware.storage.huawei_obs_storage_config import HuaweiCloudOBSStorageConfigfrom configs.middleware.storage.oci_storage_config import OCIStorageConfigfrom configs.middleware.storage.tencent_cos_storage_config import TencentCloudCOSStorageConfigfrom configs.middleware.storage.volcengine_tos_storage_config import VolcengineTOSStorageConfigfrom configs.middleware.vdb.analyticdb_config import AnalyticdbConfigfrom configs.middleware.vdb.chroma_config import ChromaConfigfrom configs.middleware.vdb.elasticsearch_config import ElasticsearchConfigfrom configs.middleware.vdb.milvus_config import MilvusConfigfrom configs.middleware.vdb.myscale_config import MyScaleConfigfrom configs.middleware.vdb.opensearch_config import OpenSearchConfigfrom configs.middleware.vdb.oracle_config import OracleConfigfrom configs.middleware.vdb.pgvector_config import PGVectorConfigfrom configs.middleware.vdb.pgvectors_config import PGVectoRSConfigfrom configs.middleware.vdb.qdrant_config import QdrantConfigfrom configs.middleware.vdb.relyt_config import RelytConfigfrom configs.middleware.vdb.tencent_vector_config import TencentVectorDBConfigfrom configs.middleware.vdb.tidb_vector_config import TiDBVectorConfigfrom configs.middleware.vdb.weaviate_config import WeaviateConfigclass StorageConfig(BaseSettings):    STORAGE_TYPE: str = Field(        description="storage type,"        " default to `local`,"        " available values are `local`, `s3`, `azure-blob`, `aliyun-oss`, `google-storage`.",        default="local",    )    STORAGE_LOCAL_PATH: str = Field(        description="local storage path",        default="storage",    )class VectorStoreConfig(BaseSettings):    VECTOR_STORE: Optional[str] = Field(        description="vector store type",        default=None,    )class KeywordStoreConfig(BaseSettings):    KEYWORD_STORE: str = Field(        description="keyword store type",        default="jieba",    )class DatabaseConfig:    DB_HOST: str = Field(        description="db host",        default="localhost",    )    DB_PORT: PositiveInt = Field(        description="db port",        default=5432,    )    DB_USERNAME: str = Field(        description="db username",        default="postgres",    )    DB_PASSWORD: str = Field(        description="db password",        default="",    )    DB_DATABASE: str = Field(        description="db database",        default="dify",    )    DB_CHARSET: str = Field(        description="db charset",        default="",    )    DB_EXTRAS: str = Field(        description="db extras options. Example: keepalives_idle=60&keepalives=1",        default="",    )    SQLALCHEMY_DATABASE_URI_SCHEME: str = Field(        description="db uri scheme",        default="postgresql",    )    @computed_field    @property    def SQLALCHEMY_DATABASE_URI(self) -> str:        db_extras = (            f"{self.DB_EXTRAS}&client_encoding={self.DB_CHARSET}" if self.DB_CHARSET else self.DB_EXTRAS        ).strip("&")        db_extras = f"?{db_extras}" if db_extras else ""        return (            f"{self.SQLALCHEMY_DATABASE_URI_SCHEME}://"            f"{quote_plus(self.DB_USERNAME)}:{quote_plus(self.DB_PASSWORD)}@{self.DB_HOST}:{self.DB_PORT}/{self.DB_DATABASE}"            f"{db_extras}"        )    SQLALCHEMY_POOL_SIZE: NonNegativeInt = Field(        description="pool size of SqlAlchemy",        default=30,    )    SQLALCHEMY_MAX_OVERFLOW: NonNegativeInt = Field(        description="max overflows for SqlAlchemy",        default=10,    )    SQLALCHEMY_POOL_RECYCLE: NonNegativeInt = Field(        description="SqlAlchemy pool recycle",        default=3600,    )    SQLALCHEMY_POOL_PRE_PING: bool = Field(        description="whether to enable pool pre-ping in SqlAlchemy",        default=False,    )    SQLALCHEMY_ECHO: bool | str = Field(        description="whether to enable SqlAlchemy echo",        default=False,    )    @computed_field    @property    def SQLALCHEMY_ENGINE_OPTIONS(self) -> dict[str, Any]:        return {            "pool_size": self.SQLALCHEMY_POOL_SIZE,            "max_overflow": self.SQLALCHEMY_MAX_OVERFLOW,            "pool_recycle": self.SQLALCHEMY_POOL_RECYCLE,            "pool_pre_ping": self.SQLALCHEMY_POOL_PRE_PING,            "connect_args": {"options": "-c timezone=UTC"},        }class CeleryConfig(DatabaseConfig):    CELERY_BACKEND: str = Field(        description="Celery backend, available values are `database`, `redis`",        default="database",    )    CELERY_BROKER_URL: Optional[str] = Field(        description="CELERY_BROKER_URL",        default=None,    )    CELERY_USE_SENTINEL: Optional[bool] = Field(        description="Whether to use Redis Sentinel mode",        default=False,    )    CELERY_SENTINEL_MASTER_NAME: Optional[str] = Field(        description="Redis Sentinel master name",        default=None,    )    CELERY_SENTINEL_SOCKET_TIMEOUT: Optional[PositiveFloat] = Field(        description="Redis Sentinel socket timeout",        default=0.1,    )    @computed_field    @property    def CELERY_RESULT_BACKEND(self) -> str | None:        return (            "db+{}".format(self.SQLALCHEMY_DATABASE_URI)            if self.CELERY_BACKEND == "database"            else self.CELERY_BROKER_URL        )    @computed_field    @property    def BROKER_USE_SSL(self) -> bool:        return self.CELERY_BROKER_URL.startswith("rediss://") if self.CELERY_BROKER_URL else Falseclass MiddlewareConfig(    # place the configs in alphabet order    CeleryConfig,    DatabaseConfig,    KeywordStoreConfig,    RedisConfig,    # configs of storage and storage providers    StorageConfig,    AliyunOSSStorageConfig,    AzureBlobStorageConfig,    GoogleCloudStorageConfig,    TencentCloudCOSStorageConfig,    HuaweiCloudOBSStorageConfig,    VolcengineTOSStorageConfig,    S3StorageConfig,    OCIStorageConfig,    # configs of vdb and vdb providers    VectorStoreConfig,    AnalyticdbConfig,    ChromaConfig,    MilvusConfig,    MyScaleConfig,    OpenSearchConfig,    OracleConfig,    PGVectorConfig,    PGVectoRSConfig,    QdrantConfig,    RelytConfig,    TencentVectorDBConfig,    TiDBVectorConfig,    WeaviateConfig,    ElasticsearchConfig,):    pass
 |