1use crate::knowledge::{EntityId, StatementId};
11use oxibrain_ports::Timestamp;
12use serde::{Deserialize, Serialize};
13
14pub use crate::rank::{DropReason, DroppedItem, RankedItem, RankingResult};
17
18#[derive(Debug, Clone, Serialize, Deserialize)]
19pub struct Query {
20 pub text: String,
21 pub mode: QueryMode,
22 pub space: String,
23 #[serde(default)]
24 pub as_of: Option<Timestamp>,
25 #[serde(default = "default_limit")]
26 pub limit: usize,
27 #[serde(default)]
28 pub min_confidence: f32,
29}
30
31fn default_limit() -> usize {
32 20
33}
34
35#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
36#[serde(rename_all = "snake_case")]
37pub enum QueryMode {
38 Hybrid,
39 Lexical,
40 LexicalVector,
41 Dense,
44 Graph,
45 Community,
46}
47
48impl QueryMode {
49 pub fn to_preset(self) -> &'static str {
52 match self {
53 QueryMode::Hybrid => "hybrid",
54 QueryMode::Lexical => "lexical",
55 QueryMode::LexicalVector => "lexical", QueryMode::Dense => "semantic",
57 QueryMode::Graph => "graph",
58 QueryMode::Community => "community",
59 }
60 }
61}
62
63#[derive(Debug, Clone, Serialize, Deserialize)]
64pub struct SearchHit {
65 pub target: SearchTarget,
66 pub score: f64,
67 pub mode: QueryMode,
68}
69
70#[derive(Debug, Clone, Serialize, Deserialize)]
71#[serde(tag = "kind", rename_all = "snake_case")]
72pub enum SearchTarget {
73 Episode { id: String },
74 Statement { id: StatementId },
75 Entity { id: EntityId },
76}
77
78#[derive(Debug, Clone, Serialize, Deserialize)]
81pub struct TraversalSpec {
82 pub start: Vec<EntityId>,
83 pub max_depth: u8,
84 pub max_nodes: u32,
85 pub predicates: PredicateFilter,
86 pub direction: Direction,
87 #[serde(default)]
88 pub valid_at: Option<Timestamp>,
89 pub min_confidence: f32,
90 pub strategy: Strategy,
91}
92
93impl Default for TraversalSpec {
94 fn default() -> Self {
95 Self {
96 start: Vec::new(),
97 max_depth: 3,
98 max_nodes: 256,
99 predicates: PredicateFilter::AllowAll,
100 direction: Direction::Both,
101 valid_at: None,
102 min_confidence: 0.0,
103 strategy: Strategy::Bfs,
104 }
105 }
106}
107pub use oxibrain_index::{Direction, PredicateFilter};
111
112#[derive(Debug, Clone, Serialize, Deserialize)]
113#[serde(tag = "kind", rename_all = "snake_case")]
114pub enum Strategy {
115 Bfs,
116 ShortestPath { to: EntityId },
117}
118
119#[derive(Debug, Clone, Serialize, Deserialize)]
120pub struct TraversalResult {
121 pub nodes: Vec<TraversalNode>,
122 pub edges: Vec<TraversalEdge>,
123 pub truncated: bool,
124}
125
126#[derive(Debug, Clone, Serialize, Deserialize)]
127pub struct TraversalNode {
128 pub entity: EntityId,
129 pub depth: u8,
130 pub salience: f64,
131}
132
133#[derive(Debug, Clone, Serialize, Deserialize)]
134pub struct TraversalEdge {
135 pub from: EntityId,
136 pub to: EntityId,
137 pub predicate: String,
138 pub statement_id: StatementId,
139 pub depth: u8,
140}