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
18#[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 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 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 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 pub fn raw_runtime(&self) -> &Arc<ModelRuntime> {
73 &self.runtime
74 }
75}
76
77impl Uni {
78 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}