Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions .github/workflows/backend-metadata.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
name: Backend metadata regression
on:
pull_request:
push:
branches: [main]
permissions:
contents: read
jobs:
metadata:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.11'
- run: pip install 'numpy<2' tflite-runtime==2.14.0 fastapi pillow
- run: python -m unittest discover -s tests -p test_backend_model_info.py -v
2 changes: 1 addition & 1 deletion backends/edgetpu/backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -601,7 +601,7 @@ def get_model_info(self) -> Dict[str, Any]:
"model_type": self.model_type,
"model_path": self.model_path,
"labels_path": self.labels_path,
"input_shape": list(self.input_shape),
"input_shape": [int(dimension) for dimension in self.input_shape],
"num_labels": len(self.labels),
"default_confidence_threshold": self.confidence_threshold,
"device": self.device or "auto",
Expand Down
2 changes: 1 addition & 1 deletion backends/tflite/backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ def get_model_info(self) -> Dict[str, Any]:
"backend": "tflite",
"model_path": self.model_path,
"labels_path": self.labels_path,
"input_shape": list(self.input_shape),
"input_shape": [int(dimension) for dimension in self.input_shape],
"num_labels": len(self.labels),
"default_confidence_threshold": self.confidence_threshold
}
32 changes: 32 additions & 0 deletions tests/test_backend_model_info.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
"""Backend discovery must serialize NumPy-shaped TFLite metadata as JSON."""
import json
import unittest

import numpy as np
from fastapi.encoders import jsonable_encoder

from backends.tflite.backend import TFLiteBackend
from backends.edgetpu.backend import EdgeTPUBackend


class ModelInfoTest(unittest.TestCase):
def test_numpy_dimensions_are_json_serializable_without_hardware(self):
for cls in (TFLiteBackend, EdgeTPUBackend):
with self.subTest(backend=cls.__name__):
# Metadata requires neither an interpreter nor a physical Coral.
backend = object.__new__(cls)
backend.model_path = "model.tflite"
backend.labels_path = "labels.txt"
backend.input_shape = np.array([1, 300, 300, 3], dtype=np.int32)
backend.labels = ["person"]
backend.confidence_threshold = 0.5
backend.model_type = "ssd"
backend.device = "usb"
backend.requires_int8 = False
info = backend.get_model_info()
self.assertEqual(json.loads(json.dumps(info))["input_shape"], [1, 300, 300, 3])
self.assertEqual(jsonable_encoder(info)["input_shape"], [1, 300, 300, 3])


if __name__ == "__main__":
unittest.main()
Loading