use std::{collections::BTreeSet, num::NonZeroUsize};
use futures::StreamExt;
use serde::Serialize;
use crate::{ids::AgentId, reactor::Agent};
#[derive(Debug, thiserror::Error)]
#[error("saved {} before failing: {inner}", saved.len())]
pub struct SaveError<E> {
pub saved: BTreeSet<AgentId>,
#[source]
pub inner: E,
}
#[async_trait::async_trait]
pub trait Inference: Send + Sync {
type Error: super::Error;
async fn infer<P>(
&self,
prompt: P,
) -> Result<misanthropic::response::Message, Self::Error>
where
P: Serialize + Send;
async fn infer_batch<P>(
&self,
prompts: &[&P],
) -> Result<
Vec<Result<misanthropic::response::Message, Self::Error>>,
Self::Error,
>
where
P: Serialize + Send + Sync,
{
let limit = self.max_concurrency().get();
let futs: Vec<_> = prompts.iter().map(|&p| self.infer(p)).collect();
let results = futures::stream::iter(futs)
.buffered(limit)
.collect::<Vec<_>>()
.await;
Ok(results)
}
async fn models(&self) -> Result<misanthropic::model::Models, Self::Error>;
fn quirks(&self) -> super::inference::Quirks {
super::inference::Quirks::default()
}
fn max_concurrency(&self) -> NonZeroUsize {
NonZeroUsize::new(1).unwrap()
}
}
#[derive(Debug, thiserror::Error)]
#[error("Agent was not found in Storage: {0}")]
pub struct AgentNotFound(pub AgentId);
#[async_trait::async_trait]
pub trait Storage: Sized + Send + Sync {
type Error: super::Error + From<serde_json::Error> + From<AgentNotFound>;
async fn save_raw(
&mut self,
id: AgentId,
value: serde_json::Value,
) -> Result<(), Self::Error>;
async fn load_raw(
&self,
id: AgentId,
) -> Result<serde_json::Value, Self::Error>;
async fn save<A: Agent>(
&mut self,
id: AgentId,
state: &A::State,
) -> Result<(), Self::Error> {
self.save_raw(id, serde_json::to_value(state)?).await
}
async fn load<A: Agent>(
&self,
id: AgentId,
) -> Result<A::State, Self::Error> {
let value = self.load_raw(id).await?;
Ok(serde_json::from_value(value)?)
}
async fn save_all_raw<It>(
&mut self,
items: It,
) -> Result<(), SaveError<Self::Error>>
where
It: ExactSizeIterator<Item = (AgentId, serde_json::Value)> + Send,
{
let mut saved = BTreeSet::new();
for (id, value) in items {
if let Err(inner) = self.save_raw(id, value).await {
return Err(SaveError { saved, inner });
}
saved.insert(id);
}
Ok(())
}
async fn load_all_raw<It>(
&self,
ids: It,
) -> Result<
Vec<(AgentId, Result<serde_json::Value, Self::Error>)>,
Self::Error,
>
where
It: ExactSizeIterator<Item = AgentId> + Send,
{
let mut raw = Vec::with_capacity(ids.len());
for id in ids {
raw.push((id, self.load_raw(id).await))
}
Ok(raw)
}
async fn save_all<It, A: Agent>(
&mut self,
items: It,
) -> Result<(), SaveError<Self::Error>>
where
It: ExactSizeIterator<Item = (AgentId, A::State)> + Send,
{
let mut raw = Vec::with_capacity(items.len());
for (id, value) in items {
let value = serde_json::to_value(value).map_err(|e| SaveError {
saved: BTreeSet::new(),
inner: Self::Error::from(e),
})?;
raw.push((id, value));
}
self.save_all_raw(raw.into_iter()).await
}
async fn load_all<It, A: Agent>(
&self,
ids: It,
) -> Result<Vec<(AgentId, Result<A::State, Self::Error>)>, Self::Error>
where
It: ExactSizeIterator<Item = AgentId> + Send,
{
let raw = self.load_all_raw(ids).await?;
let mut out = Vec::with_capacity(raw.len());
for (id, value) in raw {
match value {
Ok(value) => {
let result =
serde_json::from_value(value).map_err(Into::into);
out.push((id, result))
}
Err(e) => out.push((id, Err(e))),
}
}
Ok(out)
}
}