synderesis-api / scripts /generation_route_contract.py
cuivienen's picture
Deploy Synderesis API Docker Space
62347d6 verified
Raw
History Blame Contribute Delete
12.2 kB
"""Authoritative generation-route contract shared by deploy and runtime.
This module intentionally depends only on the Python standard library so the
same validation can run before a Space is mutated and before its API starts.
"""
from __future__ import annotations
from typing import Mapping
LLM_SYNOD_BACKEND = "llm-synod"
CATHOLIC_WEBSITE_VARIANT = "catholic"
RESEARCH_WEBSITE_VARIANT = "research"
WEBSITE_VARIANTS = (CATHOLIC_WEBSITE_VARIANT, RESEARCH_WEBSITE_VARIANT)
DEFAULT_LLM_SYNOD_MODEL_ID = "synderesis-v3-catholic-llm-synod"
DEFAULT_RESEARCH_LLM_SYNOD_MODEL_ID = "synderesis-v3-research-sol-opus"
DEFAULT_LLM_SYNOD_QWEN_MODEL = "qwen/qwen3.7-max"
DEFAULT_LLM_SYNOD_GROK_MODEL = "x-ai/grok-4.5"
DEFAULT_LLM_SYNOD_MINIMAX_MODEL = "minimax/minimax-m3"
DEFAULT_LLM_SYNOD_DEEPSEEK_MODEL = "deepseek/deepseek-v4-pro"
DEFAULT_LLM_SYNOD_GLM_MODEL = "z-ai/glm-5.2"
PRO_MODEL_ID = "moonshotai/kimi-k3"
DEFAULT_LLM_SYNOD_OPENROUTER_BASE_URL = "https://openrouter.ai/api/v1"
DEFAULT_RESEARCH_OPENAI_MODEL = "gpt-5.6-sol"
DEFAULT_RESEARCH_ANTHROPIC_MODEL = "claude-opus-5"
DEFAULT_RESEARCH_OPENAI_BASE_URL = "https://api.openai.com/v1"
DEFAULT_RESEARCH_ANTHROPIC_BASE_URL = "https://api.anthropic.com/v1"
CATHOLIC_LLM_SYNOD_ROUTE_VARIABLES = {
"SYNDERESIS_LLM_SYNOD_MODEL_ID": DEFAULT_LLM_SYNOD_MODEL_ID,
"SYNDERESIS_LLM_SYNOD_QWEN_MODEL": DEFAULT_LLM_SYNOD_QWEN_MODEL,
"SYNDERESIS_LLM_SYNOD_GROK_MODEL": DEFAULT_LLM_SYNOD_GROK_MODEL,
"SYNDERESIS_LLM_SYNOD_MINIMAX_MODEL": DEFAULT_LLM_SYNOD_MINIMAX_MODEL,
"SYNDERESIS_LLM_SYNOD_DEEPSEEK_MODEL": DEFAULT_LLM_SYNOD_DEEPSEEK_MODEL,
"SYNDERESIS_LLM_SYNOD_GLM_MODEL": DEFAULT_LLM_SYNOD_GLM_MODEL,
"SYNDERESIS_LLM_SYNOD_OPENROUTER_BASE_URL": (
DEFAULT_LLM_SYNOD_OPENROUTER_BASE_URL
),
}
RESEARCH_LLM_SYNOD_ROUTE_VARIABLES = {
"SYNDERESIS_LLM_SYNOD_MODEL_ID": DEFAULT_RESEARCH_LLM_SYNOD_MODEL_ID,
"SYNDERESIS_RESEARCH_OPENAI_MODEL": DEFAULT_RESEARCH_OPENAI_MODEL,
"SYNDERESIS_RESEARCH_ANTHROPIC_MODEL": DEFAULT_RESEARCH_ANTHROPIC_MODEL,
"SYNDERESIS_RESEARCH_OPENAI_BASE_URL": DEFAULT_RESEARCH_OPENAI_BASE_URL,
"SYNDERESIS_RESEARCH_ANTHROPIC_BASE_URL": (
DEFAULT_RESEARCH_ANTHROPIC_BASE_URL
),
}
LEGACY_LLM_SYNOD_ROUTE_VARIABLE_NAMES = (
"SYNDERESIS_FUSION_MODEL_ID",
"SYNDERESIS_FUSION_QWEN_MODEL",
"SYNDERESIS_FUSION_GROK_MODEL",
"SYNDERESIS_FUSION_MINIMAX_MODEL",
"SYNDERESIS_FUSION_DEEPSEEK_MODEL",
"SYNDERESIS_FUSION_GLM_MODEL",
"SYNDERESIS_FUSION_OPENROUTER_BASE_URL",
"SYNDERESIS_FUSION_OPENROUTER_REFERER",
"SYNDERESIS_FUSION_OPENROUTER_TITLE",
)
REMOVED_MODEL_ROUTE_VARIABLE_NAMES = (
"SYNDERESIS_LLM_SYNOD_OPENROUTER_REFERER",
"SYNDERESIS_LLM_SYNOD_OPENROUTER_TITLE",
"SYNDERESIS_ALLOWED_MODELS",
"SYNDERESIS_HF_MODEL_ID",
"HF_MODEL_ID",
"HF_INFERENCE_BASE_URL",
"HF_INFERENCE_ENDPOINT_URL",
"SYNDERESIS_TINKER_MODEL_PATH",
"TINKER_MODEL_PATH",
)
ALL_KNOWN_MODEL_ROUTE_VARIABLE_NAMES = tuple(
dict.fromkeys(
(
*CATHOLIC_LLM_SYNOD_ROUTE_VARIABLES,
*RESEARCH_LLM_SYNOD_ROUTE_VARIABLES,
*LEGACY_LLM_SYNOD_ROUTE_VARIABLE_NAMES,
*REMOVED_MODEL_ROUTE_VARIABLE_NAMES,
)
)
)
MANAGED_ROUTE_INPUT_VARIABLE_NAMES = tuple(
dict.fromkeys(
(
*CATHOLIC_LLM_SYNOD_ROUTE_VARIABLES,
*RESEARCH_LLM_SYNOD_ROUTE_VARIABLES,
*LEGACY_LLM_SYNOD_ROUTE_VARIABLE_NAMES,
*REMOVED_MODEL_ROUTE_VARIABLE_NAMES,
)
)
)
class GenerationRouteContractError(ValueError):
"""Raised when a deployment or runtime route is not canonical."""
def _nonempty(environment: Mapping[str, str], name: str) -> str:
return str(environment.get(name, "") or "").strip()
def validate_authoritative_route_values(
values: Mapping[str, str] | None = None,
) -> None:
"""Detect accidental drift in checked-in generation route constants."""
supplied = values or {}
expected = {
**CATHOLIC_LLM_SYNOD_ROUTE_VARIABLES,
**RESEARCH_LLM_SYNOD_ROUTE_VARIABLES,
"SYNDERESIS_PRO_MODEL": PRO_MODEL_ID,
}
family_prefixes = {
"SYNDERESIS_LLM_SYNOD_QWEN_MODEL": "qwen/",
"SYNDERESIS_LLM_SYNOD_GROK_MODEL": "x-ai/",
"SYNDERESIS_LLM_SYNOD_MINIMAX_MODEL": "minimax/",
"SYNDERESIS_LLM_SYNOD_DEEPSEEK_MODEL": "deepseek/",
"SYNDERESIS_LLM_SYNOD_GLM_MODEL": "z-ai/",
"SYNDERESIS_PRO_MODEL": "moonshotai/",
"SYNDERESIS_RESEARCH_OPENAI_MODEL": "gpt-",
"SYNDERESIS_RESEARCH_ANTHROPIC_MODEL": "claude-",
}
for name, canonical in expected.items():
value = str(supplied.get(name, canonical))
if value != canonical:
prefix = family_prefixes.get(name)
if prefix and not value.startswith(prefix):
raise GenerationRouteContractError(
f"{name} is configured for the wrong model family"
)
if name.endswith("_BASE_URL"):
raise GenerationRouteContractError(
f"{name} must use its canonical HTTPS API origin"
)
raise GenerationRouteContractError(
f"{name} must use the current canonical value"
)
def deployment_route_wiring(
*,
backend: str,
website_variant: str,
model_id: str,
environment: Mapping[str, str] | None = None,
) -> tuple[dict[str, str], tuple[str, ...]]:
"""Return canonical Space variables and stale variables to remove."""
validate_authoritative_route_values()
if website_variant not in WEBSITE_VARIANTS:
raise GenerationRouteContractError(
"website variant must be catholic or research"
)
if (
website_variant == RESEARCH_WEBSITE_VARIANT
and backend != LLM_SYNOD_BACKEND
):
raise GenerationRouteContractError(
"the research website variant requires llm-synod"
)
supplied = environment or {}
if backend != LLM_SYNOD_BACKEND:
variables: dict[str, str] = {}
elif website_variant == CATHOLIC_WEBSITE_VARIANT:
if model_id != DEFAULT_LLM_SYNOD_MODEL_ID:
raise GenerationRouteContractError(
"Catholic deployment requires the canonical LLM Synod model ID"
)
variables = dict(CATHOLIC_LLM_SYNOD_ROUTE_VARIABLES)
else:
if model_id not in {
DEFAULT_LLM_SYNOD_MODEL_ID,
DEFAULT_RESEARCH_LLM_SYNOD_MODEL_ID,
}:
raise GenerationRouteContractError(
"Research deployment requires the canonical research LLM Synod model ID"
)
variables = dict(RESEARCH_LLM_SYNOD_ROUTE_VARIABLES)
if backend == LLM_SYNOD_BACKEND:
validate_runtime_route(
backend=backend,
website_variant=website_variant,
model_id=variables["SYNDERESIS_LLM_SYNOD_MODEL_ID"],
qwen_model=variables.get(
"SYNDERESIS_LLM_SYNOD_QWEN_MODEL",
DEFAULT_LLM_SYNOD_QWEN_MODEL,
),
grok_model=variables.get(
"SYNDERESIS_LLM_SYNOD_GROK_MODEL",
DEFAULT_LLM_SYNOD_GROK_MODEL,
),
minimax_model=variables.get(
"SYNDERESIS_LLM_SYNOD_MINIMAX_MODEL",
DEFAULT_LLM_SYNOD_MINIMAX_MODEL,
),
deepseek_model=variables.get(
"SYNDERESIS_LLM_SYNOD_DEEPSEEK_MODEL",
DEFAULT_LLM_SYNOD_DEEPSEEK_MODEL,
),
glm_model=variables.get(
"SYNDERESIS_LLM_SYNOD_GLM_MODEL",
DEFAULT_LLM_SYNOD_GLM_MODEL,
),
openrouter_base_url=variables.get(
"SYNDERESIS_LLM_SYNOD_OPENROUTER_BASE_URL",
DEFAULT_LLM_SYNOD_OPENROUTER_BASE_URL,
),
research_openai_model=variables.get(
"SYNDERESIS_RESEARCH_OPENAI_MODEL",
DEFAULT_RESEARCH_OPENAI_MODEL,
),
research_anthropic_model=variables.get(
"SYNDERESIS_RESEARCH_ANTHROPIC_MODEL",
DEFAULT_RESEARCH_ANTHROPIC_MODEL,
),
research_openai_base_url=variables.get(
"SYNDERESIS_RESEARCH_OPENAI_BASE_URL",
DEFAULT_RESEARCH_OPENAI_BASE_URL,
),
research_anthropic_base_url=variables.get(
"SYNDERESIS_RESEARCH_ANTHROPIC_BASE_URL",
DEFAULT_RESEARCH_ANTHROPIC_BASE_URL,
),
environment=supplied,
)
clear_variable_names = tuple(
name
for name in ALL_KNOWN_MODEL_ROUTE_VARIABLE_NAMES
if name not in variables
)
return variables, clear_variable_names
def validate_runtime_route(
*,
backend: str,
website_variant: str,
model_id: str,
qwen_model: str,
grok_model: str,
minimax_model: str,
deepseek_model: str,
glm_model: str,
openrouter_base_url: str,
research_openai_model: str,
research_anthropic_model: str,
research_openai_base_url: str,
research_anthropic_base_url: str,
environment: Mapping[str, str] | None = None,
) -> None:
"""Fail closed unless the active runtime route is exactly canonical."""
if backend != LLM_SYNOD_BACKEND:
return
if website_variant not in WEBSITE_VARIANTS:
raise GenerationRouteContractError(
"website variant must be catholic or research"
)
supplied = environment or {}
for name in (
*LEGACY_LLM_SYNOD_ROUTE_VARIABLE_NAMES,
*REMOVED_MODEL_ROUTE_VARIABLE_NAMES,
):
if _nonempty(supplied, name):
raise GenerationRouteContractError(
f"{name} is a legacy or unsupported generation-route override"
)
if website_variant == CATHOLIC_WEBSITE_VARIANT:
for name in RESEARCH_LLM_SYNOD_ROUTE_VARIABLES:
if (
name != "SYNDERESIS_LLM_SYNOD_MODEL_ID"
and _nonempty(supplied, name)
):
raise GenerationRouteContractError(
f"{name} is a research route and cannot configure a Catholic deployment"
)
actual = {
"SYNDERESIS_LLM_SYNOD_MODEL_ID": model_id,
"SYNDERESIS_LLM_SYNOD_QWEN_MODEL": qwen_model,
"SYNDERESIS_LLM_SYNOD_GROK_MODEL": grok_model,
"SYNDERESIS_LLM_SYNOD_MINIMAX_MODEL": minimax_model,
"SYNDERESIS_LLM_SYNOD_DEEPSEEK_MODEL": deepseek_model,
"SYNDERESIS_LLM_SYNOD_GLM_MODEL": glm_model,
"SYNDERESIS_LLM_SYNOD_OPENROUTER_BASE_URL": openrouter_base_url,
}
expected = CATHOLIC_LLM_SYNOD_ROUTE_VARIABLES
else:
for name in CATHOLIC_LLM_SYNOD_ROUTE_VARIABLES:
if (
name != "SYNDERESIS_LLM_SYNOD_MODEL_ID"
and _nonempty(supplied, name)
):
raise GenerationRouteContractError(
f"{name} is a Catholic route and cannot configure a research deployment"
)
actual = {
"SYNDERESIS_LLM_SYNOD_MODEL_ID": model_id,
"SYNDERESIS_RESEARCH_OPENAI_MODEL": research_openai_model,
"SYNDERESIS_RESEARCH_ANTHROPIC_MODEL": research_anthropic_model,
"SYNDERESIS_RESEARCH_OPENAI_BASE_URL": research_openai_base_url,
"SYNDERESIS_RESEARCH_ANTHROPIC_BASE_URL": (
research_anthropic_base_url
),
}
expected = RESEARCH_LLM_SYNOD_ROUTE_VARIABLES
for name, canonical in expected.items():
configured = _nonempty(supplied, name)
if actual[name] != canonical or (
configured and configured != canonical
):
if name.endswith("_BASE_URL"):
raise GenerationRouteContractError(
f"{name} must use its canonical HTTPS API origin"
)
raise GenerationRouteContractError(
f"{name} must use the current canonical value"
)