54 lines
2.1 KiB
Python
54 lines
2.1 KiB
Python
"""
|
|
LLM abstraction layer with priority fallback chain.
|
|
Config lookup order:
|
|
1. <repo>/config/llm.yaml — per-install local config
|
|
2. ~/.config/circuitforge/llm.yaml — user-level config (circuitforge-core default)
|
|
3. env-var auto-config (ANTHROPIC_API_KEY, OPENAI_API_KEY, OLLAMA_HOST, …)
|
|
"""
|
|
from pathlib import Path
|
|
|
|
from circuitforge_core.llm import LLMRouter as _CoreLLMRouter
|
|
|
|
# Kept for backwards-compatibility — external callers that import CONFIG_PATH
|
|
# from this module continue to work.
|
|
CONFIG_PATH = Path(__file__).parent.parent / "config" / "llm.yaml"
|
|
|
|
|
|
class LLMRouter(_CoreLLMRouter):
|
|
"""Peregrine-specific LLMRouter — tri-level config path priority.
|
|
|
|
When ``config_path`` is supplied (e.g. in tests) it is passed straight
|
|
through to the core. When omitted, the lookup order is:
|
|
1. <repo>/config/llm.yaml (per-install local config)
|
|
2. ~/.config/circuitforge/llm.yaml (user-level, circuitforge-core default)
|
|
3. env-var auto-config (ANTHROPIC_API_KEY, OPENAI_API_KEY, OLLAMA_HOST …)
|
|
"""
|
|
|
|
def __init__(self, config_path: Path | None = None) -> None:
|
|
if config_path is not None:
|
|
# Explicit path supplied — use it directly (e.g. tests, CLI override).
|
|
super().__init__(config_path)
|
|
return
|
|
|
|
local = Path(__file__).parent.parent / "config" / "llm.yaml"
|
|
user_level = Path.home() / ".config" / "circuitforge" / "llm.yaml"
|
|
if local.exists():
|
|
super().__init__(local)
|
|
elif user_level.exists():
|
|
super().__init__(user_level)
|
|
else:
|
|
# No yaml found — let circuitforge-core's env-var auto-config run.
|
|
# The core default CONFIG_PATH (~/.config/circuitforge/llm.yaml)
|
|
# won't exist either, so _auto_config_from_env() will be triggered.
|
|
super().__init__()
|
|
|
|
|
|
# Module-level singleton for convenience
|
|
_router: LLMRouter | None = None
|
|
|
|
|
|
def complete(prompt: str, system: str | None = None) -> str:
|
|
global _router
|
|
if _router is None:
|
|
_router = LLMRouter()
|
|
return _router.complete(prompt, system)
|