Add local host mode and configurable LLM providers

This commit is contained in:
showtan001
2026-08-24 08:49:18 +08:00
parent 433ab41f95
commit 050d1329c4
8 changed files with 185 additions and 26 deletions
+18
View File
@@ -8,6 +8,7 @@ DEFAULT_PROVIDER = "anthropic"
DEFAULT_MODEL_BY_PROVIDER = {
"anthropic": "claude-sonnet-5",
"openai": "gpt-5.6",
"openai_compatible": "local-model",
}
DEFAULT_TIMEOUT_SECONDS = 30.0
@@ -16,6 +17,8 @@ PROVIDER_ENV = "AI_PLANNER_PROVIDER"
MODEL_ENV = "AI_PLANNER_MODEL"
TIMEOUT_ENV = "AI_PLANNER_TIMEOUT_SECONDS"
THINKING_BUDGET_ENV = "AI_PLANNER_THINKING_BUDGET_TOKENS"
API_KEY_ENV = "AI_PLANNER_API_KEY"
BASE_URL_ENV = "AI_PLANNER_BASE_URL"
SUPPORTED_PROVIDERS = frozenset(DEFAULT_MODEL_BY_PROVIDER)
@@ -27,6 +30,8 @@ class PlannerConfig:
model: str = ""
timeout: float = DEFAULT_TIMEOUT_SECONDS
thinking_budget_tokens: int | None = None
api_key: str | None = None
base_url: str | None = None
def resolved_model(self) -> str:
return self.model or DEFAULT_MODEL_BY_PROVIDER[self.provider]
@@ -40,6 +45,8 @@ def load_config(env: Mapping[str, str] | None = None) -> PlannerConfig:
model=values.get(MODEL_ENV) or "",
timeout=_parse_timeout(values.get(TIMEOUT_ENV)),
thinking_budget_tokens=_parse_thinking_budget(values.get(THINKING_BUDGET_ENV)),
api_key=values.get(API_KEY_ENV) or _provider_key(values),
base_url=values.get(BASE_URL_ENV) or None,
)
@@ -53,6 +60,8 @@ def _parse_provider(value: str | None) -> str:
if value is None:
return DEFAULT_PROVIDER
provider = value.strip().lower()
if provider in {"openai-compatible", "openai_compatible", "local"}:
return "openai_compatible"
return provider if provider in SUPPORTED_PROVIDERS else DEFAULT_PROVIDER
@@ -74,3 +83,12 @@ def _parse_thinking_budget(value: str | None) -> int | None:
except ValueError:
return None
return budget if budget > 0 else None
def _provider_key(values: Mapping[str, str]) -> str | None:
provider = (values.get(PROVIDER_ENV) or DEFAULT_PROVIDER).strip().lower()
if provider == "openai":
return values.get("OPENAI_API_KEY") or None
if provider == "anthropic":
return values.get("ANTHROPIC_API_KEY") or None
return None
+6 -2
View File
@@ -288,10 +288,14 @@ class OpenAIToolCallingClient:
def build_client(config: PlannerConfig) -> ToolCallingClient:
model = config.resolved_model()
if config.provider == "openai":
return OpenAIToolCallingClient(model=model)
if config.provider in {"openai", "openai_compatible"}:
return OpenAIToolCallingClient(
model=model, api_key=config.api_key, base_url=config.base_url
)
return AnthropicToolCallingClient(
model=model,
api_key=config.api_key,
base_url=config.base_url,
thinking_budget_tokens=config.thinking_budget_tokens,
)