e1250 commited on
Commit
5e55742
·
1 Parent(s): c5f1aa5

feat: full clearning the repo

Browse files
Dockerfile CHANGED
@@ -18,5 +18,5 @@ COPY . .
18
  # As HF want for backend.
19
  EXPOSE 7860
20
 
21
- # Starting the server. 0.0.0.0 accepts connections from anywhere, not just local.
22
  CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "7860", "--ws", "websockets"]
 
18
  # As HF want for backend.
19
  EXPOSE 7860
20
 
21
+ # 0.0.0.0 accepts connections from anywhere, not just local. also don't forget --ws to enable sockets on docker
22
  CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "7860", "--ws", "websockets"]
README.md CHANGED
@@ -5,4 +5,6 @@ app_port: 7860
5
  pinned: false
6
  ---
7
 
8
- This project is part of a big project proiding Real-Time Tracking system for Indoors.
 
 
 
5
  pinned: false
6
  ---
7
 
8
+ Tracking System Backend Deployed on huggingface.
9
+
10
+ This repository is being modified only from the main Github Repo using CI/CD, Making sure it is always up to date and match project requirements.
api/__pycache__/dependencies.cpython-311.pyc DELETED
Binary file (1.13 kB)
 
api/routers/__pycache__/camera_stream.cpython-311.pyc DELETED
Binary file (10.5 kB)
 
api/routers/__pycache__/dashboard_stream.cpython-311.pyc DELETED
Binary file (3.01 kB)
 
api/routers/__pycache__/health.cpython-311.pyc DELETED
Binary file (2.73 kB)
 
api/routers/__pycache__/metrics.cpython-311.pyc DELETED
Binary file (1.4 kB)
 
