Skip to content

feat: Add Valkey Integration#1668

Closed
edlng wants to merge 1 commit into
MervinPraison:mainfrom
edlng:add-valkey
Closed

feat: Add Valkey Integration#1668
edlng wants to merge 1 commit into
MervinPraison:mainfrom
edlng:add-valkey

Conversation

@edlng

@edlng edlng commented May 14, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds Valkey as a supported backend for state storage, vector knowledge, and session CRUD. Uses valkey-glide-sync throughout. Vector search goes through ValkeySearch FT with HNSW indexing.

Issue

N/A

Changes

  • src/praisonai-agents/praisonaiagents/config/feature_configs.py β€” added VALKEY to the MemoryBackend enum
  • src/praisonai-agents/praisonaiagents/storage/backends.py β€” registered ValkeyBackend and ValkeySearchBackend in the lazy-loader; added valkey branch in get_backend()
  • src/praisonai/praisonai/persistence/state/valkey.py (new) β€” ValkeyStateStore: get/set/delete/exists/keys/ttl/expire/hash ops
  • src/praisonai/praisonai/persistence/knowledge/valkey_vector.py (new) β€” ValkeyVectorKnowledgeStore: HNSW index via ValkeySearch FT, with pre-filter and score threshold support on search
  • src/praisonai/praisonai/storage/valkey_adapter.py (new) β€” ValkeyStorageAdapter for session CRUD; ValkeySearchBackend for basic vector index/search
  • src/praisonai/praisonai/storage/__init__.py β€” exports the new adapters; _make_valkey_backend_class() builds a ValkeyBackend subclass that pulls connection params from VALKEY_HOST/VALKEY_PORT/VALKEY_PASSWORD
  • src/praisonai/praisonai/persistence/registry.py β€” registers valkey in both KNOWLEDGE_STORES and STATE_STORES
  • src/praisonai/pyproject.toml β€” added valkey extras group (valkey-glide-sync>=2.3.1)
  • src/praisonai/praisonai/persistence/tests/test_valkey_backends.py (new) β€” unit tests for ValkeyVectorKnowledgeStore, ValkeyStateStore, and registry entries (all mocked)
  • src/praisonai/tests/unit/storage/test_valkey_backend.py (new) β€” unit tests for ValkeyStorageAdapter and ValkeySearchBackend (mocked)
  • src/praisonai-agents/tests/managed/test_managed_persistence_all_dbs.py β€” added TestValkeyStateStore for live server tests; auto-skips if nothing is running on localhost:6379
  • src/praisonai-agents/tests/unit/config/test_precedence_ladder.py β€” added test that resolve_memory("valkey") returns MemoryConfig with MemoryBackend.VALKEY

Tests

Unit tests mock glide_sync directly, so they pass in CI without a live server. The managed TestValkeyStateStore tests hit a real instance and skip when one isn't available.

Additional context

The glide_sync import is try/except guarded at module level, so nothing breaks if the package isn't installed. Install the extras with pip install 'praisonai[valkey]'.

Summary by CodeRabbit

Release Notes

  • New Features

    • Added Valkey as a supported storage backend option for persistence, state management, and vector search functionality.
  • Chores

    • Added optional valkey extra with valkey-glide-sync>=2.3.1 dependency for Valkey backend support.
  • Tests

    • Added comprehensive unit and integration tests for Valkey backend implementations.

Review Change Stack

Signed-off-by: Edward Liang <edward.liang@improving.com>
@edlng edlng closed this May 14, 2026
@qodo-code-review

Copy link
Copy Markdown

Qodo reviews are paused for this user.

Troubleshooting steps vary by plan Learn more β†’

On a Teams plan?
Reviews resume once this user has a paid seat and their Git account is linked in Qodo.
Link Git account β†’

Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center?
These require an Enterprise plan - Contact us
Contact us β†’

@coderabbitai

coderabbitai Bot commented May 14, 2026

Copy link
Copy Markdown
Contributor

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
βš™οΈ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b1768272-4bac-4269-afab-5ee512dc86e8

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 13d073b and 7144ff2.

