use serde::{Deserialize, Serialize};
use std::{collections::BTreeMap, fmt};
use crate::{
AgentOutput, BoxError, ContentPart, Document, Documents, FunctionDefinition, Json, Message,
Resource,
};
pub trait CompletionFeatures: Sized {
fn completion(
&self,
req: CompletionRequest,
resources: Vec<Resource>,
) -> impl Future<Output = Result<AgentOutput, BoxError>> + Send;
fn model_name(&self) -> String;
}
#[derive(Debug, Clone, Copy, Deserialize, Serialize, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
pub enum ModelEffort {
Minimal,
Low,
Medium,
High,
Max,
}
impl ModelEffort {
pub fn as_str(self) -> &'static str {
match self {
Self::Minimal => "minimal",
Self::Low => "low",
Self::Medium => "medium",
Self::High => "high",
Self::Max => "max",
}
}
}
impl fmt::Display for ModelEffort {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_str())
}
}
#[derive(Debug, Clone, Default)]
pub struct CompletionRequest {
pub instructions: String,
pub role: Option<String>,
pub chat_history: Vec<Message>,
pub raw_history: Vec<Json>,
pub documents: Documents,
pub prompt: String,
pub content: Vec<ContentPart>,
pub tools: Vec<FunctionDefinition>,
pub tool_choice_required: bool,
pub temperature: Option<f64>,
pub max_output_tokens: Option<usize>,
pub output_schema: Option<Json>,
pub stop: Option<Vec<String>>,
pub model: Option<String>,
pub effort: Option<ModelEffort>,
}
impl CompletionRequest {
pub fn context(mut self, id: String, text: String) -> Self {
self.documents.docs.push(Document {
content: text.into(),
metadata: BTreeMap::from([("id".to_string(), id.into())]),
});
self
}
pub fn append_documents(mut self, docs: Documents) -> Self {
self.documents.docs.extend(docs.docs);
self
}
pub fn append_tools(mut self, tools: Vec<FunctionDefinition>) -> Self {
self.tools.extend(tools);
self
}
}