#![allow(unused_imports)]
use super::error::CompletionError;
use crate::persistence::{self, PersistentState};
use asimov_runner::{Execute, Prompt, Prompter, PrompterOptions, TextOutput};
use axum::{Json, Router, extract, routing::post};
use jiff::Timestamp;
use openai::schemas::{
CompletionUsage, CreateCompletionRequest, CreateCompletionResponse,
CreateCompletionResponse_Choices,
};
use std::sync::{Arc, RwLock};
pub fn routes() -> Router {
Router::new()
.route("/", post(create))
.with_state(persistence::get_ref())
}
#[axum::debug_handler]
async fn create(
extract::State(state): extract::State<Arc<RwLock<PersistentState>>>,
extract::Json(request): extract::Json<CreateCompletionRequest>,
) -> Result<Json<CreateCompletionResponse>, CompletionError> {
if request.model.is_empty() {
return Err(CompletionError::EmptyModel);
}
if request.prompt.is_none() {
return Err(CompletionError::EmptyPrompt);
}
let prompt = Prompt::try_from(request.prompt.unwrap()).map_err(|_| {
CompletionError::UnimplementedFeature("prompt from an array of tokens".into())
})?;
let provider_name = state.read().unwrap().provider.clone();
let mut provider = Prompter::new(
provider_name,
prompt,
TextOutput::Captured,
PrompterOptions::default(),
);
let provider_output = provider
.execute()
.await
.map_err(|error| CompletionError::FailedExecute(error))?;
Ok(Json(CreateCompletionResponse {
id: super::util::generate_openai_id("cmpl"),
object: "text_completion".into(),
created: Timestamp::now().as_second(),
model: request.model,
choices: vec![CreateCompletionResponse_Choices {
index: 0,
finish_reason: "stop".into(),
logprobs: None,
text: provider_output,
}],
system_fingerprint: None,
usage: Some(CompletionUsage {
prompt_tokens: 0, completion_tokens: 0, total_tokens: 0, prompt_tokens_details: Default::default(),
completion_tokens_details: Default::default(),
}),
})) }