πŸ“’ Files selected for processing (13)
  • src/praisonai-agents/praisonaiagents/config/feature_configs.py
  • src/praisonai-agents/praisonaiagents/storage/backends.py
  • src/praisonai-agents/tests/managed/test_managed_persistence_all_dbs.py
  • src/praisonai-agents/tests/unit/config/test_precedence_ladder.py
  • src/praisonai/praisonai/persistence/knowledge/valkey_vector.py
  • src/praisonai/praisonai/persistence/registry.py
  • src/praisonai/praisonai/persistence/state/valkey.py
  • src/praisonai/praisonai/persistence/tests/test_valkey_backends.py
  • src/praisonai/praisonai/storage/__init__.py
  • src/praisonai/praisonai/storage/valkey_adapter.py
  • src/praisonai/pyproject.toml
  • src/praisonai/tests/unit/storage/__init__.py
  • src/praisonai/tests/unit/storage/test_valkey_backend.py

πŸ“ Walkthrough

Walkthrough

This PR introduces comprehensive Valkey support as an optional backend across the PraisonAI persistence and storage layers, including memory configuration, state/knowledge stores, storage adapters, registry wiring, and full test coverage with optional dependency declaration.

Changes

Valkey persistence and storage support

Layer / File(s) Summary
Memory backend enum and factory support
src/praisonai-agents/praisonaiagents/config/feature_configs.py, src/praisonai-agents/praisonaiagents/storage/backends.py, src/praisonai-agents/tests/unit/config/test_precedence_ladder.py
Adds MemoryBackend.VALKEY enum value, wires get_backend("valkey") factory dispatch, and unit test verification of backend resolution.
Valkey state store with KV, hash, and counter operations
src/praisonai/praisonai/persistence/state/valkey.py
Implements ValkeyStateStore with lazy Glide client, key prefixing, JSON serialization, and CRUD/hash/counter APIs wrapping errors in RuntimeError.
Valkey vector knowledge store with FT indexing and search
src/praisonai/praisonai/persistence/knowledge/valkey_vector.py
Implements ValkeyVectorKnowledgeStore with ValkeySearch index lifecycle, document insertion via binary-packed embeddings, filtered/threshold KNN search, and batch retrieval.
Valkey storage adapter and search backend
src/praisonai/praisonai/storage/valkey_adapter.py
Implements ValkeyStorageAdapter for prefixed KV storage with JSON serialization and TTL, plus ValkeySearchBackend for vector indexing via FT commands.
Storage module lazy-loading and environment configuration
src/praisonai/praisonai/storage/__init__.py
Extends module to expose ValkeyStorageAdapter, ValkeySearchBackend, and dynamically-created ValkeyBackend class pre-configured from environment variables.
Persistence registry integration
src/praisonai/praisonai/persistence/registry.py
Registers ValkeyStateStore and ValkeyVectorKnowledgeStore factories in global STATE_STORES and KNOWLEDGE_STORES registries.
Unit tests for persistence stores
src/praisonai/praisonai/persistence/tests/test_valkey_backends.py
Tests state and knowledge stores with mocked Glide clients covering CRUD/search operations and registry inclusion.
Unit tests for storage adapter
src/praisonai/tests/unit/storage/test_valkey_backend.py
Tests adapter CRUD/TTL/error paths and search backend index/document/search with mocked clients.
Integration tests for managed state
src/praisonai-agents/tests/managed/test_managed_persistence_all_dbs.py
Verifies state store CRUD and managed-agent persistence/restore with live Valkey connectivity checks.
Optional dependency declaration
src/praisonai/pyproject.toml
Adds optional valkey extra declaring valkey-glide-sync>=2.3.1 dependency.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

This PR introduces two new backend implementations (state and knowledge stores) and storage wrappers across multiple modules with dense logic around FT indexing, vector packing, and serialization. The changes are cohesive, follow established patterns for lazy loading and error handling, and include comprehensive mocked unit tests and integration tests. Review effort is moderate due to the mix of new data structures, glide client API usage, and test coverage spread across persistence and storage layers.

Possibly related PRs

  • MervinPraison/PraisonAI#1252: Main PR extends the same wrapper/lazy-loading multi-backend storage routing by adding Valkey equivalents to the existing factory patterns.

Suggested reviewers

  • MervinPraison

Poem

🐰 A rabbit hops through Valkey's gleaming keys,
Storing state and vectors with such ease,
From knowledge graphs to persisted dreams,
Glide sync brings it all together in streams! πŸŽ‰

