Source code for ooai_llm.cli.recipes

"""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] RecipeFormat = Literal["text", "markdown", "json"]
[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] title: str
[docs] summary: str
[docs] commands: list[str] = Field(default_factory=list)
[docs] python: str = ""
[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")