This release updates the SDK for Pinecone API version 2025-01. It introduces new features, several breaking changes, and improvements to the Pinecone .NET Client.
New Features
Support for Sparse Indexes
Pinecone's API now lets you create sparse indexes.
Here's an example of how to use the Pinecone SDK with sparse vectors.
using Pinecone;
// Initialize Pinecone client with your API key
var pinecone = new PineconeClient(Environment.GetEnvironmentVariable("PINECONE_API_KEY"));
var indexName = "test-sparse-index";
// Create a sparse serverless index
Console.WriteLine("Creating serverless index...");
await pinecone.CreateIndexAsync(new CreateIndexRequest
{
Name = indexName,
VectorType = VectorType.Sparse,
Spec = new ServerlessIndexSpec
{
Serverless = new ServerlessSpec
{
Cloud = ServerlessSpecCloud.Aws,
Region = "us-east-1",
}
}
});
// Wait for index to be ready
Console.WriteLine("Waiting for index to be ready...");
while (true)
{
var indexInfo = await pinecone.DescribeIndexAsync(indexName);
if (indexInfo.Status.State == IndexModelStatusState.Ready)
{
break;
}
Console.WriteLine("Index not ready yet, waiting...");
await Task.Delay(TimeSpan.FromSeconds(2));
}
// Get index instance
var index = pinecone.Index(indexName);
// Prepare sparse vector data
var sparseIndices = new uint[] { 1, 2 };
var sparseValues = new ReadOnlyMemory<float>([1f, 2f]);
// Create vector with sparse values
var vector = new Vector
{
Id = "v1",
SparseValues = new SparseValues
{
Indices = sparseIndices,
Values = sparseValues
}
};
// Upsert vector
Console.WriteLine("Upserting vector...");
var upsertResponse = await index.UpsertAsync(new UpsertRequest
{
Vectors = new List<Vector> { vector }
});
Console.WriteLine($"Upserted {upsertResponse.UpsertedCount} vector");
// Query by vector ID
Console.WriteLine("Querying vector by ID...");
var queryResponse = await index.QueryAsync(new QueryRequest
{
Id = vector.Id,
TopK = 1,
IncludeValues = true,
});
// Note: It can take up to 1 minute before upserted records are available to query.
// https://docs.pinecone.io/guides/indexes/sparse-indexes#upsert-sparse-vectors
// Display query results
Console.WriteLine("Query results:");
foreach (var match in queryResponse.Matches)
{
Console.WriteLine($"ID: {match.Id}");
if (match.SparseValues != null)
{
var indicesString = string.Join(", ", match.SparseValues.Indices);
Console.WriteLine($"Sparse Indices: [{indicesString}]");
var valuesString = string.Join(", ", match.SparseValues.Values.ToArray());
Console.WriteLine($"Sparse Values: [{valuesString}]");
}
}
// Delete the index
Console.WriteLine("Deleting index...");
await pinecone.DeleteIndexAsync(indexName);
Console.WriteLine("Index deleted successfully");
New Operations
client.CreateIndexForModelAsync(CreateIndexForModelRequest { ... }) -> Index
Breaking Changes
Embedding Type Changes
The Embedding
type has changed from a simple object to a discriminated union, supporting both DenseEmbedding
and SparseEmbedding
. This change provides better type safety but requires code updates.
New helper methods available on the Embedding
type:
IsDense
&IsSparse
- Type checkingAsDense()
&AsSparse()
- Type conversionMatch()
andVisit()
- Pattern matching
Example of updating your code:
// Before
Embedding embedding = GetEmbedding();
foreach (var value in embedding.Values.Span)
{
Console.WriteLine(value);
}
// After
Embedding embedding = GetEmbedding();
switch (embedding.VectorType)
{
case VectorType.Dense:
DenseEmbedding denseEmbedding = embedding.AsDense();
foreach (var value in denseEmbedding.Values.Span)
{
Console.WriteLine(value);
}
break;
case VectorType.Sparse:
SparseEmbedding sparseEmbedding = embedding.AsSparse();
foreach (var value in sparseEmbedding.SparseValues.Span)
{
Console.WriteLine(value);
}
break;
}
Type Changes
EmbedRequest
The Parameters
property now uses Dictionary<string, object?>?
instead of EmbedRequestParameters
:
public record EmbedRequest
{
public Dictionary<string, object?>? Parameters { get; set; }
}
RankedDocument
The Document
property now uses Dictionary<string, object?>?
instead of Dictionary<string, string>?
:
public record RankedDocument
{
public Dictionary<string, object?>? Document { get; set; }
}
RerankRequest
Update property types for more flexibility:
public record RerankRequest
{
public IEnumerable<Dictionary<string, object?>> Documents { get; set; }
public Dictionary<string, object?>? Parameters { get; set; }
}
Optional Properties
The following properties are now nullable:
Index.Dimension
:int?
Index.Tags
:Dictionary<string, string>?
PodSpec.Replicas
:int?
PodSpec.Shards
:int?
PodSpec.Pods
:int?
Vector.Values
:int?
Migration Guide
- Update embedding handling code to use the new discriminated union pattern
- Replace
EmbedRequestParameters
usage withDictionary<string, object?>?
- Update code handling
RankedDocument
to work withobject
values - Review and update code that assumes non-nullable properties for Index and PodSpec
- Update RerankRequest implementations to use the new parameter types
Full Changelog: 2.1.0...3.0.0