dev-strender's picture
Replace v24-era demo with v34 pipeline demo (engine-vendored bundle)
9c84f9d verified
Raw History Blame
5.74 kB
"""Prompt management commands — list and show prompts."""
import click
from tabulate import tabulate
from solar_eval.cli.commands.projects import _resolve_project_id
@click.group("prompts")
def prompts_group() -> None:
"""Manage evaluation prompts."""
@prompts_group.command("list")
@click.argument("project")
@click.pass_context
def list_prompts(ctx, project):
"""List available prompt YAML files."""
cfg = ctx.obj["config"]
if cfg.is_remote:
from solar_eval.cli.client import EvalClient
from solar_eval.cli.formatters import format_prompts_table
client = EvalClient(cfg.remote_url, cfg.timeout)
project_id = _resolve_project_id(client, project)
prompts = client.get(f"/api/projects/{project_id}/prompts")
if not prompts:
click.secho("No prompts found.", fg="yellow")
return
click.secho(format_prompts_table(prompts), fg="blue")
return
# Local mode: list YAML files + TXT directories in prompts/
prompts_dir = cfg.prompts_dir(project)
if not prompts_dir.exists():
click.secho("No prompts directory found.", fg="yellow")
return
entries = []
# YAML files
for f in sorted(prompts_dir.glob("*.yaml")):
entries.append(("yaml", f.stem, f))
# TXT directories (exclude _library, __pycache__)
for d in sorted(prompts_dir.iterdir()):
if d.is_dir() and not d.name.startswith("_") and list(d.glob("*.txt")):
entries.append(("txt_dir", d.name, d))
if not entries:
click.secho("No prompt files found.", fg="yellow")
return
def _classify_type(name: str) -> str:
if name.startswith("prod_"):
return "prod"
if name.startswith("dev_"):
return "dev"
if name.startswith("ci_"):
return "ci"
if name.startswith("exp"):
return "exp"
return "-"
rows = []
for fmt, name, path in entries:
ptype = _classify_type(name)
if fmt == "yaml":
size_kb = path.stat().st_size / 1024
rows.append([name, ptype, "yaml", f"{size_kb:.1f}KB"])
else:
txt_files = list(path.glob("*.txt"))
total = sum(f.stat().st_size for f in txt_files)
rows.append([name, ptype, f"txt({len(txt_files)})", f"{total / 1024:.1f}KB"])
click.secho(f"\nPrompts: {project} ({len(rows)} entries)", fg="blue", bold=True)
click.echo(tabulate(rows, headers=["Name", "Type", "Format", "Size"], tablefmt="simple"))
@prompts_group.command("show")
@click.argument("project")
@click.option("--prompt", "-p", "prompt_name", required=True, help="Prompt name")
@click.pass_context
def show_prompt(ctx, project, prompt_name):
"""Show prompt content."""
cfg = ctx.obj["config"]
if cfg.is_remote:
from solar_eval.cli.client import EvalClient
client = EvalClient(cfg.remote_url, cfg.timeout)
project_id = _resolve_project_id(client, project)
prompt = client.get(f"/api/projects/{project_id}/prompts/{prompt_name}")
click.secho(f"Prompt: {prompt_name}", fg="blue", bold=True)
click.echo(prompt.get("system_prompt", ""))
return
# Local mode
from solar_eval.cli.commands.runs import _resolve_prompt
from solar_eval.models.prompt_version import (
detect_prompt_format,
load_prompt_messages,
load_step_prompts,
)
prompts_dir = cfg.prompts_dir(project)
prompt_path = _resolve_prompt(prompts_dir, prompt_name)
is_dir = prompt_path.is_dir()
click.secho(f"Prompt: {prompt_name}", fg="blue", bold=True)
click.echo(f" {'Directory' if is_dir else 'File'}: {prompt_path}")
click.echo()
fmt = detect_prompt_format(prompt_path)
if fmt == "multi_step":
step_prompts = load_step_prompts(prompt_path)
for step_name, content in step_prompts.items():
click.secho(f"[{step_name}]", fg="cyan", bold=True)
lines = content.strip().split("\n")
preview = "\n".join(lines[:5])
click.echo(preview)
if len(lines) > 5:
click.secho(f" ... ({len(lines) - 5} more lines)", fg="yellow")
click.echo()
else:
messages = load_prompt_messages(prompt_path)
for msg in messages:
click.secho(f"[{msg['role']}]", fg="cyan", bold=True)
click.echo(msg["content"])
click.echo()
@prompts_group.command("create")
@click.argument("project")
@click.option("--task", "-t", required=True)
@click.option("--prompt-file", "-f", type=click.Path(exists=True), required=True)
@click.option("--model", "-m", default="solar-pro2")
@click.option("--temperature", default=0.0, type=float)
@click.option("--max-tokens", default=8000, type=int)
@click.pass_context
def create_prompt(ctx, project, task, prompt_file, model, temperature, max_tokens):
"""Create a new prompt version (remote mode)."""
cfg = ctx.obj["config"]
if not cfg.is_remote:
raise click.ClickException("Use 'prompts add' for local mode")
from solar_eval.cli.client import EvalClient
client = EvalClient(cfg.remote_url, cfg.timeout)
project_id = _resolve_project_id(client, project)
with open(prompt_file) as f:
system_prompt = f.read()
result = client.post(
f"/api/projects/{project_id}/prompts",
json={
"project_id": project_id,
"task": task,
"system_prompt": system_prompt,
"model": model,
"temperature": temperature,
"max_tokens": max_tokens,
},
)
click.secho(f"Created prompt v{result.get('version', '?')} (ID: {result['id']})", fg="green")