api/routers/camera_stream.py CHANGED
@@ -30,7 +30,7 @@ async def websocket_detect(
30
 
31
  url here is: ws://127.0.0.1:8000/detectors/stream/camera_id
32
  """
33
- # Yes, I asked the same questions, is using webscoket.app.state many times here is consuming. after checking, it is not performance consuming.
34
  state = websocket.app.state
35
  logger = state.logger
36
  # Using Depends is important and called Inversion Of Control (IoC)/ Dependency injection, and is important for testing.
@@ -72,37 +72,26 @@ async def websocket_detect(
72
 
73
  async def process_frames():
74
 
75
-
76
  try:
77
- # What are the info you aim to collect from the camera?
78
- # How many frames received by second.
79
- # Frame processing time.
80
- # Average processing time for logger.
81
- # Model processing time.
82
-
83
- # frame_count = itertools.count()
84
 
85
  logger.info(f"Camera {camera_id} start sending frames...")
86
 
87
- def decode_frame():
88
- # Decode image
89
- return cv.imdecode(np.frombuffer(frame_bytes, np.uint8), cv.IMREAD_COLOR)
90
 
91
  # Keep receiving messages in a loop until disconnection.
92
  while True:
93
-
94
  frame_bytes = await frame_queue.get()
95
 
96
  # Profiling
97
  t0 = time.time()
98
 
99
- image_array = await loop.run_in_executor(None, decode_frame)
100
  decode_duration_seconds.labels(camera_id).observe(round(time.time() - t0, 3))
101
  mlflow.log_metric("frame_processing_time", round(time.time() - t0, 3), next(step_counter))
102
 
 
103
  detection_task = loop.run_in_executor(None, detector.detect, image_array)
104
  safety_task = loop.run_in_executor(None, safety_detector.detect, image_array)
105
-
106
  detections, safety_detection = await asyncio.gather(detection_task, safety_task)
107
  detection_duration_seconds.labels(camera_id).observe(round(time.time() - t0, 3))
108
  mlflow.log_metric("detection_duration_seconds", round(time.time() - t0, 3), next(step_counter))
@@ -129,7 +118,6 @@ async def websocket_detect(
129
  detection_metadata = [DetectionMetadata(depth=depth, xRatio=xRatio) for depth, xRatio in zip(depth_points, boxes_center_ratio)]
130
  metadata = CameraMetadata(camera_id=camera_id, is_danger = True if safety_detection else False, detection_metadata=detection_metadata)
131
 
132
- # state.camera_metadata[camera_id] = metadata.model_dump()
133
  await redis.publish("dashboard_stream", metadata.model_dump_json())
134
  # Even if the camera was disconnected, redis is still going to show its data, which is not accurate.
135
  # Instead, we set expiry date for the camera data.
@@ -154,7 +142,6 @@ async def websocket_detect(
154
 
155
  except WebSocketDisconnect:
156
  logger.warn(f"Client ID >>{camera_id}<< Disconnected Normally...")
157
- # state.camera_metadata.pop(camera_id, None)
158
 
159
  except Exception as e:
160
  logger.error(f"Error in websocker, Client ID: >>{camera_id}<<: {e}")
@@ -164,13 +151,4 @@ async def websocket_detect(
164
 
165
  finally:
166
  active_cameras.dec()
167
- mlflow.end_run()
168
-
169
-
170
- # Uncomment this when needed, It is the same but using HTTP, which is Request Response only. could be used for testing.
171
- # from fastapi import Request, UploadFile
172
- # @router.post("/detect")
173
- # async def post_detection(request: Request, file: UploadFile):
174
- # # Request here is being used to access the app.state.model
175
-
176
- # request.app.state.model.detect(file)
 
30
 
31
  url here is: ws://127.0.0.1:8000/detectors/stream/camera_id
32
  """
33
+ # Yes, I asked the same questions, is using webscoket.app.state many times here is consuming. after checking, it is not performance consuming.
34
  state = websocket.app.state
35
  logger = state.logger
36
  # Using Depends is important and called Inversion Of Control (IoC)/ Dependency injection, and is important for testing.
 
72
 
73
  async def process_frames():
74
 
 
75
  try:
 
 
 
 
 
 
 
76
 
77
  logger.info(f"Camera {camera_id} start sending frames...")
78
 
79
+ def decode_frame(fb): return cv.imdecode(np.frombuffer(fb, np.uint8), cv.IMREAD_COLOR)
 
 
80
 
81
  # Keep receiving messages in a loop until disconnection.
82
  while True:
 
83
  frame_bytes = await frame_queue.get()
84
 
85
  # Profiling
86
  t0 = time.time()
87
 
88
+ image_array = await loop.run_in_executor(None, decode_frame, frame_bytes)
89
  decode_duration_seconds.labels(camera_id).observe(round(time.time() - t0, 3))
90
  mlflow.log_metric("frame_processing_time", round(time.time() - t0, 3), next(step_counter))
91
 
92
+ # Apply detection models
93
  detection_task = loop.run_in_executor(None, detector.detect, image_array)
94
  safety_task = loop.run_in_executor(None, safety_detector.detect, image_array)
 
95
  detections, safety_detection = await asyncio.gather(detection_task, safety_task)
96
  detection_duration_seconds.labels(camera_id).observe(round(time.time() - t0, 3))
97
  mlflow.log_metric("detection_duration_seconds", round(time.time() - t0, 3), next(step_counter))
 
118
  detection_metadata = [DetectionMetadata(depth=depth, xRatio=xRatio) for depth, xRatio in zip(depth_points, boxes_center_ratio)]
119
  metadata = CameraMetadata(camera_id=camera_id, is_danger = True if safety_detection else False, detection_metadata=detection_metadata)
120
 
 
121
  await redis.publish("dashboard_stream", metadata.model_dump_json())
122
  # Even if the camera was disconnected, redis is still going to show its data, which is not accurate.
123
  # Instead, we set expiry date for the camera data.
 
142
 
143
  except WebSocketDisconnect:
144
  logger.warn(f"Client ID >>{camera_id}<< Disconnected Normally...")
 
145
 
146
  except Exception as e:
147
  logger.error(f"Error in websocker, Client ID: >>{camera_id}<<: {e}")
 
151
 
152
  finally:
153
  active_cameras.dec()
154
+ mlflow.end_run()
 
 
 
 
 
 
 
 
 
config/__pycache__/settings.cpython-311.pyc DELETED
Binary file (5.34 kB)
 
config/config.yaml CHANGED
@@ -1,27 +1,17 @@
1
- # Shared defaults values that work for most people or envs
2
- # TODO, mostly this might not work in docker, due to the "\", feel free to replace it by [*proj_dir, ai, dl_models] for exmple
3
 
4
  project_name: Tracking Config
5
  # This one called Literal block, there is another one called Folded (>)
6
  project_desc: |
7
  Tracking System for detection, providing real-time camera status throught a Dashboard.
8
  task: indoor
9
-
10
  intervals:
11
- system_metrics_seconds: 3.0 # Logging system metrics every
12
- frames_summary_every: 30 # Number of frames to create a logs summary
13
- realtime_updates_every: 2 # backend send updates every n seconds?
14
-
15
- prometheus_port: 9091
16
-
17
- paths:
18
- # project_dir: &proj_dir G:\MyComputer\Workspace\Projects\gp-tracking-dashboard\tracking_dashboard
19
- project_dir: &proj_dir .
20
- # models_dir: &models_dir !join [*proj_dir, ai, dl_models]
21
- # logs_dir: !join [*proj_dir, backend, config, logs, logs]
22
 
23
  yolo:
24
- # model_path: !join [*models_dir, yolo26s.pt]
25
  classes:
26
  - person
27
  batch_size: 16
@@ -31,11 +21,12 @@ yolo:
31
  data_path: ""
32
 
33
  security_detector:
34
- # model_path: !join [*models_dir, "yolo_smoke_fire.pt"]
35
  classes:
36
  - fire
37
  - smoke
38
 
39
- depth:
40
- # model_path: !join [*models_dir, depth_anything_v2_vits.pth]
41
- encoder: "vits"
 
 
1
+ # YAML file contains Shared defaults values that work for most people or envs
 
2
 
3
  project_name: Tracking Config
4
  # This one called Literal block, there is another one called Folded (>)
5
  project_desc: |
6
  Tracking System for detection, providing real-time camera status throught a Dashboard.
7
  task: indoor
 
8
  intervals:
9
+ system_metrics_seconds: 3.0 # Logging system metrics every
10
+ frames_summary_every: 30 # Number of frames to create a logs summary
11
+ realtime_updates_every: 2 # backend send updates every n seconds?
 
 
 
 
 
 
 
 
12
 
13
  yolo:
14
+ model_name: "yolo26n.pt"
15
  classes:
16
  - person
17
  batch_size: 16
 
21
  data_path: ""
22
 
23
  security_detector:
24
+ model_name: "yolo_smoke_fire.pt"
25
  classes:
26
  - fire
27
  - smoke
28
 
29
+ depth:
30
+ model_name: "depth_anything_v2_vits.pth"
31
+ device: "cpu"
32
+ encoder: "vits"
config/settings.py CHANGED
@@ -11,19 +11,18 @@ def join_tag(loader, node):
11
  parts = loader.construct_sequence(node)
12
  path = Path(*(str(part) for part in parts)).resolve()
13
  return str(path)
 
14
  # It didn't work before, After some research, .SafeLoaded is unmentioned must for my case.
15
  yaml.SafeLoader.add_constructor("!join", join_tag)
16
 
17
-
18
- class PathsConfig(BaseModel):
19
- """Contains paths of directories"""
20
- project_dir: str
21
- # models_dir: str
22
- # logs_dir: str
23
 
24
  class YoloConfig(BaseModel):
25
  """Contains yolo configurations"""
26
- # model_path: str
27
  classes: List[str]
28
  batch_size: int
29
  epochs: int
@@ -33,19 +32,15 @@ class YoloConfig(BaseModel):
33
 
34
  class SecurityDetector(BaseModel):
35
  "Contains Security Detectors like Smoke - Fire"
36
- # model_path: str
37
  classes: List[str]
38
 
39
  class DepthConfig(BaseModel):
40
  "Contains depths estimation configurations"
41
- # model_path: str
 
42
  encoder: Literal["vits", "vitb", "vitl", "vitg"]
43
 
44
- class IntervalsConfig(BaseModel):
45
- system_metrics_seconds: float
46
- frames_summary_every: int
47
- realtime_updates_every: float
48
-
49
 
50
  class AppConfig(BaseSettings):
51
  """
@@ -59,33 +54,22 @@ class AppConfig(BaseSettings):
59
  env_file=Path(__file__).parent / ".env",
60
  env_file_encoding="utf-8",
61
  yaml_file=Path(__file__).parent / "config.yaml",
62
- # case_sensitive=False, # default True
63
- # env_prefix="YOLO_", # Means configs we are talking about starts with YOLO_
64
- # env_nested_delimiter="__", # Means we use _ instead of spaces for the same var
65
- extra="ignore" # Ignore other settings in yaml and env as they are not mentioedhere
66
  )
67
 
68
  project_name:str
69
  project_desc:str
70
  task: Literal["indoor", "outdoor"]
71
 
72
- paths: PathsConfig
73
  yolo: YoloConfig
74
  security_detector: SecurityDetector
75
  depth: DepthConfig
76
  intervals: IntervalsConfig
77
  redis_url:str
78
 
79
- # Backend
80
-
81
-
82
  @classmethod
83
  def settings_customise_sources(cls,
84
  settings_cls: type[BaseSettings], # Base param.
85
- # init_settings: PydanticBaseSettingsSource, # Values passed to __init__
86
- # env_settings: PydanticBaseSettingsSource, # OS Env variables
87
- # dotenv_settings: PydanticBaseSettingsSource,
88
- # file_secret_settings: PydanticBaseSettingsSource # Secret Directories
89
  **kwargs
90
  ) -> tuple[PydanticBaseSettingsSource, ...] :
91
  """
@@ -93,7 +77,7 @@ class AppConfig(BaseSettings):
93
  But this time it fixs the priority part, order by parameters priority.
94
  """
95
 
96
- # Order by priority
97
  return (
98
  DotEnvSettingsSource(settings_cls), # Most important
99
  EnvSettingsSource(settings_cls), # This allow for ex. hugging face to override .env values with its values.
@@ -101,43 +85,8 @@ class AppConfig(BaseSettings):
101
  ) # The return must be a tuple
102
 
103
 
104
- # @classmethod
105
- # def load_config(cls, yaml_path: Path | str = Path(__file__).parent / "config.yaml") -> "AppConfig":
106
- # """Loading confiuration and settings from Config.yaml file then override using .env"""
107
-
108
- # yaml_path = Path(yaml_path).resolve() # Absolute path
109
- # if not yaml_path.is_file():
110
- # raise FileNotFoundError(f"Config file not found: {yaml_path}")
111
-
112
- # with yaml_path.open("r") as f:
113
- # yaml_data = yaml.safe_load(f) or {}
114
-
115
- # # env_data = cls() # This one loaded .env and not Yaml
116
- # # When this project grow, you are going to create different types of .yaml files for products and debugging and so on
117
- # # Feel free to stack them here, so we use the yaml required for our testing
118
- # # Note that in debuging.yaml file, we only override the base, not starting from scratch.
119
- # # return cls(**{
120
- # # **yaml_data, # Loading config.yaml configurations
121
- # # # **env_data.model_dump() # TODO(FIX) Overriding everything using .env
122
- # # })
123
- # return cls(**yaml_data)
124
-
125
-
126
-
127
-
128
  if __name__ == "__main__":
129
- # Note that we must use AppConfig without () to take .env in mind.
130
- # Checking for YAML part.
131
- # config = AppConfig.load_config()
132
- # print(config.model_dump())
133
- # print(config.model_dump()["project_name"])
134
-
135
- # Checking for .env file.
136
- # config = AppConfig()
137
- # print(f".env Path we are talking about: {Path(__file__).parent / ".env"}")
138
- # print(config.model_config)
139
- # print(config.project_name)
140
-
141
  # Trying to checking both yaml and .env. This works really fine now.
142
  config = AppConfig()
143
  print(config.model_dump())
 
11
  parts = loader.construct_sequence(node)
12
  path = Path(*(str(part) for part in parts)).resolve()
13
  return str(path)
14
+
15
  # It didn't work before, After some research, .SafeLoaded is unmentioned must for my case.
16
  yaml.SafeLoader.add_constructor("!join", join_tag)
17
 
18
+ class IntervalsConfig(BaseModel):
19
+ system_metrics_seconds: float
20
+ frames_summary_every: int
21
+ realtime_updates_every: float
 
 
22
 
23
  class YoloConfig(BaseModel):
24
  """Contains yolo configurations"""
25
+ model_name: str
26
  classes: List[str]
27
  batch_size: int
28
  epochs: int
 
32
 
33
  class SecurityDetector(BaseModel):
34
  "Contains Security Detectors like Smoke - Fire"
35
+ model_name: str
36
  classes: List[str]
37
 
38
  class DepthConfig(BaseModel):
39
  "Contains depths estimation configurations"
40
+ model_name: str
41
+ device: Literal["cuda", "cpu"]
42
  encoder: Literal["vits", "vitb", "vitl", "vitg"]
43
 
 
 
 
 
 
44
 
45
  class AppConfig(BaseSettings):
46
  """
 
54
  env_file=Path(__file__).parent / ".env",
55
  env_file_encoding="utf-8",
56
  yaml_file=Path(__file__).parent / "config.yaml",
57
+ extra="ignore" # Ignore other settings in yaml and env as they are not mentioedhere
 
 
 
58
  )
