textsynth/engine/
log_probabilities.rs

1//! Operations involving log probabilities.
2
3use serde::{Deserialize, Serialize};
4
5/// A [`String`] which is guaranteed to not be empty.
6#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Serialize)]
7pub struct NonEmptyString(String);
8
9impl NonEmptyString {
10    /// Creates a new [`NonEmptyString`] from a [`String`].
11    pub fn new(s: String) -> Option<Self> {
12        if s.is_empty() {
13            None
14        } else {
15            Some(Self(s))
16        }
17    }
18
19    /// Get a reference to the inner [`String`].
20    pub fn inner(&self) -> &str {
21        &self.0
22    }
23
24    /// Take the inner [`String`].
25    pub fn into_inner(self) -> String {
26        self.0
27    }
28}
29
30#[derive(Serialize)]
31pub(crate) struct LogProbabilitiesRequest {
32    pub(crate) context: String,
33    pub(crate) continuation: NonEmptyString,
34}
35
36/// This is logarithm of the probability that a continuation is generated after a context. It can be
37/// used to answer questions when only a few answers (such as yes/no) are possible. It can also be
38/// used to benchmark the models.
39#[derive(Debug, Copy, Clone, PartialOrd, PartialEq, Deserialize)]
40pub struct LogProbabilities {
41    logprob: f64,
42    is_greedy: bool,
43    total_tokens: usize,
44}
45
46impl LogProbabilities {
47    /// Logarithm of the probability of generation of continuation preceded by context. It is
48    /// always <= 0.
49    pub const fn log_probability(&self) -> f64 {
50        self.logprob
51    }
52
53    /// `true` if `continuation` would be generated by greedy sampling from `continuation`.
54    pub const fn is_greedy(&self) -> bool {
55        self.is_greedy
56    }
57
58    /// Indicate the total number of tokens. It is useful to estimate the number of compute
59    /// resources used by the request.
60    pub const fn total_tokens(&self) -> usize {
61        self.total_tokens
62    }
63}
64
65#[cfg(test)]
66mod tests {
67    use super::*;
68    use crate::test_utils;
69
70    #[test]
71    fn test_non_empty_string_new() {
72        let empty = String::new();
73        let non_empty = String::from("textsynth");
74
75        assert!(NonEmptyString::new(empty).is_none());
76        assert!(NonEmptyString::new(non_empty).is_some());
77    }
78
79    #[test]
80    fn test_non_empty_string_inner() {
81        let s = String::from("textsynth");
82        let non_empty = NonEmptyString::new(s).unwrap();
83
84        assert_eq!(non_empty.inner(), "textsynth");
85    }
86
87    #[test]
88    fn test_non_empty_string_into_inner() {
89        let s = String::from("textsynth");
90        let non_empty = NonEmptyString::new(s).unwrap();
91
92        assert_eq!(non_empty.into_inner(), "textsynth");
93    }
94
95    #[test]
96    fn test_log_probabilities_log_probability() {
97        let _ = test_utils::cache::log_probabilities().log_probability();
98    }
99
100    #[test]
101    fn test_log_probabilities_is_greedy() {
102        let _ = test_utils::cache::log_probabilities().is_greedy();
103    }
104
105    #[test]
106    fn test_log_probabilities_total_tokens() {
107        let _ = test_utils::cache::log_probabilities().total_tokens();
108    }
109}