"""Copy/paste CLI and Python recipes for common ``ooai-llm`` workflows."""
from __future__ import annotations
import json
from typing import Literal
from pydantic import BaseModel, Field
[docs]
RecipeTopic = Literal["all", "cheapest", "coding", "rich", "suites", "profiles", "runtime", "tui"]
[docs]
RECIPE_TOPICS: tuple[str, ...] = ("all", "cheapest", "coding", "rich", "suites", "profiles", "runtime", "tui")
[docs]
class CLIRecipe(BaseModel):
"""One recipe section for terminal and package usage."""
[docs]
commands: list[str] = Field(default_factory=list)
[docs]
def recipe_sections() -> dict[str, CLIRecipe]:
"""Return all built-in CLI/package recipe sections."""
return {
"cheapest": CLIRecipe(
title="Cheapest model exploration",
summary="Rank catalog models by estimated call cost for a representative token shape.",
commands=[
"ooai-llm models cheapest --providers mistral --limit 10",
(
"ooai-llm models cheapest --providers openai,anthropic,google,deepseek,mistral "
"--input-tokens 10000 --output-tokens 2000 --per-provider"
),
(
"ooai-llm models compare --source litellm --providers mistral "
"--input-tokens 10000 --output-tokens 2000 --sort cost --limit 20"
),
],
python="""\
from ooai_llm import compare_model_catalog
comparison = compare_model_catalog(
providers=["mistral"],
source="litellm",
input_tokens=10_000,
output_tokens=2_000,
budget_usd=10,
sort_by="call_cost",
)
for row in comparison.estimates:
print(row.model.as_langchain(), row.call_cost_usd, row.calls_per_budget)
""",
),
"coding": CLIRecipe(
title="Coding model comparison",
summary="Filter to coding-oriented models, then sort by price, context, output tokens, or calls per budget.",
commands=[
"ooai-llm models coding --providers mistral --limit 10",
(
"ooai-llm models coding --providers openai,anthropic,google,deepseek,mistral "
"--tool-calling-only --structured-output-only --per-provider"
),
(
"ooai-llm models coding --source litellm --min-output-tokens 8000 "
"--sort output_tokens --format csv"
),
],
python="""\
from ooai_llm import get_coding_model_comparison
comparison = get_coding_model_comparison(
providers=["openai", "anthropic", "mistral"],
source="litellm",
input_tokens=10_000,
output_tokens=2_000,
capabilities=["tool_calling", "structured_output"],
)
for row in comparison.estimates:
print(row.model.as_langchain(), row.call_cost_usd, row.capabilities)
""",
),
"rich": CLIRecipe(
title="Pretty terminal output",
summary=(
"Install the CLI/TUI extras for Rich tables and Textual views. Table output uses Rich by "
"default when available; JSON/CSV stay available for automation."
),
commands=[
'pip install "ooai-llm[cli,tui]"',
"pdm run ooai-llm models cheapest --providers mistral --limit 10",
(
"pdm run ooai-llm models coding --providers openai,anthropic,mistral "
"--tool-calling-only --structured-output-only --limit 20"
),
"pdm run ooai-llm models list --source litellm --providers openai,mistral --no-rich",
"pdm run ooai-llm tui --theme paper",
"pdm run ooai-llm tui --theme slate",
"pdm run ooai-llm tui --theme mono --refresh-cooldown 0",
"pdm run ooai-llm tui --providers mistral --views cheapest,catalog --limit 10",
],
),
"suites": CLIRecipe(
title="Model suites",
summary="Build a stable iterable/dict-style shortlist for LangGraph variants or experiments.",
commands=[
"ooai-llm models suite --suite comparison --providers openai,anthropic,mistral",
(
"ooai-llm models suite --from-catalog --source litellm --coding-only "
"--tool-calling-only --sort cost --limit 5 --format json"
),
"ooai-llm models suite --suite comparison --parallel-tool-calls false --format csv",
],
python="""\
from ooai_llm import UsageRecorder, model_suite_from_catalog
suite = model_suite_from_catalog(
providers=["mistral"],
source="litellm",
capabilities=["coding"],
max_output_cost_per_1m=3,
sort_by="cost",
limit=5,
temperature=0,
parallel_tool_calls=True,
)
recorder = UsageRecorder()
runtimes = {
key: profile.create_runtime(recorder=recorder, id=key)
for key, profile in suite.to_profiles().items()
}
""",
),
"profiles": CLIRecipe(
title="Serializable profiles",
summary="Use ChatModelProfile for stable, JSON-serializable model configuration.",
commands=[
"ooai-llm profiles validate --input profile.json",
"ooai-llm profiles render --input profile.json",
"ooai-llm profiles resolve --input profile.json --format json",
],
python="""\
from ooai_llm import ChatModelProfile
profile = ChatModelProfile(
id="mistral-coding",
model="mistral:YOUR_MODEL_FROM_CATALOG",
temperature=0,
parallel_tool_calls=True,
cost_labels={"role": "coding"},
)
runtime = profile.create_runtime(id="coding-runtime")
""",
),
"runtime": CLIRecipe(
title="Runtime usage and cost accounting",
summary="Use LLM when you want lazy construction plus observed usage/cost totals.",
commands=[
"ooai-llm recipes --topic profiles",
"ooai-llm profiles resolve --input profile.json --format json",
],
python="""\
from enum import StrEnum
from ooai_llm import ChatModelProfile, UsageRecorder
class ModelChoice(StrEnum):
CHEAP = "cheap"
CODING = "coding"
profiles = {
ModelChoice.CHEAP: ChatModelProfile(id="cheap", model="openai:gpt-5-mini", temperature=0),
ModelChoice.CODING: ChatModelProfile(id="coding", model="anthropic:claude-sonnet-4.6", temperature=0),
}
recorder = UsageRecorder()
runtimes = {
key: profile.create_runtime(recorder=recorder, id=str(key))
for key, profile in profiles.items()
}
# response = runtimes[ModelChoice.CODING].invoke("Review this function for bugs.")
print(recorder.summary())
""",
),
"tui": CLIRecipe(
title="Interactive TUI",
summary="Launch the optional Textual explorer for catalog, cost, suite, profile, and benchmark workflows.",
commands=[
'pip install "ooai-llm[tui]"',
"pdm run ooai-llm tui --theme paper",
"pdm run ooai-llm tui --theme slate --providers openai,anthropic,mistral --source litellm",
"pdm run ooai-llm tui --providers mistral --views cheapest,catalog --limit 10",
"pdm run ooai-llm tui --theme mono --refresh-cooldown 0 --no-benchmarks",
],
),
}
[docs]
def selected_recipe_sections(topic: RecipeTopic | str) -> dict[str, CLIRecipe]:
"""Return every section or one named recipe section."""
sections = recipe_sections()
if topic == "all":
return sections
return {str(topic): sections[str(topic)]}
[docs]
def render_recipes_text(sections: dict[str, CLIRecipe], *, markdown: bool = False) -> str:
"""Render recipes as plain text or Markdown."""
chunks: list[str] = []
for section in sections.values():
if markdown:
chunks.append(f"## {section.title}\n\n{section.summary}\n")
chunks.append("```bash\n" + "\n".join(section.commands) + "\n```")
if section.python:
chunks.append("```python\n" + section.python.rstrip() + "\n```")
else:
chunks.append(f"{section.title}\n{'=' * len(section.title)}")
chunks.append(section.summary)
chunks.append("Commands:")
chunks.extend(f" {command}" for command in section.commands)
if section.python:
chunks.append("Python:")
chunks.append(section.python.rstrip())
chunks.append("")
return "\n".join(chunks).rstrip() + "\n"
[docs]
def render_recipes(sections: dict[str, CLIRecipe], *, format: RecipeFormat = "text") -> str:
"""Render recipes in the requested CLI output format."""
if format == "json":
return json.dumps(
{key: section.model_dump(mode="json") for key, section in sections.items()},
indent=2,
sort_keys=True,
) + "\n"
return render_recipes_text(sections, markdown=format == "markdown")