import uvicorn.protocols.http.httptools_impl # orig_data_received = uvicorn.protocols.http.httptools_impl.HttpToolsProtocol.data_received # def debug_data_received(self, data): # try: # print("RAW INVALID DATA RECEIVED: %r", data) # except Exception: # pass # return orig_data_received(self, data) # uvicorn.protocols.http.httptools_impl.HttpToolsProtocol.data_received = debug_data_received from typing import Union, Optional, List from fastapi.exceptions import RequestValidationError from pydantic import BaseModel from fastapi import FastAPI, Request, Depends from CommonCode.settings import get_logger from CommonCode.video_meta import FTPVideo import logging from fastapi.responses import JSONResponse, StreamingResponse import os import numpy as np from fastapi import FastAPI, Request, status import sys import json import time from util import embed_scores as ES from fastapi_server_session import SessionManager, RedisSessionInterface, Session import redis from datetime import timedelta app = FastAPI() session_manager = SessionManager( interface=RedisSessionInterface(redis.from_url("redis://localhost")) ) logger = get_logger( __name__, "/var/log/vector_search_logs/main_embed_scores", stdout=True, systemd=False, level=logging.INFO, ) r = redis.Redis(host="localhost", port=6379, db=15) @app.exception_handler(RequestValidationError) async def validation_exception_handler(request: Request, exc: RequestValidationError): exc_str = f"{exc}".replace("\n", " ").replace(" ", " ") logging.error(f"{request}: {exc_str}") content = {"status_code": 10422, "message": exc_str, "data": None} return JSONResponse( content=content, status_code=status.HTTP_422_UNPROCESSABLE_ENTITY ) @app.get("/video_embeddings") def get_video_embeddings(video_path: str): llvec = ES.get_embeddings_for_a_file(video_path) if llvec is not None: llvec = dict(llvec) llvec["embeds"] = llvec["embeds"].tolist() llvec["frame_numbers"] = llvec["frame_numbers"].tolist() return llvec @app.get("/prompt_embedding") def get_prompt_embedding(prompt: str): return ES.get_query_vector(prompt) @app.get("/match_scores") def get_clip_scores(video_path: str, prompt: str): results = ES.get_clip_scores(video_path, prompt) return results.T.tolist() class VideosPostRequest(BaseModel): query: str = "A cat and a human" threshold: float = 0.10 c_dirs: Optional[List[str]] = None task_id: str = "compute_log" @app.post("/videos.json") async def videos_json( vpr: VideosPostRequest, session: Session = Depends(session_manager.use_session), ): query = vpr.query threshold = vpr.threshold c_dirs = vpr.c_dirs task_id = vpr.task_id if c_dirs is None: c_dirs = [ # "/mnt/hdd_24tb_1/videos/ftp/leopards2/2025/08/26", # "/srv/ftp_tcc/leopards1/2025/08/27", # "/srv/ftp_tcc/leopards1/2025/08/28", # "/srv/ftp_tcc/leopards1/2025/08/29", # "/srv/ftp_tcc/leopards1/2025/08/30", # "/srv/ftp_tcc/leopards1/2025/08/31", # "/srv/ftp_tcc/leopards1/2025/09/01", # "/srv/ftp_tcc/leopards1/2025/09/02", # "/srv/ftp_tcc/leopards1/2025/09/03", # "/srv/ftp_tcc/leopards1/2025/09/04", # "/srv/ftp_tcc/leopards1/2025/09/05", # "/srv/ftp_tcc/leopards1/2025/09/06", # "/srv/ftp_tcc/leopards1/2025/09/07", "/srv/ftp_tcc/leopards1/2025/09/08", "/srv/ftp_tcc/leopards1/2025/09/09", "/srv/ftp_tcc/leopards1/2025/09/10", "/srv/ftp_tcc/leopards1/2025/09/11", ] # print(','.join([str(x) for x in c_dirs])) # message = {'task':'SCHEDULED','when':[str(x) for x in c_dirs], 'time':time.time()} # r.rpush(task_id, json.dumps(message))? for x in c_dirs: message = {"task": "QUEUEING", "when": str(x), "time": time.time()} r.rpush(task_id, json.dumps(message)) folder_scores = ES.calculate_embedding_score_in_folders( tuple(c_dirs), threshold=threshold, query=query, redis_key=task_id ) # if p_hits != ES.calculate_embedding_score_in_folders.cache_info().hits: # logger.info("FROM CACHE") # else:pp # logger.info("COMPUTED FROM SCRATCH") folder_scores["breaks"] = ES.add_breaks_between_videos(folder_scores) folder_scores["videos"] = ES.collapse_scores_to_maxmin_avg(folder_scores) return folder_scores class ClickEvent(BaseModel): timestamp: float class ClickResponse(BaseModel): path: str timeoffset: float