Skip to content

Latest commit

 

History

History
355 lines (267 loc) · 10.4 KB

File metadata and controls

355 lines (267 loc) · 10.4 KB

Automatic Embedding Generation

Overview

DevStream Direct Client now includes automatic embedding generation for all stored content. This feature enables semantic search capabilities while maintaining backward compatibility and graceful degradation.

Architecture

Embedding Generation Flow

  1. Content Storage Request → store_memory() called
  2. Automatic Embedding Generation → OllamaEmbeddingClient generates 768-dimension vectors
  3. BLOB Storage → Embeddings stored as binary BLOB (70% space reduction vs JSON)
  4. Graceful Degradation → Storage succeeds even if embedding generation fails
  5. Return Metadata → Includes embedding status and metadata

Technical Implementation

  • Model: embeddinggemma:300m (768 dimensions)
  • Storage Format: Binary BLOB using struct.pack() (70% space reduction)
  • Fallback: Content stored without embedding if Ollama fails
  • Performance: ~100ms additional latency per operation
  • Database Schema: embedding_blob, embedding_model, embedding_dimension columns

Usage

Basic Usage

from direct_client import DevStreamDirectClient

client = DevStreamDirectClient()

# Store content with automatic embedding generation
result = await client.store_memory(
    content="def fibonacci(n): return n if n <= 1 else fibonacci(n-1) + fibonacci(n-2)",
    content_type="code",
    keywords=["fibonacci", "recursion", "python"]
)

# Check embedding generation status
if result["embedding_generated"]:
    print(f"Embedding stored: {result['embedding_dimension']} dimensions")
    print(f"Storage format: {result['embedding_format']}")  # "BLOB"
else:
    print("Embedding generation failed, but content was stored")

Error Handling

result = await client.store_memory(
    content="Important code snippet",
    content_type="code"
)

# Storage always succeeds
assert result["success"] is True
assert "memory_id" in result

# Embedding generation is optional
if result.get("embedding_generated"):
    # Embedding was generated and stored
    pass
else:
    # Embedding failed, but content was still stored
    pass

Performance Characteristics

Storage Performance

  • Without Embedding: ~50ms per operation
  • With Embedding: ~150ms per operation (including Ollama call)
  • Space Efficiency: BLOB format uses 70% less space than JSON
  • Concurrent Operations: Fully supported with connection pooling

Search Performance

  • Vector Search: Available when sqlite-vec is enabled
  • FTS Fallback: Full-text search when vector search unavailable
  • Hybrid Search: Combines semantic and keyword search

Database Schema

semantic_memory Table

CREATE TABLE semantic_memory (
    id TEXT PRIMARY KEY,
    content TEXT NOT NULL,
    content_type TEXT NOT NULL,
    keywords TEXT,
    session_id TEXT,
    created_at TIMESTAMP,
    updated_at TIMESTAMP,
    access_count INTEGER DEFAULT 0,
    relevance_score REAL DEFAULT 1.0,
    importance_score REAL DEFAULT 0.0,
    last_accessed_at TIMESTAMP,
    metadata TEXT,
    source TEXT,
    -- New embedding columns
    embedding_blob BLOB,                    -- Binary embedding vector
    embedding_model TEXT,                    -- Model used for embedding
    embedding_dimension INTEGER,             -- Embedding dimensions (768)

    -- Constraints
    CHECK (content_type IN ('code', 'documentation', 'context', 'output', 'error', 'decision', 'learning')),
    CHECK (embedding_blob IS NULL OR vec_length(embedding_blob) = 768)
);

Configuration

Environment Variables

# Ollama configuration
OLLAMA_BASE_URL=http://localhost:11434     # Ollama service URL
EMBEDDING_MODEL=embeddinggemma:300m        # Embedding model

# DevStream configuration
DEVSTREAM_MEMORY_ENABLED=true              # Enable memory system
DEVSTREAM_VECTOR_SEARCH_ENABLED=true       # Enable vector search

Database Constraints

  • Embedding Dimensions: Must be exactly 768 dimensions
  • Content Types: Restricted to enum values for data integrity
  • BLOB Format: Binary storage for space efficiency
  • NULL Embeddings: Allowed for graceful degradation

Testing

Unit Tests

# Run embedding unit tests
.devstream/bin/python -m pytest tests/unit/memory/test_direct_client_embedding.py -v

Test Coverage:

  • ✅ Embedding generation success
  • ✅ Embedding generation failure (graceful degradation)
  • ✅ BLOB format validation
  • ✅ Backward compatibility
  • ✅ Performance requirements

Integration Tests

# Run embedding integration tests
.devstream/bin/python -m pytest tests/integration/test_embedding_integration.py -v

Test Coverage:

  • ✅ Full embedding flow with real Ollama service
  • ✅ Search integration with embeddings
  • ✅ Performance under load
  • ✅ Error recovery and system resilience
  • ✅ Database constraints validation

Troubleshooting

Common Issues

1. Embedding Generation Fails

Symptoms:

  • embedding_generated: False in response
  • Warning logs about Ollama unavailability
  • Content stored successfully but no embedding