✨ Finishing Touches
πŸ§ͺ Generate unit tests (beta)
  • Create PR with unit tests

Tip

πŸ’¬ Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire orgβ€”no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-inβ€”scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

πŸ‘‰ Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❀️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@MervinPraison

Copy link
Copy Markdown
Owner

@copilot Do a thorough review of this PR. Read ALL existing reviewer comments above from Qodo, Coderabbit, and Gemini first β€” incorporate their findings.

Review areas:

  1. Bloat check: Are changes minimal and focused? Any unnecessary code or scope creep?
  2. Security: Any hardcoded secrets, unsafe eval/exec, missing input validation?
  3. Performance: Any module-level heavy imports? Hot-path regressions?
  4. Tests: Are tests included? Do they cover the changes adequately?
  5. Backward compat: Any public API changes without deprecation?
  6. Code quality: DRY violations, naming conventions, error handling?
  7. Address reviewer feedback: If Qodo, Coderabbit, or Gemini flagged valid issues, include them in your review
  8. Suggest specific improvements with code examples where possible

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces Valkey support across the PraisonAI ecosystem, including a new ValkeyVectorKnowledgeStore, ValkeyStateStore, and a ValkeyStorageAdapter. The changes include adding the valkey-glide-sync dependency, registering the new backends in the persistence registry, and providing comprehensive unit and integration tests. Feedback highlights a potential issue with document ID extraction when IDs contain colons, a consistency requirement to strip prefixes from search results, and a suggestion to maintain the lazy-loading pattern by removing a top-level import.

documents = []
for doc_id_raw, fields in raw[1].items():
doc_id_str = _decode(doc_id_raw)
bare_id = doc_id_str.split(":")[-1]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The current implementation of bare_id extraction using split(":")[-1] will fail if the doc_id itself contains colons (e.g., user:123). It is safer to strip the known prefix and collection name from the start of the string to ensure the full original ID is recovered.

Suggested change
bare_id = doc_id_str.split(":")[-1]
prefix_to_strip = f"{self.prefix}{collection}:"
bare_id = doc_id_str[len(prefix_to_strip):] if doc_id_str.startswith(prefix_to_strip) else doc_id_str

results = []
for doc_id, fields in raw[1].items():
doc: Dict[str, Any] = {}
doc["id"] = doc_id.decode('utf-8') if isinstance(doc_id, bytes) else doc_id

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The search method currently returns the full Valkey key (including the index name prefix) as the document ID. To maintain consistency with other backends and the add_document method, the prefix should be stripped from the returned ID.

            doc_id_str = doc_id.decode('utf-8') if isinstance(doc_id, bytes) else doc_id
            prefix_to_strip = f"{self.index_name}:"
            doc["id"] = doc_id_str[len(prefix_to_strip):] if doc_id_str.startswith(prefix_to_strip) else doc_id_str

