diff --git a/servers/unraid/supermemory-poc/.env.example b/servers/unraid/supermemory-poc/.env.example index f8b820b..460a4a8 100644 --- a/servers/unraid/supermemory-poc/.env.example +++ b/servers/unraid/supermemory-poc/.env.example @@ -1,8 +1,6 @@ # Set only in the unRaid Arcane Project environment. Never commit the real file. SUPERMEMORY_IPV4_ADDRESS= -# Extraction/summarization LLM. OPENAI_BASE_URL may point to an approved -# OpenAI-compatible endpoint; keep it blank for the OpenAI API. -OPENAI_API_KEY= -OPENAI_BASE_URL= -OPENAI_MODEL=gpt-5.1 +# Native Gemini powers extraction/summarization and remote embeddings. +# Keep the real key only in this Project's Arcane environment. +GEMINI_API_KEY= diff --git a/servers/unraid/supermemory-poc/README.md b/servers/unraid/supermemory-poc/README.md index a9245f1..95ebff5 100644 --- a/servers/unraid/supermemory-poc/README.md +++ b/servers/unraid/supermemory-poc/README.md @@ -10,10 +10,10 @@ production Hindsight service or change the default Hermes profile. cache live under `/mnt/user/appdata/supermemory-poc/data`. - A dedicated address on Docker `br0`; port `6767` is not published on the unRaid host address. -- Remote OpenAI-compatible embeddings through HK LiteLLM using - `google/gemini-embedding-2` at 1024 dimensions. -- Extraction, summarization, and other intelligent steps use - `gemini-3.5-flash-lite` through the same LiteLLM endpoint. +- Native Gemini embeddings using `gemini-embedding-2` at 768 dimensions. +- Extraction, summarization, and other intelligent steps use Supermemory's + native Gemini provider default. This cleanly removes the LiteLLM and + OpenAI-compatible translation layer from the diagnostic path. - Ingest concurrency remains 1 so the first POC emphasizes correctness and observable cost over throughput. - Resource ceiling: 4 CPUs and 8 GiB RAM. Supermemory Local keeps its corpus @@ -26,11 +26,10 @@ directory and re-ingest when comparing a different embedding plan. 1. Confirm the chosen `SUPERMEMORY_IPV4_ADDRESS` is absent from both Arcane's `br0` attachments and the LAN neighbor/DHCP tables. -2. Add `SUPERMEMORY_IPV4_ADDRESS`, `OPENAI_API_KEY`, - `OPENAI_BASE_URL=https://api.opfo.xyz/v1`, and - `OPENAI_MODEL=gemini-3.5-flash-lite` to this Project's Arcane environment. - `OPENAI_API_KEY` is the HK LiteLLM bearer key. Do not put it in Git, - Compose, activity notes, or chat. +2. Add `SUPERMEMORY_IPV4_ADDRESS` and `GEMINI_API_KEY` to this Project's + Arcane environment. Do not put the key in Git, Compose, activity notes, or + chat. Legacy `OPENAI_*` values may remain stored in Arcane for rollback, + but this Compose file does not inject them into the container. 3. Confirm `/mnt/user/appdata` has room for the 298 MiB server binary, the multilingual model cache, data, and rollback copy. 4. Confirm no other build, image pull, backup, or migration is active on the @@ -49,7 +48,7 @@ image build is required. The server creates its client bearer token at: -`/mnt/user/appdata/supermemory-poc/data-google-gemini-embedding-2-1024/api-key` +`/mnt/user/appdata/supermemory-poc/data-gemini-embedding-2-768/api-key` Read it through an authorized unRaid/Arcane console without printing it into logs. Save it only as `SUPERMEMORY_API_KEY` in the `supermemory-lab` Hermes @@ -83,24 +82,23 @@ used by Hermes. ### Embedding plan and smoke gate -The earlier local `Xenova/bge-m3` experiment is preserved under the old `data` -directory because embedding plans cannot be changed in place. This deployment -uses the fresh `data-google-gemini-embedding-2-1024` directory. The one-shot -`supermemory-smoke` service verifies the locked embedding plan, performs a -Chinese hybrid-search round trip, checks provenance metadata, and exercises -the profile and conversation endpoints. It writes a sentinel after success so -ordinary redeploys do not add duplicate smoke documents. Do not import sampled +The earlier local `Xenova/bge-m3` and LiteLLM-backed embedding experiments are +preserved under their old data directories because embedding plans cannot be +changed in place. This deployment uses the fresh +`data-gemini-embedding-2-768` directory. The one-shot `supermemory-smoke` +service verifies the locked embedding plan, tracks the exact document ID to a +terminal state, separately checks v3 search, v4 document search, and Chinese +hybrid search, checks provenance metadata, and exercises the profile and +conversation endpoints. It writes a sentinel after success so ordinary +redeploys do not add duplicate smoke documents. Do not import sampled Hindsight or document material until this service exits successfully. -On 2026-09-08, the remote plan was accepted and locked as -`openai / google/gemini-embedding-2 / 1024`; the LiteLLM embedding and -`gemini-3.5-flash-lite` chat endpoints also passed independently. Supermemory -listed the smoke document and reported a completed document in the test -container, but exact searches for its unique marker returned no hit through -either `/v4/search` or `/v3/search` (`supermemory-smoke` exit 44). Treat this -as a self-hosted indexing/retrieval blocker. Do not import sampled material or -enable the Hermes lab profile until a newer server build or upstream fix makes -the same smoke pass. +On 2026-09-08, the previous remote plan was accepted and locked as +`openai / google/gemini-embedding-2 / 1024`; the LiteLLM embedding and chat +endpoints also passed independently. Supermemory listed a completed smoke +document, but both v4 and v3 searches returned no hit. The old smoke mixed +list-wide status checks and did not track the newly created document, so this +native Gemini run uses a new store and a stricter document-specific gate. ## Evaluation guardrails diff --git a/servers/unraid/supermemory-poc/compose.yaml b/servers/unraid/supermemory-poc/compose.yaml index 6143b22..e0613a7 100644 --- a/servers/unraid/supermemory-poc/compose.yaml +++ b/servers/unraid/supermemory-poc/compose.yaml @@ -53,20 +53,15 @@ services: PORT: "6767" SUPERMEMORY_DATA_DIR: /var/lib/supermemory SUPERMEMORY_DISABLE_TELEMETRY: "1" - SUPERMEMORY_EMBEDDING_PROVIDER: openai - SUPERMEMORY_EMBEDDING_MODEL: google/gemini-embedding-2 - SUPERMEMORY_EMBEDDING_DIMENSIONS: "1024" - SUPERMEMORY_EMBEDDING_BASE_URL: ${OPENAI_BASE_URL:?set OPENAI_BASE_URL in Arcane environment} + SUPERMEMORY_EMBEDDING_PROVIDER: gemini + SUPERMEMORY_EMBEDDING_MODEL: gemini-embedding-2 + SUPERMEMORY_EMBEDDING_DIMENSIONS: "768" SUPERMEMORY_EMBEDDING_RAM_LIMIT: 2gb SUPERMEMORY_INGEST_CONCURRENCY: "1" SSL_CERT_FILE: /opt/supermemory/bin/ca-certificates.crt SSL_CERT_DIR: /etc/ssl/certs NODE_EXTRA_CA_CERTS: /opt/supermemory/bin/ca-certificates.crt - OPENAI_API_KEY: ${OPENAI_API_KEY:?set OPENAI_API_KEY in Arcane environment} - OPENAI_BASE_URL: ${OPENAI_BASE_URL:?set OPENAI_BASE_URL in Arcane environment} - OPENAI_MODEL: ${OPENAI_MODEL:-gemini-3.5-flash-lite} - OPENAI_FAST_MODEL: ${OPENAI_MODEL:-gemini-3.5-flash-lite} - OPENAI_TEXT_MODEL: ${OPENAI_MODEL:-gemini-3.5-flash-lite} + GEMINI_API_KEY: ${GEMINI_API_KEY:?set GEMINI_API_KEY in Arcane environment} entrypoint: - /bin/bash - -ec @@ -86,7 +81,7 @@ services: volumes: - /mnt/user/appdata/supermemory-poc/bin:/opt/supermemory/bin:ro - /mnt/user/appdata/supermemory-poc/bin/ca-certificates.crt:/etc/ssl/certs/ca-certificates.crt:ro - - /mnt/user/appdata/supermemory-poc/data-google-gemini-embedding-2-1024:/var/lib/supermemory + - /mnt/user/appdata/supermemory-poc/data-gemini-embedding-2-768:/var/lib/supermemory networks: br0: ipv4_address: ${SUPERMEMORY_IPV4_ADDRESS:?set an unused LAN address in Arcane environment} @@ -117,7 +112,7 @@ services: - /opt/supermemory-poc/smoke.sh volumes: - ./smoke.sh:/opt/supermemory-poc/smoke.sh:ro - - /mnt/user/appdata/supermemory-poc/data-google-gemini-embedding-2-1024:/var/lib/supermemory + - /mnt/user/appdata/supermemory-poc/data-gemini-embedding-2-768:/var/lib/supermemory security_opt: - no-new-privileges:true cap_drop: diff --git a/servers/unraid/supermemory-poc/smoke.sh b/servers/unraid/supermemory-poc/smoke.sh index 53240c7..d25907d 100644 --- a/servers/unraid/supermemory-poc/smoke.sh +++ b/servers/unraid/supermemory-poc/smoke.sh @@ -2,7 +2,7 @@ set -eu data_dir=/var/lib/supermemory -sentinel="$data_dir/.smoke-google-gemini-embedding-2-1024.ok" +sentinel="$data_dir/.smoke-gemini-embedding-2-768.ok" base_url="${SUPERMEMORY_URL:-http://127.0.0.1:6767}" container_tag="${SUPERMEMORY_CONTAINER_TAG:-hermes_supermemory_lab}" @@ -13,7 +13,7 @@ fi api_key=$(cat "$data_dir/api-key") auth_header="Authorization: Bearer $api_key" -marker="supermemory-poc-google-embedding-2-$(date +%s)" +marker="supermemory-poc-gemini-native-$(date +%s)" fail() { code="$1" @@ -27,78 +27,68 @@ for _ in $(seq 1 30); do [ -f "$plan" ] && break sleep 1 done -grep -q 'openai' "$plan" || fail 11 embedding-plan-provider -grep -q 'google/gemini-embedding-2' "$plan" || fail 12 embedding-plan-model -grep -q '1024' "$plan" || fail 13 embedding-plan-dimensions +grep -q 'gemini' "$plan" || fail 11 embedding-plan-provider +grep -q 'gemini-embedding-2' "$plan" || fail 12 embedding-plan-model +grep -q '768' "$plan" || fail 13 embedding-plan-dimensions if ! curl --fail --silent --show-error --max-time 60 \ -H "$auth_header" \ -H 'Content-Type: application/json' \ - --data "{\"containerTags\":[\"$container_tag\"],\"limit\":20}" \ - "$base_url/v3/documents/list" >/tmp/documents.json; then - fail 21 documents-list + --data "{\"content\":\"$marker:中文跨文档检索测试;海棠计划的下一步是核对原始报告。\",\"containerTag\":\"$container_tag\",\"customId\":\"$marker\",\"metadata\":{\"source\":\"poc-smoke\",\"status\":\"temporary\"}}" \ + "$base_url/v3/documents" >/tmp/add.json; then + fail 22 document-add fi -if grep -q 'supermemory-poc-google-embedding-2' /tmp/documents.json; then - if grep -Eq '"status"[[:space:]]*:[[:space:]]*"failed"' /tmp/documents.json; then - fail 31 document-processing-failed - fi - if ! grep -Eq '"status"[[:space:]]*:[[:space:]]*"done"' /tmp/documents.json; then - if grep -Eq '"status"[[:space:]]*:[[:space:]]*"embedding"' /tmp/documents.json; then - fail 32 document-stuck-embedding - fi - if grep -Eq '"status"[[:space:]]*:[[:space:]]*"chunking"' /tmp/documents.json; then - fail 33 document-stuck-chunking - fi - if grep -Eq '"status"[[:space:]]*:[[:space:]]*"indexing"' /tmp/documents.json; then - fail 34 document-stuck-indexing - fi - fail 35 document-not-done - fi -else +document_id=$(sed -n 's/.*"id"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' /tmp/add.json | head -n 1) +[ -n "$document_id" ] || fail 23 document-id-missing + +document_status= +for _ in $(seq 1 120); do if ! curl --fail --silent --show-error --max-time 60 \ -H "$auth_header" \ - -H 'Content-Type: application/json' \ - --data "{\"content\":\"$marker:中文跨文档检索测试;海棠计划的下一步是核对原始报告。\",\"containerTag\":\"$container_tag\",\"customId\":\"$marker\",\"metadata\":{\"source\":\"poc-smoke\",\"status\":\"temporary\"}}" \ - "$base_url/v3/documents" >/tmp/add.json; then - fail 22 document-add + "$base_url/v3/documents/$document_id" >/tmp/document.json; then + fail 24 document-get fi -fi + if grep -Eq '"status"[[:space:]]*:[[:space:]]*"failed"' /tmp/document.json; then + fail 31 document-processing-failed + fi + if grep -Eq '"status"[[:space:]]*:[[:space:]]*"done"' /tmp/document.json; then + document_status=done + break + fi + sleep 2 +done +[ "$document_status" = done ] || fail 35 document-not-done -existing_marker=$(grep -o 'supermemory-poc-google-embedding-2-[0-9]*' /tmp/documents.json | head -n 1) -[ -n "$existing_marker" ] || fail 36 document-marker-missing +if ! curl --fail --silent --show-error --max-time 15 \ + -H "$auth_header" \ + -H 'Content-Type: application/json' \ + --data "{\"q\":\"$marker\",\"containerTag\":\"$container_tag\"}" \ + "$base_url/v3/search" >/tmp/search-v3.json; then + fail 41 search-v3-request +fi +grep -q "$marker" /tmp/search-v3.json || fail 44 search-v3-no-hit curl --fail --silent --show-error --max-time 15 \ -H "$auth_header" \ -H 'Content-Type: application/json' \ - --data "{\"q\":\"$existing_marker\",\"containerTag\":\"$container_tag\",\"searchMode\":\"hybrid\",\"limit\":5}" \ - "$base_url/v4/search" >/tmp/search-exact.json || fail 41 search-exact-request -if ! grep -q "$existing_marker" /tmp/search-exact.json; then - curl --fail --silent --show-error --max-time 15 \ - -H "$auth_header" \ - -H 'Content-Type: application/json' \ - --data "{\"q\":\"$existing_marker\",\"containerTag\":\"$container_tag\"}" \ - "$base_url/v3/search" >/tmp/search-exact-v3.json || fail 43 search-exact-v3-request - if grep -q "$existing_marker" /tmp/search-exact-v3.json; then - grep -q 'poc-smoke' /tmp/search-exact-v3.json || fail 49 search-v3-metadata-missing - fail 48 search-v3-only - fi - fail 44 search-exact-no-hit -fi -grep -q 'poc-smoke' /tmp/search-exact.json || fail 45 search-exact-metadata-missing + --data "{\"q\":\"$marker\",\"containerTag\":\"$container_tag\",\"searchMode\":\"documents\",\"limit\":5}" \ + "$base_url/v4/search" >/tmp/search-documents.json || fail 42 search-documents-request +grep -q "$marker" /tmp/search-documents.json || fail 45 search-documents-no-hit +grep -q 'poc-smoke' /tmp/search-documents.json || fail 46 search-documents-metadata-missing curl --fail --silent --show-error --max-time 15 \ -H "$auth_header" \ -H 'Content-Type: application/json' \ --data "{\"q\":\"海棠计划下一步是什么?\",\"containerTag\":\"$container_tag\",\"searchMode\":\"hybrid\",\"limit\":5}" \ - "$base_url/v4/search" >/tmp/search-semantic.json || fail 42 search-semantic-request -grep -q '核对原始报告' /tmp/search-semantic.json || fail 46 search-semantic-no-hit -grep -q 'poc-smoke' /tmp/search-semantic.json || fail 47 search-semantic-metadata-missing + "$base_url/v4/search" >/tmp/search-hybrid.json || fail 47 search-hybrid-request +grep -q '核对原始报告' /tmp/search-hybrid.json || fail 48 search-hybrid-no-hit +grep -q 'poc-smoke' /tmp/search-hybrid.json || fail 49 search-hybrid-metadata-missing curl --fail --silent --show-error --max-time 60 \ -H "$auth_header" \ -H 'Content-Type: application/json' \ - --data "{\"containerTag\":\"$container_tag\",\"q\":\"海棠计划\"}" \ + --data "{\"containerTag\":\"$container_tag\",\"q\":\"$marker\"}" \ "$base_url/v4/profile" >/tmp/profile.json || fail 51 profile-request grep -q '"profile"' /tmp/profile.json || fail 52 profile-shape @@ -109,4 +99,4 @@ curl --fail --silent --show-error --max-time 60 \ "$base_url/v4/conversations" >/tmp/conversation.json || fail 61 conversation-ingest touch "$sentinel" -printf '%s\n' '{"embedding_plan":"openai/google/gemini-embedding-2/1024","llm":"gemini-3.5-flash-lite","chinese_hybrid_search":"ok","metadata_traceability":"ok","profile":"ok","conversation_ingest":"accepted"}' +printf '%s\n' '{"embedding_plan":"gemini/gemini-embedding-2/768","llm":"gemini-native-default","v3_search":"ok","v4_documents_search":"ok","chinese_hybrid_search":"ok","metadata_traceability":"ok","profile":"ok","conversation_ingest":"accepted"}'