ports.rsannotatedports.rssource127 lines · 4.5 KB · raw
1use serde::{Deserialize, Serialize};
2
3use crate::chat::ChatState;
4use crate::profile::Age;
5use whiskers_icons::IconId;
6use crate::types::{Direction, Entry, Fact, Image, MemorySnapshot, NewFact, PictureId, Turn, Verdict};
7
8/// The model could not answer. `resting` is the one reason that is not a fault: the time the
9/// grown-ups allow for thinking is used up for now, which the child is told differently.
10#[derive(Debug)]
11pub struct ModelError {
12    pub reason: String,
13    pub resting: bool,
14}
15
16impl ModelError {
17    pub fn new(reason: impl Into<String>) -> Self {
18        Self { reason: reason.into(), resting: false }
19    }
20
21    pub fn resting(reason: impl Into<String>) -> Self {
22        Self { reason: reason.into(), resting: true }
23    }
24}
25#[derive(Debug)]
26pub struct GuardError(pub String);
27#[derive(Debug)]
28pub struct LogError(pub String);
29#[derive(Debug)]
30pub struct PictureError(pub String);
31#[derive(Debug)]
32pub struct MemoryError(pub String);
33#[derive(Debug)]
34pub struct EmbedError(pub String);
35#[derive(Debug)]
36pub struct RankError(pub String);
37#[derive(Debug)]
38pub struct ChatError(pub String);
39#[derive(Debug)]
40pub struct IconError(pub String);
41
42/// Where a turn failed, for the log.
43#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
44pub enum FailureStage {
45    GuardingInput,
46    Model,
47    GuardingOutput,
48    Remembering,
49    SavingChat,
50}
51
52/// The language model, reached through the gateway. The last turn in
53/// `history` is the one to answer and may carry pictures.
54pub trait Model: Send + Sync {
55    fn complete(&self, system: &str, history: &[Turn]) -> Result<String, ModelError>;
56}
57
58/// Decides whether a message may pass, judged for a child of `age`. An `Err` is not an
59/// `Allow`: the pipeline treats a guard it cannot reach as a refusal. The guard is given the
60/// age and nothing else about the child: the name cannot reach it.
61pub trait Guard: Send + Sync {
62    fn check(&self, direction: Direction, age: Age, text: &str) -> Result<Verdict, GuardError>;
63}
64
65/// The parents' record. Append-only.
66pub trait Log {
67    fn append(&mut self, entry: &Entry) -> Result<(), LogError>;
68}
69
70/// Keeps what she shows Whiskers, so the parents can see it too.
71pub trait Pictures {
72    fn save(&mut self, image: &Image) -> Result<PictureId, PictureError>;
73}
74
75/// What Whiskers remembers between conversations.
76pub trait Memory: Send {
77    fn facts(&self) -> Vec<Fact>;
78    fn add(&mut self, new: NewFact, at_ms: u64) -> Result<Fact, MemoryError>;
79    fn set_embedding(&mut self, id: u64, embedding: Vec<f32>) -> Result<(), MemoryError>;
80    fn forget(&mut self, id: u64) -> Result<Fact, MemoryError>;
81    /// Gives a fact its picture if it has none yet (the first choice is kept).
82    fn give_icon(&mut self, id: u64, icon: IconId) -> Result<Fact, MemoryError>;
83    /// She puts a fact away: it stays, the parents still see it, Whiskers stops using it. Not `forget`.
84    fn hide(&mut self, id: u64, at_ms: u64) -> Result<Fact, MemoryError>;
85    /// A parent restores a fact she put away.
86    fn restore(&mut self, id: u64, at_ms: u64) -> Result<Fact, MemoryError>;
87    /// What this device knows, for another to merge.
88    fn snapshot(&self) -> MemorySnapshot;
89    /// Takes in what another device knows. Returns how many facts changed here.
90    fn merge(&mut self, remote: MemorySnapshot) -> Result<usize, MemoryError>;
91}
92
93/// Chooses the picture for a fact from the admitted set. `Ok(None)` is an answer ("none fits"); an `Err` is
94/// "could not decide" and is worth trying again later. Never an error shown to the child: a fact with no picture
95/// simply shows a generic star.
96pub trait IconChooser: Send + Sync {
97    fn choose(&self, text: &str) -> Result<Option<IconId>, IconError>;
98}
99
100/// Chooses nothing; for a device with no service to ask.
101pub struct NoIcons;
102
103impl IconChooser for NoIcons {
104    fn choose(&self, _text: &str) -> Result<Option<IconId>, IconError> {
105        Err(IconError("no service to ask".into()))
106    }
107}
108
109/// Turns text into vectors that are close when the meanings are.
110pub trait Embedder: Send + Sync {
111    fn embed(&self, texts: &[String]) -> Result<Vec<Vec<f32>>, EmbedError>;
112}
113
114/// Says how well each candidate memory fits a message: a probability each, same order.
115pub trait Ranker: Send + Sync {
116    fn rank(&self, query: &str, candidates: &[String]) -> Result<Vec<f32>, RankError>;
117}
118
119/// Keeps the running chat between launches.
120pub trait ChatStore: Send {
121    fn load(&self) -> Result<ChatState, ChatError>;
122    fn save(&mut self, state: &ChatState) -> Result<(), ChatError>;
123}
124
125pub trait Clock: Send + Sync {
126    fn now_ms(&self) -> u64;
127}