Complete API reference for SemanticCache library.
- Core Types
- Cache Creation
- Synchronous Operations
- Asynchronous Operations
- Batch Operations
- Configuration Options
- Interfaces
The main cache type with generic key and value types.
type SemanticCache[K comparable, V any] struct {
// Internal fields (not exported)
}Type Parameters:
K comparable: Key type (must be comparable)V any: Value type (can be any type)
Represents a semantic search result with similarity score.
type Match[V any] struct {
Value V `json:"value"` // The cached value
Score float32 `json:"score"` // Similarity score
}Item for batch operations.
type BatchItem[K comparable, V any] struct {
Key K // Cache key
InputText string // Text to embed
Value V // Value to cache
}// Result from GetAsync
type GetResult[V any] struct {
Value V
Found bool
Error error
}
// Result from LookupAsync
type LookupResult[V any] struct {
Match *Match[V]
Error error
}
// Result from TopMatchesAsync
type TopMatchesResult[V any] struct {
Matches []Match[V]
Error error
}
// Result from GetBatchAsync
type GetBatchResult[K comparable, V any] struct {
Values map[K]V
Error error
}Creates a new semantic cache with functional options (recommended).
func New[K comparable, V any](opts ...options.Option[K, V]) (*SemanticCache[K, V], error)Parameters:
opts: Variable number of configuration options
Returns:
*SemanticCache[K, V]: Configured cache instanceerror: Configuration or validation error
Example:
cache, err := semanticcache.New[string, string](
options.WithOpenAIProvider("api-key"),
options.WithLRUBackend(1000),
options.WithSimilarityComparator(similarity.CosineSimilarity),
)Errors:
- Returns error if required options missing (backend, provider)
- Returns error if option application fails
Low-level constructor (use New instead for better API).
func NewSemanticCache[K comparable, V any](
backend types.CacheBackend[K, V],
provider types.EmbeddingProvider,
comparator similarity.SimilarityFunc,
) (*SemanticCache[K, V], error)Parameters:
backend: Storage backend implementationprovider: Embedding provider implementationcomparator: Similarity function (nil uses CosineSimilarity)
Returns:
*SemanticCache[K, V]: Cache instanceerror: Validation error if any parameter is nil
Stores a value with its semantic embedding.
func (sc *SemanticCache[K, V]) Set(
ctx context.Context,
key K,
inputText string,
value V,
) errorParameters:
ctx: Context for cancellation/timeoutkey: Cache key (cannot be zero value)inputText: Text to generate embedding fromvalue: Value to cache
Returns:
error: Embedding generation or storage error
Example:
err := cache.Set(ctx, "user123", "How do I reset my password?", answerStruct)Errors:
- Returns error if
keyis zero value - Returns error if embedding generation fails
- Returns error if backend storage fails
Retrieves a value by key.
func (sc *SemanticCache[K, V]) Get(
ctx context.Context,
key K,
) (V, bool, error)Parameters:
ctx: Context for cancellation/timeoutkey: Cache key
Returns:
V: Value (zero value if not found)bool:trueif found,falseotherwiseerror: Retrieval error
Example:
value, found, err := cache.Get(ctx, "user123")
if found {
fmt.Printf("Value: %v\n", value)
}Finds the first semantically similar entry above threshold.
func (sc *SemanticCache[K, V]) Lookup(
ctx context.Context,
inputText string,
threshold float32,
) (*Match[V], error)Parameters:
ctx: Context for cancellation/timeoutinputText: Query text to find similar contentthreshold: Minimum similarity score[0, 1]
Returns:
*Match[V]: First match above threshold (nil if none found)error: Embedding or search error
Example:
match, err := cache.Lookup(ctx, "password reset help", 0.8)
if match != nil {
fmt.Printf("Found: %v (score: %.2f)\n", match.Value, match.Score)
}Notes:
- Returns best match (highest score) >= threshold
- Threshold interpretation depends on similarity function
- Cosine similarity: 0.8-0.9 is typical for semantic matches
Returns top N semantically similar entries, sorted by descending score.
func (sc *SemanticCache[K, V]) TopMatches(
ctx context.Context,
inputText string,
n int,
) ([]Match[V], error)Parameters:
ctx: Context for cancellation/timeoutinputText: Query textn: Maximum number of matches (must be > 0)
Returns:
[]Match[V]: Matches sorted by score (descending)error: Validation, embedding, or search error
Example:
matches, err := cache.TopMatches(ctx, "account issues", 5)
for _, match := range matches {
fmt.Printf("Score %.2f: %v\n", match.Score, match.Value)
}Errors:
- Returns error if
n <= 0
Checks if a key exists without retrieving the value.
func (sc *SemanticCache[K, V]) Contains(
ctx context.Context,
key K,
) (bool, error)Parameters:
ctx: Contextkey: Cache key
Returns:
bool:trueif exists,falseotherwiseerror: Check error
Example:
exists, err := cache.Contains(ctx, "user123")Removes an entry from the cache.
func (sc *SemanticCache[K, V]) Delete(
ctx context.Context,
key K,
) errorParameters:
ctx: Contextkey: Key to delete
Returns:
error: Deletion error
Example:
err := cache.Delete(ctx, "user123")Clears all entries from the cache.
func (sc *SemanticCache[K, V]) Flush(ctx context.Context) errorParameters:
ctx: Context
Returns:
error: Flush error
Example:
err := cache.Flush(ctx)Warning: This operation is irreversible.
Returns the number of entries in the cache.
func (sc *SemanticCache[K, V]) Len(ctx context.Context) (int, error)Parameters:
ctx: Context
Returns:
int: Number of entrieserror: Count error
Example:
count, err := cache.Len(ctx)
fmt.Printf("Cache size: %d\n", count)Closes the cache and releases resources.
func (sc *SemanticCache[K, V]) Close() errorReturns:
error: Close error (if any)
Example:
defer cache.Close()Notes:
- Closes embedding provider
- Backend cleanup (connection pools, etc.)
- Should be called when cache no longer needed
All async operations return buffered channels (size 1) that deliver results when complete. Operations are non-blocking and execute in goroutines.
Asynchronously stores a value with embedding.
func (sc *SemanticCache[K, V]) SetAsync(
ctx context.Context,
key K,
inputText string,
value V,
) <-chan errorParameters:
- Same as
Set
Returns:
<-chan error: Receive-only channel delivering result
Example:
errCh := cache.SetAsync(ctx, "key", "text", "value")
// Do other work...
if err := <-errCh; err != nil {
log.Printf("SetAsync failed: %v", err)
}Asynchronously retrieves a value by key.
func (sc *SemanticCache[K, V]) GetAsync(
ctx context.Context,
key K,
) <-chan GetResult[V]Parameters:
- Same as
Get
Returns:
<-chan GetResult[V]: Channel delivering result
Example:
resultCh := cache.GetAsync(ctx, "key")
result := <-resultCh
if result.Error != nil {
log.Printf("Error: %v", result.Error)
} else if result.Found {
fmt.Printf("Value: %v\n", result.Value)
}Asynchronously deletes an entry.
func (sc *SemanticCache[K, V]) DeleteAsync(
ctx context.Context,
key K,
) <-chan errorParameters:
- Same as
Delete
Returns:
<-chan error: Channel delivering result
Example:
errCh := cache.DeleteAsync(ctx, "key")
err := <-errChAsynchronously finds semantically similar content.
func (sc *SemanticCache[K, V]) LookupAsync(
ctx context.Context,
inputText string,
threshold float32,
) <-chan LookupResult[V]Parameters:
- Same as
Lookup
Returns:
<-chan LookupResult[V]: Channel delivering result
Example:
resultCh := cache.LookupAsync(ctx, "query", 0.8)
result := <-resultCh
if result.Error == nil && result.Match != nil {
fmt.Printf("Match: %v\n", result.Match.Value)
}Asynchronously returns top N matches.
func (sc *SemanticCache[K, V]) TopMatchesAsync(
ctx context.Context,
inputText string,
n int,
) <-chan TopMatchesResult[V]Parameters:
- Same as
TopMatches
Returns:
<-chan TopMatchesResult[V]: Channel delivering results
Example:
resultCh := cache.TopMatchesAsync(ctx, "query", 5)
result := <-resultCh
if result.Error == nil {
for _, match := range result.Matches {
fmt.Printf("Score: %.2f\n", match.Score)
}
}Stores multiple entries efficiently.
func (sc *SemanticCache[K, V]) SetBatch(
ctx context.Context,
items []BatchItem[K, V],
) errorParameters:
ctx: Contextitems: Slice of items to store
Returns:
error: First error encountered (fail-fast)
Example:
items := []semanticcache.BatchItem[string, string]{
{Key: "q1", InputText: "What is Go?", Value: "Programming language"},
{Key: "q2", InputText: "What is Python?", Value: "Scripting language"},
}
err := cache.SetBatch(ctx, items)Notes:
- Processes items sequentially
- Stops on first error
- All items validated before processing
Asynchronously stores multiple entries with concurrent embedding generation.
func (sc *SemanticCache[K, V]) SetBatchAsync(
ctx context.Context,
items []BatchItem[K, V],
) <-chan errorParameters:
- Same as
SetBatch
Returns:
<-chan error: Channel delivering result
Example:
errCh := cache.SetBatchAsync(ctx, items)
if err := <-errCh; err != nil {
log.Printf("Batch failed: %v", err)
}Notes:
- Spawns goroutine per item for parallel embedding
- Fails fast on first error
- More efficient than sequential
SetBatch
Retrieves multiple values by keys.
func (sc *SemanticCache[K, V]) GetBatch(
ctx context.Context,
keys []K,
) (map[K]V, error)Parameters:
ctx: Contextkeys: Keys to retrieve
Returns:
map[K]V: Map of found key-value pairserror: Retrieval error
Example:
values, err := cache.GetBatch(ctx, []string{"q1", "q2", "q3"})
for key, value := range values {
fmt.Printf("%s: %v\n", key, value)
}Notes:
- Only returns found keys (missing keys not in map)
- Returns error only on operation failure, not missing keys
Asynchronously retrieves multiple values using backend async capabilities.
func (sc *SemanticCache[K, V]) GetBatchAsync(
ctx context.Context,
keys []K,
) <-chan GetBatchResult[K, V]Parameters:
- Same as
GetBatch
Returns:
<-chan GetBatchResult[K, V]: Channel delivering results
Example:
resultCh := cache.GetBatchAsync(ctx, []string{"key1", "key2"})
result := <-resultCh
if result.Error == nil {
for k, v := range result.Values {
fmt.Printf("%s: %v\n", k, v)
}
}Performance:
- Redis backend: Uses pipelining for single network round-trip
- In-memory: Concurrent goroutine retrieval
Deletes multiple entries.
func (sc *SemanticCache[K, V]) DeleteBatch(
ctx context.Context,
keys []K,
) errorParameters:
ctx: Contextkeys: Keys to delete
Returns:
error: First deletion error
Example:
err := cache.DeleteBatch(ctx, []string{"key1", "key2", "key3"})Asynchronously deletes multiple entries concurrently.
func (sc *SemanticCache[K, V]) DeleteBatchAsync(
ctx context.Context,
keys []K,
) <-chan errorParameters:
- Same as
DeleteBatch
Returns:
<-chan error: Channel delivering result
Example:
errCh := cache.DeleteBatchAsync(ctx, keys)
err := <-errChNotes:
- Spawns goroutine per key for parallel deletion
- Fails fast on first error
All options are in the options package.
Creates an LRU (Least Recently Used) in-memory backend.
func WithLRUBackend[K comparable, V any](capacity int) Option[K, V]Parameters:
capacity: Maximum number of entries
Example:
options.WithLRUBackend[string, string](1000)Creates an LFU (Least Frequently Used) in-memory backend.
func WithLFUBackend[K comparable, V any](capacity int) Option[K, V]Parameters:
capacity: Maximum number of entries
Example:
options.WithLFUBackend[string, string](500)Creates a FIFO (First In, First Out) in-memory backend.
func WithFIFOBackend[K comparable, V any](capacity int) Option[K, V]Parameters:
capacity: Maximum number of entries
Example:
options.WithFIFOBackend[string, string](100)Creates a Redis backend.
func WithRedisBackend[K comparable, V any](addr string, db int) Option[K, V]Parameters:
addr: Redis server address (host:port)db: Database number
Example:
options.WithRedisBackend[string, string]("localhost:6379", 0)Notes:
- Requires Redis with JSON support (RedisJSON module)
- Supports vector search (FT.SEARCH)
Uses a custom backend implementation.
func WithCustomBackend[K comparable, V any](
backend types.CacheBackend[K, V],
) Option[K, V]Parameters:
backend: Custom backend implementingCacheBackendinterface
Example:
options.WithCustomBackend[string, string](myBackend)Creates an OpenAI embedding provider.
func WithOpenAIProvider[K comparable, V any](
apiKey string,
model ...string,
) Option[K, V]Parameters:
apiKey: OpenAI API key (or empty to useOPENAI_API_KEYenv var)model: Optional model name (default:text-embedding-3-small)
Example:
// Default model
options.WithOpenAIProvider[string, string]("sk-...")
// Specific model
options.WithOpenAIProvider[string, string]("sk-...", "text-embedding-3-large")
// From environment
options.WithOpenAIProvider[string, string]("")Available Models:
text-embedding-3-small(1536 dims, default)text-embedding-3-large(3072 dims)text-embedding-ada-002(1536 dims, legacy)
Uses a custom embedding provider.
func WithCustomProvider[K comparable, V any](
provider types.EmbeddingProvider,
) Option[K, V]Parameters:
provider: Custom provider implementingEmbeddingProviderinterface
Example:
options.WithCustomProvider[string, string](myProvider)Sets the similarity function for semantic search.
func WithSimilarityComparator[K comparable, V any](
comparator similarity.SimilarityFunc,
) Option[K, V]Parameters:
comparator: Similarity function
Example:
options.WithSimilarityComparator[string, string](similarity.CosineSimilarity)Built-in Functions:
similarity.CosineSimilarity(default) - Range: [-1, 1]similarity.EuclideanSimilarity- Range: [0, 1]similarity.DotProductSimilarity- Range: unboundedsimilarity.ManhattanSimilarity- Range: [0, 1]similarity.PearsonCorrelationSimilarity- Range: [-1, 1]
Backend storage interface.
type CacheBackend[K comparable, V any] interface {
Set(ctx context.Context, key K, entry Entry[V]) error
Get(ctx context.Context, key K) (Entry[V], bool, error)
Delete(ctx context.Context, key K) error
Contains(ctx context.Context, key K) (bool, error)
Flush(ctx context.Context) error
Len(ctx context.Context) (int, error)
Keys(ctx context.Context) ([]K, error)
GetEmbedding(ctx context.Context, key K) ([]float32, bool, error)
Close() error
// Async methods
SetAsync(ctx context.Context, key K, entry Entry[V]) <-chan error
GetAsync(ctx context.Context, key K) <-chan AsyncGetResult[V]
DeleteAsync(ctx context.Context, key K) <-chan error
GetBatchAsync(ctx context.Context, keys []K) <-chan AsyncBatchResult[K, V]
}Embedding generation interface.
type EmbeddingProvider interface {
EmbedText(text string) ([]float32, error)
Close()
}Similarity calculation function type.
type SimilarityFunc func(a, b []float32) float32Parameters:
a,b: Embedding vectors
Returns:
float32: Similarity score (interpretation depends on function)
Notes:
- Should handle empty vectors gracefully (return 0)
- Should handle mismatched lengths (return 0)
- Higher scores = more similar (except inverted distances)
Configuration Errors:
cache, err := semanticcache.New[string, string](
// Missing required options
)
// err: "backend is required - use WithLRUBackend, etc"
// err: "embedding provider is required - use WithOpenAIProvider, etc"Operation Errors:
err := cache.Set(ctx, "", "text", "value")
// err: "key cannot be zero value"
matches, err := cache.TopMatches(ctx, "query", -1)
// err: "n must be positive"Provider Errors:
// OpenAI API errors
// err: "failed to generate embedding: <OpenAI error>"Backend Errors:
// Redis connection errors
// err: "failed to connect to Redis: <connection error>"// Construction
cache, err := semanticcache.New[string, string](opts...)
if err != nil {
log.Fatalf("Failed to create cache: %v", err)
}
defer cache.Close()
// Operations
if err := cache.Set(ctx, key, text, value); err != nil {
log.Printf("Set failed: %v", err)
return err
}
// Semantic search
match, err := cache.Lookup(ctx, query, 0.8)
if err != nil {
log.Printf("Lookup failed: %v", err)
return err
}
if match == nil {
log.Println("No match found")
return
}
fmt.Printf("Found: %v (score: %.2f)\n", match.Value, match.Score)In-Memory Backends:
Set: O(1)Get: O(1)Delete: O(1) for LRU/LFU, O(n) for FIFOLookup: O(n) - iterates all entriesTopMatches: O(n log n) - sorts all similarities
Redis Backend:
Set: O(1) + networkGet: O(1) + networkLookup: O(n) - could use FT.SEARCH KNN for O(log n)GetBatchAsync: O(n) with pipelining (single round-trip)
-
Choose Right Backend:
- LRU: Time-based locality
- LFU: Frequency-based access
- FIFO: Simple caching
- Redis: Shared cache, persistence
-
Use Async for Concurrency:
- Non-blocking operations
- Parallel processing
- Better throughput
-
Batch Operations:
- Reduce API calls (embeddings)
- Network efficiency (Redis)
- Better performance
-
Context Timeouts:
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel()
-
Similarity Thresholds:
- 0.9+: High precision
- 0.8-0.9: Balanced (recommended)
- 0.7-0.8: High recall