Skip to content

Commit aa293cc

Browse files
committed
Examples added to README
1 parent e883b52 commit aa293cc

File tree

1 file changed

+289
-32
lines changed

1 file changed

+289
-32
lines changed

README.md

Lines changed: 289 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
11
# Pinecone Scala Client 🗄️
22
[![version](https://img.shields.io/badge/version-0.0.1-green.svg)](https://cequence.io) [![License](https://img.shields.io/badge/License-MIT-lightgrey.svg)](https://opensource.org/licenses/MIT) ![GitHub Stars](https://img.shields.io/github/stars/cequence-io/pinecone-scala?style=social) [![Twitter Follow](https://img.shields.io/twitter/follow/0xbnd?style=social)](https://twitter.com/0xbnd)
33

4-
This is a no-nonsense async Scala client for Pinecone API supporting all the available vector and index/collection operations/endpoints, provided in two convenient services called [PineconeVectorService](./pinecone-core/src/main/scala/io/cequence/pineconescala/service/PineconeVectorService.scala) and [PineconeIndexService](./pinecone-core/src/main/scala/io/cequence/pineconescala/service/PineconeIndexService.scala). The supported calls are:
4+
This is an intuitive async Scala client for Pinecone API supporting all the available vector and index/collection operations/endpoints, provided in two convenient services called [PineconeVectorService](./pinecone-core/src/main/scala/io/cequence/pineconescala/service/PineconeVectorService.scala) and [PineconeIndexService](./pinecone-core/src/main/scala/io/cequence/pineconescala/service/PineconeIndexService.scala). The supported calls are:
55

66
* **Vector Operations**: [describeIndexStats](https://docs.pinecone.io/reference/describe_index_stats_post), [query](https://docs.pinecone.io/reference/query), [delete](https://docs.pinecone.io/reference/delete_post), [fetch](https://docs.pinecone.io/reference/fetch), [update](https://docs.pinecone.io/reference/update), and [upsert](https://docs.pinecone.io/reference/upsert)
7-
* **Collection Operations**: [listCollections](https://docs.pinecone.io/reference/list_collections), [createCollection](https://docs.pinecone.io/reference/create_collection), [describeCollection](https://docs.pinecone.io/reference/describe_collection), and [delete_collection](https://docs.pinecone.io/reference/delete_collection)
7+
* **Collection Operations**: [listCollections](https://docs.pinecone.io/reference/list_collections), [createCollection](https://docs.pinecone.io/reference/create_collection), [describeCollection](https://docs.pinecone.io/reference/describe_collection), and [deleteCollection](https://docs.pinecone.io/reference/delete_collection)
88
* **Index Operations**: [listIndexes](https://docs.pinecone.io/reference/list_indexes), [creatIndex](https://docs.pinecone.io/reference/create_index), [describeIndex](https://docs.pinecone.io/reference/describe_index), [deleteIndex](https://docs.pinecone.io/reference/delete_index), and [configureIndex](https://docs.pinecone.io/reference/configure_index)
99

1010
Note that in order to be consistent with the Pinecone API naming, the service function names match exactly the API endpoint titles/descriptions with camelcase.
11-
Also, we aimed the lib to be self-contained with the fewest dependencies possible therefore we ended up using only two libs `play-ahc-ws-standalone` and `play-ws-standalone-json` (at the top level). Additionally, if dependency injection is required we use `scala-guice` lib as well.
11+
Also, we aimed the lib to be self-contained with the fewest dependencies possible therefore we ended up using only two libs `play-ahc-ws-standalone` and `play-ws-standalone-json` (at the top level).
1212

1313
**✔️ Important**: this is a "community-maintained" library and, as such, has no relation to Pinecone company.
1414

1515
## Installation 🚀
1616

17-
The currently supported Scala versions are **2.12, 2.13**, and **3**. Note that an optional module `pinecone-scala-guice` is available only for Scala 2.12 and 2.13.
17+
The currently supported Scala versions are **2.12, 2.13**, and **3**.
1818

1919
To pull the library you have to add the following dependency to your *build.sbt*
2020

@@ -39,7 +39,7 @@ or to *pom.xml* (if you use maven)
3939

4040
## Usage 👨‍🎓
4141

42-
**I. Obtaining `PineconeVectorService` and `PineconeIndexService`**
42+
**Ia. Obtaining `PineconeIndexService`**
4343

4444
First you need to provide an implicit execution context as well as akka materializer, e.g., as
4545

@@ -51,11 +51,6 @@ First you need to provide an implicit execution context as well as akka material
5151
Then you can obtain a service in one of the following ways.
5252

5353
- Default config (expects env. variable(s) to be set as defined in `Config` section)
54-
```scala
55-
val service = PineconeVectorServiceFactory("index_name")
56-
```
57-
58-
or
5954

6055
```scala
6156
val service = PineconeIndexServiceFactory()
@@ -64,56 +59,318 @@ or
6459
- Custom config
6560
```scala
6661
val config = ConfigFactory.load("path_to_my_custom_config")
67-
val service = PineconeVectorServiceFactory("index_name", config)
62+
val service = PineconeIndexServiceFactory(config)
63+
```
64+
65+
- Without config
66+
```scala
67+
val service = PineconeIndexServiceFactory(
68+
apiKey = "your_api_key",
69+
environment = "your_env" // e.g. "northamerica-northeast1-gcp
70+
)
6871
```
6972

70-
or
73+
**Ib. Obtaining `PineconeVectorService`**
74+
75+
Same as with `PineconeIndexService`, you need to first provide implicit execution context and akka materializer. Then you can obtain a service in one of the following ways.
7176

77+
- Default config (expects env. variable(s) to be set as defined in `Config` section). Note that if the index with a given name is not available, the factory will return `None`.
78+
```scala
79+
PineconeVectorServiceFactory("index_name").map { serviceOption =>
80+
val service = serviceOption.getOrElse(
81+
throw new Exception(s"Index with a given name does not exist.")
82+
)
83+
// do something with the service
84+
}
85+
```
86+
87+
- Custom config
7288
```scala
7389
val config = ConfigFactory.load("path_to_my_custom_config")
74-
val service = PineconeIndexServiceFactory(config)
90+
PineconeVectorServiceFactory("index_name", config).map { service =>
91+
val service = serviceOption.getOrElse(
92+
throw new Exception(s"Index with a given name does not exist.")
93+
)
94+
// do something with the service
95+
}
7596
```
7697

7798
- Without config
7899

79100
```scala
80-
val service = PineconeVectorServiceFactory(
81-
apiKey = "your_api_key",
82-
environment = "your_env", // e.g. "northamerica-northeast1-gcp
83-
indexName = "index_name", // e.g. "auto-gpt-xxxxxxx"
101+
PineconeVectorServiceFactory(
102+
apiKey = "your_api_key",
103+
indexName = "index_name", // e.g. "auto-gpt"
104+
pineconeIndexService = pineconeIndexService // index service to be used to find the index host URL
105+
).map { serviceOption =>
106+
val service = serviceOption.getOrElse(
107+
throw new Exception(s"Index with a given name does not exist.")
108+
)
109+
// do something with the service
110+
}
111+
```
112+
113+
**II. Calling functions**
114+
115+
Full documentation of each call with its respective inputs and settings is provided in [PineconeVectorService](./pinecone-core/src/main/scala/io/cequence/pineconescala/service/PineconeVectorService.scala) and [PineconeIndexService](./pinecone-core/src/main/scala/io/cequence/pineconescala/service/PineconeIndexService.scala). Since all the calls are async they return responses wrapped in `Future`.
116+
117+
Examples:
118+
119+
**Index Operations**
120+
121+
- List indexes
122+
123+
```scala
124+
pineconeIndexService.listIndexes.map(indexes =>
125+
indexes.foreach(println)
84126
)
85127
```
86128

87-
or
129+
- Create index (with default settings)
88130

89131
```scala
90-
val service = PineconeIndexServiceFactory(
91-
apiKey = "your_api_key",
92-
environment = "your_env" // e.g. "northamerica-northeast1-gcp
132+
import io.cequence.pineconescala.domain.response.CreateResponse
133+
134+
pineconeIndexService.createIndex(
135+
name = "auto-gpt-test",
136+
dimension = 1536
137+
).map(
138+
_ match {
139+
case CreateResponse.Created => println("Index successfully created.")
140+
case CreateResponse.BadRequest => println("Index creation failed. Request exceeds quota or an invalid index name.")
141+
case CreateResponse.AlreadyExists => println("Index with a given name already exists.")
142+
}
93143
)
94144
```
95145

96-
**II. Calling functions**
146+
- Describe index
97147

98-
Full documentation of each call with its respective inputs and settings is provided in [PineconeVectorService](./pinecone-core/src/main/scala/io/cequence/pineconescala/service/PineconeVectorService.scala) and [PineconeIndexService](./pinecone-core/src/main/scala/io/cequence/pineconescala/service/PineconeIndexService.scala). Since all the calls are async they return responses wrapped in `Future`.
148+
```scala
149+
pineconeIndexService.describeIndex("index_name").map(indexInfo =>
150+
// if not found, indexInfo will be None
151+
println(indexInfo)
152+
)
153+
```
99154

100-
Examples:
155+
- Delete index
156+
157+
```scala
158+
import io.cequence.pineconescala.domain.response.DeleteResponse
159+
160+
pineconeIndexService.deleteIndex("index_name").map(
161+
_ match {
162+
case DeleteResponse.Deleted => println("Index successfully deleted.")
163+
case DeleteResponse.NotFound => println("Index with a given name not found.")
164+
}
165+
)
166+
```
167+
168+
- Configure index
169+
170+
```scala
171+
import io.cequence.pineconescala.domain.response.ConfigureIndexResponse
172+
173+
pineconeIndexService.configureIndex(
174+
name = "index_name",
175+
replicas = Some(2),
176+
pod_type = Some(PodType.p1_x2)
177+
).map(deleteResponse =>
178+
deleteResponse match {
179+
case ConfigureIndexResponse.Updated => println("Index successfully updated.")
180+
case ConfigureIndexResponse.BadRequestNotEnoughQuota => println("Index update failed. Not enough quota.")
181+
case ConfigureIndexResponse.NotFound => println("Index with a given name not found.")
182+
}
183+
)
184+
```
185+
186+
**Collection Operations**
101187

102188
- List collections
103189

104190
```scala
105-
service.listCollections.map(models =>
106-
models.foreach(println)
191+
pineconeIndexService.listCollections.map(collectionNames =>
192+
println(collectionNames.mkString(", "))
193+
)
194+
```
195+
196+
- Create collection
197+
198+
```scala
199+
import io.cequence.pineconescala.domain.response.CreateResponse
200+
201+
pineconeIndexService.createCollection(
202+
name = "collection_name",
203+
source = "index_name"
204+
).map(
205+
_ match {
206+
case CreateResponse.Created => println("Collection successfully created.")
207+
case CreateResponse.BadRequest => println("Collection creation failed. Request exceeds quota or an invalid collection name.")
208+
case CreateResponse.AlreadyExists => println("Collection with a given name already exists.")
209+
}
210+
)
211+
```
212+
213+
- Describe collection
214+
215+
```scala
216+
pineconeIndexService.describeCollection("collection_name").map(collectionInfo =>
217+
// if not found, collectionInfo will be None
218+
println(collectionInfo)
219+
)
220+
```
221+
222+
- Delete collection
223+
224+
```scala
225+
import io.cequence.pineconescala.domain.response.DeleteResponse
226+
227+
pineconeIndexService.deleteCollection("collection_name").map(
228+
_ match {
229+
case DeleteResponse.Deleted => println("Collection successfully deleted.")
230+
case DeleteResponse.NotFound => println("Collection with a given name not found.")
231+
}
107232
)
108233
```
109234

110-
TODO
235+
**Vector Operations**
236+
237+
- Upsert
238+
239+
```scala
240+
val dimension = 1536
241+
242+
pineconeVectorService.upsert(
243+
vectors = Seq(
244+
PVector(
245+
id = "666",
246+
values = Seq.fill(dimension)(Random.nextDouble),
247+
metadata = Map(
248+
"is_relevant" -> "not really but for testing it's ok, you know",
249+
"food_quality" -> "brunches are perfect but don't go there before closing time"
250+
)
251+
),
252+
PVector(
253+
id = "777",
254+
values = Seq.fill(dimension)(Random.nextDouble),
255+
metadata = Map(
256+
"is_relevant" -> "very much so",
257+
"food_quality" -> "burritos are the best!"
258+
)
259+
)
260+
),
261+
namespace = "my_namespace",
262+
).map(vectorUpsertedCount =>
263+
println(s"Upserted $vectorUpsertedCount vectors.")
264+
)
265+
```
266+
267+
- Update
268+
269+
```scala
270+
val fetchedValues = ... // vectors fetched from somewhere
271+
272+
pineconeVectorService.update(
273+
id = "777",
274+
namespace = "my_namespace",
275+
values = fetchedValues.map(_ / 100), // divide fetched values by 100
276+
sparseValues = Some(SparseVector(
277+
indices = Seq(1, 2, 3),
278+
values = Seq(8.8, 7.7, 2.2)
279+
)),
280+
setMetaData = Map(
281+
"solid_info" -> "this is the source of the truth"
282+
)
283+
).map(_ =>
284+
println(s"Vectors updated.")
285+
)
286+
```
287+
288+
- Query with default settings
289+
290+
```scala
291+
pineconeVectorService.query(
292+
vector = Seq.fill(1536)(Random.nextDouble), // some values/embeddings
293+
namespace = "my_namespace"
294+
).map { queryResponse =>
295+
queryResponse.matches.foreach { matchInfo =>
296+
println(s"Matched vector id: ${matchInfo.id}")
297+
println(s"Matched vector values: ${matchInfo.values.take(20).mkString(", ")}..")
298+
println(s"Matched vector score: ${matchInfo.score}")
299+
println(s"Matched vector metadata: ${matchInfo.metadata}")
300+
}
301+
}
302+
```
303+
304+
- Query with custom settings
305+
306+
```scala
307+
pineconeVectorService.query(
308+
vector = Seq.fill(1536)(Random.nextDouble), // some values/embeddings
309+
namespace = "my_namespace",
310+
settings = QuerySettings(
311+
topK = 5,
312+
includeValues = true,
313+
includeMetadata = true
314+
)
315+
).map { queryResponse =>
316+
queryResponse.matches.foreach { matchInfo =>
317+
println(s"Matched vector id: ${matchInfo.id}")
318+
println(s"Matched vector values: ${matchInfo.values.take(20).mkString(", ")}..")
319+
println(s"Matched vector score: ${matchInfo.score}")
320+
println(s"Matched vector metadata: ${matchInfo.metadata}")
321+
}
322+
}
323+
```
324+
325+
- Fetch
326+
327+
```scala
328+
pineconeVectorService.fetch(
329+
ids = Seq("666", "777"),
330+
namespace = "my_namespace"
331+
).map { fetchResponse =>
332+
fetchResponse.vectors.values.map { pVector =>
333+
println(s"Fetched vector id: ${pVector.id}")
334+
println(s"Fetched vector values: ${pVector.values.take(20).mkString(", ")}..")
335+
println(s"Fetched vector metadata: ${pVector.metadata}")
336+
}
337+
}
338+
```
339+
340+
- Delete by id(s)
341+
342+
```scala
343+
pineconeVectorService.delete(
344+
ids = Seq("666", "777"),
345+
namespace = "my_namespace"
346+
).map(_ =>
347+
println("Vectors deleted")
348+
)
349+
```
350+
351+
- Delete all
352+
353+
```scala
354+
pineconeVectorService.deleteAll(
355+
namespace = "my_namespace"
356+
).map(_ =>
357+
println("All vectors deleted")
358+
)
359+
```
360+
361+
- Describe index stats
362+
363+
```scala
364+
pineconeVectorService.describeIndexStats.map(stats =>
365+
println(stats)
366+
)
367+
```
111368

112369
## FAQ 🤔
113370

114-
1. I got a timeout exception. How can I change the timeout setting?_
371+
1. _I got a timeout exception. How can I change the timeout setting?_
115372

116-
You can do it either by passing the `timeouts` param to `PineconeServiceFactory` or, if you use your own configuration file, then you can simply add it there as:
373+
You can do it either by passing the `timeouts` param to `Pinecone{Vector,Index}ServiceFactory` or, if you use your own configuration file, then you can simply add it there as:
117374

118375
```
119376
pinecone-scala-client {
@@ -126,12 +383,12 @@ pinecone-scala-client {
126383
}
127384
```
128385

129-
2. I got an exception like `com.typesafe.config.ConfigException$UnresolvedSubstitution: pinecone-scala-client.conf @ jar:file:.../io/cequence/pinecone-scala-client_2.13/0.0.1/pinecone-scala-client_2.13-0.0.1.jar!/pinecone-scala-client.conf: 4: Could not resolve substitution to a value: ${PINECONE_SCALA_CLIENT_API_KEY}`. What should I do?_
386+
2. _I got an exception like `com.typesafe.config.ConfigException$UnresolvedSubstitution: pinecone-scala-client.conf @ jar:file:.../io/cequence/pinecone-scala-client_2.13/0.0.1/pinecone-scala-client_2.13-0.0.1.jar!/pinecone-scala-client.conf: 4: Could not resolve substitution to a value: ${PINECONE_SCALA_CLIENT_API_KEY}`. What should I do?_
130387

131-
Set the env. variable `PINECONE_SCALA_CLIENT_API_KEY`. If you don't have one register [here](https://beta.pinecone.com/signup).
388+
Set the env. variable `PINECONE_SCALA_CLIENT_API_KEY`. If you don't have one register [here](https://app.pinecone.io/?sessionType=signup).
132389

133390

134-
3_It all looks cool. I want to chat with you about your research and development?_
391+
3. _It all looks cool. I want to chat with you about your research and development?_
135392

136393
Just shoot us an email at [[email protected]](mailto:[email protected]?subject=Research%20andDevelopment).
137394

0 commit comments

Comments
 (0)