1111//!
1212//! The Preprocessor will accept any IngressRequest and transform it to a BackendRequest.
1313
14+ pub mod media;
1415pub mod prompt;
1516pub mod tools;
1617use anyhow:: Context ;
@@ -26,11 +27,11 @@ use std::{collections::HashMap, pin::Pin, sync::Arc};
2627use tracing;
2728
2829use crate :: model_card:: { ModelDeploymentCard , ModelInfo } ;
30+ use crate :: preprocessor:: media:: MediaLoader ;
2931use crate :: preprocessor:: prompt:: OAIChatLikeRequest ;
3032use crate :: protocols:: common:: preprocessor:: {
3133 MultimodalData , MultimodalDataMap , PreprocessedRequestBuilder ,
3234} ;
33-
3435use crate :: tokenizers:: Encoding ;
3536
3637use dynamo_parsers:: { ReasoningParser , ReasoningParserType } ;
@@ -113,6 +114,7 @@ pub struct OpenAIPreprocessor {
113114 /// Per-model runtime configuration propagated to response generator (e.g., reasoning/tool parser)
114115 runtime_config : crate :: local_model:: runtime_config:: ModelRuntimeConfig ,
115116 tool_call_parser : Option < String > ,
117+ media_loader : Option < MediaLoader > ,
116118}
117119
118120impl OpenAIPreprocessor {
@@ -141,14 +143,15 @@ impl OpenAIPreprocessor {
141143
142144 // // Initialize runtime config from the ModelDeploymentCard
143145 let runtime_config = mdc. runtime_config . clone ( ) ;
144-
146+ let media_loader = None ; // TODO: enable with decoder config from MDC
145147 Ok ( Arc :: new ( Self {
146148 formatter,
147149 tokenizer,
148150 model_info,
149151 mdcsum,
150152 runtime_config,
151153 tool_call_parser,
154+ media_loader,
152155 } ) )
153156 }
154157 /// Encode a string to it's tokens
@@ -162,7 +165,7 @@ impl OpenAIPreprocessor {
162165 /// Annotations evaluated by this method include:
163166 /// - `formatted_prompt`
164167 /// - `token_ids`
165- pub fn preprocess_request <
168+ pub async fn preprocess_request <
166169 R : OAIChatLikeRequest
167170 + AnnotationsProvider
168171 + SamplingOptionsProvider
@@ -181,6 +184,7 @@ impl OpenAIPreprocessor {
181184 . gather_tokens ( request, & mut builder, formatted_prompt)
182185 . with_context ( || "Failed to gather tokens" ) ?;
183186 self . gather_multi_modal_data ( request, & mut builder)
187+ . await
184188 . with_context ( || "Failed to gather multimodal data" ) ?;
185189
186190 Ok ( ( builder. build ( ) ?, annotations) )
@@ -267,14 +271,15 @@ impl OpenAIPreprocessor {
267271 }
268272 }
269273
270- pub fn gather_multi_modal_data < R : OAIChatLikeRequest > (
274+ pub async fn gather_multi_modal_data < R : OAIChatLikeRequest > (
271275 & self ,
272276 request : & R ,
273277 builder : & mut PreprocessedRequestBuilder ,
274278 ) -> Result < ( ) > {
275279 let messages = request. messages ( ) ;
276280 let message_count = messages. len ( ) . unwrap_or ( 0 ) ;
277281 let mut media_map: MultimodalDataMap = HashMap :: new ( ) ;
282+ let mut fetch_tasks = Vec :: new ( ) ;
278283
279284 for idx in 0 ..message_count {
280285 let msg = messages
@@ -307,10 +312,31 @@ impl OpenAIPreprocessor {
307312 _ => continue ,
308313 } ;
309314
310- let map_item = media_map. entry ( type_str. clone ( ) ) . or_default ( ) ;
311- map_item. push ( MultimodalData :: Url ( url) ) ;
315+ if self . media_loader . is_some ( ) {
316+ fetch_tasks. push ( ( type_str, content_part. clone ( ) ) ) ;
317+ } else {
318+ // No loader, just pass the URL through
319+ media_map
320+ . entry ( type_str)
321+ . or_default ( )
322+ . push ( MultimodalData :: Url ( url) ) ;
323+ }
312324 }
313325 }
326+
327+ // Execute all fetch tasks
328+ if !fetch_tasks. is_empty ( ) {
329+ let loader = self . media_loader . as_ref ( ) . unwrap ( ) ;
330+ let _results = futures:: future:: join_all (
331+ fetch_tasks
332+ . iter ( )
333+ . map ( |( _, content_part) | loader. fetch_media_part ( content_part) ) ,
334+ )
335+ . await ;
336+
337+ // TODO: decode and pass NIXL descriptors to the media map
338+ }
339+
314340 if !media_map. is_empty ( ) {
315341 builder. multi_modal_data ( Some ( media_map) ) ;
316342 }
839865 let response_generator = request. response_generator ( context. id ( ) . to_string ( ) ) ;
840866
841867 // convert the chat completion request to a common completion request
842- let ( common_request, annotations) = self . preprocess_request ( & request) ?;
868+ let ( common_request, annotations) = self . preprocess_request ( & request) . await ?;
843869
844870 let mut response_generator = Box :: new ( response_generator) ;
845871
@@ -974,7 +1000,7 @@ impl
9741000 // convert the chat completion request to a common completion request
9751001 let mut builder = self . builder ( & request) ?;
9761002 let annotations = self . gather_tokens ( & request, & mut builder, None ) ?;
977- self . gather_multi_modal_data ( & request, & mut builder) ?;
1003+ self . gather_multi_modal_data ( & request, & mut builder) . await ?;
9781004
9791005 let common_request = builder. build ( ) ?;
9801006
0 commit comments