These implementations are kept in the wrapper to avoid bloating the core SDK.
"""
import os
from .valkey_adapter import ValkeyStorageAdapter

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This top-level import of ValkeyStorageAdapter defeats the lazy-loading pattern established for other storage adapters in this module. Since ValkeyStorageAdapter is already handled in __getattr__, this import should be removed from the top level and moved inside _make_valkey_backend_class where it is needed as a base class.

@greptile-apps

greptile-apps Bot commented May 14, 2026

Copy link
Copy Markdown

Greptile Summary

This PR adds Valkey as a first-class storage backend across state storage, vector knowledge, and session CRUD, using valkey-glide-sync throughout. The integration is architecturally well-structured β€” enum registration, lazy-loader wiring, registry factories, and the pyproject.toml extras group all follow the existing Redis/DynamoDB patterns cleanly.

  • storage/__init__.py contains a top-level from .valkey_adapter import ValkeyStorageAdapter that eagerly loads valkey_adapter whenever any code imports from praisonai.storage, defeating the lazy-loading design shared by every other adapter; the __getattr__ branch added for the same name is therefore unreachable dead code.
  • valkey_vector.py has two compounding issues: the ValkeySearch filter query escapes only - and . (a value like sha256:abc123 will produce a malformed query at runtime), and bare_id = doc_id_str.split(":")[-1] silently truncates document IDs that contain colons.
  • Both unit-test fixture helpers (_make_knowledge_store, _make_state_store) use __new__ to bypass __init__ but never set instance attributes such as prefix, causing AttributeError in every test that exercises a key-building method.

Confidence Score: 3/5

The new Valkey wiring is structurally sound but several concrete defects need fixing before the feature is production-ready.

The eager import in storage/init.py breaks lazy loading for the entire praisonai.storage module the moment it lands. The incomplete ValkeySearch filter escaping means any filter value containing characters like ':', '(', or '@' will raise a runtime error. Both unit test fixture helpers are missing required instance attributes, so the majority of the added test cases will fail with AttributeError rather than exercise the code they claim to cover.

src/praisonai/praisonai/storage/init.py, src/praisonai/praisonai/persistence/knowledge/valkey_vector.py, src/praisonai/praisonai/persistence/tests/test_valkey_backends.py, src/praisonai/tests/unit/storage/test_valkey_backend.py

Important Files Changed

Filename Overview
src/praisonai/praisonai/storage/init.py Registers Valkey adapters but has a top-level eager import of ValkeyStorageAdapter that defeats the module-wide lazy-loading pattern and leaves the corresponding getattr branch as dead code.
src/praisonai/praisonai/persistence/knowledge/valkey_vector.py New ValkeyVectorKnowledgeStore with HNSW index support; filter query escaping is incomplete, score-to-similarity conversion is only valid for cosine distance, and document IDs with colons are silently truncated in search results.
src/praisonai/praisonai/persistence/tests/test_valkey_backends.py Unit tests for the new Valkey backends, but both _make_knowledge_store() and _make_state_store() use new without initializing instance attributes (prefix, host, port, password), causing AttributeError in the majority of test cases.
src/praisonai/praisonai/persistence/state/valkey.py New ValkeyStateStore implementation covering get/set/delete/exists/keys/ttl/hash operations; logic is clean and consistent with existing Redis state store patterns.
src/praisonai/praisonai/storage/valkey_adapter.py New ValkeyStorageAdapter and ValkeySearchBackend with lazy client init, SCAN-based key listing, and graceful ImportError guards; consistent with other adapters.
src/praisonai/praisonai/persistence/registry.py Registers valkey in both KNOWLEDGE_STORES and STATE_STORES; follows the exact same factory pattern as Redis and DynamoDB.
src/praisonai/tests/unit/storage/test_valkey_backend.py Unit tests for ValkeyStorageAdapter and ValkeySearchBackend; shares the same new-without-initialization pattern, causing tests that access adapter.prefix to fail.

Comments Outside Diff (3)

  1. src/praisonai/praisonai/persistence/knowledge/valkey_vector.py, line 440-446 (link)

    P1 Incomplete special-character escaping breaks ValkeySearch filter queries

    Only - and . are escaped, but ValkeySearch requires escaping of many more characters: ,, <, >, {, }, [, ], ", ', :, ;, !, @, #, $, %, ^, &, *, (, ), +, =, ~. A content_hash value such as sha256:abc123 contains :, which in ValkeySearch query syntax starts a field name β€” passing it unescaped will generate a malformed query and raise a runtime error (or silently match nothing). Additionally, the field key itself is interpolated without any sanitisation.

  2. src/praisonai/praisonai/persistence/knowledge/valkey_vector.py, line 480-484 (link)

    P2 score_threshold only behaves correctly for cosine distance

    similarity = 1 - score is the right formula when the metric is COSINE (where the returned score is the cosine distance). For L2 (Euclidean) the score ranges from 0 to ∞, and for IP (inner product) it can be negative, so 1 - score produces values that bear no consistent relationship to similarity. Any caller who creates a collection with distance="euclidean" or distance="dot" and then passes a score_threshold will get silently incorrect filtering.

  3. src/praisonai/praisonai/persistence/knowledge/valkey_vector.py, line 470-472 (link)

    P2 Document IDs containing : are silently truncated

    bare_id = doc_id_str.split(":")[-1] only keeps the last colon-delimited segment. The key format is {prefix}{collection}:{doc_id}, so a doc_id like "user:abc123" is stored as "praison:vec:docs:user:abc123" but round-trips back as "abc123". Callers that use UUID-style IDs are unaffected, but any structured ID with a colon will be corrupted on retrieval from search(). A correct approach is to strip only the known {prefix}{collection}: prefix instead of splitting on :.

Reviews (1): Last reviewed commit: "feat: Add Valkey Integration" | Re-trigger Greptile

These implementations are kept in the wrapper to avoid bloating the core SDK.
"""
import os
from .valkey_adapter import ValkeyStorageAdapter

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Eager import defeats the lazy-loading design

