Skip to content

Commit 2f30530

Browse files
committed
add CI test
1 parent a9b21f4 commit 2f30530

File tree

2 files changed

+74
-0
lines changed

2 files changed

+74
-0
lines changed
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import pytest
2+
from utils import *
3+
import base64
4+
import requests
5+
6+
server: ServerProcess
7+
8+
IMG_URL_0 = "https://huggingface.co/ggml-org/tinygemma3-GGUF/resolve/main/test/11_truck.png"
9+
IMG_URL_1 = "https://huggingface.co/ggml-org/tinygemma3-GGUF/resolve/main/test/91_cat.png"
10+
11+
response = requests.get(IMG_URL_0)
12+
response.raise_for_status() # Raise an exception for bad status codes
13+
IMG_BASE64_0 = "data:image/png;base64," + base64.b64encode(response.content).decode("utf-8")
14+
15+
16+
@pytest.fixture(autouse=True)
17+
def create_server():
18+
global server
19+
server = ServerPreset.tinygemma3()
20+
21+
22+
@pytest.mark.parametrize(
23+
"image_url, success, re_content",
24+
[
25+
# test model is trained on CIFAR-10, but it's quite dumb due to small size
26+
(IMG_URL_0, True, "(cat)+"),
27+
(IMG_BASE64_0, True, "(cat)+"),
28+
(IMG_URL_1, True, "(frog)+"),
29+
("malformed", False, None),
30+
("https://google.com/404", False, None), # non-existent image
31+
("https://ggml.ai", False, None), # non-image data
32+
]
33+
)
34+
def test_vision_chat_completion(image_url, success, re_content):
35+
global server
36+
server.start(timeout_seconds=60) # vision model may take longer to load due to download size
37+
res = server.make_request("POST", "/chat/completions", data={
38+
"temperature": 0.0,
39+
"top_k": 1,
40+
"messages": [
41+
{"role": "user", "content": [
42+
{"type": "text", "text": "What is this:\n"},
43+
{"type": "image_url", "image_url": {
44+
"url": image_url,
45+
}},
46+
]},
47+
],
48+
})
49+
if success:
50+
assert res.status_code == 200
51+
choice = res.body["choices"][0]
52+
assert "assistant" == choice["message"]["role"]
53+
assert match_regex(re_content, choice["message"]["content"])
54+
else:
55+
assert res.status_code != 200
56+

tools/server/tests/utils.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ class ServerProcess:
8888
chat_template: str | None = None
8989
chat_template_file: str | None = None
9090
server_path: str | None = None
91+
mmproj_url: str | None = None
9192

9293
# session variables
9394
process: subprocess.Popen | None = None
@@ -194,6 +195,8 @@ def start(self, timeout_seconds: int | None = DEFAULT_HTTP_TIMEOUT) -> None:
194195
server_args.extend(["--chat-template", self.chat_template])
195196
if self.chat_template_file:
196197
server_args.extend(["--chat-template-file", self.chat_template_file])
198+
if self.mmproj_url:
199+
server_args.extend(["--mmproj-url", self.mmproj_url])
197200

198201
args = [str(arg) for arg in [server_path, *server_args]]
199202
print(f"tests: starting server with: {' '.join(args)}")
@@ -379,6 +382,21 @@ def jina_reranker_tiny() -> ServerProcess:
379382
server.server_reranking = True
380383
return server
381384

385+
@staticmethod
386+
def tinygemma3() -> ServerProcess:
387+
server = ServerProcess()
388+
# mmproj is already provided by HF registry API
389+
server.model_hf_repo = "ggml-org/tinygemma3-GGUF"
390+
server.model_hf_file = "tinygemma3-Q8_0.gguf"
391+
server.mmproj_url = "https://huggingface.co/ggml-org/tinygemma3-GGUF/resolve/main/mmproj-tinygemma3.gguf"
392+
server.model_alias = "tinygemma3"
393+
server.n_ctx = 1024
394+
server.n_batch = 32
395+
server.n_slots = 2
396+
server.n_predict = 4
397+
server.seed = 42
398+
return server
399+
382400

383401
def parallel_function_calls(function_list: List[Tuple[Callable[..., Any], Tuple[Any, ...]]]) -> List[Any]:
384402
"""

0 commit comments

Comments
 (0)