mirror of
https://github.com/Sea-Haven-Industries/open-swe.git
synced 2026-10-06 00:42:11 +00:00
feat: validate LLM API keys on startup (#1438)
* feat: validate LLM API keys on startup * fix: correct relative import for options module * refactor: move imports to top of file * style: fix linting and formatting issues * refactor: scope LLM validation to local dev and rename function --------- Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com> Co-authored-by: open-swe[bot] <johannes@langchain.dev>
This commit is contained in:
parent
c07434a221
commit
4030001ebf
2 changed files with 31 additions and 0 deletions
|
|
@ -1,7 +1,10 @@
|
||||||
|
import os
|
||||||
from typing import Literal, TypedDict, Unpack
|
from typing import Literal, TypedDict, Unpack
|
||||||
|
|
||||||
from langchain.chat_models import init_chat_model
|
from langchain.chat_models import init_chat_model
|
||||||
|
|
||||||
|
from ..dashboard.options import DEFAULT_MODEL_ID
|
||||||
|
|
||||||
OPENAI_RESPONSES_WS_BASE_URL = "wss://api.openai.com/v1"
|
OPENAI_RESPONSES_WS_BASE_URL = "wss://api.openai.com/v1"
|
||||||
|
|
||||||
# Anthropic SDK default is 2; a 529 burst can outlive that. Bump to give the
|
# Anthropic SDK default is 2; a 529 burst can outlive that. Bump to give the
|
||||||
|
|
@ -185,3 +188,29 @@ def provider_model_kwargs(
|
||||||
if effort is not None:
|
if effort is not None:
|
||||||
kwargs["model_kwargs"] = {"reasoning_effort": effort}
|
kwargs["model_kwargs"] = {"reasoning_effort": effort}
|
||||||
return kwargs
|
return kwargs
|
||||||
|
|
||||||
|
|
||||||
|
def validate_local_dev_llm_config() -> None:
|
||||||
|
"""Validate API keys for the locally configured default model.
|
||||||
|
|
||||||
|
This check only runs in localhost development environments and is
|
||||||
|
intended to catch missing credentials for the default model specified
|
||||||
|
via LLM_MODEL_ID/DEFAULT_MODEL_ID. Runtime model selection may come
|
||||||
|
from team, profile, or thread configuration and is not validated here.
|
||||||
|
"""
|
||||||
|
dashboard_url = os.environ.get("DASHBOARD_BASE_URL", "")
|
||||||
|
if not dashboard_url.startswith("http://localhost"):
|
||||||
|
return
|
||||||
|
|
||||||
|
model_id = os.environ.get("LLM_MODEL_ID", DEFAULT_MODEL_ID)
|
||||||
|
|
||||||
|
if model_id.startswith("openai:") and not os.environ.get("OPENAI_API_KEY"):
|
||||||
|
raise ValueError(f"OPENAI_API_KEY is required for configured model {model_id}")
|
||||||
|
elif model_id.startswith("anthropic:") and not os.environ.get("ANTHROPIC_API_KEY"):
|
||||||
|
raise ValueError(f"ANTHROPIC_API_KEY is required for configured model {model_id}")
|
||||||
|
elif model_id.startswith("google_genai:") and not os.environ.get("GOOGLE_API_KEY"):
|
||||||
|
raise ValueError(f"GOOGLE_API_KEY is required for configured model {model_id}")
|
||||||
|
elif model_id.startswith("groq:") and not os.environ.get("GROQ_API_KEY"):
|
||||||
|
raise ValueError(f"GROQ_API_KEY is required for configured model {model_id}")
|
||||||
|
elif model_id.startswith("fireworks:") and not os.environ.get("FIREWORKS_API_KEY"):
|
||||||
|
raise ValueError(f"FIREWORKS_API_KEY is required for configured model {model_id}")
|
||||||
|
|
|
||||||
|
|
@ -131,9 +131,11 @@ logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@asynccontextmanager
|
@asynccontextmanager
|
||||||
async def lifespan(_app: FastAPI) -> AsyncIterator[None]:
|
async def lifespan(_app: FastAPI) -> AsyncIterator[None]:
|
||||||
|
from .utils.model import validate_local_dev_llm_config
|
||||||
from .utils.sandbox import validate_sandbox_startup_config
|
from .utils.sandbox import validate_sandbox_startup_config
|
||||||
|
|
||||||
validate_sandbox_startup_config()
|
validate_sandbox_startup_config()
|
||||||
|
validate_local_dev_llm_config()
|
||||||
yield
|
yield
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue