experiment-configuration-agent 0.1.6__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
File without changes
@@ -0,0 +1,121 @@
1
+ import logging
2
+ from typing import Dict, Any, Optional, Tuple
3
+
4
+ from sfn_blueprint.utils.llm_handler import SFNAIHandler
5
+
6
+ from .config import GluonConfig
7
+ from .constants import (
8
+ format_autogluon_config_prompt,
9
+ AUTOGLUON_CONFIG_SYSTEM_PROMPT,
10
+ AUTOGLUON_STRUCTURING_SYSTEM_PROMPT,
11
+ )
12
+ from .models import AutoGluonConfig
13
+
14
+
15
+ class AutoGluonConfigAgent:
16
+ """
17
+ Two-stage AutoGluon configuration agent:
18
+
19
+ Agent 1 → Reasoning / recommendation (human-style)
20
+ Agent 2 → Structuring / strict JSON (Pydantic enforced)
21
+ """
22
+
23
+ def __init__(self, config: Optional[GluonConfig] = None):
24
+ self.config = config or GluonConfig()
25
+ self.logger = logging.getLogger(__name__)
26
+ self.ai_handler = SFNAIHandler(logger_name="AutoGluonConfigAgent")
27
+
28
+ def _run_reasoning_agent(
29
+ self,
30
+ domain: Dict[str, Any],
31
+ use_case: Dict[str, Any],
32
+ methodology: str,
33
+ dataset_insights: Dict[str, Any],
34
+ ) -> Tuple[str, Dict[str, Any]]:
35
+
36
+ system_prompt, user_prompt = format_autogluon_config_prompt(
37
+ domain=domain,
38
+ use_case=use_case,
39
+ methodology=methodology,
40
+ dataset_insights=dataset_insights,
41
+ )
42
+
43
+ response, cost = self.ai_handler.route_to(
44
+ llm_provider=self.config.provider,
45
+ model=self.config.model,
46
+ configuration={
47
+ "messages": [
48
+ {"role": "system", "content": AUTOGLUON_CONFIG_SYSTEM_PROMPT},
49
+ {"role": "user", "content": user_prompt},
50
+ ],
51
+ "temperature": self.config.temperature,
52
+ "max_tokens": self.config.max_tokens,
53
+ },
54
+ )
55
+
56
+ return response, cost
57
+
58
+
59
+ def _run_structuring_agent(
60
+ self,
61
+ reasoning_output: str,
62
+ ) -> Tuple[AutoGluonConfig, Dict[str, Any]]:
63
+
64
+ response, cost = self.ai_handler.route_to(
65
+ llm_provider=self.config.provider,
66
+ model=self.config.model,
67
+ configuration={
68
+ "messages": [
69
+ {
70
+ "role": "system",
71
+ "content": AUTOGLUON_STRUCTURING_SYSTEM_PROMPT,
72
+ },
73
+ {
74
+ "role": "user",
75
+ "content": reasoning_output,
76
+ },
77
+ ],
78
+ "temperature": self.config.temperature,
79
+ "max_tokens": self.config.max_tokens,
80
+ },
81
+ )
82
+
83
+ config = AutoGluonConfig.model_validate_json(response)
84
+
85
+ return config, cost
86
+
87
+
88
+ def configure_training(
89
+ self,
90
+ domain: Dict[str, Any],
91
+ use_case: Dict[str, Any],
92
+ methodology: str,
93
+ dataset_insights: Dict[str, Any],
94
+ ) -> Tuple[AutoGluonConfig, Dict[str, Any]]:
95
+
96
+ reasoning_output, cost_1 = self._run_reasoning_agent(
97
+ domain, use_case, methodology, dataset_insights
98
+ )
99
+
100
+ config, cost_2 = self._run_structuring_agent(reasoning_output)
101
+
102
+ return config, {
103
+ "reasoning_agent": cost_1,
104
+ "structuring_agent": cost_2,
105
+ }
106
+
107
+ def execute_task(self, task_data: Dict[str, Any]) -> Dict[str, Any]:
108
+ config, cost = self.configure_training(
109
+ domain=task_data["domain"],
110
+ use_case=task_data["use_case"],
111
+ methodology=task_data["methodology"],
112
+ dataset_insights=task_data["dataset_insights"],
113
+ )
114
+
115
+ return {
116
+ "configuration": config.model_dump(),
117
+ "cost_summary": cost,
118
+ }
119
+
120
+ def __call__(self, task_data: Dict[str, Any]) -> Dict[str, Any]:
121
+ return self.execute_task(task_data)
@@ -0,0 +1,26 @@
1
+ from pydantic import Field
2
+ from pydantic_settings import BaseSettings, SettingsConfigDict
3
+ import os
4
+
5
+
6
+
7
+ class GluonConfig(BaseSettings):
8
+ model_config = SettingsConfigDict(
9
+ env_file='.env',
10
+ env_file_encoding='utf-8',
11
+ case_sensitive=False,
12
+ extra='ignore'
13
+ )
14
+
15
+ # provider: str = Field(default="openai", description="AI provider to use")
16
+ # model: str = Field(default="gpt-5-mini", description="AI model to use")
17
+ # temperature: float = Field(default=0.3, ge=0.0, le=0.5, description="AI model temperature")
18
+ # max_tokens: int = Field(default=4000, ge=0, le=8000, description="Maximum tokens for AI response")
19
+
20
+
21
+ # This will now read from LM_PROVIDER environment variable
22
+ provider: str = Field(default=os.getenv('LM_SERVICE_PROVIDER', 'openai'), description="AI provider to use")
23
+ model: str = Field(default=os.getenv('LLM_MODEL_NAME', 'gpt-5-mini'), description="AI model to use")
24
+ temperature: float = Field(default=0.3, ge=0.0, le=0.5, description="AI model temperature")
25
+ max_tokens: int = Field(default=4000, ge=0, le=8000, description="Maximum tokens for AI response")
26
+
@@ -0,0 +1,210 @@
1
+ AUTOGLUON_CONFIG_SYSTEM_PROMPT = """You are an expert AutoGluon configuration advisor specializing in TabularPredictor. Your goal is to provide production-ready configurations that optimize predictive performance while strictly adhering to the defined schema.
2
+
3
+ Your role is to analyze the business domain and dataset characteristics to recommend optimal settings.
4
+
5
+ CORE MODEL CONCEPTS:
6
+ ====================
7
+
8
+ 1. EVALUATION METRICS (Must be one of: 'accuracy', 'log_loss', 'f1', 'roc_auc', 'precision', 'recall'):
9
+ - Use 'roc_auc' or 'f1' for imbalanced classification.
10
+ - Use 'precision' or 'recall' when the cost of False Positives vs. False Negatives is asymmetric.
11
+ - Use 'log_loss' for well-calibrated probability estimates.
12
+
13
+ 2. ENSEMBLE STRATEGY:
14
+ - BAGGING (num_bag_folds): Essential for 'best_quality' or 'extreme_quality'. If > 0, k-fold cross-validation is used.
15
+ - STACKING (num_stack_levels): Uses model predictions as features for higher layers. 1-2 levels recommended for 'extreme_quality'.
16
+ - WEIGHTED ENSEMBLE: Always set fit_weighted_ensemble=True for maximum accuracy.
17
+
18
+ 3. ALLOWED MODELS (Only use these aliases):
19
+ - 'GBM': LightGBM (Gradient Boosting Machine).
20
+ - 'CAT': CatBoost (Excellent for categorical data).
21
+ - 'XGB': XGBoost (High-performance gradient boosting).
22
+ - 'RF': Random Forest (Robust and stable).
23
+ - 'XT': Extremely Randomized Trees (Reduces variance).
24
+ - 'KNN': K-Nearest Neighbors (Simple distance-based baseline).
25
+
26
+ 4. VALIDATION STRATEGY:
27
+ - If bagging is enabled (num_bag_folds > 0), 'split_test_size' is ignored as CV is used.
28
+ - If bagging is 0, 'split_test_size' (e.g., 0.1 to 0.2) is mandatory to monitor overfitting.
29
+
30
+ PRESET SELECTION LOGIC (Ordered by Quality/Complexity):
31
+ ======================================================
32
+
33
+ - "best_quality": High accuracy with bagging/stacking. Standard for competitions.
34
+ - "high_quality": Balance of high accuracy and reasonable training time.
35
+ - "good_quality": Recommended default for most production use cases.
36
+ - "medium_quality": Fast prototyping and quick iterations.
37
+
38
+ DOMAIN GUIDANCE:
39
+ ================
40
+ - FRAUD/HEALTHCARE: High recall focus. Use 'f1' or 'roc_auc'. Enable bagging for stability.
41
+ - AD TECH/CLICK-THROUGH: Use 'log_loss' to optimize probability calibration.
42
+ - CUSTOMER CHURN: Focus on 'f1' to balance identifying leavers vs. misclassifying loyalists.
43
+
44
+ CONSTRAINTS:
45
+ - You MUST only use the 6 allowed models ('GBM', 'CAT', 'XGB', 'RF', 'XT', 'KNN').
46
+ - You MUST only use the 5 allowed presets ('extreme_quality', 'best_quality', 'high_quality', 'good_quality', 'medium_quality').
47
+ - You MUST only use the 6 allowed metrics for both eval_metric and additional_metrics.
48
+
49
+ Provide three distinct scenarios: Max Accuracy (Heavy), Production-Ready (Balanced), and Fast-Track (Speed)."""
50
+
51
+
52
+
53
+ AUTOGLUON_STRUCTURING_SYSTEM_PROMPT = """
54
+ You are a STRICT JSON CONVERSION AGENT.
55
+
56
+ You will receive a human-written AutoGluon recommendation that may contain:
57
+ - multiple scenarios
58
+ - explanations
59
+ - markdown
60
+ - YAML blocks
61
+
62
+ YOUR TASK:
63
+ 1. Select ONLY the **Production-Ready / Balanced** scenario
64
+ 2. Convert it into VALID JSON
65
+ 3. The JSON MUST strictly match this schema:
66
+
67
+ - The 'models' field MUST include at least one model from the allowed list: ['GBM', 'CAT', 'XGB', 'RF', 'XT']
68
+ - If num_bag_folds > 0, set split_test_size to 0.0 (as bagging handles validation)
69
+ - If num_bag_folds = 0, set split_test_size to a value between 0.1 and 0.5
70
+
71
+
72
+ {
73
+ "eval_metric": string,
74
+ "preset": string,
75
+ "additional_metrics": list[string],
76
+ "time_limit": integer,
77
+ "num_bag_folds": integer,
78
+ "num_bag_sets": integer,
79
+ "num_stack_levels": integer,
80
+ "models": list[string],
81
+ "fit_weighted_ensemble": boolean,
82
+ "split_test_size": float # Must be one of: 0.1, 0.15, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, or 0.5
83
+ }
84
+
85
+ STRICT RULES:
86
+ - OUTPUT JSON ONLY
87
+ - NO markdown
88
+ - NO YAML
89
+ - NO explanations
90
+ - NO comments
91
+ - NO extra keys
92
+ - Start with '{' and end with '}'
93
+ """
94
+
95
+
96
+ def format_autogluon_config_prompt(
97
+ domain: dict,
98
+ use_case: str,
99
+ methodology: str,
100
+ dataset_insights: dict
101
+ ) -> tuple[str, str]:
102
+ """
103
+ Format the system and user prompts for AutoGluon configuration recommendation.
104
+
105
+ Args:
106
+ domain_name: Name of the business domain
107
+ domain_description: Detailed description of the domain context
108
+ use_case: Description of the specific use case and problem
109
+ methodology: Type of ML problem (binary_classification, multiclass_classification, regression)
110
+ dataset_insights: Dictionary containing feature and target information
111
+
112
+ Returns:
113
+ Tuple of (system_prompt, user_prompt)
114
+ """
115
+
116
+ # feature_columns = dataset_insights.get('feature_columns', {})
117
+ # target_info = dataset_insights.get('target', {})
118
+
119
+ # feature_summary = []
120
+ # for col_name, col_info in feature_columns.items():
121
+ # feature_summary.append(
122
+ # f" - {col_name}: "
123
+ # f"type={col_info.get('dtype', 'unknown')}, "
124
+ # f"missing={col_info.get('missing_pct', 0):.1f}%, "
125
+ # f"unique={col_info.get('unique_count', 'N/A')}"
126
+ # )
127
+ # if 'min' in col_info and 'max' in col_info:
128
+ # feature_summary.append(f" range=[{col_info['min']}, {col_info['max']}]")
129
+
130
+ # feature_text = "\n".join(feature_summary) if feature_summary else "No feature information provided"
131
+
132
+ # # Format target information
133
+ # target_text = []
134
+ # if target_info:
135
+ # target_text.append(f"Target Column: {target_info.get('name', 'unknown')}")
136
+ # target_text.append(f" Type: {target_info.get('dtype', 'unknown')}")
137
+
138
+ # if 'class_distribution' in target_info:
139
+ # target_text.append(" Class Distribution:")
140
+ # for cls, count in target_info['class_distribution'].items():
141
+ # target_text.append(f" - {cls}: {count}")
142
+
143
+ # if 'min' in target_info and 'max' in target_info:
144
+ # target_text.append(f" Range: [{target_info['min']}, {target_info['max']}]")
145
+
146
+ # if 'mean' in target_info:
147
+ # target_text.append(f" Mean: {target_info['mean']:.2f}")
148
+
149
+ # target_summary = "\n".join(target_text) if target_text else "No target information provided"
150
+
151
+ # # Get dataset size information
152
+ # num_samples = dataset_insights.get('num_samples', 'unknown')
153
+ # num_features = len(feature_columns) if feature_columns else 'unknown'
154
+
155
+ # DATASET INSIGHTS:
156
+ # ================
157
+ # Number of Samples: {num_samples}
158
+ # Number of Features: {num_features}
159
+
160
+ # Features:
161
+ # {feature_text}
162
+
163
+ # {target_summary}
164
+ # 8. hyperparameters: Hyperparameter preset ("default", "light", "very_light")
165
+ # 9. auto_stack: Whether to use automatic stacking (true/false)
166
+ # 10. infer_limit: Max inference time per row in seconds (or null)
167
+ # 11. infer_limit_batch_size: Batch size for inference speed (or null)
168
+ # 12. refit_full: Whether to retrain on full data (true/false)
169
+ # 13. calibrate_decision_threshold: Threshold calibration setting ("auto", true, false)
170
+
171
+
172
+ user_prompt = f"""Please recommend optimal AutoGluon TabularPredictor configuration for the following scenario:
173
+
174
+ DOMAIN INFORMATION:
175
+ ==================
176
+ Domain: {domain}
177
+
178
+ USE CASE:
179
+ =========
180
+ {use_case}
181
+
182
+ METHODOLOGY:
183
+ ===========
184
+ Problem Type: {methodology}
185
+
186
+ DATASET INSIGHTS:
187
+ ================
188
+ {dataset_insights}
189
+
190
+ TASK:
191
+ =====
192
+ Based on the above information, recommend an optimal AutoGluon configuration that includes:
193
+
194
+ 1. eval_metric: The primary metric to optimize
195
+ 2. preset: Quality/speed tradeoff preset
196
+ 3. additional_metrics: Other metrics to track (list)
197
+ 4. time_limit: Training time in seconds
198
+ 5. num_bag_folds: Number of k-fold bagging folds (0 for none, 5-10 for bagging)
199
+ 6. num_bag_sets: Number of bagging sets (1-3, only if bagging is used)
200
+ 7. num_stack_levels: Number of stacking levels
201
+
202
+
203
+ Consider multiple scenarios:
204
+ - Scenario A: Maximum accuracy (accepting longer training time)
205
+ - Scenario B: Balanced accuracy and speed (production-ready)
206
+ - Scenario C: Fast training and inference (prototyping/deployment constrained)
207
+
208
+ """
209
+
210
+ return AUTOGLUON_CONFIG_SYSTEM_PROMPT, user_prompt
@@ -0,0 +1,61 @@
1
+ from pydantic import BaseModel, Field
2
+ from typing import List, Literal
3
+
4
+ class AutoGluonConfig(BaseModel):
5
+ eval_metric: str = Field(
6
+ ...,
7
+ description="Primary metric to optimize. Allowed: 'accuracy', 'log_loss', 'f1', 'roc_auc', 'precision', 'recall'."
8
+ )
9
+
10
+ preset: Literal[
11
+ 'best_quality', 'high_quality', 'good_quality', 'medium_quality'
12
+ ] = Field(
13
+ ...,
14
+ description="Preset configurations. 'extreme_quality' and 'best_quality' enable bagging/stacking for maximum accuracy."
15
+ )
16
+
17
+ additional_metrics: List[str] = Field(
18
+ ...,
19
+ description="List of additional metrics to track. Allowed: 'accuracy', 'log_loss', 'f1', 'roc_auc', 'precision', 'recall'."
20
+ )
21
+
22
+ time_limit: int = Field(
23
+ ...,
24
+ description="Total training time in seconds. AutoGluon will distribute this across models. Small datasets: 300, Medium: 3600, Large: 7200+."
25
+ )
26
+
27
+ num_bag_folds: int = Field(
28
+ ...,
29
+ description="Number of folds for k-fold bagging. 0 = no bagging. 5-10 is standard for 'best_quality'. Bagging reduces variance and allows the model to be trained on all data (if refit_full=True)."
30
+ )
31
+
32
+ num_bag_sets: int = Field(
33
+ ...,
34
+ description="Number of bagging sets. Each set repeats k-fold bagging to reduce variance further. Only used if num_bag_folds > 0. Usually 1-3."
35
+ )
36
+
37
+ num_stack_levels: int = Field(
38
+ ...,
39
+ description="Levels of stacking. 0 = no stacking, 1 = one level (models trained on base model predictions). Higher values increase accuracy but exponentially increase training time."
40
+ )
41
+
42
+ models: list[str] = Field(
43
+ ...,
44
+ description="""Models to train.
45
+ 'GBM',
46
+ 'CAT',
47
+ 'XGB',
48
+ 'RF',
49
+ 'XT',
50
+ 'KNN'. """
51
+ )
52
+
53
+ fit_weighted_ensemble: bool = Field(
54
+ ...,
55
+ description="Whether to fit an ensemble that weights predictions of base models to improve accuracy. Usually recommended to keep True."
56
+ )
57
+
58
+ split_test_size: float = Field(
59
+ ...,
60
+ description="Fraction of data held out for validation. You MUST choose exactly one value from: [0.1, 0.15, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5]."
61
+ )
@@ -0,0 +1,120 @@
1
+ Metadata-Version: 2.4
2
+ Name: experiment-configuration-agent
3
+ Version: 0.1.6
4
+ Summary: Add your description here
5
+ Requires-Python: >=3.10
6
+ Description-Content-Type: text/markdown
7
+ Requires-Dist: pydantic-settings
8
+ Requires-Dist: sfn-blueprint>=0.7.4
9
+ Provides-Extra: dev
10
+ Requires-Dist: pytest; extra == "dev"
11
+ Requires-Dist: pytest-mock; extra == "dev"
12
+
13
+ # Experiment Configuration Agent for AutoGluon
14
+
15
+ This agent uses a Large Language Model to recommend optimal configurations for AutoGluon's `TabularPredictor` based on your machine learning problem context. By providing details about your domain, use case, and dataset, the agent will generate a set of `TabularPredictor` parameters designed to optimize for performance and efficiency.
16
+
17
+ ## Features
18
+
19
+ - **Intelligent Configuration:** Leverages LLMs to recommend `eval_metric`, `presets`, `time_limit`, and ensembling parameters.
20
+ - **Context-Aware:** Considers the business domain, specific use case, ML methodology (e.g., classification, regression), and dataset characteristics.
21
+ - **Flexible Backend:** Powered by `sfn-blueprint`, allowing for a configurable LLM backend.
22
+ - **Multiple Scenarios:** Provides recommendations for different optimization goals, such as maximizing accuracy, balancing performance and speed, or fast prototyping.
23
+
24
+ ## Installation
25
+
26
+ This project uses `uv` for dependency management and requires Python 3.10 or higher.
27
+
28
+ 1. **Clone the repository:**
29
+ ```bash
30
+ git clone https://github.com/stepfnAI/experiment_config_agent.git
31
+ cd experiment-configuration-agent
32
+ ```
33
+
34
+ 2. **Set up the environment and install dependencies:**
35
+ It is recommended to use a virtual environment. `uv` can create one for you.
36
+ ```bash
37
+ # Create a virtual environment and install dependencies
38
+ uv sync --extra dev
39
+ source .venv/bin/activate
40
+ ```
41
+
42
+ ## Usage
43
+
44
+ ### Basic usage
45
+ ```python
46
+ python ./examples/basic_usage.py
47
+ ```
48
+
49
+ To get a configuration recommendation, instantiate the `AutoGluonConfigAgent` and pass a dictionary containing the problem context.
50
+
51
+ 1. **Create a `.env` file** in the project root to configure the LLM provider. See the [Configuration](#configuration) section for more details.
52
+
53
+ ```
54
+ PROVIDER="openai"
55
+ MODEL="gpt-4-turbo"
56
+ # Add your API key, e.g., OPENAI_API_KEY="sk-..."
57
+ ```
58
+
59
+ 2. **Create your Python script:**
60
+
61
+ ```python
62
+ from experiment_configuration_agent.agent import AutoGluonConfigAgent
63
+
64
+ # 1. Define the problem context
65
+ task_data = {
66
+ "domain": {
67
+ "name": "Manufacturing",
68
+ "description": "An automotive parts manufacturing facility with multiple production lines."
69
+ },
70
+ "use_case": {
71
+ "name": "Predictive Maintenance",
72
+ "description": "Detect unusual temporal patterns in sensor data to predict equipment failure and prevent breakdowns."
73
+ },
74
+ "methodology": "binary_classification",
75
+ "dataset_insights": {
76
+ "num_samples": 5000,
77
+ "num_features": 10,
78
+ "target": {
79
+ "name": "failure_flag",
80
+ "imbalance_ratio": 0.05 # Highly imbalanced
81
+ },
82
+ "feature_summary": {
83
+ "sensor_A": {"min": 0.1, "max": 100.5, "dtype": "float"},
84
+ "production_line_id": {"unique_count": 3, "dtype": "category"}
85
+ }
86
+ }
87
+ }
88
+
89
+ # 2. Initialize the agent
90
+ agent = AutoGluonConfigAgent()
91
+
92
+ # 3. Get the configuration recommendation
93
+ result = agent(task_data)
94
+
95
+ # 4. Print the result
96
+ print("Recommended AutoGluon Configuration:")
97
+ print(result.get("configuration"))
98
+ print("\nCost Summary:")
99
+ print(result.get("cost_summary"))
100
+
101
+ ```
102
+
103
+ ## Configuration
104
+
105
+ The agent is configured via environment variables, which can be placed in a `.env` file in the project root. The primary configurations are inherited from the `GluonConfig` class.
106
+
107
+ - `PROVIDER`: The LLM provider to use (e.g., `"openai"`, `"anthropic"`).
108
+ - `MODEL`: The specific model to use (e.g., `"gpt-4-turbo"`, `"claude-3-opus-20240229"`).
109
+ - `TEMPERATURE`: The model's temperature setting (e.g., `0.3`).
110
+ - `MAX_TOKENS`: The maximum number of tokens for the response (e.g., `4000`).
111
+
112
+ You will also need to set the API key for your chosen provider, for example `OPENAI_API_KEY="your-key-here"`.
113
+
114
+ ## Testing
115
+
116
+ This project uses `pytest`. To run the test suite, execute the following command from the project root:
117
+
118
+ ```bash
119
+ pytest
120
+ ```
@@ -0,0 +1,9 @@
1
+ experiment_config_agent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ experiment_config_agent/agent.py,sha256=bjFBjyR0_0hRUePfCDICitGfG7fVuZxBhPkwZZ0gsxM,3700
3
+ experiment_config_agent/config.py,sha256=yAS1XWdOklcpuHwq5F3u-j2zQmX-ErLowj9IqcgnqH4,1138
4
+ experiment_config_agent/constants.py,sha256=O7fsJQXVmt8Zs-A3sYxTafyNdpQv2H4tbL3E--rJ7Ug,8167
5
+ experiment_config_agent/models.py,sha256=u8bANPWUUE2hlH8S7ZA2N9bRKuN6vp7vGRpVRwXn-aE,2271
6
+ experiment_configuration_agent-0.1.6.dist-info/METADATA,sha256=y30snhqZgHUF5XXxG8DCPR9-1uQ2XplYdu-h6TEfu-I,4453
7
+ experiment_configuration_agent-0.1.6.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
8
+ experiment_configuration_agent-0.1.6.dist-info/top_level.txt,sha256=5c9CyVEjFUlvEf08vJIvi6BkzGuS4wdwtjdmCk2uL2U,24
9
+ experiment_configuration_agent-0.1.6.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (80.9.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1 @@
1
+ experiment_config_agent