59
 
60
  project_name:str
61
  project_desc:str
62
  task: Literal["indoor", "outdoor"]
63
 
 
64
  yolo: YoloConfig
65
  security_detector: SecurityDetector
66
  depth: DepthConfig
67
  intervals: IntervalsConfig
68
  redis_url:str
69
 
 
 
 
70
  @classmethod
71
  def settings_customise_sources(cls,
72
  settings_cls: type[BaseSettings], # Base param.
 
 
 
 
73
  **kwargs
74
  ) -> tuple[PydanticBaseSettingsSource, ...] :
75
  """
 
77
  But this time it fixs the priority part, order by parameters priority.
78
  """
79
 
80
+ # Order by priority (first, more important)
81
  return (
82
  DotEnvSettingsSource(settings_cls), # Most important
83
  EnvSettingsSource(settings_cls), # This allow for ex. hugging face to override .env values with its values.
 
85
  ) # The return must be a tuple
86
 
87
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
88
  if __name__ == "__main__":
89
+
 
 
 
 
 
 
 
 
 
 
 
90
  # Trying to checking both yaml and .env. This works really fine now.
91
  config = AppConfig()
92
  print(config.model_dump())
contracts/__pycache__/camera_metadata.cpython-311.pyc DELETED
Binary file (999 Bytes)
 
