use crate::dto::{api, ollama}; use chrono::Utc; use uuid::Uuid; impl From for api::ModelInfo { fn from(m: ollama::OllamaModel) -> Self { Self { name: m.name, family: m.details.as_ref().and_then(|d| d.family.clone()), parameter_size: m.details.as_ref().and_then(|d| d.parameter_size.clone()), quantization: m .details .as_ref() .and_then(|d| d.quantization_level.clone()), } } } impl From for api::CompletionResponse { fn from(res: ollama::OllamaGenerateResponse) -> Self { Self { id: Uuid::new_v4().to_string(), object: api::CompletionObject::TextCompletion, model: res.model, created: Utc::now().timestamp() as u64, choices: vec![api::Choice { text: res.response, index: 0, finish_reason: api::FinishReason::Stop, }], usage: api::Usage { prompt_tokens: res.prompt_eval_count.unwrap_or(0), completion_tokens: res.eval_count.unwrap_or(0), total_tokens: res.prompt_eval_count.unwrap_or(0) + res.eval_count.unwrap_or(0), }, } } } impl From<&api::BaseLLMRequest> for ollama::OllamaOptions { fn from(base: &api::BaseLLMRequest) -> Self { Self { temperature: base.temperature, top_p: base.top_p, top_k: base.top_k, repeat_penalty: base.repeat_penalty, seed: base.seed, num_ctx: base.num_ctx, num_predict: base.num_predict, } } } impl From for api::ChatCompletionResponse { fn from(res: ollama::OllamaChatResponse) -> Self { let prompt_tokens = res.prompt_eval_count.unwrap_or(0); let completion_tokens = res.eval_count.unwrap_or(0); Self { id: Uuid::new_v4().to_string(), object: "chat.completion".to_string(), created: Utc::now().timestamp() as u64, model: res.model, choices: vec![api::ChatChoice { index: 0, message: res.message, finish_reason: if res.done { api::FinishReason::Stop } else { api::FinishReason::Length }, }], usage: Some(api::Usage { prompt_tokens, completion_tokens, total_tokens: prompt_tokens + completion_tokens, }), } } }