feat(llm): let each model tier run on its own provider (#1440)

- quick_think_provider / deep_think_provider and their backend URLs (with TRADINGAGENTS_* variables) choose a tier's provider; unset, a tier uses llm_provider and backend_url
- a tier on another provider gets that provider's own settings and endpoint, and the run settings and report header name each tier's provider
- the CLI checks each tier provider's model variable and key before the run
This commit is contained in:
Yijia-Xiao
2026-10-03 21:27:43 +00:00
parent f65fcabb60
commit cc39a35c42
11 changed files with 225 additions and 32 deletions
+25 -6
View File
@@ -68,6 +68,29 @@ def unattended_gaps(flags) -> list[str]:
return gaps
def _check_tier_providers(main_provider: str) -> None:
"""Check each provider the model tiers use (#1440) before the run.
A tier on another provider needs its model from its variable, since the
model question offers the main provider's models. Each provider a tier uses
has its key checked now, prompting for a missing one, rather than at its
first call, which for the deep tier comes after everything else has been
paid for; a provider no tier uses needs no key.
"""
used = []
for tier in ("quick", "deep"):
provider = (DEFAULT_CONFIG.get(f"{tier}_think_provider") or main_provider).lower()
if provider != main_provider.lower():
variable = f"TRADINGAGENTS_{tier.upper()}_THINK_LLM"
if not os.environ.get(variable):
console.print(f"[red]The {tier} tier runs on {provider}; set {variable} to one of its models.[/red]")
raise typer.Exit(code=1)
if provider not in used:
used.append(provider)
for provider in used:
ensure_api_key(provider)
def _from_flag(parse, value, *args):
"""A flag's value through the same check its prompt applies; a bad one ends the run."""
try:
@@ -223,8 +246,6 @@ def _prompt_selections(prefs, flags):
)
console.print(f"[green]✓ LLM provider from environment:[/green] {selected_llm_provider}")
console.print(f"[green]✓ Backend URL:[/green] {backend_url}")
# Still confirm/persist the API key so the run doesn't fail later.
ensure_api_key(selected_llm_provider)
else:
console.print(
create_question_box(
@@ -261,10 +282,8 @@ def _prompt_selections(prefs, flags):
if selected_llm_provider == "ollama":
confirm_ollama_endpoint(backend_url)
# Confirm the provider's API key is present; prompt the user to paste
# one and persist it to .env if it's missing, so the analysis run
# doesn't fail later at the first API call.
ensure_api_key(selected_llm_provider)
_check_tier_providers(selected_llm_provider)
# Step 7: Thinking agents (skipped when either model is set via environment)
if os.environ.get("TRADINGAGENTS_QUICK_THINK_LLM") or os.environ.get("TRADINGAGENTS_DEEP_THINK_LLM"):