domain/__pycache__/detector.cpython-311.pyc DELETED
Binary file (1.12 kB)
 
domain/__pycache__/logger.cpython-311.pyc DELETED
Binary file (1.36 kB)
 
domain/__pycache__/logger.cpython-314.pyc DELETED
Binary file (1.66 kB)
 
infra/__pycache__/logger_structlog.cpython-311.pyc DELETED
Binary file (3.22 kB)
 
infra/__pycache__/logger_structlog.cpython-314.pyc DELETED
Binary file (3.82 kB)
 
infra/__pycache__/system_metrics.cpython-311.pyc DELETED
Binary file (1.43 kB)
 
infra/__pycache__/system_metrics.cpython-314.pyc DELETED
Binary file (1.27 kB)
 
main.py CHANGED
@@ -1,5 +1,4 @@
1
- from fastapi import FastAPI
2
- # from prometheus_client import metrics
3
  from ai.depth.depth_anything import DepthAnything
4
  from ai.detectors.yolo_detector import YOLO_Detector
5
  from config.settings import AppConfig
@@ -8,15 +7,16 @@ from infra.system_metrics import log_system_metrics
8
  from api.routers import camera_stream
9
  from api.routers import dashboard_stream
10
  from api.routers import health
11
- from contextlib import asynccontextmanager
12
  from infra.logger_structlog import StructLogger
