1use 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
18fn not_configured() -> UniError {
19 UniError::Internal(anyhow::anyhow!("Uni-Xervo runtime is not configured"))
20}
21
22#[derive(Clone)]
29pub struct UniXervo {
30 runtime: Option<Arc<ModelRuntime>>,
31}
32
33impl UniXervo {
34 pub fn is_available(&self) -> bool {
36 self.runtime.is_some()
37 }
38
39 pub async fn embed(&self, alias: &str, texts: &[&str]) -> Result<Vec<Vec<f32>>> {
41 let runtime = self.runtime.as_ref().ok_or_else(not_configured)?;
42 let embedder = runtime.embedding(alias).await.map_err(into_uni_error)?;
43 embedder.embed(texts.to_vec()).await.map_err(into_uni_error)
44 }
45
46 pub async fn generate(
48 &self,
49 alias: &str,
50 messages: &[Message],
51 options: GenerationOptions,
52 ) -> Result<GenerationResult> {
53 let runtime = self.runtime.as_ref().ok_or_else(not_configured)?;
54 let generator = runtime.generator(alias).await.map_err(into_uni_error)?;
55 generator
56 .generate(messages, options)
57 .await
58 .map_err(into_uni_error)
59 }
60
61 pub async fn generate_text(
66 &self,
67 alias: &str,
68 messages: &[&str],
69 options: GenerationOptions,
70 ) -> Result<GenerationResult> {
71 let structured: Vec<Message> = messages.iter().map(|s| Message::user(*s)).collect();
72 self.generate(alias, &structured, options).await
73 }
74
75 pub fn raw_runtime(&self) -> Option<&Arc<ModelRuntime>> {
77 self.runtime.as_ref()
78 }
79}
80
81impl Uni {
82 pub fn xervo(&self) -> UniXervo {
88 UniXervo {
89 runtime: self.inner.xervo_runtime.clone(),
90 }
91 }
92}