fluxloop-cli 0.2.0__tar.gz → 0.2.2__tar.gz
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.
Potentially problematic release.
This version of fluxloop-cli might be problematic. Click here for more details.
- {fluxloop_cli-0.2.0 → fluxloop_cli-0.2.2}/PKG-INFO +1 -1
- {fluxloop_cli-0.2.0 → fluxloop_cli-0.2.2}/fluxloop_cli/__init__.py +1 -1
- {fluxloop_cli-0.2.0 → fluxloop_cli-0.2.2}/fluxloop_cli/config_loader.py +39 -1
- {fluxloop_cli-0.2.0 → fluxloop_cli-0.2.2}/fluxloop_cli/input_generator.py +8 -28
- {fluxloop_cli-0.2.0 → fluxloop_cli-0.2.2}/fluxloop_cli/main.py +2 -1
- {fluxloop_cli-0.2.0 → fluxloop_cli-0.2.2}/fluxloop_cli/templates.py +3 -3
- {fluxloop_cli-0.2.0 → fluxloop_cli-0.2.2}/fluxloop_cli.egg-info/PKG-INFO +1 -1
- {fluxloop_cli-0.2.0 → fluxloop_cli-0.2.2}/pyproject.toml +1 -1
- {fluxloop_cli-0.2.0 → fluxloop_cli-0.2.2}/README.md +0 -0
- {fluxloop_cli-0.2.0 → fluxloop_cli-0.2.2}/fluxloop_cli/arg_binder.py +0 -0
- {fluxloop_cli-0.2.0 → fluxloop_cli-0.2.2}/fluxloop_cli/commands/__init__.py +0 -0
- {fluxloop_cli-0.2.0 → fluxloop_cli-0.2.2}/fluxloop_cli/commands/config.py +0 -0
- {fluxloop_cli-0.2.0 → fluxloop_cli-0.2.2}/fluxloop_cli/commands/generate.py +0 -0
- {fluxloop_cli-0.2.0 → fluxloop_cli-0.2.2}/fluxloop_cli/commands/init.py +0 -0
- {fluxloop_cli-0.2.0 → fluxloop_cli-0.2.2}/fluxloop_cli/commands/parse.py +0 -0
- {fluxloop_cli-0.2.0 → fluxloop_cli-0.2.2}/fluxloop_cli/commands/record.py +0 -0
- {fluxloop_cli-0.2.0 → fluxloop_cli-0.2.2}/fluxloop_cli/commands/run.py +0 -0
- {fluxloop_cli-0.2.0 → fluxloop_cli-0.2.2}/fluxloop_cli/commands/status.py +0 -0
- {fluxloop_cli-0.2.0 → fluxloop_cli-0.2.2}/fluxloop_cli/config_schema.py +0 -0
- {fluxloop_cli-0.2.0 → fluxloop_cli-0.2.2}/fluxloop_cli/constants.py +0 -0
- {fluxloop_cli-0.2.0 → fluxloop_cli-0.2.2}/fluxloop_cli/llm_generator.py +0 -0
- {fluxloop_cli-0.2.0 → fluxloop_cli-0.2.2}/fluxloop_cli/project_paths.py +0 -0
- {fluxloop_cli-0.2.0 → fluxloop_cli-0.2.2}/fluxloop_cli/runner.py +0 -0
- {fluxloop_cli-0.2.0 → fluxloop_cli-0.2.2}/fluxloop_cli/target_loader.py +0 -0
- {fluxloop_cli-0.2.0 → fluxloop_cli-0.2.2}/fluxloop_cli/validators.py +0 -0
- {fluxloop_cli-0.2.0 → fluxloop_cli-0.2.2}/fluxloop_cli.egg-info/SOURCES.txt +0 -0
- {fluxloop_cli-0.2.0 → fluxloop_cli-0.2.2}/fluxloop_cli.egg-info/dependency_links.txt +0 -0
- {fluxloop_cli-0.2.0 → fluxloop_cli-0.2.2}/fluxloop_cli.egg-info/entry_points.txt +0 -0
- {fluxloop_cli-0.2.0 → fluxloop_cli-0.2.2}/fluxloop_cli.egg-info/requires.txt +0 -0
- {fluxloop_cli-0.2.0 → fluxloop_cli-0.2.2}/fluxloop_cli.egg-info/top_level.txt +0 -0
- {fluxloop_cli-0.2.0 → fluxloop_cli-0.2.2}/setup.cfg +0 -0
- {fluxloop_cli-0.2.0 → fluxloop_cli-0.2.2}/tests/test_arg_binder.py +0 -0
- {fluxloop_cli-0.2.0 → fluxloop_cli-0.2.2}/tests/test_config_command.py +0 -0
- {fluxloop_cli-0.2.0 → fluxloop_cli-0.2.2}/tests/test_input_generator.py +0 -0
- {fluxloop_cli-0.2.0 → fluxloop_cli-0.2.2}/tests/test_target_loader.py +0 -0
|
@@ -22,7 +22,7 @@ from .constants import CONFIG_DIRECTORY_NAME
|
|
|
22
22
|
# Add shared schemas to path
|
|
23
23
|
sys.path.insert(0, str(Path(__file__).parent.parent.parent.parent / "shared"))
|
|
24
24
|
|
|
25
|
-
from fluxloop.schemas import ExperimentConfig
|
|
25
|
+
from fluxloop.schemas import ExperimentConfig, VariationStrategy
|
|
26
26
|
|
|
27
27
|
|
|
28
28
|
def load_experiment_config(
|
|
@@ -75,6 +75,8 @@ def load_experiment_config(
|
|
|
75
75
|
data = merged
|
|
76
76
|
source_dir = project_root
|
|
77
77
|
|
|
78
|
+
_normalize_variation_strategies(data)
|
|
79
|
+
|
|
78
80
|
# Validate and create config object
|
|
79
81
|
try:
|
|
80
82
|
config = ExperimentConfig(**data)
|
|
@@ -222,6 +224,42 @@ def _deep_merge(target: Dict[str, Any], incoming: Dict[str, Any]) -> Dict[str, A
|
|
|
222
224
|
return target
|
|
223
225
|
|
|
224
226
|
|
|
227
|
+
def _normalize_variation_strategies(payload: Dict[str, Any]) -> None:
|
|
228
|
+
"""Ensure variation strategies are represented as enum-compatible strings."""
|
|
229
|
+
|
|
230
|
+
strategies = payload.get("variation_strategies")
|
|
231
|
+
if not isinstance(strategies, list):
|
|
232
|
+
return
|
|
233
|
+
|
|
234
|
+
normalized = []
|
|
235
|
+
for entry in strategies:
|
|
236
|
+
if isinstance(entry, VariationStrategy):
|
|
237
|
+
normalized.append(entry.value)
|
|
238
|
+
continue
|
|
239
|
+
|
|
240
|
+
candidate: Optional[str]
|
|
241
|
+
if isinstance(entry, str):
|
|
242
|
+
candidate = entry
|
|
243
|
+
elif isinstance(entry, dict):
|
|
244
|
+
candidate = (
|
|
245
|
+
entry.get("type")
|
|
246
|
+
or entry.get("name")
|
|
247
|
+
or entry.get("strategy")
|
|
248
|
+
or entry.get("value")
|
|
249
|
+
)
|
|
250
|
+
else:
|
|
251
|
+
candidate = str(entry)
|
|
252
|
+
|
|
253
|
+
if not candidate:
|
|
254
|
+
continue
|
|
255
|
+
|
|
256
|
+
normalized.append(
|
|
257
|
+
candidate.strip().lower().replace(" ", "_").replace("-", "_")
|
|
258
|
+
)
|
|
259
|
+
|
|
260
|
+
payload["variation_strategies"] = normalized
|
|
261
|
+
|
|
262
|
+
|
|
225
263
|
def _detect_config_context(resolved_path: Path) -> tuple[str, Path, Path]:
|
|
226
264
|
"""Determine whether the path points to legacy or multi-section config."""
|
|
227
265
|
|
|
@@ -88,40 +88,27 @@ class GenerationError(Exception):
|
|
|
88
88
|
def generate_inputs(
|
|
89
89
|
config: ExperimentConfig,
|
|
90
90
|
settings: GenerationSettings,
|
|
91
|
-
recording_template: Optional[Dict[str, Any]] = None,
|
|
92
91
|
) -> GenerationResult:
|
|
93
92
|
"""Generate deterministic input entries based on configuration."""
|
|
94
93
|
base_inputs = config.base_inputs
|
|
95
|
-
config_for_generation = config
|
|
96
|
-
if recording_template:
|
|
97
|
-
base_inputs = [
|
|
98
|
-
{
|
|
99
|
-
"input": recording_template["base_content"],
|
|
100
|
-
"metadata": {
|
|
101
|
-
"source": "recording",
|
|
102
|
-
"target": recording_template.get("target"),
|
|
103
|
-
},
|
|
104
|
-
}
|
|
105
|
-
]
|
|
106
|
-
config_for_generation = config.model_copy(update={"base_inputs": base_inputs})
|
|
107
94
|
|
|
108
95
|
if not base_inputs:
|
|
109
96
|
raise GenerationError("base_inputs must be defined to generate inputs")
|
|
110
97
|
|
|
111
|
-
mode = settings.mode or
|
|
98
|
+
mode = settings.mode or config.input_generation.mode
|
|
112
99
|
|
|
113
100
|
if mode == InputGenerationMode.LLM:
|
|
114
101
|
strategies: Sequence[VariationStrategy]
|
|
115
102
|
if settings.strategies and len(settings.strategies) > 0:
|
|
116
103
|
strategies = list(settings.strategies)
|
|
117
|
-
elif
|
|
118
|
-
strategies =
|
|
104
|
+
elif config.variation_strategies:
|
|
105
|
+
strategies = config.variation_strategies
|
|
119
106
|
else:
|
|
120
107
|
strategies = DEFAULT_STRATEGIES
|
|
121
108
|
|
|
122
109
|
try:
|
|
123
110
|
raw_entries = generate_llm_inputs(
|
|
124
|
-
config=
|
|
111
|
+
config=config,
|
|
125
112
|
strategies=strategies,
|
|
126
113
|
settings=settings,
|
|
127
114
|
)
|
|
@@ -134,23 +121,16 @@ def generate_inputs(
|
|
|
134
121
|
]
|
|
135
122
|
|
|
136
123
|
metadata = {
|
|
137
|
-
"config_name":
|
|
124
|
+
"config_name": config.name,
|
|
138
125
|
"total_base_inputs": len(base_inputs),
|
|
139
|
-
"total_personas": len(
|
|
126
|
+
"total_personas": len(config.personas),
|
|
140
127
|
"strategies": [strategy.value for strategy in strategies],
|
|
141
128
|
"limit": settings.limit,
|
|
142
129
|
"generation_mode": InputGenerationMode.LLM.value,
|
|
143
|
-
"llm_provider":
|
|
144
|
-
"llm_model":
|
|
130
|
+
"llm_provider": config.input_generation.llm.provider,
|
|
131
|
+
"llm_model": config.input_generation.llm.model,
|
|
145
132
|
}
|
|
146
133
|
|
|
147
|
-
if recording_template:
|
|
148
|
-
for entry in entries:
|
|
149
|
-
entry.metadata["args_template"] = "use_recorded"
|
|
150
|
-
entry.metadata["template_kwargs"] = recording_template.get("full_kwargs")
|
|
151
|
-
metadata["recording_target"] = recording_template.get("target")
|
|
152
|
-
metadata["recording_base_input"] = recording_template.get("base_content")
|
|
153
|
-
|
|
154
134
|
return GenerationResult(entries=entries, metadata=metadata)
|
|
155
135
|
|
|
156
136
|
raise GenerationError(
|
|
@@ -11,7 +11,7 @@ from rich.console import Console
|
|
|
11
11
|
from rich.panel import Panel
|
|
12
12
|
|
|
13
13
|
from . import __version__
|
|
14
|
-
from .commands import config, generate, init, parse, run, status
|
|
14
|
+
from .commands import config, generate, init, parse, run, status, record
|
|
15
15
|
|
|
16
16
|
# Create the main Typer app
|
|
17
17
|
app = typer.Typer(
|
|
@@ -31,6 +31,7 @@ app.add_typer(status.app, name="status", help="Check status and view results")
|
|
|
31
31
|
app.add_typer(config.app, name="config", help="Manage configuration")
|
|
32
32
|
app.add_typer(generate.app, name="generate", help="Generate input datasets")
|
|
33
33
|
app.add_typer(parse.app, name="parse", help="Parse experiments into readable files")
|
|
34
|
+
app.add_typer(record.app, name="record", help="Manage recording mode and settings")
|
|
34
35
|
|
|
35
36
|
|
|
36
37
|
def version_callback(value: bool):
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|