-
Notifications
You must be signed in to change notification settings - Fork 63
feat(llm): support configurations with YAML #277
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,3 +18,4 @@ openpyxl~=3.1.5 | |
| pydantic-settings~=2.6.1 | ||
| apscheduler~=3.10.4 | ||
| litellm~=1.61.13 | ||
| OmegaConf~=2.3 | ||
| Original file line number | Diff line number | Diff line change | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -18,118 +18,139 @@ | |||||||||||
|
|
||||||||||||
| import os | ||||||||||||
|
|
||||||||||||
| from dotenv import dotenv_values, set_key | ||||||||||||
| from pydantic_settings import BaseSettings | ||||||||||||
| import yaml | ||||||||||||
|
|
||||||||||||
| from hugegraph_llm.utils.log import log | ||||||||||||
|
|
||||||||||||
| dir_name = os.path.dirname | ||||||||||||
| env_path = os.path.join(os.getcwd(), ".env") # Load .env from the current working directory | ||||||||||||
|
|
||||||||||||
| yaml_path = os.path.join(os.getcwd(), "config.yaml") | ||||||||||||
|
|
||||||||||||
| class BaseConfig(BaseSettings): | ||||||||||||
| class Config: | ||||||||||||
| env_file = env_path | ||||||||||||
| yaml_file = yaml_path | ||||||||||||
| case_sensitive = False | ||||||||||||
| extra = 'ignore' # ignore extra fields to avoid ValidationError | ||||||||||||
| extra = 'ignore' # Ignore extra fields to avoid ValidationError | ||||||||||||
| env_ignore_empty = True | ||||||||||||
|
|
||||||||||||
| def generate_env(self): | ||||||||||||
| if os.path.exists(env_path): | ||||||||||||
| log.info("%s already exists, do you want to override with the default configuration? (y/n)", env_path) | ||||||||||||
| update = input() | ||||||||||||
| if update.lower() != "y": | ||||||||||||
| return | ||||||||||||
| self.update_env() | ||||||||||||
| else: | ||||||||||||
| config_dict = self.model_dump() | ||||||||||||
| config_dict = {k.upper(): v for k, v in config_dict.items()} | ||||||||||||
| with open(env_path, "w", encoding="utf-8") as f: | ||||||||||||
| for k, v in config_dict.items(): | ||||||||||||
| if v is None: | ||||||||||||
| f.write(f"{k}=\n") | ||||||||||||
| else: | ||||||||||||
| f.write(f"{k}={v}\n") | ||||||||||||
| log.info("Generate %s successfully!", env_path) | ||||||||||||
|
|
||||||||||||
| def update_env(self): | ||||||||||||
| def generate_yaml(self): | ||||||||||||
| # Generate a YAML file based on the current configuration | ||||||||||||
| config_dict = self.model_dump() | ||||||||||||
| config_dict = {k.upper(): v for k, v in config_dict.items()} | ||||||||||||
| env_config = dotenv_values(f"{env_path}") | ||||||||||||
|
|
||||||||||||
| # dotenv_values make None to '', while pydantic make None to None | ||||||||||||
| # dotenv_values make integer to string, while pydantic make integer to integer | ||||||||||||
| current_class_name = self.__class__.__name__ | ||||||||||||
| yaml_data = {} | ||||||||||||
| yaml_section_data = {} | ||||||||||||
| for k, v in config_dict.items(): | ||||||||||||
| if k in env_config: | ||||||||||||
| if not (env_config[k] or v): | ||||||||||||
| continue | ||||||||||||
| if env_config[k] == str(v): | ||||||||||||
| continue | ||||||||||||
| log.info("Update %s: %s=%s", env_path, k, v) | ||||||||||||
| set_key(env_path, k, v if v else "", quote_mode="never") | ||||||||||||
|
|
||||||||||||
| def check_env(self): | ||||||||||||
| """Synchronize configs between .env file and object. | ||||||||||||
| yaml_section_data[k] = v | ||||||||||||
| yaml_data[current_class_name] = yaml_section_data | ||||||||||||
| with open(yaml_path, "w", encoding="utf-8") as f: | ||||||||||||
| yaml.dump(yaml_data, f, sort_keys=False) | ||||||||||||
| log.info("Generate %s successfully!", yaml_path) | ||||||||||||
|
|
||||||||||||
| def update_configs(self): | ||||||||||||
| """Update the configurations of subclasses to the config.yaml files.""" | ||||||||||||
| config_dict = self.model_dump() | ||||||||||||
| config_dict = {k.upper(): v for k, v in config_dict.items()} | ||||||||||||
|
|
||||||||||||
| try: | ||||||||||||
| current_class_name = self.__class__.__name__ | ||||||||||||
| with open(yaml_path, "r", encoding="utf-8") as f: | ||||||||||||
| content = f.read() | ||||||||||||
| yaml_config = yaml.safe_load(content) if content.strip() else {} | ||||||||||||
|
||||||||||||
| yaml_config = yaml.safe_load(content) if content.strip() else {} | |
| yaml_config = yaml.safe_load(content) if content.strip() else {} | |
| current_class_name = self.__class__.__name__ | |
| if current_class_name not in yaml_config: | |
| yaml_config[current_class_name] = {} |
Copilot
AI
Jun 18, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is a minor typo in the comment ('onfig' should be 'config') – please correct it for clarity.
| # Step 2: Add missing onfig items from object to yaml.config | |
| # Step 2: Add missing config items from object to yaml.config |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
keep a line -> EOF