use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
#[cfg(feature = "typescript")]
use tsify::Tsify;
use crate::role::RoleName;
use crate::term::NormalizedTermValue;
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, JsonSchema)]
#[cfg_attr(feature = "typescript", derive(Tsify))]
#[cfg_attr(feature = "typescript", tsify(into_wasm_abi, from_wasm_abi))]
pub enum LogicalOperator {
#[serde(rename = "and")]
And,
#[serde(rename = "or")]
Or,
}
#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq, Default, JsonSchema)]
#[cfg_attr(feature = "typescript", derive(Tsify))]
#[cfg_attr(feature = "typescript", tsify(into_wasm_abi, from_wasm_abi))]
pub enum Layer {
#[serde(rename = "1")]
#[default]
One,
#[serde(rename = "2")]
Two,
#[serde(rename = "3")]
Three,
}
impl Layer {
pub fn from_u8(value: u8) -> Option<Self> {
match value {
1 => Some(Layer::One),
2 => Some(Layer::Two),
3 => Some(Layer::Three),
_ => None,
}
}
pub fn includes_content(&self) -> bool {
matches!(self, Layer::Two | Layer::Three)
}
pub fn includes_full_content(&self) -> bool {
matches!(self, Layer::Three)
}
}
impl std::fmt::Display for Layer {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Layer::One => write!(f, "1"),
Layer::Two => write!(f, "2"),
Layer::Three => write!(f, "3"),
}
}
}
#[derive(Debug, Serialize, Deserialize, Clone, Default)]
#[cfg_attr(feature = "typescript", derive(Tsify))]
#[cfg_attr(feature = "typescript", tsify(into_wasm_abi, from_wasm_abi))]
pub struct SearchQuery {
#[serde(alias = "query")]
pub search_term: NormalizedTermValue,
pub search_terms: Option<Vec<NormalizedTermValue>>,
pub operator: Option<LogicalOperator>,
pub skip: Option<usize>,
pub limit: Option<usize>,
pub role: Option<RoleName>,
#[serde(default)]
pub layer: Layer,
#[serde(default)]
pub include_pinned: bool,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub min_quality: Option<f64>,
}
impl SearchQuery {
pub fn get_all_terms(&self) -> Vec<&NormalizedTermValue> {
if let Some(ref multiple_terms) = self.search_terms {
let mut all_terms: Vec<&NormalizedTermValue> =
Vec::with_capacity(1 + multiple_terms.len());
all_terms.push(&self.search_term);
for term in multiple_terms.iter() {
if term.as_str() != self.search_term.as_str() {
all_terms.push(term);
}
}
all_terms
} else {
vec![&self.search_term]
}
}
pub fn is_multi_term_query(&self) -> bool {
self.search_terms.is_some() && !self.search_terms.as_ref().unwrap().is_empty()
}
pub fn get_operator(&self) -> LogicalOperator {
self.operator
.as_ref()
.unwrap_or(&LogicalOperator::Or)
.clone()
}
pub fn with_terms_and_operator(
primary_term: NormalizedTermValue,
additional_terms: Vec<NormalizedTermValue>,
operator: LogicalOperator,
role: Option<RoleName>,
) -> Self {
Self {
search_term: primary_term,
search_terms: Some(additional_terms),
operator: Some(operator),
skip: None,
limit: None,
role,
layer: Layer::default(),
include_pinned: false,
min_quality: None,
}
}
}
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Copy, JsonSchema, Default)]
#[cfg_attr(feature = "typescript", derive(Tsify))]
#[cfg_attr(feature = "typescript", tsify(into_wasm_abi, from_wasm_abi))]
pub enum RelevanceFunction {
#[serde(rename = "terraphim-graph")]
TerraphimGraph,
#[default]
#[serde(rename = "title-scorer")]
TitleScorer,
#[serde(rename = "bm25")]
BM25,
#[serde(rename = "bm25f")]
BM25F,
#[serde(rename = "bm25plus")]
BM25Plus,
}
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, JsonSchema)]
#[cfg_attr(feature = "typescript", derive(Tsify))]
#[cfg_attr(feature = "typescript", tsify(into_wasm_abi, from_wasm_abi))]
pub enum KnowledgeGraphInputType {
#[serde(rename = "markdown")]
Markdown,
#[serde(rename = "json")]
Json,
}