13
- import asyncio
 
14
  import mlflow
15
  import torch
16
- from huggingface_hub import hf_hub_download
17
  import redis.asyncio as aioredis
18
  from fastapi.middleware.trustedhost import TrustedHostMiddleware
19
  import dagshub
 
 
20
 
21
  @asynccontextmanager
22
  async def lifespan(app: FastAPI):
@@ -26,28 +26,25 @@ async def lifespan(app: FastAPI):
26
 
27
  settings = AppConfig()
28
  logger = StructLogger(settings=settings)
 
 
 
29
 
30
  logger.info("Starting Server.... ")
31
- asyncio.create_task(log_system_metrics(logger, logger_interval_sec=settings.intervals.system_metrics_seconds))
32
 
33
- # Using this way to can store data. it is acts as a dict which holds instances
34
- detection_model_path = hf_hub_download(repo_id="Ultralytics/YOLO26", filename="yolo26n.pt")
35
  app.state.detection_model = YOLO_Detector(detection_model_path)
36
 
37
- depth_model_path = hf_hub_download(repo_id="depth-anything/Depth-Anything-V2-Small", filename="depth_anything_v2_vits.pth")
38
- app.state.depth_model = DepthAnything(encoder=settings.depth.encoder, depth_model_path=depth_model_path, DEVICE="cpu")
39
 
