Ini adalah klien scala penuh async intuitif untuk API Pinecone yang mendukung semua indeks, vektor, pengumpulan, inferensi, dan operasi/titik akhir yang tersedia, disediakan dalam dua layanan nyaman yang disebut PineconEvectorService dan PineconeIndexService. Panggilan yang didukung adalah:
PineconeAssistantService dan PineconeAssistantFileService Perhatikan bahwa agar konsisten dengan penamaan API Pinecone, nama fungsi layanan cocok dengan judul/deskripsi titik akhir API dengan CamelCase. Juga, kami mengarahkan Lib untuk mandiri dengan ketergantungan sececepat yang dimungkinkan oleh karena itu kami akhirnya hanya menggunakan dua LIBS play-ahc-ws-standalone dan play-ws-standalone-json (di level atas).
✔️ PENTING : Ini adalah perpustakaan "terawat di komunitas" dan, dengan demikian, tidak ada hubungannya dengan perusahaan Pinecone.
Lihat artikel tentang lib/klien di medium. Juga, jika Anda ingin melihat contoh langsung, buka contoh-contoh Pinecone atau modul Contoh Pinecone OpenAi + Pinecone.
Versi Scala yang saat ini didukung adalah 2.12, 2.13 , dan 3 .
Untuk menarik perpustakaan, Anda harus menambahkan ketergantungan berikut ke build.sbt Anda
"io.cequence" %% "pinecone-scala-client" % "1.2.2"
atau ke pom.xml (jika Anda menggunakan maven)
<dependency>
<groupId>io.cequence</groupId>
<artifactId>pinecone-scala-client_2.12</artifactId>
<version>1.2.2</version>
</dependency>
PINECONE_SCALA_CLIENT_API_KEY , dan PINECONE_SCALA_CLIENT_ENV jika layanan berbasis pod digunakan Ia. Mendapatkan PineconeIndexService
Pertama, Anda perlu memberikan konteks eksekusi implisit serta AKKA Materizer, misalnya, sebagai
implicit val ec = ExecutionContext .global
implicit val materializer = Materializer ( ActorSystem ())Kemudian Anda dapat memperoleh layanan (pod atau berbasis server tanpa server) dengan salah satu cara berikut.
Config ) import io . cequence . pineconescala . service . PineconeIndexServiceFactory . FactoryImplicits
val service = PineconeIndexServiceFactory ().asOne val config = ConfigFactory .load( " path_to_my_custom_config " )
val service = PineconeIndexServiceFactory (config).asOnePineconePodBasedIndexService val service = PineconeIndexServiceFactory (
apiKey = " your_api_key " ,
environment = " your_env " // e.g. "northamerica-northeast1-gcp
)PineconeServerlessIndexService val service = PineconeIndexServiceFactory (
apiKey = " your_api_key "
) IB. Memperoleh PineconeVectorService
Sama seperti dengan PineconeIndexService , Anda harus terlebih dahulu memberikan konteks eksekusi implisit dan Akka Materizer. Kemudian Anda dapat memperoleh layanan dengan salah satu cara berikut.
Config ). Perhatikan bahwa jika indeks dengan nama yang diberikan tidak tersedia, pabrik tidak akan mengembalikan None . PineconeVectorServiceFactory ( " index_name " ).map { serviceOption =>
val service = serviceOption.getOrElse(
throw new Exception ( s " Index with a given name does not exist. " )
)
// do something with the service
} Ic. Mendapatkan PineconeInferenceService
Sama seperti dengan PineconeIndexService , Anda harus terlebih dahulu memberikan konteks eksekusi implisit dan Akka Materizer. Kemudian Anda dapat memperoleh layanan dengan salah satu cara berikut.
val service = PineconeInferenceServiceFactory () val config = ConfigFactory .load( " path_to_my_custom_config " )
val service = PineconeInferenceServiceFactory (config) val service = PineconeInferenceServiceFactory (
apiKey = " your_api_key "
) Pengenal. Mendapatkan PineconeAssistantService
val service = PineconeAssistantServiceFactory () val config = ConfigFactory .load( " path_to_my_custom_config " )
val service = PineconeAssistantServiceFactory (config) val service = PineconeAssistantServiceFactory (
apiKey = " your_api "
) Yaitu. Mendapatkan PineconeAssistantFileService
val service = PineconeAssistantFileServiceFactory () val config = ConfigFactory .load( " path_to_my_custom_config " )
val service = PineconeAssistantFileServiceFactory (config) val service = PineconeAssistantFileServiceFactory (
apiKey = " your_api "
)Ii. Fungsi panggilan
Dokumentasi lengkap dari setiap panggilan dengan input dan pengaturan masing -masing disediakan di PineconevectorService dan PineconeIndexService. Karena semua panggilan tidak ada, mereka mengembalikan tanggapan yang dibungkus di Future .
Contoh:
Operasi Indeks
pineconeIndexService.listIndexes.map(indexes =>
indexes.foreach(println)
) import io . cequence . pineconescala . domain . response . CreateResponse
pineconeIndexService.createIndex(
name = " auto-gpt-test " ,
dimension = 1536
).map {
case CreateResponse . Created => println( " Index successfully created. " )
case CreateResponse . BadRequest => println( " Index creation failed. Request exceeds quota or an invalid index name. " )
case CreateResponse . AlreadyExists => println( " Index with a given name already exists. " )
} pineconeIndexService.describeIndex( " index_name " ).map(indexInfo =>
// if not found, indexInfo will be None
println(indexInfo)
) import io . cequence . pineconescala . domain . response . DeleteResponse
pineconeIndexService.deleteIndex( " index_name " ).map {
case DeleteResponse . Deleted => println( " Index successfully deleted. " )
case DeleteResponse . NotFound => println( " Index with a given name not found. " )
} import io . cequence . pineconescala . domain . response . ConfigureIndexResponse
pineconeIndexService.configureIndex(
name = " index_name " ,
replicas = Some ( 2 ),
pod_type = Some ( PodType .p1_x2)
).map {
case ConfigureIndexResponse . Updated => println( " Index successfully updated. " )
case ConfigureIndexResponse . BadRequestNotEnoughQuota => println( " Index update failed. Not enough quota. " )
case ConfigureIndexResponse . NotFound => println( " Index with a given name not found. " )
}Operasi Pengumpulan
pineconeIndexService.listCollections.map(collectionNames =>
println(collectionNames.mkString( " , " ))
) import io . cequence . pineconescala . domain . response . CreateResponse
pineconeIndexService.createCollection(
name = " collection_name " ,
source = " index_name "
).map {
case CreateResponse . Created => println( " Collection successfully created. " )
case CreateResponse . BadRequest => println( " Collection creation failed. Request exceeds quota or an invalid collection name. " )
case CreateResponse . AlreadyExists => println( " Collection with a given name already exists. " )
} pineconeIndexService.describeCollection( " collection_name " ).map(collectionInfo =>
// if not found, collectionInfo will be None
println(collectionInfo)
) import io . cequence . pineconescala . domain . response . DeleteResponse
pineconeIndexService.deleteCollection( " collection_name " ).map {
case DeleteResponse . Deleted => println( " Collection successfully deleted. " )
case DeleteResponse . NotFound => println( " Collection with a given name not found. " )
}Operasi Vektor
val dimension = 1536
pineconeVectorService.upsert(
vectors = Seq (
PVector (
id = " 666 " ,
values = Seq .fill(dimension)( Random .nextDouble),
metadata = Map (
" is_relevant " -> " not really but for testing it's ok, you know " ,
" food_quality " -> " brunches are perfect but don't go there before closing time "
)
),
PVector (
id = " 777 " ,
values = Seq .fill(dimension)( Random .nextDouble),
metadata = Map (
" is_relevant " -> " very much so " ,
" food_quality " -> " burritos are the best! "
)
)
),
namespace = " my_namespace " ,
).map(vectorUpsertedCount =>
println( s " Upserted $vectorUpsertedCount vectors. " )
) val fetchedValues = ... // vectors fetched from somewhere
pineconeVectorService.update(
id = " 777 " ,
namespace = " my_namespace " ,
values = fetchedValues.map(_ / 100 ), // divide fetched values by 100
sparseValues = Some ( SparseVector (
indices = Seq ( 1 , 2 , 3 ),
values = Seq ( 8.8 , 7.7 , 2.2 )
)),
setMetaData = Map (
" solid_info " -> " this is the source of the truth "
)
).map(_ =>
println( s " Vectors updated. " )
) pineconeVectorService.query(
vector = Seq .fill( 1536 )( Random .nextDouble), // some values/embeddings
namespace = " my_namespace "
).map { queryResponse =>
queryResponse.matches.foreach { matchInfo =>
println( s " Matched vector id: ${matchInfo.id} " )
println( s " Matched vector values: ${matchInfo.values.take( 20 ).mkString( " , " )} .. " )
println( s " Matched vector score: ${matchInfo.score} " )
println( s " Matched vector metadata: ${matchInfo.metadata} " )
}
} pineconeVectorService.query(
vector = Seq .fill( 1536 )( Random .nextDouble), // some values/embeddings
namespace = " my_namespace " ,
settings = QuerySettings (
topK = 5 ,
includeValues = true ,
includeMetadata = true
)
).map { queryResponse =>
queryResponse.matches.foreach { matchInfo =>
println( s " Matched vector id: ${matchInfo.id} " )
println( s " Matched vector values: ${matchInfo.values.take( 20 ).mkString( " , " )} .. " )
println( s " Matched vector score: ${matchInfo.score} " )
println( s " Matched vector metadata: ${matchInfo.metadata} " )
}
} pineconeVectorService.fetch(
ids = Seq ( " 666 " , " 777 " ),
namespace = " my_namespace "
).map { fetchResponse =>
fetchResponse.vectors.values.map { pVector =>
println( s " Fetched vector id: ${pVector.id} " )
println( s " Fetched vector values: ${pVector.values.take( 20 ).mkString( " , " )} .. " )
println( s " Fetched vector metadata: ${pVector.metadata} " )
}
} pineconeVectorService.delete(
ids = Seq ( " 666 " , " 777 " ),
namespace = " my_namespace "
).map(_ =>
println( " Vectors deleted " )
) pineconeVectorService.deleteAll(
namespace = " my_namespace "
).map(_ =>
println( " All vectors deleted " )
) pineconeVectorService.describeIndexStats.map(stats =>
println(stats)
)Operasi Inferensi
pineconeInferenceService.createEmbeddings(
Seq ( " The quick brown fox jumped over the lazy dog " )
).map { embeddings =>
println(embeddings.data.mkString( " n " ))
} pineconeInferenceService.rerank(
query = " The tech company Apple is known for its innovative products like the iPhone. " ,
documents = Seq (...)
).map(
_.data.foreach(println)
) pineconeInferenceService.evaluate(
question = " What are the capital cities of France, England and Spain? " ,
answer = " Paris is a city of France and Barcelona of Spain " ,
groundTruthAnswer = " Paris is the capital city of France, London of England and Madrid of Spain "
).map { response =>
println(response)
}** Asisten Operasi **
pineconeAssistantService.listAssistants.map(assistants =>
println(assistants.mkString( " , " ))
) import io . cequence . pineconescala . domain . response . CreateResponse
pineconeAssistantService.createAssistant(
name = " assistant_name " ,
description = " assistant_description " ,
assistantType = " assistant_type "
).map {
case CreateResponse . Created => println( " Assistant successfully created. " )
case CreateResponse . BadRequest => println( " Assistant creation failed. Request exceeds quota or an invalid assistant name. " )
case CreateResponse . AlreadyExists => println( " Assistant with a given name already exists. " )
} pineconeAssistantService.describeAssistant( " assistant_name " ).map(assistant =>
// if not found, assistant will be None
println(assistant)
) import io . cequence . pineconescala . domain . response . DeleteResponse
pineconeAssistantService.deleteAssistant( " assistant_name " ).map {
case DeleteResponse . Deleted => println( " Assistant successfully deleted. " )
case DeleteResponse . NotFound => println( " Assistant with a given name not found. " )
} pineconeAssistantService.listFiles( " assistant_name " ).map(files =>
println(files.mkString( " , " ))
) import io . cequence . pineconescala . domain . response . CreateResponse
pineconeAssistantService.uploadFile(
assistantName = " assistant_name " ,
filePath = " path_to_file "
).map {
case CreateResponse . Created => println( " File successfully uploaded. " )
case CreateResponse . BadRequest => println( " File upload failed. Request exceeds quota or an invalid file path. " )
case CreateResponse . AlreadyExists => println( " File with a given name already exists. " )
} pineconeAssistantService.describeFile( " assistant_name " , " file_name " ).map(file =>
// if not found, file will be None
println(file)
) pineconeAssistantService.chatWithAssistant(
" assistant_name " ,
" What is the maximum height of a red pine? "
).map(response =>
println(response)
)Untuk demo siap pakai, mohon. Lihat modul terpisah:
Saya mendapat pengecualian timeout. Bagaimana cara mengubah pengaturan batas waktu?
Anda dapat melakukannya dengan meneruskan param timeouts ke Pinecone{Vector,Index}ServiceFactory atau, jika Anda menggunakan file konfigurasi Anda sendiri, maka Anda cukup menambahkannya di sana sebagai:
pinecone-scala-client {
timeouts {
requestTimeoutSec = 200
readTimeoutSec = 200
connectTimeoutSec = 5
pooledConnectionIdleTimeoutSec = 60
}
}
Saya mendapat pengecualian seperti com.typesafe.config.ConfigException$UnresolvedSubstitution: pinecone-scala-client.conf @ jar:file:.../io/cequence/pinecone-scala-client_2.13/1.2.2/pinecone-scala-client_2.13-1.2.2.jar!/pinecone-scala-client.conf: 4: Could not resolve substitution to a value: ${PINECONE_SCALA_CLIENT_API_KEY} . Apa yang harus saya lakukan?
Atur env. variabel PINECONE_SCALA_CLIENT_API_KEY . Jika Anda tidak memiliki satu daftar di sini.
Semuanya terlihat keren. Saya ingin mengobrol dengan Anda tentang penelitian dan pengembangan Anda?
Cukup tembak kami email di [email protected].
Perpustakaan ini tersedia dan diterbitkan sebagai open source di bawah ketentuan lisensi MIT.
Proyek ini open-source dan menyambut setiap kontribusi atau umpan balik (di sini).
Pengembangan perpustakaan ini telah didukung oleh - cequence.io - The future of contracting
Dibuat dan dikelola oleh Peter Banda.