Merge pull request #41992 from BerriAI/litellm_deepseek_ocr_defaults

fix(ocr): set DeepSeek OCR sampling defaults
This commit is contained in:
yujonglee 2026-09-19 11:42:49 -07:00 committed by GitHub
commit f081e447a4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -19,6 +19,13 @@ const MODEL_PREFIX: &str = "deepseek-ai/";
const DEFAULT_LOCATION: &str = "us-central1";
const DEEPSEEK_OCR_PARAMS: &[&str] = &["stream", "temperature", "max_tokens", "top_p", "n", "stop"];
/// DeepSeek-OCR is a transcription model: at the endpoint's default sampling temperature it
/// hallucinates extra text, so requests are greedy unless the caller sets a temperature.
const DEFAULT_TEMPERATURE: f64 = 0.0;
/// Greedy decoding on dense screenshots falls into repetition loops that run to the token limit;
/// a mild penalty breaks them without changing clean-document output.
const DEFAULT_REPETITION_PENALTY: f64 = 1.05;
pub type DeepSeekOcrParams = OpaqueParams;
#[derive(Clone, Debug, Serialize, Deserialize)]
@ -171,11 +178,19 @@ impl BaseOcrConfig for VertexAIDeepSeekOCRConfig {
image_url: document.source().to_string(),
}],
}],
params: optional_params
.iter()
.filter(|(name, _)| DEEPSEEK_OCR_PARAMS.contains(&name.as_str()))
.map(|(name, value)| (name.clone(), value.clone()))
.collect(),
params: [
("temperature", DEFAULT_TEMPERATURE),
("repetition_penalty", DEFAULT_REPETITION_PENALTY),
]
.into_iter()
.map(|(name, value)| (name.to_string(), Value::from(value)))
.chain(
optional_params
.iter()
.filter(|(name, _)| DEEPSEEK_OCR_PARAMS.contains(&name.as_str()))
.map(|(name, value)| (name.clone(), value.clone())),
)
.collect(),
})
}
}
@ -484,6 +499,46 @@ mod tests {
assert!(result.get("ignored").is_none());
}
#[test]
fn request_uses_greedy_defaults_unless_the_caller_overrides_them() {
let request = |params: DeepSeekOcrParams| {
serde_json::to_value(
VertexAIDeepSeekOCRConfig
.transform_ocr_request(
"deepseek-ai/deepseek-ocr-maas",
document(),
&params,
&[],
)
.unwrap(),
)
.unwrap()
};
let defaults = request(DeepSeekOcrParams::default());
assert_eq!(defaults["temperature"], 0.0);
assert_eq!(defaults["repetition_penalty"], 1.05);
assert_eq!(
request(serde_json::from_value(json!({"temperature":0.7})).unwrap())["temperature"],
0.7
);
}
#[test]
fn caller_temperature_argument_overrides_the_greedy_default_in_the_composed_body() {
let arguments = serde_json::from_value(json!({"temperature":0.7})).unwrap();
let body = VertexAIDeepSeekOCRConfig
.transform_ocr_request(
"deepseek-ai/deepseek-ocr-maas",
document(),
&DeepSeekOcrParams::default(),
&[],
)
.unwrap();
let composed =
litellm_core_utils::call_arguments::compose_body(&arguments, &body, &[]).unwrap();
assert_eq!(composed["temperature"], 0.7);
}
#[rstest]
#[case(json!({"type":"image_url","image_url":"data:image/png;base64,AA=="}))]
#[case(json!({"type":"document_url","document_url":"data:application/pdf;base64,AA=="}))]