103 lines
3.8 KiB
Diff
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<_>>())})
|
|
+ );
|
|
+}
|