File size: 3,098 Bytes
6d35aff
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
"""Exercise the public one-image control path without APIs or model weights."""

import json
import sys
import tempfile
from pathlib import Path

from PIL import Image


if __package__ in {None, ""}:
    sys.path.insert(0, str(Path(__file__).resolve().parents[1]))

from approach.run_ape import build_parser as build_ape_parser
from approach.run_ape import run as run_ape
from approach.run_vlm import build_parser as build_vlm_parser
from approach.run_vlm import run as run_vlm
from scripts.generate_questions import build_questions, write_jsonl


def main():
    with tempfile.TemporaryDirectory(prefix="orienter-smoke-") as tmpdir:
        root = Path(tmpdir)
        images_dir = root / "images"
        images_dir.mkdir()
        Image.new("RGB", (32, 32), color=(32, 64, 96)).save(images_dir / "123_4.png")

        questions_path = root / "questions.jsonl"
        write_jsonl(questions_path, build_questions(images_dir, "Smoke test"))

        candidates_path = root / "candidates.jsonl"
        vlm_args = build_vlm_parser().parse_args(
            [
                "--questions",
                str(questions_path),
                "--images-dir",
                str(images_dir),
                "--output",
                str(candidates_path),
            ]
        )

        def offline_processor(profile, question, image_path, ablation, key_index):
            return {"objects": {"button": "synthetic blue square"}}

        vlm_report = run_vlm(vlm_args, processor=offline_processor)

        predictions_path = root / "predictions.json"
        ape_args = build_ape_parser().parse_args(
            [
                "--questions",
                str(questions_path),
                "--candidates",
                str(candidates_path),
                "--images-dir",
                str(images_dir),
                "--output",
                str(predictions_path),
            ]
        )

        def offline_inference(**kwargs):
            return [
                {
                    "category_name": "button",
                    "bbox": [4, 5, 12, 10],
                    "score": 0.9,
                }
            ]

        ape_report = run_ape(ape_args, inference=offline_inference)
        predictions = json.loads(predictions_path.read_text(encoding="utf-8"))
        expected = {
            "image_id": 123004,
            "category_id": "button",
            "category_name": "button",
            "bbox": [4, 5, 12, 10],
        }
        if len(predictions) != 1 or any(
            predictions[0].get(key) != value for key, value in expected.items()
        ):
            raise RuntimeError(f"Unexpected smoke prediction: {predictions}")

        print(
            json.dumps(
                {
                    "status": "ok",
                    "vlm_records": vlm_report["completed"],
                    "ape_predictions": ape_report["predictions"],
                    "image_id": predictions[0]["image_id"],
                },
                indent=2,
            )
        )
    return 0


if __name__ == "__main__":
    sys.exit(main())