(
&self,
py: Python<'_>,
texts_batch: Vec<Vec<String>>,
max_concurrency: Option<usize>,
timeout_ms: Option<u64>,
)
| 108 | /// ``` |
| 109 | #[pyo3(signature = (texts_batch, max_concurrency=None, timeout_ms=None))] |
| 110 | fn embed_batch_parallel( |
| 111 | &self, |
| 112 | py: Python<'_>, |
| 113 | texts_batch: Vec<Vec<String>>, |
| 114 | max_concurrency: Option<usize>, |
| 115 | timeout_ms: Option<u64>, |
| 116 | ) -> PyResult<Py<PyDict>> { |
| 117 | // Validate input |
| 118 | if texts_batch.is_empty() { |
| 119 | return Err(PyErr::new::<pyo3::exceptions::PyValueError, _>( |
| 120 | "Batch cannot be empty", |
| 121 | )); |
| 122 | } |
| 123 | |
| 124 | // Build batch request |
| 125 | let requests: Vec<EmbeddingRequest> = texts_batch |
| 126 | .into_iter() |
| 127 | .map(|texts| EmbeddingRequest { |
| 128 | input: EmbeddingInput::Multiple(texts), |
| 129 | user: None, |
| 130 | params: HashMap::new(), |
| 131 | }) |
| 132 | .collect(); |
| 133 | |
| 134 | let batch_request = EmbeddingBatchRequest { |
| 135 | requests, |
| 136 | max_concurrency, |
| 137 | timeout_ms, |
| 138 | }; |
| 139 | |
| 140 | let service = Arc::clone(&self.service); |
| 141 | let rt = get_runtime(); |
| 142 | |
| 143 | // CRITICAL: Release GIL during lock-free parallel execution |
| 144 | // This enables true parallelism with atomic operations for concurrency control |
| 145 | let batch_response = py.allow_threads(|| { |
| 146 | rt.block_on(async move { |
| 147 | service |
| 148 | .process_batch(batch_request) |
| 149 | .await |
| 150 | .map_err(to_py_runtime_error) |
| 151 | }) |
| 152 | })?; |
| 153 | |
| 154 | // Convert response to Python dictionary |
| 155 | let result_dict = PyDict::new(py); |
| 156 | |
| 157 | // Extract embeddings from successful responses |
| 158 | let mut all_embeddings: Vec<Vec<Vec<f32>>> = Vec::new(); |
| 159 | let mut errors: Vec<String> = Vec::new(); |
| 160 | |
| 161 | for (idx, response_result) in batch_response.responses.into_iter().enumerate() { |
| 162 | match response_result { |
| 163 | Ok(response) => { |
| 164 | all_embeddings.push(response.embeddings); |
| 165 | } |
| 166 | Err(e) => { |
| 167 | errors.push(format!("Batch {}: {}", idx, e)); |
nothing calls this directly
no test coverage detected