
Installation
Install both the Netra SDK and Redis:pip install netra-sdk redis
npm install netra-sdk redis
Usage
Initialize the Netra SDK to automatically trace all Redis operations:from netra import Netra
import redis
from redis.commands.search.field import VectorField
import os
# Initialize Netra
Netra.init(
headers=f"x-api-key={os.environ.get('NETRA_API_KEY')}",
trace_content=True
)
# Create Redis client - automatically traced
client = redis.Redis.from_url(os.environ.get('REDIS_URL'))
# Create index for vector search
client.ft("idx:vectors").create_index([
VectorField("vector",
"HNSW", {
"TYPE": "FLOAT32",
"DIM": 384,
"DISTANCE_METRIC": "COSINE"
}
)
])
import { Netra } from "netra-sdk";
import { createClient } from "redis";
// Initialize Netra
await Netra.init({
headers: `x-api-key=${process.env.NETRA_API_KEY}`,
traceContent: true
});
// Create Redis client - automatically traced
const client = createClient({
url: process.env.REDIS_URL
});
await client.connect();
// Create index for vector search
await client.ft.create("idx:vectors", {
vector: {
type: "VECTOR",
ALGORITHM: "HNSW",
DIM: 384,
DISTANCE_METRIC: "COSINE"
}
});
Index Operations
Trace index creation and management:from netra.decorators import task
from netra import SpanWrapper
from redis.commands.search.field import VectorField
@task()
def create_vector_index(client, index_name: str, dimension: int):
span = SpanWrapper("redis-create-index", {
"index.name": index_name,
"vector.dimension": dimension
}).start()
client.ft(index_name).create_index([
VectorField("vector", "HNSW", {
"TYPE": "FLOAT32",
"DIM": dimension,
"DISTANCE_METRIC": "COSINE"
})
])
span.end()
import { task, SpanWrapper } from "netra-sdk";
@task()
async function createVectorIndex(client: any, indexName: string, dimension: number) {
const span = new SpanWrapper("redis-create-index", {
"index.name": indexName,
"vector.dimension": dimension
}).start();
await client.ft.create(indexName, {
vector: {
type: "VECTOR",
ALGORITHM: "HNSW",
DIM: dimension,
DISTANCE_METRIC: "COSINE"
}
});
span.end();
}
Vector Storage
Trace vector insertions:from netra.decorators import task
from netra import SpanWrapper, ActionModel
import numpy as np
@task()
def store_vector(client, key: str, vector: list[float], metadata: dict):
span = SpanWrapper("redis-store-vector", {
"key": key,
"vector.size": len(vector)
}).start()
client.hset(key, mapping={
"vector": np.array(vector, dtype=np.float32).tobytes(),
**metadata
})
span.set_action([ActionModel(
action="set",
action_type="database.set",
success=True,
affected_records=[{"id": key}],
metadata={"vector_size": len(vector)}
)])
span.set_attribute("status", "success")
span.end()
import { task, SpanWrapper, ActionModel } from "netra-sdk";
@task()
async function storeVector(client: any, key: string, vector: number[], metadata: any) {
const span = new SpanWrapper("redis-store-vector", {
"key": key,
"vector.size": vector.length
}).start();
await client.hSet(key, {
vector: Buffer.from(new Float32Array(vector).buffer),
...metadata
});
span.setAction([{
action: "set",
action_type: "database.set",
success: true,
affected_records: [{ id: key }],
metadata: { vector_size: vector.length }
}]);
span.setAttribute("status", "success");
span.end();
}
Vector Search
Trace similarity searches:from netra.decorators import workflow
from netra import SpanWrapper
import numpy as np
@workflow()
def search_vectors(client, index_name: str, query: list[float], limit: int = 5):
span = SpanWrapper("redis-search", {
"index": index_name,
"query.size": len(query),
"limit": limit
}).start()
query_vec = np.array(query, dtype=np.float32).tobytes()
results = client.ft(index_name).search(
f"*=>[KNN {limit} @vector $query_vec]",
query_params={"query_vec": query_vec}
)
span.set_attribute("results.count", results.total)
span.end()
return results
import { workflow, SpanWrapper } from "netra-sdk";
@workflow()
async function searchVectors(client: any, indexName: string, query: number[], limit: number = 5) {
const span = new SpanWrapper("redis-search", {
"index": indexName,
"query.size": query.length,
"limit": limit
}).start();
const results = await client.ft.search(
indexName,
`*=>[KNN ${limit} @vector $query_vec]`,
{
PARAMS: {
query_vec: Buffer.from(new Float32Array(query).buffer)
},
RETURN: ["id", "score"]
}
);
span.setAttribute("results.count", results.total);
span.end();
return results;
}
Hybrid Search
Trace combined vector and metadata searches:from netra.decorators import task
from netra import SpanWrapper
import numpy as np
@task()
def hybrid_search(client, index_name: str, query: list[float], filter: str):
span = SpanWrapper("redis-hybrid-search", {
"index": index_name,
"filter": filter
}).start()
query_vec = np.array(query, dtype=np.float32).tobytes()
results = client.ft(index_name).search(
f"{filter}=>[KNN 10 @vector $query_vec]",
query_params={"query_vec": query_vec}
)
span.set_attribute("results.count", results.total)
span.end()
return results
import { task, SpanWrapper } from "netra-sdk";
@task()
async function hybridSearch(client: any, indexName: string, query: number[], filter: string) {
const span = new SpanWrapper("redis-hybrid-search", {
"index": indexName,
"filter": filter
}).start();
const results = await client.ft.search(
indexName,
`${filter}=>[KNN 10 @vector $query_vec]`,
{
PARAMS: {
query_vec: Buffer.from(new Float32Array(query).buffer)
}
}
);
span.setAttribute("results.count", results.total);
span.end();
return results;
}
Next Steps
- Quick Start Guide - Complete setup and configuration
- Decorators - Add custom tracing with
@workflow,@agent, and@taskdecorators - Redis Documentation - Redis vector search documentation
