PhillSwarm-4b / launch_swarm_app.py
ayjays132's picture
Upload 223 files
c318200 verified
Raw History Blame Contribute Delete
5.63 kB
"""Launch the local Phill Swarm App.
Portable launcher:
py launch_swarm_app.py --install
python scripts/launch_swarm_app.py --install --config configs/phill_swarm_app.json
The same file works from a source checkout or from a packaged HF snapshot.
"""
import argparse
import importlib.util
import os
from pathlib import Path
import shutil
import subprocess
import sys
def _detect_root() -> Path:
here = Path(__file__).resolve()
candidates = [here.parent, Path.cwd()]
if len(here.parents) > 1:
candidates.append(here.parents[1])
for root in candidates:
if (root / "swarm_app_config.example.json").exists() or (root / "config.json").exists():
return root.resolve()
if (root / "configs" / "phill_swarm_app.json").exists():
return root.resolve()
if (root / "src" / "swarm_moe_model").exists():
return root.resolve()
return here.parent.resolve()
PROJECT_ROOT = _detect_root()
SRC_ROOT = PROJECT_ROOT / "src"
if SRC_ROOT.exists():
sys.path.insert(0, str(SRC_ROOT))
from swarm_moe_model.swarm_app import SwarmAppConfig, run_app # noqa: E402
def _run(cmd, cwd=None, timeout=600):
print(f"[swarm-app] run: {' '.join(str(x) for x in cmd)}")
return subprocess.run(cmd, cwd=str(cwd) if cwd else None, check=True, timeout=timeout)
def _default_config() -> Path:
candidates = [
PROJECT_ROOT / "swarm_app_config.example.json",
Path.cwd() / "swarm_app_config.example.json",
PROJECT_ROOT / "configs" / "phill_swarm_app.json",
]
for path in candidates:
if path.exists():
return path.resolve()
return candidates[0]
def _tools_dir(explicit: str | None = None) -> Path:
if explicit:
return Path(os.path.expandvars(explicit)).expanduser().resolve()
candidates = [
PROJECT_ROOT / "src" / "swarm_moe_model" / "Tools",
PROJECT_ROOT / "swarm_moe_model" / "Tools",
]
spec = importlib.util.find_spec("swarm_moe_model")
if spec and spec.submodule_search_locations:
candidates.append(Path(list(spec.submodule_search_locations)[0]) / "Tools")
for path in candidates:
if path.exists():
return path.resolve()
return candidates[0].resolve()
def ensure_python_extras(include_browser: bool = True):
packages = []
if importlib.util.find_spec("ddgs") is None and importlib.util.find_spec("duckduckgo_search") is None:
packages.append("ddgs")
if include_browser and importlib.util.find_spec("playwright") is None:
packages.append("playwright")
if importlib.util.find_spec("yaml") is None:
packages.append("pyyaml")
if packages:
_run([sys.executable, "-m", "pip", "install", *packages], cwd=PROJECT_ROOT)
if include_browser:
try:
import playwright # noqa: F401
_run([sys.executable, "-m", "playwright", "install", "chromium"], cwd=PROJECT_ROOT, timeout=1200)
except Exception as exc:
print(f"[swarm-app] WARN playwright browser install skipped/failed: {exc}")
def ensure_npm_tools(tools_dir: Path):
npm = shutil.which("npm.cmd" if os.name == "nt" else "npm") or shutil.which("npm")
if npm is None:
print("[swarm-app] WARN npm not found; Python tools still work, Wrench TypeScript tools remain catalogued.")
return
if not (tools_dir / "package.json").exists():
print("[swarm-app] WARN Tools/package.json not found; skipping npm install.")
return
command = "ci" if (tools_dir / "package-lock.json").exists() else "install"
_run([npm, command], cwd=tools_dir, timeout=1200)
def main():
ap = argparse.ArgumentParser()
ap.add_argument("--config", default=str(_default_config()))
ap.add_argument("--host", default=None)
ap.add_argument("--port", type=int, default=None)
ap.add_argument("--model", default=None)
ap.add_argument("--permission-mode", choices=["default", "yolo"], default=None)
ap.add_argument("--install", action="store_true", help="install optional DDGS/Playwright/npm tool dependencies before launch")
ap.add_argument("--no-browser-install", action="store_true")
ap.add_argument("--no-npm-install", action="store_true")
ap.add_argument("--tools-dir", default=None, help="optional Tools directory for npm install")
ap.add_argument("--headless", action="store_true", help="run Playwright browser tools headless to save memory")
ap.add_argument("--visible-browser", action="store_true", help="force visible Playwright browser windows for browser tools")
ap.add_argument("--capture-dir", default=None, help="browser snapshot directory; defaults to state/browser_captures")
ap.add_argument("--no-open", action="store_true")
args = ap.parse_args()
if args.install:
ensure_python_extras(include_browser=not args.no_browser_install)
if not args.no_npm_install:
ensure_npm_tools(_tools_dir(args.tools_dir))
cfg = SwarmAppConfig.from_json(args.config)
if args.host:
cfg.host = args.host
if args.port:
cfg.port = args.port
if args.model:
cfg.model_path = args.model
cfg.swarm_config = None
if args.permission_mode:
cfg.permission_mode = args.permission_mode
if args.headless:
cfg.browser_headless = True
if args.visible_browser:
cfg.browser_headless = False
if args.capture_dir:
cfg.browser_capture_dir = args.capture_dir
if args.no_open:
cfg.auto_open = False
run_app(cfg, project_root=PROJECT_ROOT)
if __name__ == "__main__":
main()