Skip to main content

writerslogic_warm/core/engine/
knowledge.rs

1// Copyright 2024-2026 WritersLogic Contributors
2// SPDX-License-Identifier: Apache-2.0
3
4use super::WarmCore;
5use crate::core::entangled::EntangledHVec;
6use crate::core::types::RetrievalResult;
7use anyhow::Result;
8
9impl WarmCore {
10    /// Encode a (head, relation, tail) triplet as `h XOR r XOR t` and memorize it.
11    pub fn memorize_triplet(&self, id: String, h: String, r: String, t: String) -> Result<()> {
12        super::mutation::validate_public_id(&id)?;
13        if !self.meaning_enabled() {
14            let triplet = self
15                .try_encode_text(&h)?
16                .bind(&self.try_encode_text(&r)?)
17                .bind(&self.try_encode_text(&t)?);
18            return self.memorize(id, triplet);
19        }
20        self.commit(&[super::mutation::Mutation::Triplet {
21            id,
22            subject: h,
23            relation: r,
24            object: t,
25        }])
26    }
27
28    /// Encode an ordered sequence using position-based permutation and memorize it.
29    pub fn memorize_sequence(&self, id: String, sequence: &[String]) -> Result<()> {
30        if sequence.is_empty() {
31            return Ok(());
32        }
33        self.memorize(id, self.encode_sequence(sequence)?)
34    }
35
36    /// Query for tails matching `head XOR relation`.
37    pub fn query_triplet(&self, h: String, r: String, k: u32) -> Result<Vec<RetrievalResult>> {
38        let vec_h = self.try_encode_text(&h)?;
39        let vec_r = self.try_encode_text(&r)?;
40        let query_vec = vec_h.bind(&vec_r);
41        Ok(self.query(&query_vec, k))
42    }
43
44    /// Find analogy: A is to B as C is to ? Returns k closest matches.
45    pub fn find_analogy(&self, a: &str, b: &str, c: &str, k: u32) -> Vec<RetrievalResult> {
46        self.try_find_analogy(a, b, c, k).expect(
47            "analogy encoding failed; use try_find_analogy to handle model or resource errors",
48        )
49    }
50
51    pub fn try_find_analogy(
52        &self,
53        a: &str,
54        b: &str,
55        c: &str,
56        k: u32,
57    ) -> Result<Vec<RetrievalResult>> {
58        let vec_a = self.try_encode_text(a)?;
59        let vec_b = self.try_encode_text(b)?;
60        let vec_c = self.try_encode_text(c)?;
61        let target = vec_a.bind(&vec_b).bind(&vec_c);
62        Ok(self.query(&target, k))
63    }
64
65    /// Query for sequences matching a partial sequence prefix.
66    pub fn query_sequence(&self, partial: &[String], k: u32) -> Result<Vec<RetrievalResult>> {
67        if partial.is_empty() {
68            return Ok(vec![]);
69        }
70        Ok(self.query(&self.encode_sequence(partial)?, k))
71    }
72
73    /// Bundles `items`, each permuted by its position.
74    fn encode_sequence(&self, items: &[String]) -> Result<EntangledHVec> {
75        let texts: Vec<_> = items.iter().map(String::as_str).collect();
76        let vecs: Vec<EntangledHVec> = self
77            .try_encode_texts(&texts)?
78            .into_iter()
79            .enumerate()
80            .map(|(i, vector)| vector.permute(i))
81            .collect();
82        Ok(self.bundle(&vecs))
83    }
84}