1+ import logging
12import os
23
34from pathlib import Path
@@ -135,7 +136,7 @@ class GraphDBAuthConfig(BaseConfig, DictConversionMixin, EnvConfigMixin):
135136 password : str = Field (
136137 default = "" ,
137138 description = "Password for graph database authentication" ,
138- min_length = 8 , # 建议密码最小长度
139+ min_length = 8 , # Recommended minimum password length
139140 )
140141 db_name : str = Field (default = "neo4j" , description = "Database name to connect to" )
141142 auto_create : bool = Field (
@@ -150,13 +151,51 @@ class OpenAIConfig(BaseConfig, DictConversionMixin, EnvConfigMixin):
150151
151152
152153class AuthConfig (BaseConfig , DictConversionMixin ):
153- rabbitmq : RabbitMQConfig
154- openai : OpenAIConfig
155- graph_db : GraphDBAuthConfig
154+ rabbitmq : RabbitMQConfig | None = None
155+ openai : OpenAIConfig | None = None
156+ graph_db : GraphDBAuthConfig | None = None
156157 default_config_path : ClassVar [str ] = (
157158 f"{ BASE_DIR } /examples/data/config/mem_scheduler/scheduler_auth.yaml"
158159 )
159160
161+ @model_validator (mode = "after" )
162+ def validate_partial_initialization (self ) -> "AuthConfig" :
163+ """
164+ Validate that at least one configuration component is successfully initialized.
165+ Log warnings for any failed initializations but allow partial success.
166+ """
167+ logger = logging .getLogger (__name__ )
168+
169+ initialized_components = []
170+ failed_components = []
171+
172+ if self .rabbitmq is not None :
173+ initialized_components .append ("rabbitmq" )
174+ else :
175+ failed_components .append ("rabbitmq" )
176+
177+ if self .openai is not None :
178+ initialized_components .append ("openai" )
179+ else :
180+ failed_components .append ("openai" )
181+
182+ if self .graph_db is not None :
183+ initialized_components .append ("graph_db" )
184+ else :
185+ failed_components .append ("graph_db" )
186+
187+ # Allow all components to be None for flexibility, but log a warning
188+ if not initialized_components :
189+ logger .warning (
190+ "All configuration components are None. This may indicate missing environment variables or configuration files."
191+ )
192+ elif failed_components :
193+ logger .warning (
194+ f"Failed to initialize components: { ', ' .join (failed_components )} . Successfully initialized: { ', ' .join (initialized_components )} "
195+ )
196+
197+ return self
198+
160199 @classmethod
161200 def from_local_config (cls , config_path : str | Path | None = None ) -> "AuthConfig" :
162201 """
@@ -205,24 +244,75 @@ def from_local_env(cls) -> "AuthConfig":
205244
206245 This method loads configuration for all nested components (RabbitMQ, OpenAI, GraphDB)
207246 from their respective environment variables using each component's specific prefix.
247+ If any component fails to initialize, it will be set to None and a warning will be logged.
208248
209249 Returns:
210250 AuthConfig: Configured instance with values from environment variables
211251
212252 Raises:
213- ValueError: If any required environment variables are missing
253+ ValueError: If all components fail to initialize
214254 """
255+ logger = logging .getLogger (__name__ )
256+
257+ rabbitmq_config = None
258+ openai_config = None
259+ graph_db_config = None
260+
261+ # Try to initialize RabbitMQ config - check if any RabbitMQ env vars exist
262+ try :
263+ rabbitmq_prefix = RabbitMQConfig .get_env_prefix ()
264+ has_rabbitmq_env = any (key .startswith (rabbitmq_prefix ) for key in os .environ )
265+ if has_rabbitmq_env :
266+ rabbitmq_config = RabbitMQConfig .from_env ()
267+ logger .info ("Successfully initialized RabbitMQ configuration" )
268+ else :
269+ logger .info (
270+ "No RabbitMQ environment variables found, skipping RabbitMQ initialization"
271+ )
272+ except (ValueError , Exception ) as e :
273+ logger .warning (f"Failed to initialize RabbitMQ config from environment: { e } " )
274+
275+ # Try to initialize OpenAI config - check if any OpenAI env vars exist
276+ try :
277+ openai_prefix = OpenAIConfig .get_env_prefix ()
278+ has_openai_env = any (key .startswith (openai_prefix ) for key in os .environ )
279+ if has_openai_env :
280+ openai_config = OpenAIConfig .from_env ()
281+ logger .info ("Successfully initialized OpenAI configuration" )
282+ else :
283+ logger .info ("No OpenAI environment variables found, skipping OpenAI initialization" )
284+ except (ValueError , Exception ) as e :
285+ logger .warning (f"Failed to initialize OpenAI config from environment: { e } " )
286+
287+ # Try to initialize GraphDB config - check if any GraphDB env vars exist
288+ try :
289+ graphdb_prefix = GraphDBAuthConfig .get_env_prefix ()
290+ has_graphdb_env = any (key .startswith (graphdb_prefix ) for key in os .environ )
291+ if has_graphdb_env :
292+ graph_db_config = GraphDBAuthConfig .from_env ()
293+ logger .info ("Successfully initialized GraphDB configuration" )
294+ else :
295+ logger .info (
296+ "No GraphDB environment variables found, skipping GraphDB initialization"
297+ )
298+ except (ValueError , Exception ) as e :
299+ logger .warning (f"Failed to initialize GraphDB config from environment: { e } " )
300+
215301 return cls (
216- rabbitmq = RabbitMQConfig . from_env () ,
217- openai = OpenAIConfig . from_env () ,
218- graph_db = GraphDBAuthConfig . from_env () ,
302+ rabbitmq = rabbitmq_config ,
303+ openai = openai_config ,
304+ graph_db = graph_db_config ,
219305 )
220306
221307 def set_openai_config_to_environment (self ):
222- # Set environment variables
223- os .environ ["OPENAI_API_KEY" ] = self .openai .api_key
224- os .environ ["OPENAI_BASE_URL" ] = self .openai .base_url
225- os .environ ["MODEL" ] = self .openai .default_model
308+ # Set environment variables only if openai config is available
309+ if self .openai is not None :
310+ os .environ ["OPENAI_API_KEY" ] = self .openai .api_key
311+ os .environ ["OPENAI_BASE_URL" ] = self .openai .base_url
312+ os .environ ["MODEL" ] = self .openai .default_model
313+ else :
314+ logger = logging .getLogger (__name__ )
315+ logger .warning ("OpenAI config is not available, skipping environment variable setup" )
226316
227317 @classmethod
228318 def default_config_exists (cls ) -> bool :
0 commit comments