Pinecone.net是Pinecone Vector數據庫的符合人數的C#庫。
這是一個社區庫,在C#和F#中為Pinecone提供一流的支持。
dotnet add package Pinecone.NET或Install-Package Pinecone.NET
使用索引
using Pinecone ;
// Initialize the client with your API key
using var pinecone = new PineconeClient ( "your-api-key" ) ;
// List all indexes
var indexes = await pinecone . ListIndexes ( ) ;
// Create a new index if it doesn't exist
var indexName = "myIndex" ;
if ( ! indexes . Contains ( indexName ) )
{
await pinecone . CreateServerlessIndex ( indexName , 1536 , Metric . Cosine , "aws" , "us-east-1" ) ;
}
// Get the Pinecone index by name (uses REST by default).
// The index client is thread-safe, consider caching and/or
// injecting it as a singleton into your DI container.
using var index = await pinecone . GetIndex ( indexName ) ;
// Configure an index
await pinecone . ConfigureIndex ( indexName , replicas : 2 , podType : "p2" ) ;
// Delete an index
await pinecone . DeleteIndex ( indexName ) ;與矢量一起工作
// Assuming you have an instance of `index`
// Create and upsert vectors
var vectors = new [ ]
{
new Vector
{
Id = "vector1" ,
Values = new float [ ] { 0.1f , 0.2f , 0.3f , .. . } ,
Metadata = new MetadataMap
{
[ "genre" ] = "horror" ,
[ "duration" ] = 120
}
}
} ;
await index . Upsert ( vectors ) ;
// Fetch vectors by IDs
var fetched = await index . Fetch ( [ "vector1" ] ) ;
// Query scored vectors by ID
var scored = await index . Query ( "vector1" , topK : 10 ) ;
// Query scored vectors by a new, previously unseen vector
var vector = new [ ] { 0.1f , 0.2f , 0.3f , .. . } ;
var scored = await index . Query ( vector , topK : 10 ) ;
// Query scored vectors by ID with metadata filter
var filter = new MetadataMap
{
[ "genre" ] = new MetadataMap
{
[ "$in" ] = new [ ] { "documentary" , "action" }
}
} ;
var scored = await index . Query ( "birds" , topK : 10 , filter ) ;
// Delete vectors by vector IDs
await index . Delete ( new [ ] { "vector1" } ) ;
// Delete vectors by metadata filter
await index . Delete ( new MetadataMap
{
[ "genre" ] = new MetadataMap
{
[ "$in" ] = new [ ] { "documentary" , "action" }
}
} ) ;
// Delete all vectors in the index
await index . DeleteAll ( ) ;與收藏合作
using Pinecone ;
// Assuming you have an instance of `PineconeClient` named `pinecone`
// List all collections
var collections = await pinecone . ListCollections ( ) ;
// Create a new collection
await pinecone . CreateCollection ( "myCollection" , "myIndex" ) ;
// Describe a collection
var details = await pinecone . DescribeCollection ( "myCollection" ) ;
// Delete a collection
await pinecone . DeleteCollection ( "myCollection" ) ; 從批處理平行的UPSERT上的失敗中恢復
// Upsert with recovery from up to three failures on batched parallel upsert.
//
// The parallelization is done automatically by the client based on the vector
// dimension and the number of vectors to upsert. It aims to keep the individual
// request size below Pinecone's 2MiB limit with some safety margin for metadata.
// This behavior can be further controlled by calling the 'Upsert' overload with
// custom values for 'batchSize' and 'parallelism' parameters.
//
// This is not the most efficient implementation in terms of allocations in
// GC pause frequency sensitive scenarios, but is perfectly acceptable
// for pretty much all regular back-end applications.
// Assuming there is an instance of 'index' available
// Generate 25k random vectors
var vectors = Enumerable
. Range ( 0 , 25_000 )
. Select ( _ => new Vector
{
Id = Guid . NewGuid ( ) . ToString ( ) ,
Values = Enumerable
. Range ( 0 , 1536 )
. Select ( _ => Random . Shared . NextSingle ( ) )
. ToArray ( )
} )
. ToArray ( ) ;
// Specify the retry limit we are okay with
var retries = 3 ;
while ( true )
{
try
{
// Perform the upsert
await index . Upsert ( vectors ) ;
// If no exception is thrown, break out of the retry loop
break ;
}
catch ( ParallelUpsertException e ) when ( retries -- > 0 )
{
// Create a hash set to efficiently filter out the failed vectors
var filter = e . FailedBatchVectorIds . ToHashSet ( ) ;
// Filter out the failed vectors from the batch and assign them to
// the 'vectors' variable consumed by 'Upsert' operation above
vectors = vectors . Where ( v => filter . Contains ( v . Id ) ) . ToArray ( ) ;
Console . WriteLine ( $ "Retrying upsert due to error: { e . Message } " ) ;
}
}可以使用類似的方法來從其他流或批處理操作中恢復。
請參閱vectortypes.cs中的ListOperationException , ParallelFetchException和ParallelDeleteException 。
默認情況下,更喜歡RestTransport 。請找到以下特定方案的詳細說明。
GrpcTransport是在低至中等吞吐量方案下與大型向量合作時,可以減少網絡流量的可行替代方案。
Protobuf以更緊湊的方式編碼矢量,因此,如果您具有高維矢量(1536-3072+),請求較低的並發性程度,通常在小型BACTHES中使用或提取向量,則值得考慮使用GrpcTransport 。
從理論上講,由於網絡流量的減少, GrpcTransport的同時吞吐量可能會更高,但是由於簡單地並行派遣多個請求是多麼微不足道(以及Fetch , Upsert和Delete自動這樣做的事實),因此此方法的優勢可能受到限制。
在撰寫本文時,Pinecone的HTTP/2堆棧被配置為每個單個HTTP/2連接的幾乎甚至1個並發流。
由於HTTP/2對於GRPC是強制性的,因此在高並發方案下,這會導致在GRPC通道上排隊的重大請求,從而導致GrpcTransport的可擴展性較差,而吞吐量較低。
不知道此限制的用戶在每個應用程序節點的用戶數量增長和/或比預期的UPSERT和獲取吞吐量低得多的用戶可能會出現意外的延遲增加,即使手動指定了更高的Upsert和Fetch操作的並行性。
Pinecone.NET通過配置GRPC頻道利用客戶端負載平衡(基於DNS記錄)來部分緩解此問題,以利用多個子渠道(當前有3個由DNS查詢返回的3個),預計將提供比其他客戶端更好的吞吐量。它還可以使每個端點的多個HTTP/2連接用於基礎SocketsHttpHandler ,但是當前的GRPC實現似乎無法正確利用這一點。
以上是對負載測試下的客戶行為的觀察,其他基礎架構因素可能正在發揮作用,如Pinecone社區論壇WRT可伸縮性在其他實現中所示。
仍然希望在高負載方案中使用GRPC運輸的專家用戶可能需要探索不超出這個簡單社區支持的庫的範圍的進一步的操作項目:
建議常規用戶使用RestTransport進行高通量和/或高並發方案,除非他們在特定環境中對GrpcTransport的評估會產生更好的結果。
截至目前, RestTransport和System.Text.Json用於序列化似乎比GrpcTransport和Protobuf更具記憶效率。這不是GRPC的固有限制,而是grpc-dotnet當前實現的結果。 System.Text.Json在分配流量方面得到了大量優化,並在輕度和重載下導致持續記憶使用量明顯降低。鑑於grpc-dotnet實施的當前狀態,我預計在不久的將來會發生變化。對於大多數應用程序,它已經“足夠好”,但是負載下持續的堆尺寸差異足夠顯著,可以明確說明這一點。
請注意, Pinecone.NET已經執行零拷貝的構造/讀取RepeatedField<float>存儲矢量值以減輕分配壓力,但這還不足以抵消使用System.Text.Json序列化的優勢。
歡迎捐款!隨意打開問題或公關。