metrale_bench/benchmarks/video/
request.rs1use base64::Engine;
10use serde_json::{Value, json};
11
12pub const ORDER_PROMPT: &str = "This video is a sequence of solid background colors. List the colors in the order they \
15 appear, separated by commas. Answer with only the color names.";
16
17pub fn data_uri(mime: &str, bytes: &[u8]) -> String {
19 let mut s = format!("data:{mime};base64,");
20 base64::engine::general_purpose::STANDARD.encode_string(bytes, &mut s);
21 s
22}
23
24pub fn video_body(model: &str, mime: &str, bytes: &[u8], prompt: &str, max_tokens: usize) -> Value {
30 json!({
31 "model": model,
32 "stream": true,
33 "temperature": 0.0,
34 "max_tokens": max_tokens,
35 "chat_template_kwargs": {"enable_thinking": false},
36 "messages": [{"role": "user", "content": [
37 {"type": "video_url", "video_url": {"url": data_uri(mime, bytes)}},
38 {"type": "text", "text": prompt},
39 ]}],
40 })
41}
42
43pub fn mixed_body(
47 model: &str,
48 png: &[u8],
49 mime: &str,
50 video: &[u8],
51 prompt: &str,
52 max_tokens: usize,
53) -> Value {
54 json!({
55 "model": model,
56 "stream": true,
57 "temperature": 0.0,
58 "max_tokens": max_tokens,
59 "chat_template_kwargs": {"enable_thinking": false},
60 "messages": [{"role": "user", "content": [
61 {"type": "image_url", "image_url": {"url": data_uri("image/png", png)}},
62 {"type": "video_url", "video_url": {"url": data_uri(mime, video)}},
63 {"type": "text", "text": prompt},
64 ]}],
65 })
66}
67
68pub fn text_only_body(model: &str, prompt: &str, max_tokens: usize) -> Value {
70 json!({
71 "model": model,
72 "stream": true,
73 "temperature": 0.0,
74 "max_tokens": max_tokens,
75 "chat_template_kwargs": {"enable_thinking": false},
76 "messages": [{"role": "user", "content": prompt}],
77 })
78}
79
80pub fn image_body(model: &str, mime: &str, png: &[u8], prompt: &str, max_tokens: usize) -> Value {
87 json!({
88 "model": model,
89 "stream": true,
90 "temperature": 0.0,
91 "max_tokens": max_tokens,
92 "chat_template_kwargs": {"enable_thinking": false},
93 "messages": [{"role": "user", "content": [
94 {"type": "image_url", "image_url": {"url": data_uri(mime, png)}},
95 {"type": "text", "text": prompt},
96 ]}],
97 })
98}
99
100pub fn text_array_body(model: &str, prompt: &str, max_tokens: usize) -> Value {
102 json!({
103 "model": model,
104 "stream": true,
105 "temperature": 0.0,
106 "max_tokens": max_tokens,
107 "chat_template_kwargs": {"enable_thinking": false},
108 "messages": [{"role": "user", "content": [
109 {"type": "text", "text": prompt},
110 ]}],
111 })
112}
113
114pub fn is_decoder_unavailable(err: &str) -> bool {
124 let e = err.to_lowercase();
125 let quoted_binary_unavailable = e
126 .split_once(" could not be run:")
127 .is_some_and(|(binary, _)| binary.starts_with('"') && binary.ends_with('"'));
128 e.contains("subprocess decoding is disabled")
129 || (e.contains("could not run ") && e.contains("is ffmpeg installed"))
130 || quoted_binary_unavailable
131}
132
133#[cfg(test)]
134#[path = "request_tests.rs"]
135mod request_tests;