#!/usr/bin/env bash # bench-memory-retrieval.sh — benchmark memory retrieval quality and latency. # # Tests the core's memory query (semantic search) and tree file-based content # retrieval against a set of benchmark queries. Measures wall-clock time per # query, result count, and content quality. # # Usage: # ./scripts/bench-memory-retrieval.sh # ./scripts/bench-memory-retrieval.sh --verbose set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" VERBOSE=0 [[ "${1:-}" == "--verbose" ]] && VERBOSE=1 CORE_BIN="$REPO_ROOT/target/debug/openhuman-core" if [[ ! -x "$CORE_BIN" ]]; then echo "ERROR: Build openhuman-core first: cargo build --bin openhuman-core" exit 1 fi WORKSPACE_DIR="${OPENHUMAN_WORKSPACE:-$HOME/.openhuman-staging}" USERS_DIR="$WORKSPACE_DIR/users" if [[ ! -d "$USERS_DIR" ]]; then echo "ERROR: Workspace users dir not found: $USERS_DIR" exit 1 fi # Find first user workspace with memory_tree content CONTENT_ROOT=$(find "$USERS_DIR" -path "*/workspace/memory_tree/content" -type d 2>/dev/null | head -1 || true) if [[ -z "$CONTENT_ROOT" ]]; then echo "ERROR: No memory_tree content found under $USERS_DIR/" exit 1 fi RESULTS_DIR="$REPO_ROOT/target/bench-memory" mkdir -p "$RESULTS_DIR" TIMESTAMP=$(date +%Y%m%d-%H%M%S) RESULTS_FILE="$RESULTS_DIR/retrieval-$TIMESTAMP.txt" # Inventory FILE_COUNT=$(find "$CONTENT_ROOT" -type f -name "*.md" 2>/dev/null | wc -l | tr -d ' ') TOTAL_SIZE=$(du -sh "$CONTENT_ROOT" 2>/dev/null | cut -f1) CHAT_COUNT=$(find "$CONTENT_ROOT/chat" -type f -name "*.md" 2>/dev/null | wc -l | tr -d ' ') EPISODIC_COUNT=$(find "$CONTENT_ROOT/episodic" -type f -name "*.md" 2>/dev/null | wc -l | tr -d ' ') RAW_COUNT=$(find "$CONTENT_ROOT/raw" -type f -name "*.md" 2>/dev/null | wc -l | tr -d ' ') WIKI_COUNT=$(find "$CONTENT_ROOT/wiki" -type f -name "*.md" 2>/dev/null | wc -l | tr -d ' ') cat <&1) || true END_NS=$(python3 -c "import time; print(int(time.time()*1e9))") ELAPSED_MS=$(python3 -c "print(($END_NS - $START_NS) / 1_000_000)") RESULT_COUNT=$(echo "$OUTPUT" | grep -c '^\[' || true) FIRST_RESULT=$(echo "$OUTPUT" | grep '^\[' | head -1 | cut -c1-120) echo " -> ${ELAPSED_MS}ms, $RESULT_COUNT results" | tee -a "$RESULTS_FILE" if [[ -n "$FIRST_RESULT" ]]; then echo " -> Top: $FIRST_RESULT..." | tee -a "$RESULTS_FILE" fi if [[ $VERBOSE -eq 1 ]]; then echo "$OUTPUT" | head -20 fi done cat </dev/null | wc -l | tr -d ' ') SAMPLE=$(grep -rl "$pattern" "$CONTENT_ROOT" 2>/dev/null | head -3 | while read f; do basename "$f" | tr '\n' ' ' done) END_NS=$(python3 -c "import time; print(int(time.time()*1e9))") ELAPSED_MS=$(python3 -c "print(($END_NS - $START_NS) / 1_000_000)") echo " -> ${ELAPSED_MS}ms, $HIT_COUNT files matched" | tee -a "$RESULTS_FILE" if [[ -n "$SAMPLE" ]]; then echo " -> Sample: $SAMPLE" | tee -a "$RESULTS_FILE" fi done cat <&1) || true END_NS=$(python3 -c "import time; print(int(time.time()*1e9))") ELAPSED_MS=$(python3 -c "print(($END_NS - $START_NS) / 1_000_000)") # Extract hit count from JSON HITS=$(echo "$OUTPUT" | python3 -c " import sys,json raw = sys.stdin.read() last_line = [l for l in raw.split('\n') if '{' in l] d = json.loads(last_line[-1]) if last_line else {} print(d.get('result',{}).get('total',0)) " 2>/dev/null || echo "parse-error") echo " -> ${ELAPSED_MS}ms, hits=$HITS" | tee -a "$RESULTS_FILE" if [[ $VERBOSE -eq 1 ]]; then echo "$OUTPUT" | tail -5 fi done cat <