Skip to main content

uni_db/api/
xervo.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright 2024-2026 Dragonscale Team
3
4use std::sync::Arc;
5
6use crate::api::Uni;
7use uni_common::{Result, UniError};
8use uni_xervo::runtime::ModelRuntime;
9pub use uni_xervo::traits::{
10    AudioOutput, ContentBlock, GeneratedImage, GenerationOptions, GenerationResult, ImageInput,
11    Message, MessageRole, TokenUsage,
12};
13
14fn into_uni_error<E: std::fmt::Display>(err: E) -> UniError {
15    UniError::Internal(anyhow::anyhow!(err.to_string()))
16}
17
18/// Facade for using Uni-Xervo runtime from the Uni API surface.
19#[derive(Clone)]
20pub struct UniXervo {
21    runtime: Arc<ModelRuntime>,
22}
23
24impl UniXervo {
25    pub(crate) fn new(runtime: Arc<ModelRuntime>) -> Self {
26        Self { runtime }
27    }
28
29    /// Embed text inputs using a configured model alias.
30    pub async fn embed(&self, alias: &str, texts: &[&str]) -> Result<Vec<Vec<f32>>> {
31        let embedder = self
32            .runtime
33            .embedding(alias)
34            .await
35            .map_err(into_uni_error)?;
36        embedder.embed(texts.to_vec()).await.map_err(into_uni_error)
37    }
38
39    /// Generate using a configured model alias with structured messages.
40    pub async fn generate(
41        &self,
42        alias: &str,
43        messages: &[Message],
44        options: GenerationOptions,
45    ) -> Result<GenerationResult> {
46        let generator = self
47            .runtime
48            .generator(alias)
49            .await
50            .map_err(into_uni_error)?;
51        generator
52            .generate(messages, options)
53            .await
54            .map_err(into_uni_error)
55    }
56
57    /// Generate text using plain string messages (convenience wrapper).
58    ///
59    /// Each string is treated as a user message. For multi-role conversations
60    /// or multimodal inputs, use [`generate`](Self::generate) with [`Message`] directly.
61    pub async fn generate_text(
62        &self,
63        alias: &str,
64        messages: &[&str],
65        options: GenerationOptions,
66    ) -> Result<GenerationResult> {
67        let structured: Vec<Message> = messages.iter().map(|s| Message::user(*s)).collect();
68        self.generate(alias, &structured, options).await
69    }
70
71    /// Access the underlying Uni-Xervo runtime.
72    pub fn raw_runtime(&self) -> &Arc<ModelRuntime> {
73        &self.runtime
74    }
75}
76
77impl Uni {
78    /// Access Uni-Xervo runtime facade configured for this database.
79    pub fn xervo(&self) -> Result<UniXervo> {
80        let runtime = self.xervo_runtime.clone().ok_or_else(|| {
81            UniError::Internal(anyhow::anyhow!("Uni-Xervo runtime is not configured"))
82        })?;
83        Ok(UniXervo::new(runtime))
84    }
85}