Skip to content

v5.0.0 Release

Latest
Compare
Choose a tag to compare
@rohanshah18 rohanshah18 released this 19 May 15:47
· 3 commits to main since this release
cb00bc3

This version of the Pinecone Java SDK introduces indexes with integrated inference, backups and restore, and ability to work more explicitly with namespaces. It also supports version 2025-04 of the Pinecone API. You can read more about versioning here.

Features

Indexes with Integrated Inference

This release adds the following method for integrated inference. Together these methods provide a way for you to easily store your data and let us manage the process of creating embeddings. To learn about available models, see the Model Gallery.

  1. Create index for model i.e. create an index with an associated embedding model
  2. Configure an existing index to associate it with an embedding model
  3. Upsert records
  4. Search records by id
  5. Search records by vector
  6. Search records by text
import io.pinecone.clients.Index;
import io.pinecone.clients.Pinecone;
import io.pinecone.helpers.RandomStringBuilder;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.openapitools.db_control.client.model.CreateIndexForModelRequest;
import org.openapitools.db_control.client.model.CreateIndexForModelRequestEmbed;
import org.openapitools.db_control.client.model.DeletionProtection;
import org.openapitools.db_data.client.ApiException;
import org.openapitools.db_data.client.model.SearchRecordsRequestQuery;
import org.openapitools.db_data.client.model.SearchRecordsResponse;
import org.openapitools.db_data.client.model.UpsertRecord;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
...

Pinecone pinecone = new Pinecone.Builder(System.getenv("PINECONE_API_KEY")).build();
String indexName = RandomStringBuilder.build("inf", 8);

// Create index associated with a model
HashMap<String, String> fieldMap = new HashMap<>();
fieldMap.put("text", "chunk_text");
CreateIndexForModelRequestEmbed embed = new CreateIndexForModelRequestEmbed()
        .model("multilingual-e5-large")
        .fieldMap(fieldMap);
pinecone.createIndexForModel(indexName, CreateIndexForModelRequest.CloudEnum.AWS, "us-west-2", embed, DeletionProtection.DISABLED, new HashMap<>());

// Wait for index to be created
Thread.sleep(10000);

Index index = pinecone.getIndexConnection(indexName);

// Upsert records
HashMap<String, String> record1 = new HashMap<>();
record1.put("_id", "rec1");
record1.put("category", "digestive system");
record1.put("chunk_text", "Apples are a great source of dietary fiber, which supports digestion and helps maintain a healthy gut.");

HashMap<String, String> record2 = new HashMap<>();
record2.put("_id", "rec2");
record2.put("category", "cultivation");
record2.put("chunk_text", "Apples originated in Central Asia and have been cultivated for thousands of years, with over 7,500 varieties available today.");

HashMap<String, String> record3 = new HashMap<>();
record3.put("_id", "rec3");
record3.put("category", "immune system");
record3.put("chunk_text", "Rich in vitamin C and other antioxidants, apples contribute to immune health and may reduce the risk of chronic diseases.");

HashMap<String, String> record4 = new HashMap<>();
record4.put("_id", "rec4");
record4.put("category", "endocrine system");
record4.put("chunk_text", "The high fiber content in apples can also help regulate blood sugar levels, making them a favorable snack for people with diabetes.");

upsertRecords.add(record1);
upsertRecords.add(record2);
upsertRecords.add(record3);
upsertRecords.add(record4);

index.upsertRecords("example-namespace", upsertRecords);

// Wait for vectors to be upserted
Thread.sleep(5000);

String namespace = "example-namespace";
List<String> fields = new ArrayList<>();
fields.add("category");
fields.add("chunk_text");

SearchRecordsRequestRerank rerank = new SearchRecordsRequestRerank()
    .model("bge-reranker-v2-m3")
    .topN(2)
    .rankFields(Arrays.asList("chunk_text"));

// Search records
SearchRecordsResponse recordsResponse = index.searchRecordsByText("Disease prevention", namespace, fields, 4, null, rerank);
System.out.println(recordsResponse);

Backups and restore

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.

Following methods were added for Backups:

  1. createBackup(String indexName, String backupName, String description)
  2. listIndexBackups(String indexName)
  3. listIndexBackups(String indexName, Integer limit, String paginationToken)
  4. listProjectBackups()
  5. describeBackup(String backupId)
  6. deleteBackup(String backupId)
  7. createIndexFromBackup(String backupId,
  8. String indexName,
  9. Map<String, String> tags,
  10. DeletionProtection deletionProtection)
  11. CreateIndexFromBackupResponse createIndexFromBackup(String backupId, String indexName)

