mod common;
use modelc::generate::{GenerationConfig, generate_token_ids, generate_token_ids_with_cache};
use modelc::prefix_cache::PrefixCache;
use modelc::runtime::serve::Runtime;
use modelc::tokenizer::BpeTokenizer;
fn config(max_tokens: usize) -> GenerationConfig {
GenerationConfig {
max_tokens,
temperature: 0.0,
top_p: 0.0,
gamma: 0,
use_int8_kv: false,
use_mixed_kv: false,
constraint: None,
max_context: None,
anchor_tokens: 0,
stop: vec![],
}
}
#[test]
fn cache_is_transparent_for_identical_prompt() {
let model = common::create_gpt2_test_model();
let runtime = Runtime::from_raw(&model.tensors);
let hidden = model
.metadata
.get("hidden")
.and_then(|v| v.parse::<usize>().ok())
.unwrap_or(12);
let tokenizer = BpeTokenizer::byte_fallback();
let prompt = "system: you are helpful. user: hello";
let cfg = config(8);
let baseline = generate_token_ids(&runtime, "gpt2", hidden, &tokenizer, prompt, &cfg, None);
let mut cache = PrefixCache::new(8);
let cold = generate_token_ids_with_cache(
&runtime,
"gpt2",
hidden,
&tokenizer,
prompt,
&cfg,
Some(&mut cache),
None,
);
assert_eq!(cold, baseline, "cold (miss) output must match the no-cache baseline");
assert_eq!(cache.len(), 1, "cold call should populate the cache");
let warm = generate_token_ids_with_cache(
&runtime,
"gpt2",
hidden,
&tokenizer,
prompt,
&cfg,
Some(&mut cache),
None,
);
assert_eq!(warm, baseline, "warm (hit) output must match the no-cache baseline");
assert_eq!(cache.len(), 1, "exact repeat should not grow the cache");
}
#[test]
fn cache_reuses_shared_prefix() {
let model = common::create_gpt2_test_model();
let runtime = Runtime::from_raw(&model.tensors);
let hidden = model
.metadata
.get("hidden")
.and_then(|v| v.parse::<usize>().ok())
.unwrap_or(12);
let tokenizer = BpeTokenizer::byte_fallback();
let cfg = config(6);
let prompt_a = "system: you are helpful.";
let prompt_b = "system: you are helpful. user: what is 2+2?";
let baseline_b = generate_token_ids(&runtime, "gpt2", hidden, &tokenizer, prompt_b, &cfg, None);
let mut cache = PrefixCache::new(8);
let _ = generate_token_ids_with_cache(
&runtime,
"gpt2",
hidden,
&tokenizer,
prompt_a,
&cfg,
Some(&mut cache),
None,
);
assert_eq!(cache.len(), 1);
let b_cached = generate_token_ids_with_cache(
&runtime,
"gpt2",
hidden,
&tokenizer,
prompt_b,
&cfg,
Some(&mut cache),
None,
);
assert_eq!(
b_cached, baseline_b,
"prefix-reuse output must match the cold baseline for the same prompt"
);
assert_eq!(cache.len(), 2);
}
#[test]
fn cache_ignores_non_prefix_entries() {
let model = common::create_gpt2_test_model();
let runtime = Runtime::from_raw(&model.tensors);
let hidden = model
.metadata
.get("hidden")
.and_then(|v| v.parse::<usize>().ok())
.unwrap_or(12);
let tokenizer = BpeTokenizer::byte_fallback();
let cfg = config(4);
let unrelated = "completely different prompt xyz";
let baseline = generate_token_ids(&runtime, "gpt2", hidden, &tokenizer, unrelated, &cfg, None);
let mut cache = PrefixCache::new(8);
let _ = generate_token_ids_with_cache(
&runtime,
"gpt2",
hidden,
&tokenizer,
"system prompt one",
&cfg,
Some(&mut cache),
None,
);
let got = generate_token_ids_with_cache(
&runtime,
"gpt2",
hidden,
&tokenizer,
unrelated,
&cfg,
Some(&mut cache),
None,
);
assert_eq!(got, baseline, "unrelated prompt must produce its cold baseline");
assert_eq!(cache.len(), 2);
}
#[test]
fn neural_draft_model_speculative_matches_non_speculative() {
let model = common::create_gpt2_test_model();
let runtime = Runtime::from_raw(&model.tensors);
let hidden = model
.metadata
.get("hidden")
.and_then(|v| v.parse::<usize>().ok())
.unwrap_or(12);
let tokenizer = BpeTokenizer::byte_fallback();
let baseline_cfg = config(6);
let baseline = generate_token_ids(&runtime, "gpt2", hidden, &tokenizer, "hello", &baseline_cfg, None);
let draft = modelc::draft::MlpDraftModel::from_runtime(
&runtime,
tokenizer.vocab_size(),
hidden,
2,
0.0,
0.0,
);
let spec_cfg = GenerationConfig {
gamma: 3,
..baseline_cfg
};
let spec = generate_token_ids_with_cache(
&runtime,
"gpt2",
hidden,
&tokenizer,
"hello",
&spec_cfg,
None,
draft.as_ref().map(|d| d as &dyn modelc::draft::DraftModel),
);
assert_eq!(spec, baseline, "speculative with draft must match non-speculative baseline");
}