feat: Memory Phase 3 — LLM ingest, observability, migrations #49

Open
rock wants to merge 18 commits from feat/memory-ingest-retrieval into main
Showing only changes of commit 1506a93ebb - Show all commits
+17 -3
View File
@@ -1342,16 +1342,30 @@ async fn query_temporal_graph(
state: &web::Data<AppState>, state: &web::Data<AppState>,
params: &QueryParams, params: &QueryParams,
) -> anyhow::Result<serde_json::Value> { ) -> anyhow::Result<serde_json::Value> {
// Step 1: Find entities (order by name for deterministic results) // Step 1: Find entities matching question (fuzzy name/description search)
let entities_rows: Vec<(String, String, String)> = sqlx::query_as( let entities_rows: Vec<(String, String, String)> = sqlx::query_as(
"SELECT id, name, entity_type FROM memory_entity WHERE project_id = $1 LIMIT $2" "SELECT id, name, entity_type FROM memory_entity
WHERE project_id = $1
AND (name ILIKE '%' || $2 || '%' OR description ILIKE '%' || $2 || '%')
ORDER BY confidence DESC
LIMIT $3"
) )
.bind(&params.project) .bind(&params.project)
.bind(&params.question)
.bind(params.limit as i32) .bind(params.limit as i32)
.fetch_all(&state.pool) .fetch_all(&state.pool)
.await .await
.unwrap_or_default(); .unwrap_or_default();
tracing::info!(
target: "observability",
event = "query_entity_search",
project = %params.project,
question = %params.question,
matched = entities_rows.len(),
"Entity search complete"
);
// Step 2: Traverse edges from found entities // Step 2: Traverse edges from found entities
// NOTE: Edges will be empty until temporal schema is migrated // NOTE: Edges will be empty until temporal schema is migrated
let mut edges_data: Vec<(String, String, String, String, String, f32)> = Vec::new(); let mut edges_data: Vec<(String, String, String, String, String, f32)> = Vec::new();
@@ -1360,7 +1374,7 @@ async fn query_temporal_graph(
for (entity_id, _name, _type_str) in &entities_rows { for (entity_id, _name, _type_str) in &entities_rows {
let entity_edges: Vec<(String, String, String, String, f32, Option<chrono::DateTime<chrono::Utc>>, Option<chrono::DateTime<chrono::Utc>>)> = let entity_edges: Vec<(String, String, String, String, f32, Option<chrono::DateTime<chrono::Utc>>, Option<chrono::DateTime<chrono::Utc>>)> =
sqlx::query_as( sqlx::query_as(
"SELECT id, target_entity_id, relation_type, fact, confidence, t_valid, t_invalid FROM memory_edge WHERE project_id = $1 AND source_entity_id = $2" "SELECT id, target_id, relation_type, fact, confidence, t_valid, t_invalid FROM memory_edge WHERE project_id = $1 AND source_id = $2"
) )
.bind(&params.project) .bind(&params.project)
.bind(entity_id) .bind(entity_id)