daimon_plugin_opensearch/lib.rs
1//! # daimon-plugin-opensearch
2//!
3//! An OpenSearch k-NN backed [`VectorStore`](daimon_core::VectorStore) plugin
4//! for the [Daimon](https://docs.rs/daimon) AI agent framework.
5//!
6//! This crate provides [`OpenSearchVectorStore`], which stores document
7//! embeddings in [OpenSearch](https://opensearch.org/) using its native
8//! [k-NN plugin](https://opensearch.org/docs/latest/search-plugins/knn/index/).
9//! It supports cosine similarity, L2 (euclidean), and inner product distance
10//! metrics with HNSW indexing via nmslib, faiss, or lucene engines.
11//!
12//! ## Quick Start
13//!
14//! ```ignore
15//! use daimon_plugin_opensearch::{OpenSearchVectorStoreBuilder, SpaceType, Engine};
16//! use daimon::retriever::SimpleKnowledgeBase;
17//! use std::sync::Arc;
18//!
19//! let store = OpenSearchVectorStoreBuilder::new("http://localhost:9200", 1536)
20//! .index("my_docs")
21//! .space_type(SpaceType::CosineSimilarity)
22//! .engine(Engine::Lucene)
23//! .build()
24//! .await?;
25//!
26//! // Compose with an embedding model for a full RAG pipeline:
27//! let kb = SimpleKnowledgeBase::new(embedding_model, store);
28//! ```
29//!
30//! ## Manual Index Setup
31//!
32//! If you prefer to manage index creation yourself, disable auto-creation
33//! and use the JSON from [`index_settings`]:
34//!
35//! ```ignore
36//! let store = OpenSearchVectorStoreBuilder::new(url, 1536)
37//! .auto_create_index(false)
38//! .build()
39//! .await?;
40//! ```
41//!
42//! ## AWS OpenSearch Service
43//!
44//! Enable the `aws-auth` feature for SigV4 authentication:
45//!
46//! ```toml
47//! daimon-plugin-opensearch = { version = "0.15", features = ["aws-auth"] }
48//! ```
49
50mod builder;
51pub mod index_settings;
52mod store;
53
54pub use builder::OpenSearchVectorStoreBuilder;
55pub use store::OpenSearchVectorStore;
56
57/// Distance metric / space type for k-NN vector search.
58#[derive(Debug, Clone, Copy, PartialEq, Eq)]
59pub enum SpaceType {
60 /// Cosine similarity. Best for normalized embeddings.
61 CosineSimilarity,
62 /// Euclidean (L2) distance. Best for absolute spatial similarity.
63 L2,
64 /// Inner product. Best for maximum inner product search (MIPS).
65 InnerProduct,
66}
67
68impl SpaceType {
69 /// Returns the OpenSearch space type string used in index mappings.
70 pub fn as_str(&self) -> &'static str {
71 match self {
72 Self::CosineSimilarity => "cosinesimil",
73 Self::L2 => "l2",
74 Self::InnerProduct => "innerproduct",
75 }
76 }
77}
78
79impl Default for SpaceType {
80 fn default() -> Self {
81 Self::CosineSimilarity
82 }
83}
84
85/// k-NN engine used for approximate nearest neighbor search.
86#[derive(Debug, Clone, Copy, PartialEq, Eq)]
87pub enum Engine {
88 /// Apache Lucene engine. Good default, supports all space types.
89 Lucene,
90 /// NMSLIB engine. High performance for cosine and L2.
91 Nmslib,
92 /// FAISS engine. Supports IVF and HNSW, GPU-accelerated options.
93 Faiss,
94}
95
96impl Engine {
97 /// Returns the OpenSearch engine string used in index mappings.
98 pub fn as_str(&self) -> &'static str {
99 match self {
100 Self::Lucene => "lucene",
101 Self::Nmslib => "nmslib",
102 Self::Faiss => "faiss",
103 }
104 }
105}
106
107impl Default for Engine {
108 fn default() -> Self {
109 Self::Lucene
110 }
111}
112
113#[cfg(test)]
114mod tests {
115 use super::*;
116
117 #[test]
118 fn test_space_type_as_str() {
119 assert_eq!(SpaceType::CosineSimilarity.as_str(), "cosinesimil");
120 assert_eq!(SpaceType::L2.as_str(), "l2");
121 assert_eq!(SpaceType::InnerProduct.as_str(), "innerproduct");
122 }
123
124 #[test]
125 fn test_space_type_default() {
126 assert_eq!(SpaceType::default(), SpaceType::CosineSimilarity);
127 }
128
129 #[test]
130 fn test_engine_as_str() {
131 assert_eq!(Engine::Lucene.as_str(), "lucene");
132 assert_eq!(Engine::Nmslib.as_str(), "nmslib");
133 assert_eq!(Engine::Faiss.as_str(), "faiss");
134 }
135
136 #[test]
137 fn test_engine_default() {
138 assert_eq!(Engine::default(), Engine::Lucene);
139 }
140}