pub const STRUCTURED_EXTRACTION_TEMPLATE: &str = "\
You are a document data extraction system. Extract structured data from the \
following document content according to the provided JSON schema.
{% if schema_description %}Schema description: {{ schema_description }}
{% endif %}
Document content:
{{ content }}
Extract the requested data and return valid JSON that conforms to the schema. \
Return ONLY the JSON object, with no additional text, explanation, or markdown formatting.";
pub const VLM_OCR_TEMPLATE: &str = "\
Extract all visible text from this image. \
Reproduce the text exactly as it appears, preserving the original structure, \
paragraph breaks, and reading order. \
Render mathematical formulas as LaTeX, wrapped in $$ for display equations \
and $ for inline ones. \
Do not add any commentary, explanation, or formatting beyond what is present \
in the image. \
If the image contains no text, respond with an empty string.\
{% if language and language != 'eng' and language != 'en' %}
The document is in language: {{ language }}\
{% endif %}";
pub(crate) fn render_template(template: &str, context: &minijinja::value::Value) -> crate::Result<String> {
let env = minijinja::Environment::new();
let tmpl = env
.template_from_str(template)
.map_err(|e| crate::XbergError::validation(format!("Invalid prompt template: {e}")))?;
tmpl.render(context)
.map_err(|e| crate::XbergError::validation(format!("Failed to render prompt template: {e}")))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_vlm_ocr_template_includes_math_instruction_and_language_block() {
let ctx_non_english = minijinja::context! { language => "deu" };
let prompt = render_template(VLM_OCR_TEMPLATE, &ctx_non_english).unwrap();
assert!(prompt.contains("LaTeX"), "must instruct math as LaTeX; got: {prompt}");
assert!(
prompt.contains("$$"),
"must mention the display-math delimiter; got: {prompt}"
);
assert!(
prompt.contains("language: deu"),
"language block must still render; got: {prompt}"
);
let ctx_english = minijinja::context! { language => "eng" };
let prompt_en = render_template(VLM_OCR_TEMPLATE, &ctx_english).unwrap();
assert!(
prompt_en.contains("LaTeX"),
"math instruction must be unconditional; got: {prompt_en}"
);
assert!(
!prompt_en.contains("language:"),
"English must skip the language hint; got: {prompt_en}"
);
}
}