uni_xervo/provider/
local_onnx.rs1#[allow(dead_code)]
22mod autoreg;
23mod common;
24mod decoder_inputs;
25mod det;
26mod document_extract;
27mod embed_hybrid;
28mod embed_multi_vector;
29mod embed_sparse;
30mod embedding;
31mod image;
32mod image_embed;
33mod nlp;
34mod nlp_v7;
35mod ocr;
36mod presets;
37mod raw;
38mod rerank;
39mod rerank_generative;
40
41use std::path::PathBuf;
42use std::sync::Arc;
43
44use async_trait::async_trait;
45use dashmap::DashMap;
46
47use crate::api::{ModelAliasSpec, ModelTask};
48use crate::error::{Result, RuntimeError};
49use crate::traits::{
50 DocumentExtractionModel, EmbeddingModel, HybridEmbeddingModel, ImageEmbeddingModel,
51 LoadedModelHandle, ModelProvider, MultiVectorEmbeddingModel, NlpModel, OcrModel,
52 ProviderCapabilities, ProviderHealth, RawTensorModel, RerankerModel, SparseEmbeddingModel,
53};
54
55pub struct LocalOnnxProvider {
56 base_dir: Option<PathBuf>,
57 sessions: DashMap<String, Arc<raw::LoadedOnnxSession>>,
58}
59
60impl Default for LocalOnnxProvider {
61 fn default() -> Self {
62 Self::new()
63 }
64}
65
66impl LocalOnnxProvider {
67 pub fn new() -> Self {
68 Self {
69 base_dir: None,
70 sessions: DashMap::new(),
71 }
72 }
73
74 pub fn with_base_dir(mut self, base_dir: impl Into<PathBuf>) -> Self {
75 self.base_dir = Some(base_dir.into());
76 self
77 }
78}
79
80#[async_trait]
81impl ModelProvider for LocalOnnxProvider {
82 fn provider_id(&self) -> &'static str {
83 "local/onnx"
84 }
85
86 fn capabilities(&self) -> ProviderCapabilities {
87 ProviderCapabilities {
88 supported_tasks: vec![
89 ModelTask::Raw,
90 ModelTask::Rerank,
91 ModelTask::Embed,
92 ModelTask::Nlp,
93 ModelTask::EmbedImage,
94 ModelTask::Ocr,
95 ModelTask::DocumentExtract,
96 ModelTask::EmbedSparse,
97 ModelTask::EmbedMultiVector,
98 ModelTask::EmbedHybrid,
99 ],
100 }
101 }
102
103 async fn load(&self, spec: &ModelAliasSpec) -> Result<LoadedModelHandle> {
104 match spec.task {
105 ModelTask::Raw => {
106 let runner: Arc<dyn RawTensorModel> =
107 raw::load_raw(spec, self.base_dir.as_deref(), &self.sessions).await?;
108 Ok(Arc::new(runner) as LoadedModelHandle)
109 }
110 ModelTask::Rerank => {
111 let style = spec
112 .options
113 .get("style")
114 .and_then(|v| v.as_str())
115 .unwrap_or("cross-encoder");
116 let reranker: Arc<dyn RerankerModel> = match style {
117 "cross-encoder" => rerank::load_rerank(spec).await?,
118 "generative" => rerank_generative::load(spec).await?,
119 other => {
120 return Err(RuntimeError::Config(format!(
121 "Unknown rerank style '{other}' for alias '{}'; expected one of cross-encoder, generative",
122 spec.alias
123 )));
124 }
125 };
126 Ok(Arc::new(reranker) as LoadedModelHandle)
127 }
128 ModelTask::Embed => {
129 let embedder: Arc<dyn EmbeddingModel> = embedding::load_embedding(spec).await?;
130 Ok(Arc::new(embedder) as LoadedModelHandle)
131 }
132 ModelTask::Nlp => {
133 let model: Arc<dyn NlpModel> = match nlp_v7::detect_generation(spec).await? {
139 nlp_v7::Generation::V7 => nlp_v7::load_nlp_v7(spec).await?,
140 nlp_v7::Generation::V1 => nlp::load_nlp(spec).await?,
141 };
142 Ok(Arc::new(model) as LoadedModelHandle)
143 }
144 ModelTask::EmbedImage => {
145 let model: Arc<dyn ImageEmbeddingModel> =
146 image_embed::load_image_embedder(spec).await?;
147 Ok(Arc::new(model) as LoadedModelHandle)
148 }
149 ModelTask::Ocr => {
150 let model: Arc<dyn OcrModel> = ocr::load_ocr(spec).await?;
151 Ok(Arc::new(model) as LoadedModelHandle)
152 }
153 ModelTask::DocumentExtract => {
154 let model: Arc<dyn DocumentExtractionModel> =
155 document_extract::load_document_extractor(spec).await?;
156 Ok(Arc::new(model) as LoadedModelHandle)
157 }
158 ModelTask::EmbedSparse => {
159 let model: Arc<dyn SparseEmbeddingModel> =
160 embed_sparse::load_sparse_embedder(spec).await?;
161 Ok(Arc::new(model) as LoadedModelHandle)
162 }
163 ModelTask::EmbedMultiVector => {
164 let model: Arc<dyn MultiVectorEmbeddingModel> =
165 embed_multi_vector::load_multi_vector_embedder(spec).await?;
166 Ok(Arc::new(model) as LoadedModelHandle)
167 }
168 ModelTask::EmbedHybrid => {
169 let model: Arc<dyn HybridEmbeddingModel> =
170 embed_hybrid::load_hybrid_embedder(spec).await?;
171 Ok(Arc::new(model) as LoadedModelHandle)
172 }
173 _ => Err(RuntimeError::CapabilityMismatch(format!(
174 "ONNX provider does not support task {:?}",
175 spec.task
176 ))),
177 }
178 }
179
180 async fn health(&self) -> ProviderHealth {
181 ProviderHealth::Healthy
182 }
183}