40
- safety_detection_path = hf_hub_download(repo_id="e1250/safety_detection", filename="yolo_smoke_fire.pt")
41
  app.state.safety_detection_model = YOLO_Detector(safety_detection_path)
42
 
43
- app.state.logger = logger
44
- app.state.settings = settings
45
- # app.state.camera_metadata = {}
46
- # app.state.dashboard_clients = set()
47
- # Redis(host="localhost", port=6379, db=0, decode_responses=True)
48
  app.state.redis = aioredis.from_url(settings.redis_url, decode_responses=True)
49
- # Cnecking connection to redis.
50
- # Thinking of moving this to the health check.
51
  try:
52
  await app.state.redis.ping()
53
  logger.info("Redis connected successfully...")
@@ -55,15 +52,14 @@ async def lifespan(app: FastAPI):
55
  logger.error(f"Failed to connect to Redis: {e}")
56
  raise e
57
 
58
- # Each camera should have its tracker to be able to work fine.
59
- # app.state.camera_trackers = {}
60
  yield
61
 
 
62
  logger.warn("Shutting down the server....")
63
  torch.cuda.empty_cache()
64
  await app.state.redis.close()
65
- # You can remove connections and release gpu here .
66
 
 
67
  dagshub.init(repo_owner='eslam760000', repo_name='p-tracking_system', mlflow=True)
68
  mlflow.set_tracking_uri("sqlite:///config/logs/mlflow.db")
69
  mlflow.set_experiment("realtime-detection-system")
@@ -76,7 +72,6 @@ app = FastAPI(
76
  lifespan=lifespan
77
  )
78
 