Solutions:

# Check Ollama service status
curl http://localhost:11434/api/tags

# Ensure embedding model is available
ollama pull embeddinggemma:300m

# Check Ollama logs
docker logs ollama

2. Database Constraint Errors

Symptoms:

  • CHECK constraint failed errors
  • Invalid content_type values
  • Embedding dimension mismatches

Solutions:

# Use valid content types
valid_types = ['code', 'documentation', 'context', 'output', 'error', 'decision', 'learning']

# Check embedding dimensions (should be 768)
import struct
embedding = [0.1] * 768  # Must be exactly 768 dimensions
blob = struct.pack('768f', *embedding)
assert len(blob) == 3072  # 768 * 4 bytes

3. Performance Issues

Symptoms:

  • Slow storage operations (>200ms)
  • High memory usage
  • Database timeouts

Solutions:

# Use concurrent operations for bulk storage
import asyncio

tasks = []
for content in contents:
    task = client.store_memory(content, "code")
    tasks.append(task)

results = await asyncio.gather(*tasks)

Debug Information

# Get client statistics
stats = client.get_stats()
print(f"Vector search available: {stats['features']['vector_search']}")
print(f"Active connections: {stats['active_connections']}")

# Check embedding generation status
result = await client.store_memory("test", "code")
print(f"Embedding generated: {result['embedding_generated']}")
print(f"Embedding dimension: {result['embedding_dimension']}")

Migration Guide

From MCP Server

The direct client maintains 100% API compatibility with the MCP client:

# Old MCP client code (unchanged)
from mcp_client import DevStreamMCPClient
client = DevStreamMCPClient()
result = await client.store_memory("content", "code")

# New direct client code (same API)
from direct_client import DevStreamDirectClient
client = DevStreamDirectClient()
result = await client.store_memory("content", "code")

New Features

The direct client adds new return fields for embedding metadata:

result = await client.store_memory("content", "code")

# New embedding metadata fields
embedding_generated = result.get("embedding_generated", False)
embedding_format = result.get("embedding_format")  # "BLOB" or None
embedding_dimension = result.get("embedding_dimension")  # 768 or None

Best Practices

Performance Optimization

  1. Batch Operations: Use asyncio.gather() for concurrent storage
  2. Content Optimization: Avoid extremely large content (>10MB)
  3. Connection Pooling: Reuse client instances for multiple operations
  4. Error Handling: Always check embedding_generated status

Data Management

  1. Content Types: Use appropriate content types for better search
  2. Keywords: Provide relevant keywords for improved FTS search
  3. Session Tracking: Use session IDs for debugging and analytics
  4. Monitoring: Track embedding generation success rates

Error Recovery

  1. Graceful Degradation: Design for embedding generation failures
  2. Retry Logic: Implement exponential backoff for transient failures
  3. Fallback Search: Use FTS search when vector search unavailable
  4. Monitoring: Alert on embedding generation failure rates

Future Enhancements

Planned Features

  • Embedding Model Selection: Support for multiple embedding models
  • Batch Embedding: Generate embeddings for multiple items efficiently
  • Embedding Caching: Cache embeddings for duplicate content
  • Hybrid Search: Improved semantic + keyword search ranking
  • Embedding Analytics: Track embedding quality and usage patterns

Performance Improvements

  • Async Embedding Generation: Non-blocking embedding generation
  • Vector Index Optimization: Improved vector search performance
  • Connection Pool Optimization: Better resource utilization
  • Memory Management: Optimized BLOB storage and retrieval

API Reference

DevStreamDirectClient.store_memory()

async def store_memory(
    self,
    content: str,
    content_type: str,
    keywords: Optional[List[str]] = None,
    session_id: Optional[str] = None
) -> Optional[Dict[str, Any]]:

Parameters:

  • content (str): Content to store
  • content_type (str): Type of content ('code', 'documentation', 'context', 'output', 'error', 'decision', 'learning')
  • keywords (Optional[List[str]]): Associated keywords for search
  • session_id (Optional[str]): Session ID for tracking

Returns:

  • success (bool): True if storage succeeded
  • memory_id (str): Unique identifier for stored memory
  • content_type (str): Type of content stored
  • created_at (str): ISO timestamp of storage
  • embedding_generated (bool): True if embedding was generated and stored
  • embedding_format (str): "BLOB" if embedding was stored, None otherwise
  • embedding_dimension (int): Embedding vector dimensions (768), None if no embedding

Raises:

  • DatabaseException: If storage operation fails

Changelog

v2.2.0 (2025-10-14)

  • ✅ NEW: Automatic embedding generation for all stored content
  • ✅ NEW: BLOB format storage (70% space reduction vs JSON)
  • ✅ NEW: Graceful degradation for embedding generation failures
  • ✅ NEW: Comprehensive unit and integration test coverage
  • ✅ NEW: Enhanced documentation and examples
  • ✅ IMPROVED: Performance monitoring and logging
  • ✅ IMPROVED: Error handling and recovery mechanisms