From 4476431d1ead2b537cf51dd87dbf26317594bc2d Mon Sep 17 00:00:00 2001 From: Pascal Date: Thu, 16 Apr 2026 06:21:31 +0200 Subject: [PATCH 1/5] server: tests: fetch random media marker via /apply-template (#21962 fix) --- tools/server/tests/unit/test_vision_api.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tools/server/tests/unit/test_vision_api.py b/tools/server/tests/unit/test_vision_api.py index 9408116d1cf..9d08563c5f9 100644 --- a/tools/server/tests/unit/test_vision_api.py +++ b/tools/server/tests/unit/test_vision_api.py @@ -1,6 +1,7 @@ import pytest from utils import * import base64 +import re import requests server: ServerProcess @@ -34,6 +35,23 @@ def get_img_url(id: str) -> str: JSON_MULTIMODAL_KEY = "multimodal_data" JSON_PROMPT_STRING_KEY = "prompt_string" +# the server picks a random media marker at startup; fetch it by asking +# /apply-template to render a message with image_url, which substitutes the +# marker inline via oaicompat_chat_params_parse +MEDIA_MARKER_RE = re.compile(r"<__media_[0-9A-Za-z]{32}__>") +MEDIA_MARKER_PROBE_IMG = "data:image/png;base64,AAAA" + +def fetch_media_marker(server) -> str: + res = server.make_request("POST", "/apply-template", data={ + "messages": [{"role": "user", "content": [ + {"type": "image_url", "image_url": {"url": MEDIA_MARKER_PROBE_IMG}}, + ]}], + }) + assert res.status_code == 200 + match = MEDIA_MARKER_RE.search(res.body["prompt"]) + assert match is not None, f"media marker not found in rendered prompt: {res.body['prompt']!r}" + return match.group(0) + @pytest.fixture(autouse=True) def create_server(): global server @@ -110,6 +128,7 @@ def test_vision_chat_completion(prompt, image_url, success, re_content): def test_vision_completion(prompt, image_data, success, re_content): global server server.start() + prompt = prompt.replace("<__media__>", fetch_media_marker(server)) res = server.make_request("POST", "/completions", data={ "temperature": 0.0, "top_k": 1, @@ -141,6 +160,7 @@ def test_vision_embeddings(prompt, image_data, success): server.server_embeddings = True server.n_batch = 512 server.start() + prompt = prompt.replace("<__media__>", fetch_media_marker(server)) image_data = get_img_url(image_data) res = server.make_request("POST", "/embeddings", data={ "content": [ From b17efd8e4554c243b142b2c13d0596d60e655afc Mon Sep 17 00:00:00 2001 From: Pascal Date: Thu, 16 Apr 2026 14:04:53 +0200 Subject: [PATCH 2/5] server: allow pinning media marker via LLAMA_MEDIA_MARKER env var get_media_marker() checks LLAMA_MEDIA_MARKER at first call and uses it as-is if set, falling back to the random marker otherwise. Tests no longer need to fetch the marker dynamically via /apply-template: the fixture sets LLAMA_MEDIA_MARKER=<__media__> so the hardcoded prompts work as before. Address review feedback from ngxson --- tools/server/server-common.cpp | 8 +++++++- tools/server/tests/unit/test_vision_api.py | 21 +-------------------- 2 files changed, 8 insertions(+), 21 deletions(-) diff --git a/tools/server/server-common.cpp b/tools/server/server-common.cpp index fd417393f8c..66f1d39be28 100644 --- a/tools/server/server-common.cpp +++ b/tools/server/server-common.cpp @@ -87,7 +87,13 @@ std::string gen_tool_call_id() { static std::string media_marker = ""; const char * get_media_marker() { if (media_marker.empty()) { - media_marker = "<__media_" + random_string() + "__>"; + // allow user to pin a reproducible marker via env var (useful for tests and external pipelines) + const char * env = getenv("LLAMA_MEDIA_MARKER"); + if (env && env[0] != '\0') { + media_marker = env; + } else { + media_marker = "<__media_" + random_string() + "__>"; + } } return media_marker.c_str(); } diff --git a/tools/server/tests/unit/test_vision_api.py b/tools/server/tests/unit/test_vision_api.py index 9d08563c5f9..fb77084c89b 100644 --- a/tools/server/tests/unit/test_vision_api.py +++ b/tools/server/tests/unit/test_vision_api.py @@ -1,7 +1,6 @@ import pytest from utils import * import base64 -import re import requests server: ServerProcess @@ -35,26 +34,10 @@ def get_img_url(id: str) -> str: JSON_MULTIMODAL_KEY = "multimodal_data" JSON_PROMPT_STRING_KEY = "prompt_string" -# the server picks a random media marker at startup; fetch it by asking -# /apply-template to render a message with image_url, which substitutes the -# marker inline via oaicompat_chat_params_parse -MEDIA_MARKER_RE = re.compile(r"<__media_[0-9A-Za-z]{32}__>") -MEDIA_MARKER_PROBE_IMG = "data:image/png;base64,AAAA" - -def fetch_media_marker(server) -> str: - res = server.make_request("POST", "/apply-template", data={ - "messages": [{"role": "user", "content": [ - {"type": "image_url", "image_url": {"url": MEDIA_MARKER_PROBE_IMG}}, - ]}], - }) - assert res.status_code == 200 - match = MEDIA_MARKER_RE.search(res.body["prompt"]) - assert match is not None, f"media marker not found in rendered prompt: {res.body['prompt']!r}" - return match.group(0) - @pytest.fixture(autouse=True) def create_server(): global server + os.environ['LLAMA_MEDIA_MARKER'] = '<__media__>' server = ServerPreset.tinygemma3() def test_models_supports_multimodal_capability(): @@ -128,7 +111,6 @@ def test_vision_chat_completion(prompt, image_url, success, re_content): def test_vision_completion(prompt, image_data, success, re_content): global server server.start() - prompt = prompt.replace("<__media__>", fetch_media_marker(server)) res = server.make_request("POST", "/completions", data={ "temperature": 0.0, "top_k": 1, @@ -160,7 +142,6 @@ def test_vision_embeddings(prompt, image_data, success): server.server_embeddings = True server.n_batch = 512 server.start() - prompt = prompt.replace("<__media__>", fetch_media_marker(server)) image_data = get_img_url(image_data) res = server.make_request("POST", "/embeddings", data={ "content": [ From 997ba03f7f5705bcbd9360b6c1f7788c1660bb97 Mon Sep 17 00:00:00 2001 From: Pascal Date: Thu, 16 Apr 2026 15:48:44 +0200 Subject: [PATCH 3/5] server: make get_media_marker() thread-safe via magic statics Use a C++11 static local with a lambda initializer instead of a global static with an empty-check. The runtime guarantees initialization exactly once without explicit locking. Address review feedback from ggerganov --- tools/server/server-common.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/tools/server/server-common.cpp b/tools/server/server-common.cpp index 66f1d39be28..c5a6051e8ce 100644 --- a/tools/server/server-common.cpp +++ b/tools/server/server-common.cpp @@ -84,18 +84,17 @@ std::string gen_tool_call_id() { return random_string(); } -static std::string media_marker = ""; const char * get_media_marker() { - if (media_marker.empty()) { + // magic statics: initialized exactly once, thread-safe by C++11 + static const std::string marker = []() { // allow user to pin a reproducible marker via env var (useful for tests and external pipelines) const char * env = getenv("LLAMA_MEDIA_MARKER"); if (env && env[0] != '\0') { - media_marker = env; - } else { - media_marker = "<__media_" + random_string() + "__>"; + return std::string(env); } - } - return media_marker.c_str(); + return std::string("<__media_") + random_string() + "__>"; + }(); + return marker.c_str(); } // From d56231ff7443d6e511cb4e3356c2dda07d651c64 Mon Sep 17 00:00:00 2001 From: Pascal Date: Thu, 16 Apr 2026 15:51:31 +0200 Subject: [PATCH 4/5] nits --- tools/server/server-common.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/tools/server/server-common.cpp b/tools/server/server-common.cpp index c5a6051e8ce..a3906818697 100644 --- a/tools/server/server-common.cpp +++ b/tools/server/server-common.cpp @@ -85,9 +85,7 @@ std::string gen_tool_call_id() { } const char * get_media_marker() { - // magic statics: initialized exactly once, thread-safe by C++11 static const std::string marker = []() { - // allow user to pin a reproducible marker via env var (useful for tests and external pipelines) const char * env = getenv("LLAMA_MEDIA_MARKER"); if (env && env[0] != '\0') { return std::string(env); From 68e04273145b69c17c3336d17bd2d080be86f30f Mon Sep 17 00:00:00 2001 From: Pascal Date: Thu, 16 Apr 2026 15:56:08 +0200 Subject: [PATCH 5/5] nits --- tools/server/server-common.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/server/server-common.cpp b/tools/server/server-common.cpp index a3906818697..f66b1f2557c 100644 --- a/tools/server/server-common.cpp +++ b/tools/server/server-common.cpp @@ -86,6 +86,7 @@ std::string gen_tool_call_id() { const char * get_media_marker() { static const std::string marker = []() { + // allow user to pin a reproducible marker via env var const char * env = getenv("LLAMA_MEDIA_MARKER"); if (env && env[0] != '\0') { return std::string(env);