use super::{
document::GqlDocument,
edge::GqlEdge,
node::GqlNode,
vectorised_graph::{IntoWindowTuple, VectorisedGraphWindow},
};
use crate::rayon::blocking_compute;
use dynamic_graphql::{InputObject, ResolvedObject, ResolvedObjectFields};
use raphtory::{
db::api::view::MaterializedGraph,
errors::GraphResult,
vectors::{vector_selection::VectorSelection, Embedding},
};
#[derive(InputObject)]
pub(super) struct InputEdge {
src: String,
dst: String,
}
#[derive(ResolvedObject)]
#[graphql(name = "VectorSelection")]
pub(crate) struct GqlVectorSelection(VectorSelection<MaterializedGraph>);
impl From<VectorSelection<MaterializedGraph>> for GqlVectorSelection {
fn from(value: VectorSelection<MaterializedGraph>) -> Self {
Self(value)
}
}
#[ResolvedObjectFields]
impl GqlVectorSelection {
async fn nodes(&self) -> Vec<GqlNode> {
self.0.nodes().into_iter().map(|e| e.into()).collect()
}
async fn edges(&self) -> Vec<GqlEdge> {
self.0.edges().into_iter().map(|e| e.into()).collect()
}
async fn get_documents(&self) -> GraphResult<Vec<GqlDocument>> {
let cloned = self.0.clone();
let docs = cloned.get_documents_with_distances().await?.into_iter();
Ok(docs
.map(|(doc, score)| GqlDocument {
content: doc.content,
entity: doc.entity.into(),
embedding: doc.embedding.to_vec(),
score,
})
.collect())
}
async fn add_nodes(&self, nodes: Vec<String>) -> Self {
let mut selection = self.cloned();
selection.add_nodes(nodes);
selection.into()
}
async fn add_edges(&self, edges: Vec<InputEdge>) -> Self {
let mut selection = self.cloned();
let edges = edges.into_iter().map(|edge| (edge.src, edge.dst)).collect();
selection.add_edges(edges);
selection.into()
}
async fn expand(&self, hops: usize, window: Option<VectorisedGraphWindow>) -> Self {
let window = window.into_window_tuple();
let mut selection = self.cloned();
blocking_compute(move || {
selection.expand(hops, window);
selection.into()
})
.await
}
async fn expand_entities_by_similarity(
&self,
query: String,
limit: usize,
window: Option<VectorisedGraphWindow>,
) -> GraphResult<Self> {
let vector = self.embed_text(query).await?;
let window = window.into_window_tuple();
let mut selection = self.cloned();
selection
.expand_entities_by_similarity(&vector, limit, window, blocking_compute)
.await?;
Ok(selection.into())
}
async fn expand_nodes_by_similarity(
&self,
query: String,
limit: usize,
window: Option<VectorisedGraphWindow>,
) -> GraphResult<Self> {
let vector = self.embed_text(query).await?;
let window = window.into_window_tuple();
let mut selection = self.cloned();
selection
.expand_nodes_by_similarity(&vector, limit, window, blocking_compute)
.await?;
Ok(selection.into())
}
async fn expand_edges_by_similarity(
&self,
query: String,
limit: usize,
window: Option<VectorisedGraphWindow>,
) -> GraphResult<Self> {
let vector = self.embed_text(query).await?;
let window = window.into_window_tuple();
let mut selection = self.cloned();
selection
.expand_edges_by_similarity(&vector, limit, window, blocking_compute)
.await?;
Ok(selection.into())
}
}
impl GqlVectorSelection {
fn cloned(&self) -> VectorSelection<MaterializedGraph> {
self.0.clone()
}
async fn embed_text(&self, text: String) -> GraphResult<Embedding> {
self.0.get_vectorised_graph().embed_text(text).await
}
}