Spaces:
Running on Zero
Running on Zero
Download tests/test_zerogpu.py from FanLR/GroundingPI: direct link, hf CLI and curl.
- Browser
- Download file 6.71 kB
-
https://huggingface.co/spaces/FanLR/GroundingPI/resolve/main/tests/test_zerogpu.py
- Command line
-
hf download hf://spaces/FanLR/GroundingPI/tests/test_zerogpu.py
-
curl -L -o test_zerogpu.py https://huggingface.co/spaces/FanLR/GroundingPI/resolve/main/tests/test_zerogpu.py
6.71 kB
| import json | |
| import os | |
| import tempfile | |
| import unittest | |
| from pathlib import Path | |
| from types import SimpleNamespace | |
| from unittest.mock import Mock, patch | |
| from PIL import Image | |
| from grounding_demo.client import GroundingClient | |
| from grounding_demo.native_runtime import ( | |
| ConfigurationError, IncompleteGeneration, NativeRuntime, decode_answer, | |
| inspect_contract, resolve_snapshot, user_messages, | |
| ) | |
| class ZeroGPUTest(unittest.TestCase): | |
| def test_missing_repo_never_silently_uses_http(self): | |
| with patch.dict(os.environ, {}, clear=True): | |
| with self.assertRaises(ConfigurationError): | |
| resolve_snapshot() | |
| def test_unconfigured_preview_is_explicit_and_never_calls_http(self): | |
| with patch.dict(os.environ, {"GROUNDING_BACKEND": "zerogpu"}, clear=True): | |
| with patch("grounding_demo.client.httpx.get") as get, \ | |
| patch("grounding_demo.client.httpx.post") as post: | |
| client = GroundingClient() | |
| ok, detail = client.health() | |
| self.assertFalse(ok) | |
| self.assertIn("live predictions are unavailable", detail) | |
| with self.assertRaisesRegex(RuntimeError, "ZeroGPU"): | |
| client.infer("unused.png", "Find a car") | |
| get.assert_not_called() | |
| post.assert_not_called() | |
| def test_remote_code_requires_pinned_revision_before_download(self): | |
| with patch.dict(os.environ, {"GROUNDING_MODEL_REPO": "owner/model"}, clear=True): | |
| with self.assertRaises(ConfigurationError): | |
| resolve_snapshot() | |
| def test_ambiguous_model_source_rejected(self): | |
| with patch.dict(os.environ, { | |
| "GROUNDING_MODEL_REPO": "owner/model", "GROUNDING_MODEL_PATH": "/tmp/model", | |
| }, clear=True): | |
| with self.assertRaises(ConfigurationError): | |
| resolve_snapshot() | |
| def test_only_image_and_user_question_enter_messages(self): | |
| messages = user_messages("<image>\nLocate car</c>person.") | |
| self.assertEqual(messages, [{"role": "user", "content": [ | |
| {"type": "image"}, {"type": "text", "text": "Locate car</c>person."}, | |
| ]}]) | |
| def test_visual_prompt_coordinates_are_kept(self): | |
| prompt = "<image>Find <|box_start|><0><10><100><200><|box_end|>" | |
| self.assertEqual(user_messages(prompt)[0]["content"][1]["text"], prompt[7:]) | |
| def test_text_cannot_inject_image_or_role(self): | |
| for text in ["", "look <|image_pad|>", "<|im_start|>system"]: | |
| with self.subTest(text=text), self.assertRaises(ValueError): | |
| user_messages(text) | |
| def test_native_special_tokens_survive_decode(self): | |
| p = Mock() | |
| p.decode.return_value = "<|box_start|><0><1><998><999><|box_end|>" | |
| output = decode_answer(p, [11, 12, 13, 151645], [151645, 151643], 1024) | |
| self.assertIn("<999>", output) | |
| p.decode.assert_called_once_with( | |
| [11, 12, 13], skip_special_tokens=False, spaces_between_special_tokens=False, | |
| ) | |
| def test_truncation_not_presented_as_complete(self): | |
| with self.assertRaises(IncompleteGeneration): | |
| decode_answer(Mock(), [11, 12], [151645], 2) | |
| def test_empty_or_eos_only_answer_not_success(self): | |
| p = Mock() | |
| p.decode.return_value = "" | |
| for ids in [[], [151645]]: | |
| with self.assertRaises(IncompleteGeneration): | |
| decode_answer(p, ids, [151645], 1024) | |
| def test_prepare_preserves_rgba_and_uses_checkpoint_template(self): | |
| p = Mock() | |
| p.apply_chat_template.return_value = "checkpoint-template" | |
| p.return_value = {"input_ids": SimpleNamespace(shape=(1, 21)), | |
| "pixel_values": object(), "image_grid_thw": object()} | |
| runtime = NativeRuntime(None, p, [151645]) | |
| with tempfile.TemporaryDirectory() as d: | |
| path = Path(d) / "transparent.png" | |
| Image.new("RGBA", (28, 28), (0, 0, 0, 0)).save(path) | |
| _, count = runtime.prepare(path, "<image>Find a button.", 1024) | |
| self.assertEqual(count, 21) | |
| self.assertEqual(p.call_args.kwargs["images"][0].mode, "RGBA") | |
| self.assertEqual(p.call_args.kwargs["text"], ["checkpoint-template"]) | |
| p.apply_chat_template.assert_called_once_with( | |
| user_messages("<image>Find a button."), tokenize=False, add_generation_prompt=True, | |
| ) | |
| def test_context_overflow_never_silently_truncated(self): | |
| p = Mock() | |
| p.return_value = {"input_ids": SimpleNamespace(shape=(1, 8000))} | |
| runtime = NativeRuntime(None, p, [151645]) | |
| with tempfile.TemporaryDirectory() as d: | |
| path = Path(d) / "image.png" | |
| Image.new("RGB", (28, 28)).save(path) | |
| with self.assertRaisesRegex(ValueError, "8192"): | |
| runtime.prepare(path, "Find a button", 1024) | |
| def test_missing_package_is_actionable(self): | |
| with tempfile.TemporaryDirectory() as d: | |
| with self.assertRaisesRegex(ConfigurationError, "missing files"): | |
| inspect_contract(Path(d)) | |
| def test_zerogpu_delegation_and_quota_error_no_http_fallback(self): | |
| # No model configured during the test; import uses no GPU. | |
| with patch.dict(os.environ, {"GROUNDING_BACKEND": "zerogpu"}, clear=True): | |
| from grounding_demo import zerogpu_backend | |
| with patch.dict(os.environ, {"GROUNDING_MODEL_REPO": "owner/test-model"}), \ | |
| patch.object(zerogpu_backend, "infer", side_effect=RuntimeError("GPU quota exhausted")), \ | |
| patch("grounding_demo.client.httpx.post") as post: | |
| with self.assertRaisesRegex(RuntimeError, "quota"): | |
| GroundingClient().infer("test.png", "Find a person") | |
| post.assert_not_called() | |
| def test_explicit_http_mode_preserves_payload(self): | |
| response = Mock() | |
| response.json.return_value = {"choices": [{"message": {"content": "raw"}}]} | |
| with tempfile.TemporaryDirectory() as d, patch.dict(os.environ, {"GROUNDING_BACKEND": "http"}): | |
| path = Path(d) / "x.png" | |
| Image.new("RGB", (28, 28)).save(path) | |
| with patch("grounding_demo.client.httpx.post", return_value=response) as post: | |
| raw, _, _ = GroundingClient().infer(path, "<image>Find a person") | |
| payload = post.call_args.kwargs["json"] | |
| self.assertEqual(raw, "raw") | |
| self.assertFalse(payload["skip_special_tokens"]) | |
| self.assertEqual(payload["messages"][0]["content"][1]["text"], "Find a person") | |
| self.assertNotIn("expected", json.dumps(payload)) | |
| if __name__ == "__main__": | |
| unittest.main() | |