Following methods were added for Restore:

  1. describeRestoreJob(String jobId)
  2. listRestoreJobs(Integer limit)
  3. listRestoreJobs(String paginationToken)
  4. listRestoreJobs(Integer limit, String paginationToken)

Below code shows all of the methods added for backup and restore for a serverless index.

import io.pinecone.clients.Pinecone;
import org.openapitools.db_control.client.ApiException;
import org.openapitools.db_control.client.model.*;
...

Pinecone pinecone = new Pinecone.Builder("PINECONE_API_KEY").build();

String indexName1 = "test-index-1";
String indexName2 = "test-index-2";

// create a backup from index
BackupModel backupModel1 = pinecone.createBackup(indexName1, "backup-id-1", "description-for-backup-1");
System.out.println("backupModel1: " + backupModel1);

BackupModel backupModel2 = pinecone.createBackup(indexName2, "backup-id-2", "description-for-backup-2");
System.out.println("backupModel2: " + backupModel2);

// list all backups for an index
BackupList backupList = pinecone.listIndexBackups(indexName1);
System.out.println("backupList for index1: " + backupList);

// list all backups for a project
backupList = pinecone.listProjectBackups();
System.out.println("backupList for project: " + backupList);

// describe backup
backupModel1 = pinecone.describeBackup(backupModel1.getBackupId());
System.out.println("describe backup for index1: " + backupModel1);

backupModel2 = pinecone.describeBackup(backupModel2.getBackupId());
System.out.println("describe backup index2: " + backupModel2);

// delete backup
pinecone.deleteBackup(backupModel1.getBackupId());

// wait for the backup to be ready
Thread.sleep(10000);

// create index from a backup
CreateIndexFromBackupResponse backupResponse = pinecone.createIndexFromBackup(backupModel1.getBackupId(), "test-index-3");
System.out.println(backupResponse.getRestoreJobId());

// wait for index to be created
Thread.sleep(5000);

// describeRestoreJob
RestoreJobModel restoreJobModel = pinecone.describeRestoreJob(backupResponse.getRestoreJobId());
System.out.println("restore model: " + restoreJobModel);

// listRestoreJobs
RestoreJobList restoreJobList = pinecone.listRestoreJobs(2);
System.out.println("restore job list: " + restoreJobList);

Namespaces

You now have the ability to work more explicitly with namespaces that are associated with an index. There have been several namespace methods added to the Index class:

  1. listNamespaces()
  2. listNamespaces(String paginationToken)
  3. listNamespaces(String paginationToken, int limit)
  4. describeNamespace(String namespace)
  5. deleteNamespace(String namespace)

Following example shows listNamespaces(), describeNamespace(), and deleteNamespace() methods for both index and asyncIndex.

import io.pinecone.clients.AsyncIndex;
import io.pinecone.clients.Index;
import io.pinecone.clients.Pinecone;
import io.pinecone.proto.ListNamespacesResponse;
import io.pinecone.proto.NamespaceDescription;

import java.util.concurrent.ExecutionException;
...

String indexName = "PINECONE_INDEX_NAME";
Pinecone pinecone = new Pinecone.Builder("PINECONE_API_KEY").build();

//// Sync index example
Index index = pinecone.getIndexConnection(indexName);

// list namespaces without pagination token and limit (if no limit is passed, it'll default to 100)
ListNamespacesResponse listNamespacesResponse = index.listNamespaces();

// list namespaces with pagination token
listNamespacesResponse = index.listNamespaces("some-pagination-token");

// list namespaces with pagination token and a custom limit of 5
listNamespacesResponse = index.listNamespaces("some-pagination-token", 5);

// describe a namespace
NamespaceDescription namespaceDescription = index.describeNamespace("namespace");

// delete a namespace
index.deleteNamespace("namespace");


//// AsyncIndex example
AsyncIndex asyncIndex = pinecone.getAsyncIndexConnection(indexName);

// list namespaces without pagination token and limit (if no limit is passed, it'll default to 100)
ListNamespacesResponse asyncListNamespacesResponse = index.listNamespaces();

// list namespaces with pagination token
asyncListNamespacesResponse = asyncIndex.listNamespaces("some-pagination-token").get();

// list namespaces with pagination token and a custom limit of 5
asyncListNamespacesResponse = asyncIndex.listNamespaces("some-pagination-token", 5).get();

// describe a namespace
NamespaceDescription asyncNamespaceDescription = asyncIndex.describeNamespace("some-namespace").get();

// delete a namespace
asyncIndex.deleteNamespace("some-namespace");

What's Changed

  • Add integrated inference by @rohanshah18 in #181
  • Generate code for 2025-04, automate ndjson handling, add backups, restore, and namespaces. by @rohanshah18 in #183

Full Changelog: v4.0.1...v5.0.0