#![doc = include_str!("../README.MD")]
#![warn(missing_docs)]
use std::future::Future;
pub mod prelude;
#[cfg_attr(not(any(feature = "ollama", feature = "llama.cpp")), deny(warnings))]
mod error;
mod message;
mod prompts;
#[cfg(any(feature = "candle", feature = "candle-git"))]
pub mod candle;
#[cfg(feature = "llama.cpp")]
pub mod llama_cpp;
#[cfg(feature = "ollama")]
pub mod ollama;
#[cfg(feature = "simple-api")]
pub mod simple_api;
#[cfg(feature = "template")]
pub mod template;
pub use error::Error;
pub use message::{Message, Role};
pub use prompts::{ChatPrompt, Format, GenerationPrompt};
pub type Result<T, E = Error> = std::result::Result<T, E>;
pub type StringStream = ccutils::streams::BoxedStream<Result<String>>;
fn accumulate<T>(stream_maker: T) -> Result<impl Future<Output = Result<String>> + Send>
where
T: Future<Output = Result<StringStream>> + Send,
{
use futures::stream::StreamExt;
Ok(async {
let mut result: String = Default::default();
let mut stream = Box::pin(stream_maker.await?);
while let Some(next_token) = stream.next().await
{
if result.is_empty()
{
result = next_token?;
}
else
{
result.push_str(&next_token?);
}
}
Ok(result)
})
}
#[allow(dead_code)]
pub(crate) fn generate_with_chat<LLM>(
llm: &LLM,
prompt: GenerationPrompt,
) -> Result<impl Future<Output = Result<StringStream>> + Send + use<'_, LLM>>
where
LLM: LargeLanguageModel,
{
let chat_prompt = ChatPrompt::default()
.system_opt(prompt.system)
.assistant_opt(prompt.assistant)
.user(prompt.user)
.options(prompt.options);
llm.chat_stream(chat_prompt)
}
pub trait LargeLanguageModel
{
fn chat_stream(
&self,
prompt: ChatPrompt,
) -> Result<impl Future<Output = Result<StringStream>> + Send>;
fn chat(&self, prompt: ChatPrompt) -> Result<impl Future<Output = Result<String>> + Send>
{
let stream = self.chat_stream(prompt)?;
accumulate(stream)
}
fn generate_stream(
&self,
prompt: GenerationPrompt,
) -> Result<impl Future<Output = Result<StringStream>> + Send>;
fn generate(
&self,
prompt: GenerationPrompt,
) -> Result<impl Future<Output = Result<String>> + Send>
{
let stream = self.generate_stream(prompt)?;
accumulate(stream)
}
}