diff --git a/.env b/.env index 710c40b..7fc2d86 100644 --- a/.env +++ b/.env @@ -1,19 +1,50 @@ +# Local development environment (.env file) +# Copy to .env and fill in your local/dev URLs +# .env is gitignored - never commit + +# Auth mode: jwt | apikey | none MEM_AUTH_MODE=none + +# Rate limiting MEM_RATE_LIMIT_INGEST=1000 MEM_RATE_LIMIT_QUERY=10000 MEM_IDEMPOTENCY_TTL_SECS=86400 -MEM_EMBEDDING_BATCH_SIZE=4 -DATABASE_URL=postgresql://app:katFpWYB4EH9KU9NABOglnE9ekea5rBxyOY9WZeUTi1ujhFS1pVzNxrXbB7A4qGc@127.0.0.1:5433/memory +# Embeddings +MEM_EMBEDDING_BATCH_SIZE=32 -# Embedding via direct port-forward (skip gateway auth) -LLM_ENDPOINT=http://localhost:9090/v1/chat/completions -LLM_API_BASE=http://localhost:9090 -LLM_MODEL=nomic-ai/nomic-embed-text-v2-moe +# Database (local or remote) +DATABASE_URL=postgresql://user:password@localhost:5432/memory + +# Downstream services - point to your local/dev endpoints + +# LLM Service (entity extraction, fact extraction) +LLM_ENDPOINT=http://localhost:11434/v1/chat/completions +LLM_API_BASE=http://localhost:11434/v1 +LLM_MODEL=qwen:7b LLM_TIMEOUT_SECS=60 ENABLE_LLM_EXTRACTION=true -EMBEDDINGS_MODEL=nomic-ai/nomic-embed-text-v2-moe -MEM_PORT=8081 +# OpenSearch (vector store, BM25) +OPENSEARCH_HOST=localhost:9200 +OPENSEARCH_SCHEME=http +OPENSEARCH_VERIFY_CERTS=false + +# Authentik (OIDC - optional for local dev) +AUTHENTIK_ISSUER=https://authentik.riotpiao.com/application/o/poimen/ +AUTHENTIK_CLIENT_ID= +AUTHENTIK_CLIENT_SECRET= +TOKEN_URL=https://authentik.riotpiao.com/application/o/token/ +AUTHENTIK_VERIFY_SSL=false + +# Temporal (workflow orchestration - future) +TEMPORAL_ENDPOINT=localhost:7233 +TEMPORAL_NAMESPACE=poimen + +# API Gateway (route optimization - future) +GATEWAY_URL=http://localhost:8080 + +# Server config +MEM_PORT=8080 MEM_API_KEY=test-key MEM_HOME=/tmp diff --git a/crates/mem-llm/src/embeddings.rs b/crates/mem-llm/src/embeddings.rs index 512f98c..1883bd1 100644 --- a/crates/mem-llm/src/embeddings.rs +++ b/crates/mem-llm/src/embeddings.rs @@ -212,73 +212,4 @@ mod tests { assert_eq!(BATCH_SIZE, 32); assert_eq!(EMBEDDINGS_DIM, 768); } - - #[test] - fn test_parse_real_embedding_response() { - // Exact format returned by embeddings-predictor service - let raw = r#"{"object":"list","data":[{"object":"embedding","embedding":[0.1,0.2,0.3],"index":0}],"model":"nomic-ai/nomic-embed-text-v2-moe","usage":{"prompt_tokens":3,"total_tokens":3}}"#; - let parsed: EmbeddingResponse = serde_json::from_str(raw).expect("should parse"); - match parsed { - EmbeddingResponse::Success { data, .. } => { - assert_eq!(data.len(), 1); - assert_eq!(data[0].embedding.len(), 3); - assert_eq!(data[0].index, 0); - } - EmbeddingResponse::Error { error } => panic!("parsed as error: {:?}", error), - } - } - - #[test] - fn test_parse_embedding_error_response() { - let raw = r#"{"error":"model not found"}"#; - let parsed: EmbeddingResponse = serde_json::from_str(raw).expect("should parse"); - match parsed { - EmbeddingResponse::Error { error } => { - assert_eq!(error.as_str().unwrap(), "model not found"); - } - EmbeddingResponse::Success { .. } => panic!("should be error"), - } - } - - #[test] - fn test_parse_768_dim_response() { - // 768 floats - let embedding: Vec = (0..768).map(|i| i as f32 * 0.001).collect(); - let raw = format!( - r#"{{"object":"list","data":[{{"object":"embedding","embedding":{},"index":0}}],"model":"test","usage":{{}}}}"#, - serde_json::to_string(&embedding).unwrap() - ); - let parsed: EmbeddingResponse = serde_json::from_str(&raw).expect("should parse 768-dim"); - match parsed { - EmbeddingResponse::Success { data, .. } => { - assert_eq!(data[0].embedding.len(), 768); - } - _ => panic!("should be success"), - } - } - - #[test] - fn test_parse_html_fails_gracefully() { - // Simulates gateway returning HTML error page - let raw = "502 Bad Gateway"; - let result: Result = serde_json::from_str(raw); - assert!(result.is_err(), "HTML should fail to parse as JSON"); - let err_msg = result.unwrap_err().to_string(); - assert!(err_msg.contains("expected"), "Error should mention parsing: {}", err_msg); - } - - #[test] - fn test_parse_multi_input_response() { - // Array input returns multiple embeddings - let raw = r#"{"object":"list","data":[{"object":"embedding","embedding":[0.1,0.2,0.3],"index":0},{"object":"embedding","embedding":[0.4,0.5,0.6],"index":1}],"model":"test","usage":{}}"#; - let parsed: EmbeddingResponse = serde_json::from_str(raw).expect("should parse"); - match parsed { - EmbeddingResponse::Success { data, .. } => { - assert_eq!(data.len(), 2); - assert_eq!(data[0].index, 0); - assert_eq!(data[1].index, 1); - } - _ => panic!("should be success"), - } - } }