from .valkey_adapter import ValkeyStorageAdapter at module level loads valkey_adapter.py β€” and therefore tries to import glide_sync β€” the moment any code imports from praisonai.storage, even for Redis or Postgres. The __getattr__ branch for "ValkeyStorageAdapter" added a few lines later is dead code and will never be reached, because the name is already present in the module namespace. Every other adapter (RedisStorageAdapter, MongoDBStorageAdapter, etc.) is intentionally lazy; the direct import here breaks that contract for all callers of this module.

Remove the top-level import and let the existing __getattr__ branch handle ValkeyStorageAdapter on demand (the same pattern used for the other adapters).

Comment on lines +18 to +39
def _make_knowledge_store():
"""Return a ValkeyVectorKnowledgeStore with a pre-injected MagicMock client."""
from praisonai.persistence.knowledge.valkey_vector import ValkeyVectorKnowledgeStore

store = ValkeyVectorKnowledgeStore.__new__(ValkeyVectorKnowledgeStore)
mock_client = MagicMock()
store._client = mock_client
store._get_client = lambda: mock_client

return store, mock_client


def _make_state_store():
"""Return a ValkeyStateStore with a pre-injected MagicMock client."""
from praisonai.persistence.state.valkey import ValkeyStateStore

store = ValkeyStateStore.__new__(ValkeyStateStore)
mock_client = MagicMock()
store._client = mock_client
store._get_client = lambda: mock_client

return store, mock_client

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Test fixtures skip __init__, leaving required instance attributes unset

Both _make_knowledge_store() and _make_state_store() call __new__ directly and then only inject _client / _get_client. Instance attributes set in __init__ β€” notably self.prefix, self.host, self.port, and self.password β€” are never assigned. Every test that exercises a method touching those attributes (e.g. test_insert, test_search, test_get, test_get_existing, test_keys, etc.) will raise AttributeError: '...' object has no attribute 'prefix' before even reaching the mock assertion. The tests in src/praisonai/tests/unit/storage/test_valkey_backend.py share the same pattern and have the same gap.

@MervinPraison

Copy link
Copy Markdown
Owner

@claude You are the FINAL architecture reviewer. If the branch is under MervinPraison/PraisonAI (not a fork), you are able to make modifications to this branch and push directly. SCOPE: Focus ONLY on Python packages (praisonaiagents, praisonai). Do NOT modify praisonai-rust or praisonai-ts. Read ALL comments above from Gemini, Qodo, CodeRabbit, and Copilot carefully before responding.

Phase 1: Review per AGENTS.md

  1. Protocol-driven: check heavy implementations vs core SDK
  2. Backward compatible: ensure zero feature regressions
  3. Performance: no hot-path regressions

Phase 2: FIX Valid Issues
4. For any VALID bugs or architectural flaws found by Gemini, CodeRabbit, Qodo, Copilot, or any other reviewer: implement the fix
5. Push all code fixes directly to THIS branch (do NOT create a new PR)
6. Comment a summary of exact files modified and what you skipped

Phase 3: Final Verdict
7. If all issues are resolved, approve the PR / close the Issue
8. If blocking issues remain, request changes / leave clear action items

@praisonai-triage-agent

praisonai-triage-agent Bot commented May 14, 2026

Copy link
Copy Markdown
Contributor

Claude finished @MervinPraison's task β€”β€” View job


Final Architecture Review - Valkey Integration

Phase 1: Architecture Review per AGENTS.md

  • Read AGENTS.md guidelines
  • Review protocol-driven design compliance - βœ… GOOD
  • Check backward compatibility - βœ… GOOD
  • Assess performance impact - ⚠️ CRITICAL ISSUES FOUND

Phase 2: Critical Issues Analysis

  • Analyze eager import defeating lazy-loading pattern
  • Analyze incomplete ValkeySearch filter escaping
  • Analyze document ID extraction bugs
  • Analyze test fixture initialization issues
  • Analyze score threshold calculation flaws