79
- # Allow
80
  app.add_middleware(
81
  TrustedHostMiddleware,
82
  allowed_hosts=["*"]
 
1
+ from ai.utils.hugging_face import hf_fetch_model
 
2
  from ai.depth.depth_anything import DepthAnything
3
  from ai.detectors.yolo_detector import YOLO_Detector
4
  from config.settings import AppConfig
 
7
  from api.routers import camera_stream
8
  from api.routers import dashboard_stream
9
  from api.routers import health
 
10
  from infra.logger_structlog import StructLogger
11
+
12
+ from contextlib import asynccontextmanager
13
  import mlflow
14
  import torch
 
15
  import redis.asyncio as aioredis
16
  from fastapi.middleware.trustedhost import TrustedHostMiddleware
17
  import dagshub
18
+ from fastapi import FastAPI
19
+
20
 
21
  @asynccontextmanager
22
  async def lifespan(app: FastAPI):
 
26
 
27
  settings = AppConfig()
28
  logger = StructLogger(settings=settings)
29
+ # Using this way to can store data. it is acts as a dict which holds instances
30
+ app.state.logger = logger
31
+ app.state.settings = settings
32
 
33
  logger.info("Starting Server.... ")
34
+ # asyncio.create_task(log_system_metrics(logger, logger_interval_sec=settings.intervals.system_metrics_seconds))
35
 
36
+ detection_model_path = hf_fetch_model(repo_id="Ultralytics/YOLO26", filename=settings.yolo.model_name)
 
37
  app.state.detection_model = YOLO_Detector(detection_model_path)
38
 
39
+ depth_model_path = hf_fetch_model(repo_id="depth-anything/Depth-Anything-V2-Small", filename=settings.depth.model_name)
40
+ app.state.depth_model = DepthAnything(encoder=settings.depth.encoder, depth_model_path=depth_model_path, DEVICE=settings.depth.device)
41
 
42
+ safety_detection_path = hf_fetch_model(repo_id="e1250/safety_detection", filename=settings.security_detector.model_name)
43
  app.state.safety_detection_model = YOLO_Detector(safety_detection_path)
44
 
45
+
 
 
 
 
46
  app.state.redis = aioredis.from_url(settings.redis_url, decode_responses=True)
47
+ # Checking connection to redis - TODO add to health check
 
48
  try:
49
  await app.state.redis.ping()
50
  logger.info("Redis connected successfully...")
 
52
  logger.error(f"Failed to connect to Redis: {e}")
53
  raise e
54
 
 
 
55
  yield
56
 
57
+ # Here You remove connections and release gpu here..
58
  logger.warn("Shutting down the server....")
59
  torch.cuda.empty_cache()
60
  await app.state.redis.close()
 
61
 
62
+ # MLFlow setup
63
  dagshub.init(repo_owner='eslam760000', repo_name='p-tracking_system', mlflow=True)
64
  mlflow.set_tracking_uri("sqlite:///config/logs/mlflow.db")
65
  mlflow.set_experiment("realtime-detection-system")
 
72
  lifespan=lifespan
73
  )
74
 
 
75
  app.add_middleware(
76
  TrustedHostMiddleware,
77
  allowed_hosts=["*"]
requirements.txt CHANGED
@@ -1,22 +1,27 @@
 
1
  fastapi
2
  uvicorn
3
  gunicorn
4
- websockets
5
 
 
6
  ultralytics
 
7
 
 
8
  pydantic
9
  pydantic_settings
10
  structlog
11
 
12
- tracking_system@git+https://github.com/E1250/p-tracking_system.git@main
13
 
14
  redis
15
  upstash_redis
 
 
16
  prometheus_client
 
 
17
 
18
  numpy
19
  pandas
20
- mlflow
21
- huggingface_hub
22
- dagshub
 
1
+ # Web
2
  fastapi
3
  uvicorn
4
  gunicorn
5
+ websockets
6
 
7
+ # AI
8
  ultralytics
9
+ tracking_system@git+https://github.com/E1250/p-tracking_system.git@main
10
 
11
+ # Arch
12
  pydantic
13
  pydantic_settings
14
  structlog
15
 
 
16
 
17
  redis
18
  upstash_redis
19
+
20
+ # Logging & Monitoring
21
  prometheus_client
22
+ dagshub
23
+ mlflow
24
 
25
  numpy
26
  pandas
27
+ huggingface_hub
 
 
utils/__pycache__/experiment.cpython-311.pyc DELETED
Binary file (1.22 kB)
 
utils/experiment.py CHANGED
@@ -1,12 +1,11 @@
 
1
  import mlflow
2
 
3
- def start_run(camera_id: str):
4
- return mlflow.start_run(run_name=f"camera_{camera_id}")
5
-
6
  def log_config():
7
- mlflow.log_param("detector", "yolov26_n")
8
- mlflow.log_param("safety_model", "custom YOLO26_n")
9
- mlflow.log_param("depth_model", "depthAnything_n")
10
 
11
  def log_metrics(metrics:dict):
12
  for k, v in metrics.items():
 
1
+ from backend.config.settings import AppConfig
2
  import mlflow
3
 
4
+ config = AppConfig()
 
 
5
  def log_config():
6
+ mlflow.log_param("Detector", config.yolo.model_name)
7
+ mlflow.log_param("Safety Model", config.security_detector.model_name)
8
+ mlflow.log_param("Depth Model", config.depth.model_name)
9
 
10
  def log_metrics(metrics:dict):
11
  for k, v in metrics.items():