Files
caption-local/deploy.py
T

82 lines
4.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Portable bootstrap/launcher. Uses only Python's standard library."""
import argparse
import os
from pathlib import Path
import subprocess
import sys
import venv
ROOT = Path(__file__).resolve().parent
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('command', nargs='?', choices=['run', 'setup', 'download', 'doctor'], default='run')
parser.add_argument('--venv', type=Path, default=ROOT / '.venv')
parser.add_argument('--model', default='small')
parser.add_argument('--port', type=int, default=8765)
parser.add_argument('--beam-size', type=int, choices=range(1,6), default=5)
parser.add_argument('--workers', type=int, default=1)
parser.add_argument('--max-streams', type=int, default=12)
parser.add_argument('--threads', type=int, default=4)
parser.add_argument('--offline', action='store_true')
parser.add_argument('--log-requests', action='store_true')
parser.add_argument('--device', choices=['cpu', 'cuda', 'auto'], default='cpu')
parser.add_argument('--compute-type', choices=['auto', 'int8', 'float32', 'float16', 'int8_float16'], default='auto')
args = parser.parse_args()
if sys.version_info < (3, 12):
parser.error('Install Python 3.12 or newer (3.12 is tested).')
if args.threads < 1 or not 1 <= args.workers <= 8 or not 1 <= args.max_streams <= 64 or not 1 <= args.port <= 65535:
parser.error('Threads must be positive; workers 1–8; streams 1–64; port 1–65535')
env_dir = args.venv.expanduser().resolve()
python = env_dir / ('Scripts/python.exe' if os.name == 'nt' else 'bin/python')
other_python = env_dir / ('bin/python' if os.name == 'nt' else 'Scripts/python.exe')
if os.path.lexists(other_python):
parser.error('This environment contains another platform\'s Python. Preserve it and use a separate '
'--venv directory (for example --venv .venv-wsl inside WSL).')
def run(*command):
subprocess.run([str(c) for c in command], cwd=ROOT, check=True)
if args.command == 'setup' or (args.command == 'run' and not python.exists()):
if args.offline:
parser.error('Offline run requires an existing environment. Run setup and download online first.')
print(f'Installing dependencies into {env_dir}', flush=True)
venv.EnvBuilder(with_pip=True).create(env_dir)
requirements = 'requirements-linux.lock' if sys.platform == 'linux' else 'requirements.txt'
run(python, '-m', 'pip', 'install', '-r', ROOT / requirements)
if not python.exists():
parser.error('Environment missing. Run: python deploy.py setup')
if args.command == 'setup':
print('Setup complete. Next: python deploy.py run', flush=True)
elif args.command == 'doctor':
run(python, '-m', 'pip', 'check')
run(python, '-c', 'import server, ctranslate2; print("Runtime imports OK"); print("CUDA devices:", ctranslate2.get_cuda_device_count()); print("CPU types:", sorted(ctranslate2.get_supported_compute_types("cpu")))')
print('Runtime ready. This check does not download models or test a microphone.', flush=True)
elif args.command == 'download':
run(python, '-c', 'from server import Engine; import sys; Engine(sys.argv[1], offline=sys.argv[2] == "1"); print("Model ready")', args.model, '1' if args.offline else '0')
else:
print(f'Open http://localhost:{args.port} once the server is ready. Ctrl+C stops it.', flush=True)
command = [str(python), str(ROOT / 'server.py'), '--model', args.model,
'--port', str(args.port), '--threads', str(args.threads),
'--beam-size', str(args.beam_size), '--workers', str(args.workers), '--max-streams', str(args.max_streams),
'--device', args.device, '--compute-type', args.compute_type]
if args.offline:
command.append('--offline')
if args.log_requests:
command.append('--log-requests')
if os.name != 'nt':
os.execv(str(python), command)
else:
run(*command)
if __name__ == '__main__':
try:
main()
except subprocess.CalledProcessError as exc:
print(f'Command failed (exit {exc.returncode}). Fix the error above and rerun setup or doctor.', file=sys.stderr)
sys.exit(exc.returncode)
except KeyboardInterrupt:
pass