recipe-app / scripts /hf_patch_config.py
ronheichman's picture
Deploy recipe web app
38e1fed verified
Raw
History Blame Contribute Delete
3.63 kB
"""Patch recipe_web/config.yaml for HF Spaces deployment.
Sets host=0.0.0.0, port=7860, image_source=remote, Turso config, and HF image URL.
"""
from __future__ import annotations
import logging
import os # nosemgrep: python-no-os-environ -- HF Space injects secrets as env vars
from pathlib import Path
import yaml
logging.basicConfig(level=logging.INFO, format="%(message)s")
log = logging.getLogger(__name__)
WEB_CONFIG_PATH = Path("recipe_web/config.yaml")
PIPELINE_CONFIG_PATH = Path("parsing_pipeline/config.yaml")
HF_IMAGE_BASE_URL = "https://huggingface.co/datasets/ronheichman/recipe-images/resolve/main"
PIPELINE_ONLY_KEYS = ["pipeline_scripts"]
def main() -> None:
config = yaml.safe_load(WEB_CONFIG_PATH.read_text())
config["server"]["host"] = "0.0.0.0" # noqa: S104 -- HF Space container must bind all interfaces
config["server"]["port"] = 7860
config["image_source"] = "remote"
config["image_base_url"] = HF_IMAGE_BASE_URL
config["observability"]["enabled"] = False
log.info("Observability disabled (no OTEL collector in HF Spaces)")
# nosemgrep: python-no-os-environ -- HF Space env vars; no config in container
turso_url = os.environ.get(
"TURSO_DATABASE_URL",
"",
)
# nosemgrep: python-no-os-environ -- HF Space env vars; no config in container
turso_token = os.environ.get(
"TURSO_AUTH_TOKEN",
"",
)
if turso_url:
config["user_db"]["turso_sync_url"] = ""
config["user_db"]["turso_auth_token"] = ""
config["user_db_backup"]["enabled"] = True
config["user_db_backup"]["turso_sync_url"] = turso_url
config["user_db_backup"]["turso_auth_token"] = turso_token
log.info("Turso backup config injected: %s", turso_url)
# nosemgrep: python-no-os-environ -- HF Space env vars; no config in container
jwt_secret = os.environ.get("JWT_SECRET", "")
if jwt_secret:
config.setdefault("auth", {})
config["auth"]["jwt_secret"] = jwt_secret
log.info("JWT secret injected from env (length %d)", len(jwt_secret))
else:
log.warning("JWT_SECRET not set; auth uses the config.yaml dev placeholder")
WEB_CONFIG_PATH.write_text(yaml.dump(config, default_flow_style=False, sort_keys=False))
log.info("Web config patched: host=0.0.0.0, port=7860, image_source=remote")
if PIPELINE_CONFIG_PATH.exists():
pipeline_config = yaml.safe_load(PIPELINE_CONFIG_PATH.read_text())
for key in PIPELINE_ONLY_KEYS:
pipeline_config.pop(key, None)
pipeline_config.setdefault("litellm_router", {})
# nosemgrep: python-no-os-environ -- HF Space env vars; no config in container
mistral_key = os.environ.get("MISTRAL_API_KEY", "")
if mistral_key:
pipeline_config["litellm_router"]["proxy_url"] = "https://api.mistral.ai/v1"
pipeline_config["litellm_router"]["proxy_api_key"] = mistral_key
pipeline_config["litellm_router"]["model_alias"] = "mistral-small-latest"
log.info("LiteLLM router pointed at Mistral API (model=mistral-small-latest)")
else:
pipeline_config["litellm_router"]["proxy_url"] = (
"https://ronheichman-llm-service.hf.space"
)
log.info("LiteLLM router pointed at llm-service Space (no MISTRAL_API_KEY)")
PIPELINE_CONFIG_PATH.write_text(
yaml.dump(pipeline_config, default_flow_style=False, sort_keys=False),
)
log.info("Pipeline config patched: stripped %s", PIPELINE_ONLY_KEYS)
if __name__ == "__main__":
main()