scholarshipid / scripts /serve.py
ydmhmhm's picture
feat: add /parse-cv endpoint for extracting student data from resumes
946b422
Raw
History Blame Contribute Delete
2.82 kB
"""FastAPI serving entry point.
Usage:
python scripts/serve.py
Configuration is read from configs/default.yaml (all config in one place).
Override model paths via CLI flags if needed:
python scripts/serve.py --student-tower outputs/checkpoints/student_tower_best.keras \\
--scholarship-tower outputs/checkpoints/scholarship_tower_best.keras
Before starting, pulls latest data + model artifacts from HuggingFace (checks both repos).
"""
import os
os.environ["OMP_NUM_THREADS"] = "1"
os.environ["TOKENIZERS_PARALLELISM"] = "false"
import argparse
import signal
import sys
import uvicorn
from scripts.hf_sync import pull_data_artifacts, pull_model_artifacts
from src.serving.inference_engine import InferenceEngine
from src.serving.api import create_app
def parse_args():
parser = argparse.ArgumentParser(description="Start recommendation serving API")
parser.add_argument(
"--student-tower",
type=str,
default=None,
help="Override student tower checkpoint path (defaults from config)",
)
parser.add_argument(
"--scholarship-tower",
type=str,
default=None,
help="Override scholarship tower checkpoint path (defaults from config)",
)
parser.add_argument("--config", type=str, default="configs/default.yaml")
return parser.parse_args()
def main():
args = parse_args()
# Pull data + model artifacts from HuggingFace before starting server (blocks until done)
print("Pulling data artifacts...")
pull_data_artifacts(config_path=args.config)
print("Pulling model artifacts...")
pull_model_artifacts(config_path=args.config)
# Build and initialize inference engine (loads models, warms up SBERT, caches scholarships)
# Pass None for paths not provided via CLI — InferenceEngine will resolve defaults from config
print(f"Initializing InferenceEngine (config: {args.config}) ...")
engine = InferenceEngine(
student_tower_path=args.student_tower,
scholarship_tower_path=args.scholarship_tower,
config_path=args.config,
)
engine.initialize()
# Create FastAPI app bound to this engine instance
app = create_app(engine)
# Start uvicorn server with config-driven host/port
print(f"Starting server on {engine.server_config.server_host}:{engine.server_config.server_port}")
def shutdown(signum, frame):
print("\nShutting down gracefully...")
sys.exit(0)
signal.signal(signal.SIGINT, shutdown)
signal.signal(signal.SIGTERM, shutdown)
try:
uvicorn.run(
app,
host=engine.server_config.server_host,
port=engine.server_config.server_port,
)
except KeyboardInterrupt:
pass
if __name__ == "__main__":
main()