Download _backend/cli/build_tool.py from IOE-IFAD/test: direct link, hf CLI and curl.
- Browser
- Download file 6.32 kB
-
https://huggingface.co/spaces/IOE-IFAD/test/resolve/main/_backend/cli/build_tool.py
- Command line
-
hf download hf://spaces/IOE-IFAD/test/_backend/cli/build_tool.py
-
curl -L -o build_tool.py https://huggingface.co/spaces/IOE-IFAD/test/resolve/main/_backend/cli/build_tool.py
6.32 kB
| import os | |
| import sys | |
| import subprocess | |
| from pathlib import Path | |
| from typing import List | |
| from dotenv import load_dotenv | |
| ROOT = Path(__file__).resolve().parents[2] | |
| load_dotenv(str(Path(__file__).resolve().parents[1] / ".env")) | |
| sys.path.append(str(Path(__file__).resolve().parents[1])) # Add parent directory to path | |
| import typer | |
| try: | |
| import questionary # type: ignore | |
| except ImportError: | |
| questionary = None # Fallback if not installed | |
| from docker_builder import build_dockerfile, write_dockerfile | |
| from graphrag_builder import build_graphrag | |
| from hf_deployer import deploy_space | |
| from vector_db_builder import build_vector_db_for_dir | |
| app = typer.Typer(help="Interactive build & deploy tool") | |
| BACKEND_DIR = ROOT / "_backend" | |
| DATA_DIR = BACKEND_DIR / "data" | |
| DEFAULT_DOCKERFILE = ROOT / "Dockerfile.generated" | |
| def list_data_files() -> List[Path]: | |
| # Listing all the directories in the data directory | |
| folders = [p for p in DATA_DIR.iterdir() if p.is_dir()] | |
| if not folders: | |
| return [] | |
| return sorted(folders) | |
| def run_command(cmd: List[str], cwd: Path | None = None): | |
| typer.echo(f"Running: {' '.join(cmd)}") | |
| res = subprocess.run(cmd, cwd=cwd, text=True) | |
| if res.returncode != 0: | |
| raise typer.Exit(code=res.returncode) | |
| def ensure_questionary(): | |
| if questionary is None: | |
| typer.echo("questionary not installed. Please add it to requirements and install.") | |
| raise typer.Exit(code=1) | |
| def interactive( | |
| graphrag: bool = typer.Option(False, help="Build GraphRAG artifacts"), | |
| deploy: bool = typer.Option(False, help="Deploy to Hugging Face after build"), | |
| dockerfile_out: Path = typer.Option(DEFAULT_DOCKERFILE, help="Path for generated Dockerfile"), | |
| non_interactive: bool = typer.Option(False, help="Skip confirmations where possible") | |
| ): | |
| """Run the interactive (or semi-interactive) build workflow.""" | |
| if not non_interactive: | |
| ensure_questionary() | |
| files = list_data_files() | |
| if not files: | |
| typer.echo("No data files found under _backend/data.") | |
| raise typer.Exit(code=1) | |
| if non_interactive: | |
| selected_paths = files # take all | |
| else: | |
| choices = [f.relative_to(DATA_DIR).as_posix() for f in files] | |
| selected_rel = questionary.checkbox( | |
| "Select data files to include:", choices=choices | |
| ).ask() | |
| if not selected_rel: | |
| typer.echo("No files selected.") | |
| raise typer.Exit() | |
| selected_paths = [DATA_DIR / r for r in selected_rel] | |
| # Optional vector DB build using new utility | |
| do_reset = True if non_interactive else questionary.confirm( | |
| "Build/reset vector database(s) for selected data directories?" | |
| ).ask() | |
| if do_reset: | |
| for data_path in selected_paths: | |
| # Prompt for file suffix and collection name | |
| if non_interactive: | |
| file_suffix = None | |
| collection_name = data_path.name | |
| else: | |
| file_suffix = questionary.text( | |
| f"File suffix to include for {data_path.name} (e.g. .md, .srt, leave blank for all):", | |
| default="" | |
| ).ask() | |
| file_suffix = file_suffix if file_suffix.strip() else None | |
| collection_name = questionary.text( | |
| f"Collection name for {data_path.name}:", | |
| default=data_path.name | |
| ).ask() | |
| build_vector_db_for_dir( | |
| data_dir=str(data_path), | |
| collection_name=collection_name, | |
| file_suffix=file_suffix, | |
| verbose=True | |
| ) | |
| graphrag_artifact_paths: List[str] = [] | |
| build_graphrag_flag = graphrag or (False if non_interactive else questionary.confirm( | |
| "Build GraphRAG artifacts?" | |
| ).ask()) | |
| if build_graphrag_flag: | |
| out_dir = BACKEND_DIR / "graphrag_artifacts" | |
| build_graphrag(selected_paths, out_dir) | |
| graphrag_artifact_paths.append(str(out_dir.relative_to(ROOT))) | |
| frontend_dir = Path(os.getenv("FRONTEND_DIR", "frontend")) | |
| build_cmd = os.getenv("FRONTEND_BUILD_CMD", "npm run build") | |
| build_out = os.getenv("FRONTEND_BUILD_OUTPUT", "dist") | |
| prebuild_frontend = True if non_interactive else questionary.confirm( | |
| "Pre-build frontend locally first?" | |
| ).ask() | |
| if prebuild_frontend: | |
| if frontend_dir.exists(): | |
| run_command(build_cmd.split(), cwd=ROOT / frontend_dir) | |
| else: | |
| typer.echo(f"Frontend directory {frontend_dir} not found; skipping pre-build.") | |
| docker_content = build_dockerfile( | |
| frontend_build_cmd=build_cmd, | |
| frontend_build_output=build_out, | |
| graphrag_artifact_paths=graphrag_artifact_paths or None, | |
| ) | |
| write_dockerfile(dockerfile_out, docker_content) | |
| typer.echo(f"Wrote Dockerfile to {dockerfile_out}") | |
| build_image = True if non_interactive else questionary.confirm( | |
| "Build Docker image locally?" | |
| ).ask() | |
| if build_image: | |
| tag = os.getenv("IMAGE_TAG", "interview-synth:latest") if non_interactive else questionary.text( | |
| "Image tag:", default="interview-synth:latest" | |
| ).ask() | |
| run_command(["docker", "build", "-f", str(dockerfile_out), "-t", tag, "."], cwd=ROOT) | |
| do_deploy = deploy or (False if non_interactive else questionary.confirm( | |
| "Deploy to Hugging Face Spaces?" | |
| ).ask()) | |
| if do_deploy: | |
| space_id = os.getenv("HF_SPACE_ID") or ("" if non_interactive else questionary.text( | |
| "Enter HF Space (user/space):" | |
| ).ask()) | |
| token = os.getenv("HF_TOKEN") or ("" if non_interactive else questionary.password( | |
| "Enter Hugging Face token:" | |
| ).ask()) | |
| if not space_id or not token: | |
| typer.echo("Space ID or token missing; aborting deploy.") | |
| else: | |
| # Write the generated Dockerfile to project root for Spaces | |
| (ROOT / "Dockerfile").write_text(docker_content, encoding="utf-8") | |
| deploy_space(space_id, ROOT, token) | |
| typer.echo("Done.") | |
| if __name__ == "__main__": | |
| app() | |