car_inference/tasks/
rerank.rs1use serde::{Deserialize, Serialize};
14
15#[derive(Debug, Clone, Serialize, Deserialize)]
17pub struct RerankRequest {
18 pub query: String,
20 pub documents: Vec<String>,
23 #[serde(default)]
25 pub model: Option<String>,
26 #[serde(default)]
29 pub top_n: Option<usize>,
30 #[serde(default)]
34 pub instruction: Option<String>,
35}
36
37#[derive(Debug, Clone, Serialize, Deserialize)]
39pub struct RerankedDocument {
40 pub index: usize,
42 pub score: f32,
44 pub document: String,
47}
48
49#[derive(Debug, Clone, Serialize, Deserialize)]
51pub struct RerankResult {
52 pub ranked: Vec<RerankedDocument>,
55 #[serde(default, skip_serializing_if = "Option::is_none")]
57 pub model_used: Option<String>,
58}
59
60#[cfg(test)]
61mod tests {
62 use super::*;
63
64 #[test]
65 fn minimal_request_deserializes_with_defaults() {
66 let json = r#"{"query":"who is the president","documents":["doc a","doc b"]}"#;
67 let req: RerankRequest = serde_json::from_str(json).unwrap();
68 assert_eq!(req.query, "who is the president");
69 assert_eq!(req.documents.len(), 2);
70 assert!(req.model.is_none());
71 assert!(req.top_n.is_none());
72 assert!(req.instruction.is_none());
73 }
74
75 #[test]
76 fn full_request_roundtrip() {
77 let req = RerankRequest {
78 query: "q".into(),
79 documents: vec!["d1".into(), "d2".into()],
80 model: Some("Qwen3-Reranker-0.6B".into()),
81 top_n: Some(1),
82 instruction: Some("retrieve passages relevant to the query".into()),
83 };
84 let json = serde_json::to_string(&req).unwrap();
85 let parsed: RerankRequest = serde_json::from_str(&json).unwrap();
86 assert_eq!(parsed.query, req.query);
87 assert_eq!(parsed.documents, req.documents);
88 assert_eq!(parsed.top_n, Some(1));
89 assert_eq!(
90 parsed.instruction.as_deref(),
91 Some("retrieve passages relevant to the query")
92 );
93 }
94
95 #[test]
96 fn result_serializes_without_null_model_used() {
97 let result = RerankResult {
98 ranked: vec![RerankedDocument {
99 index: 0,
100 score: 0.97,
101 document: "doc".into(),
102 }],
103 model_used: None,
104 };
105 let json = serde_json::to_string(&result).unwrap();
106 assert!(
107 !json.contains("model_used"),
108 "None should be omitted, not null"
109 );
110 assert!(json.contains("\"index\":0"));
111 assert!(json.contains("\"score\":0.97"));
112 }
113}