Skip to content

Commit 45c56fd

Browse files
Expose unified synthesis mode via the CLI
The CLI (python llama_stack_configuration.py -c config.yaml) only called generate_configuration(), the legacy enrichment mode that requires an already-built run.yaml as input. There was no CLI path to synthesize_configuration()/synthesize_to_file(), the unified mode that builds run.yaml from lightspeed-stack.yaml alone, so consumers of unified mode had to import the module instead of using the documented script interface. Add a --synthesize flag: when set, the CLI builds the config via synthesize_to_file() from -c alone (ignoring -i), instead of enriching an existing run.yaml. An empty or comment-only -c file now loads as {} rather than None, so it doesn't crash synthesize_to_file() with an opaque AttributeError.
1 parent 0362d70 commit 45c56fd

2 files changed

Lines changed: 118 additions & 5 deletions

File tree

src/llama_stack_configuration.py

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1481,7 +1481,7 @@ def generate_configuration(
14811481
def main() -> None:
14821482
"""CLI entry point."""
14831483
parser = ArgumentParser(
1484-
description="Enrich Llama Stack config with Lightspeed values",
1484+
description="Enrich or synthesize Llama Stack config from Lightspeed values",
14851485
)
14861486
parser.add_argument(
14871487
"-c",
@@ -1493,20 +1493,32 @@ def main() -> None:
14931493
"-i",
14941494
"--input",
14951495
default="run.yaml",
1496-
help="Input Llama Stack config (default: run.yaml)",
1496+
help="Input Llama Stack config for legacy enrichment mode; ignored "
1497+
"with --synthesize (default: run.yaml)",
14971498
)
14981499
parser.add_argument(
14991500
"-o",
15001501
"--output",
15011502
default="run_.yaml",
1502-
help="Output enriched config (default: run_.yaml)",
1503+
help="Output config file (default: run_.yaml)",
1504+
)
1505+
parser.add_argument(
1506+
"--synthesize",
1507+
action="store_true",
1508+
help="Build a complete run.yaml from -c alone instead of enriching "
1509+
"an existing run.yaml given by -i",
15031510
)
15041511
args = parser.parse_args()
15051512

15061513
with open(args.config, "r", encoding="utf-8") as f:
1507-
config = yaml.safe_load(f)
1514+
config = yaml.safe_load(f) or {}
15081515

1509-
generate_configuration(args.input, args.output, config)
1516+
if args.synthesize:
1517+
synthesize_to_file(
1518+
config, args.output, config_file_dir=str(Path(args.config).parent)
1519+
)
1520+
else:
1521+
generate_configuration(args.input, args.output, config)
15101522

15111523

15121524
if __name__ == "__main__":

tests/unit/test_llama_stack_synthesize.py

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,11 @@
66
write-to-file step (persistent path, mode 0600).
77
"""
88

9+
# pylint: disable=too-many-lines
10+
911
import os
1012
import stat
13+
import sys
1114
from pathlib import Path
1215
from typing import Any, Optional, get_args
1316

@@ -20,6 +23,7 @@
2023
deep_merge_list_replace,
2124
ensure_mcp_tool_runtime,
2225
load_default_baseline,
26+
main,
2327
migrate_config_dumb,
2428
synthesize_configuration,
2529
synthesize_to_file,
@@ -915,6 +919,103 @@ def test_migrate_config_dumb_rejects_non_mapping_inputs(tmp_path: Path) -> None:
915919
migrate_config_dumb(str(empty_run), lcs_path, out_path)
916920

917921

922+
# ---------------------------------------------------------------------------
923+
# CLI entry point
924+
# ---------------------------------------------------------------------------
925+
926+
927+
def test_main_synthesize_flag_builds_run_yaml(
928+
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
929+
) -> None:
930+
"""--synthesize builds a complete run.yaml from -c alone."""
931+
config_path = tmp_path / "lightspeed-stack.yaml"
932+
config_path.write_text(
933+
yaml.dump(
934+
{
935+
"llama_stack": {
936+
"config": {
937+
"baseline": "empty",
938+
"native_override": {"version": 2, "apis": ["inference"]},
939+
}
940+
}
941+
}
942+
),
943+
encoding="utf-8",
944+
)
945+
output_path = tmp_path / "run.yaml"
946+
947+
monkeypatch.setattr(
948+
sys,
949+
"argv",
950+
[
951+
"llama_stack_configuration.py",
952+
"-c",
953+
str(config_path),
954+
"-o",
955+
str(output_path),
956+
"--synthesize",
957+
],
958+
)
959+
main()
960+
961+
result = yaml.safe_load(output_path.read_text(encoding="utf-8"))
962+
assert result == {"version": 2, "apis": ["inference"]}
963+
964+
965+
def test_main_default_uses_legacy_enrichment(
966+
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
967+
) -> None:
968+
"""Without --synthesize, the CLI keeps calling legacy generate_configuration."""
969+
config_path = tmp_path / "lightspeed-stack.yaml"
970+
config_path.write_text(yaml.dump({}), encoding="utf-8")
971+
input_path = tmp_path / "run.yaml"
972+
input_path.write_text(yaml.dump({"version": 2}), encoding="utf-8")
973+
output_path = tmp_path / "run_.yaml"
974+
975+
monkeypatch.setattr(
976+
sys,
977+
"argv",
978+
[
979+
"llama_stack_configuration.py",
980+
"-c",
981+
str(config_path),
982+
"-i",
983+
str(input_path),
984+
"-o",
985+
str(output_path),
986+
],
987+
)
988+
main()
989+
990+
result = yaml.safe_load(output_path.read_text(encoding="utf-8"))
991+
assert result["version"] == 2
992+
993+
994+
def test_main_synthesize_flag_handles_empty_config_file(
995+
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
996+
) -> None:
997+
"""An empty/comment-only -c file loads as {} instead of crashing on None."""
998+
config_path = tmp_path / "lightspeed-stack.yaml"
999+
config_path.write_text("# only a comment\n", encoding="utf-8")
1000+
output_path = tmp_path / "run.yaml"
1001+
1002+
monkeypatch.setattr(
1003+
sys,
1004+
"argv",
1005+
[
1006+
"llama_stack_configuration.py",
1007+
"-c",
1008+
str(config_path),
1009+
"-o",
1010+
str(output_path),
1011+
"--synthesize",
1012+
],
1013+
)
1014+
main()
1015+
1016+
assert output_path.exists()
1017+
1018+
9181019
# ---------------------------------------------------------------------------
9191020
# reference profiles (LCORE-2346)
9201021
# ---------------------------------------------------------------------------

0 commit comments

Comments
 (0)