Release v4.0.0
This version of the Pinecone Go SDK depends on version 2025-04
of the Pinecone API. You can read more about versioning here. This v4 SDK release line should continue to receive fixes as long as the 2025-04
API version is in support.
Features
Namespaces
You can now work directly with namespaces associated with a specific index. There have been three new methods added to the IndexConnection
class allowing you to DescribeNamespace
, ListNamespaces
within an index, and DeleteNamespace
. Currently, namespaces are still created implicitly when calling Upsert
against a specific IndexConnection
targeting a namespace.
Note: You can now use IndexConnection.WithNamespace
to create a shallow copy of the gRPC connection targeting a different namespace which reuses the underlying connection internals. See "Bug fixes & Breaking Changes" below for more details.
import (
"context"
"log"
"github.com/pinecone-io/go-pinecone/v4/pinecone"
)
func Namespaces() {
ctx := context.Background()
pc, err := pinecone.NewClient(pinecone.NewClientParams{
ApiKey: "YOUR_API_KEY",
})
if err != nil {
log.Fatalf("Failed to create Client: %v", err)
}
idx, err := pc.DescribeIndex(ctx, "example-index")
if err != nil {
log.Fatalf("Failed to describe index \"%v\": %v", idx.Name, err)
}
idxConnection, err := pc.Index(pinecone.NewIndexConnParams{Host: idx.Host})
if err != nil {
log.Fatalf("Failed to create IndexConnection for Host: %v: %v", idx.Host, err)
}
// list namespaces
limit := uint32(10)
namespaces, err := idxConnection.ListNamespaces(ctx, &pinecone.ListNamespacesParams{
Limit: &limit,
})
if err != nil {
log.Fatalf("Failed to list namespaces for Host: %v: %v", idx.Host, err)
}
// describe a namespace
namespace1, err := idxConnection.DescribeNamespace(ctx, namespaces.Namespaces[0].Name)
if err != nil {
log.Fatalf("Failed to describe namespace: %v: %v", namespaces.Namespaces[0].Name, err)
}
// delete a namespace
err = idxConnection.DeleteNamespace(namespace1.Name)
if err != nil {
log.Fatalf("Failed to delete namespace: %v: %v", "my-namespace-1", err)
}
// target a new specific namespace
idxConnectionNs2 := idxConnection.WithNamespace(namespaces.Namespaces[1].Name)
}
Backups and Restore Jobs
You can now create and manage backups of serverless indexes. It is a static, non-queryable copy of an index that represents a set of records. You can create a backup of a serverless index, and you can create a new serverless index from a backup. You can read more about backups here.
import (
"context"
"fmt"
"log"
"os"
"time"
"github.com/pinecone-io/go-pinecone/v4/pinecone"
)
func BackupsAndRestore() {
ctx := context.Background()
clientParams := pinecone.NewClientParams{
ApiKey: os.Getenv("PINECONE_API_KEY"),
}
pc, err := pinecone.NewClient(clientParams)
if err != nil {
log.Fatalf("Failed to create Client: %w", err)
}
indexName := "my-index"
backupName := fmt.Sprintf("backup-%s")
backupDesc := fmt.Sprintf("Backup created for index %s", indexName)
fmt.Printf("Creating backup: %s for index: %s\n", backupName, indexName)
backup, err := pc.CreateBackup(ctx, &pinecone.CreateBackupParams{
IndexName: indexName,
Name: &backupName,
Description: &backupDesc,
})
if err != nil {
log.Fatalf("Failed to create backup: %w", err)
}
backup, err = pc.DescribeBackup(ctx, backup.BackupId)
if err != nil {
log.Fatalf("Failed to describe backup: %w", err)
}
// wait for backup to be "Complete" before triggering a restore job
log.Printf("Backup status: %v", backup.Status)
limit := 10
backups, err := pc.ListBackups(ctx, &pinecone.ListBackupsParams{
Limit: &limit,
IndexName: &indexName,
})
if err != nil {
log.Fatalf("Failed to list backups: %w", err)
}
// create a new serverless index from the backup
restoredIndexName := indexName + "-from-backup"
restoredIndexTags := pinecone.IndexTags{"restored_on": time.Now().Format("2006-01-02 15:04")}
createIndexFromBackupResp, err := pc.CreateIndexFromBackup(context.Background(), &pinecone.CreateIndexFromBackupParams{
BackupId: ts.backupId,
Name: restoredIndexName,
Tags: &restoredIndexTags,
})
// check the status of the index restoration
restoreJob, err := pc.DescribeRestoreJob(ctx, restoreJob.RestoreJobId)
if err != nil {
log.Fatalf("Failed to describe restore job: %w", err)
}
}
Inference Models
You can now use the InferenceService
class within Client.Inference
to browse models hosted by Pinecone, including detailed configuration options for each model.
You can list all available models, with the options of filtering by model Type
("embed"
, "rerank"
), and VectorType
("sparse"
, "dense"
) for models with Type
"embed"
.
import (
"context"
"log"
"github.com/pinecone-io/go-pinecone/v4/pinecone"
)
func InferenceModels() {
ctx := context.Background()
pc, err := pinecone.NewClient(pinecone.NewClientParams{
ApiKey: "YOUR_API_KEY",
})
if err != nil {
log.Fatalf("Failed to create Client: %v", err)
}
embed := "embed"
rerank := "rerank"
embedModels, err := pc.Inference.ListModels(ctx, &pinecone.ListModelsParams{
Type: &embed,
})
if err != nil {
log.Fatalf("Failed to list embedding models: %v", err)
}
rerankModels, err := pc.Inference.ListModels(ctx, &pinecone.ListModelsParams{
Type: &rerank,
})
if err != nil {
log.Fatalf("Failed to list reranking models: %v", err)
}
}
You can also describe a single model by name:
import (
"context"
"fmt"
"log"
"github.com/pinecone-io/go-pinecone/v4/pinecone"
)
func InferenceModel() {
ctx := context.Background()
pc, err := pinecone.NewClient(pinecone.NewClientParams{
ApiKey: "YOUR_API_KEY",
})
if err != nil {
log.Fatalf("Failed to create Client: %v", err)
}
model, err := pc.Inference.DescribeModel(ctx, "multilingual-e5-large")
if err != nil {
log.Fatalf("Failed to get model: %v", err)
}
fmt.Printf("Model (multilingual-e5-large): %+v\n", model)
}
Bug fixes & Breaking Changes
IndexConnection
now properly supports targeting multiple namespaces in an index while reusing the underlying gRPC connection instead of needing to re-dial every time. you want to target a new namespace in your index. IndexConnection
used to expose Namespace
as a field, which could be updated at any time, and was originally set when creating a new IndexConnection
through Client
using NewIndexConnParams
. Now, you can re-use IndexConnection
against a new namespace by using IndexConnection.WithNamespace
, which will return a new pointer to a shallow copy of the struct.
package main
import (
"context"
"log"
"github.com/pinecone-io/go-pinecone/v4/pinecone"
)
func WithNamespace() {
ctx := context.Background()
pc, err := pinecone.NewClient(pinecone.NewClientParams{
ApiKey: "YOUR_API_KEY",
})
if err != nil {
log.Fatalf("Failed to create Client: %v", err)
}
idx, err := pc.DescribeIndex(ctx, "example-index")
if err != nil {
log.Fatalf("Failed to describe index \"%v\": %v", idx.Name, err)
}
idxConnectionNs1, err := pc.Index(pinecone.NewIndexConnParams{Host: idx.Host, Namespace: "namespace-1"})
if err != nil {
log.Fatalf("Failed to create IndexConnection for Host: %v: %v", idx.Host, err)
}
// This will reuse the gRPC connection while targeting a different namespace
idxConnectionNs2 := idxConnectionNs1.WithNamespace("namespace-2")
vectors := []*pinecone.Vector{
{
Id: "A",
Values: []float32{0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1},
},
{
Id: "B",
Values: []float32{0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2},
},
{
Id: "C",
Values: []float32{0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3},
},
{
Id: "D",
Values: []float32{0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4},
},
}
countNs1, err := idxConnectionNs1.UpsertVectors(ctx, vectors)
if err != nil {
log.Fatalf("Failed to upsert vectors to \"example-index\" in \"namespace-1\": %w", err)
}
countNs2, err := idxConnectionNs2.UpsertVectors(ctx, vectors)
if err != nil {
log.Fatalf("Failed to upsert vectors to \"example-index\" in \"namespace-1\": %w", err)
}
}
The Embed
operation on InferenceService
now properly returns different structs when you're embedding using a sparse or dense model. Previously, only dense embedding values would be returned successfully. To handle this, the Embedding
type has been updated to a tagged union holding one of either two pointers to a SparseEmbedding
, or DenseEmbedding
.
What's Changed
- Bump dependency:
golang.org/x/net@v0.35.0
by @austin-denoble in #111 - Update go.mod to support v4.0.0 major version update by @austin-denoble in #110
- Implement Backups/Restore by @austin-denoble in #109
- docs: update example code for
StartImport
function by @HurSungYun in #108 - Implement Inference Models and Namespaces APIs by @austin-denoble in #107
- Regenerate core off of
2025-04
by @austin-denoble in #106
New Contributors
- @HurSungYun made their first contribution in #108
Full Changelog: v3.1.0...v4.0.0