Files
DS4Server/docs/issue107-vision-qsa/baseline-capture.patch
T

103 lines
3.8 KiB
Diff

--- a/src/engine/metal/qwen_mtplx/owner.rs
+++ b/src/engine/metal/qwen_mtplx/owner.rs
@@ -1068,3 +1068,7 @@
#[cfg(test)]
#[path = "issue106_product.rs"]
mod issue106_product;
+
+#[cfg(test)]
+#[path = "issue107_product.rs"]
+mod issue107_product;
--- /dev/null
+++ b/src/engine/metal/qwen_mtplx/issue107_product.rs
@@ -0,0 +1,89 @@
+//! Long multi-image request and cache compatibility through the product owner.
+use super::*;
+use crate::settings::{
+ GenerationPreferences, ReasoningMode, RuntimePreferences, SpeculativePreferences,
+ effective_settings,
+};
+use base64::Engine as _;
+
+#[test]
+#[ignore = "installed model plus vision tower; serial external memory supervisor required"]
+fn issue107_vision_product() {
+ let root = std::path::PathBuf::from(std::env::var_os("DS4_QWEN38_ARTIFACTS").unwrap());
+ let image = std::fs::read(std::env::var_os("DS4_QWEN_VISION_IMAGE").unwrap()).unwrap();
+ let directory = std::path::PathBuf::from(std::env::var_os("DS4_ISSUE107_DIR").unwrap());
+ std::fs::create_dir_all(&directory).unwrap();
+ let settings = effective_settings(
+ crate::model::ModelChoice::Qwen38FlashNext,
+ &GenerationPreferences {
+ context_tokens: 8192,
+ max_generated_tokens: 1,
+ system_prompt: String::new(),
+ temperature: Some(0.),
+ top_p: Some(0.95),
+ min_p: Some(0.),
+ seed: Some(1),
+ reasoning_mode: ReasoningMode::Low,
+ },
+ &RuntimePreferences {
+ speculative: SpeculativePreferences {
+ glm_mtp: true,
+ ..Default::default()
+ },
+ ..Default::default()
+ },
+ root.parent().unwrap(),
+ )
+ .unwrap();
+ let marker = crate::engine::vision_data_marker(&format!(
+ "data:image/png;base64,{}",
+ base64::engine::general_purpose::STANDARD.encode(&image)
+ ));
+ let messages = [ChatTurn {
+ user: true,
+ tool: false,
+ system: false,
+ skip_previous_eos: false,
+ reasoning: None,
+ reasoning_complete: true,
+ content: format!("Describe these images{marker}{marker}"),
+ }];
+ let mut owner = QwenExecutor::open(&settings.engine).unwrap();
+ owner.policy.store_min_suffix = Some(0);
+ let metrics = Metrics::new(&directory.join("metrics"));
+ let (out, complete) = owner
+ .generate(
+ &messages,
+ &settings.turn,
+ &AtomicBool::new(false),
+ &metrics,
+ |p, _, _| {
+ eprintln!("#107 prefill {p}");
+ },
+ |_, _| {},
+ )
+ .unwrap();
+ assert!(complete);
+ assert!(out.prompt_tokens > 2048);
+ assert_eq!(out.cached_tokens, 0);
+ let saved = owner.live.current.as_ref().unwrap();
+ let logits = owner.execution.values_f32(&saved.logits).unwrap();
+ std::fs::write(
+ directory.join("long-final.f32"),
+ logits
+ .iter()
+ .flat_map(|v| v.to_le_bytes())
+ .collect::<Vec<_>>(),
+ )
+ .unwrap();
+ std::fs::write(directory.join("long-input.json"),serde_json::to_vec(&serde_json::json!({"ids":saved.token_ids,"images":owner.live.current_images,"prompt_tokens":out.prompt_tokens})).unwrap()).unwrap();
+ owner
+ .save_checkpoint(&directory.join("long.bin"), [107; 32], &mut |_| {})
+ .unwrap();
+ println!(
+ "{}",
+ serde_json::json!({"case":"vision_long","prompt_tokens":out.prompt_tokens,"cached_tokens":out.cached_tokens,
+ "tokens":owner.live.current.as_ref().unwrap().token_ids,"text":out.message.content,"reasoning":out.message.reasoning,
+ "logits_sha256":crate::engine::metal::qwen_mtplx_tests::hex_digest(&logits.iter().flat_map(|v|v.to_le_bytes()).collect::<Vec<_>>())})
+ );
+}