Phase 3: Final Verdict

  • Unable to fix - PR is from a fork and branch is unavailable
  • Provide comprehensive review and recommendations

Architecture Assessment

βœ… Protocol-driven compliance: Excellent - follows existing Redis/MongoDB patterns with proper lazy loading in the agents package

βœ… Backward compatibility: Perfect - purely additive changes, no breaking modifications

⚠️ Performance impact: CRITICAL ISSUE - Several bugs break lazy-loading and runtime behavior

Critical Issues Found

1. 🚨 BLOCKING: Eager Import Breaks Lazy Loading

File: src/praisonai/praisonai/storage/__init__.py (line 14)

# ❌ WRONG: This breaks lazy loading for ALL users
from .valkey_adapter import ValkeyStorageAdapter  # Top-level import

# The corresponding __getattr__ branch is now dead code

Impact: Any import of praisonai.storage immediately loads valkey dependencies, defeating the entire lazy-loading architecture
Fix: Remove the eager import and rely on __getattr__ pattern like all other adapters

2. 🚨 BLOCKING: Incomplete ValkeySearch Filter Escaping

File: src/praisonai/praisonai/persistence/knowledge/valkey_vector.py (lines 440-446)

# ❌ WRONG: Only escapes - and . but ValkeySearch requires escaping many more
escaped = str(value).replace("-", "\\-").replace(".", "\\.")

Impact: Any filter value with :, (, ), @, etc. will cause runtime errors
Missing chars: `,<>{}[]"':;!@#$%^&*()+="
Fix: Implement complete ValkeySearch escaping or use parameterized queries

3. 🚨 BLOCKING: Document ID Corruption

File: src/praisonai/praisonai/persistence/knowledge/valkey_vector.py (line 470)

# ❌ WRONG: Truncates IDs containing colons
bare_id = doc_id_str.split(":")[-1]  # "user:123" becomes "123"

Impact: Document IDs like "user:123" get corrupted on retrieval from search()
Fix: Strip only the known prefix: doc_id_str[len(f"{self.prefix}{collection}:"):]

4. 🚨 BLOCKING: Test Fixtures Broken

Files: Multiple test files use __new__() without proper initialization

# ❌ WRONG: Missing required instance attributes
def _make_knowledge_store():
    store = ValkeyVectorKnowledgeStore.__new__(ValkeyVectorKnowledgeStore)
    store._client = mock_client
    return store  # Missing: prefix, host, port, password

Impact: Most tests will fail with AttributeError: 'object has no attribute 'prefix'
Fix: Call __init__() or manually set all required attributes

5. 🚨 BLOCKING: Score Threshold Only Works for Cosine

File: src/praisonai/praisonai/persistence/knowledge/valkey_vector.py (lines 480-484)

# ❌ WRONG: Only valid for cosine distance
similarity = 1 - score  # Breaks for L2 and IP metrics

Impact: Incorrect filtering when using distance="euclidean" or distance="dot"
Fix: Handle each distance metric correctly based on distance parameter

Minor Issues

6. Inconsistent ID Prefix Handling

File: src/praisonai/praisonai/storage/valkey_adapter.py (line 331)
Similar to issue #3 - search results should strip prefixes for consistency

Recommendation

❌ DO NOT MERGE - Multiple Blocking Issues

While the architectural approach is sound and follows AGENTS.md principles well, there are 5 critical bugs that make this PR unsuitable for production:

  1. Performance regression - breaks lazy loading for all users
  2. Runtime errors - filter escaping will fail on common characters
  3. Data corruption - document IDs get truncated
  4. Broken tests - fixtures don't work
  5. Wrong similarity calculation - incorrect for non-cosine metrics

Required Actions:

  1. Fix eager import in storage/__init__.py
  2. Implement proper ValkeySearch escaping or use parameterized queries
  3. Fix document ID extraction to preserve full IDs
  4. Fix test fixtures to properly initialize all required attributes
  5. Fix score-to-similarity conversion for all distance metrics
  6. Re-run all tests to ensure functionality

Architecture Quality: ⭐⭐⭐⭐⭐

The overall design is excellent - proper lazy loading, protocol-driven approach, follows existing patterns, and maintains backward compatibility. Once the implementation bugs are fixed, this would be a high-quality addition to PraisonAI.


Job Run: View workflow

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants