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序列化的优势。
欢迎捐款!随意打开问题或公关。