Pinecone.net เป็นไลบรารี C# เต็มรูปแบบสำหรับฐานข้อมูลเวกเตอร์ Pinecone
นี่คือห้องสมุดชุมชนที่ให้การสนับสนุนชั้นหนึ่งสำหรับ Pinecone ใน C# และ F#
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 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 } " ) ;
}
} วิธีการที่คล้ายกันสามารถใช้ในการกู้คืนจากการดำเนินการที่สตรีมหรือแบทช์อื่น ๆ
ดู ListOperationException , ParallelFetchException และ ParallelDeleteException ใน vectortypes.cs
ชอบ RestTransport ตามค่าเริ่มต้น โปรดค้นหาคำอธิบายโดยละเอียดสำหรับสถานการณ์เฉพาะด้านล่าง
GrpcTransport เป็นทางเลือกที่ทำงานได้สำหรับการลดทราฟฟิกเครือข่ายเมื่อทำงานกับเวกเตอร์ขนาดใหญ่ภายใต้สถานการณ์การรับส่งข้อมูลต่ำถึงปานกลาง
Protobuf เข้ารหัสเวกเตอร์ในลักษณะที่กะทัดรัดมากขึ้นดังนั้นหากคุณมีเวกเตอร์มิติสูง ( GrpcTransport +), การร้องขอพร้อมกันในระดับต่ำ
ในทางทฤษฎีปริมาณงานที่เกิดขึ้นพร้อมกันต่ำอาจสูงขึ้นด้วย GrpcTransport เนื่องจากการรับส่งข้อมูลเครือข่ายที่ลดลง แต่เนื่องจากการส่งคำขอหลายครั้งในแบบขนาน (และความจริงที่ว่าการ Fetch Upsert และ Delete ทำโดยอัตโนมัติ) ข้อดีของวิธีการนี้มีแนวโน้มที่จะถูก จำกัด
ในช่วงเวลาของการเขียนสแต็ก HTTP/2 ของ Pinecone ได้รับการกำหนดค่าให้อนุญาตให้ใช้สตรีม HTTP/2 เพียงไม่กี่หรือเพียง 1
เนื่องจาก HTTP/2 เป็นข้อบังคับสำหรับ GRPC สิ่งนี้ทำให้เกิดการร้องขออย่างมีนัยสำคัญในช่อง GRPC ภายใต้สถานการณ์ที่เกิดขึ้นพร้อมกันสูงส่งผลให้ความสามารถในการปรับขนาดได้ไม่ดีของ GrpcTransport ที่มีเพดานต่ำสำหรับปริมาณงาน
ผู้ใช้ที่ไม่ได้ตระหนักถึงข้อ จำกัด นี้อาจประสบกับการเพิ่มขึ้นของเวลาแฝงที่ไม่คาดคิดในการดำเนินการแบบสอบถามภายใต้การเพิ่มจำนวนผู้ใช้ต่อโหนดแอปพลิเคชันและ/หรือต่ำกว่าที่คาดไว้มากที่สุดและดึงข้อมูลปริมาณงานแม้ว่าจะระบุระดับความเท่าเทียมกันของการดำเนินการของ Upsert และ Fetch ด้วยตนเอง
Pinecone.NET บางส่วนบรรเทาปัญหานี้โดยการกำหนดค่าช่อง GRPC เพื่อใช้ประโยชน์จากการปรับสมดุลโหลดฝั่งไคลเอ็นต์ (บันทึก DNS) เพื่อใช้ประโยชน์จากหลายช่องทางย่อย (ปัจจุบันมี 3 รายการที่ส่งคืนโดยแบบสอบถาม DNS) ซึ่งคาดว่าจะให้การรับส่งข้อมูลที่ดีกว่าลูกค้าอื่น ๆ นอกจากนี้ยังช่วยให้การใช้การเชื่อมต่อ HTTP/2 หลายครั้งต่อจุดสิ้นสุดสำหรับ SocketsHttpHandler พื้นฐาน แต่การใช้งาน GRPC ปัจจุบันดูเหมือนจะไม่ได้ใช้ประโยชน์จากสิ่งนี้อย่างเหมาะสม
ข้างต้นเป็นการสังเกตพฤติกรรมของลูกค้าภายใต้การทดสอบโหลดและปัจจัยโครงสร้างพื้นฐานเพิ่มเติมอาจมีการเล่นตามที่ระบุไว้โดยรายงานผู้ใช้ที่ Forum WRT ของชุมชน Pinecone ในการใช้งานอื่น ๆ
ผู้ใช้ผู้เชี่ยวชาญที่ยังคงต้องการใช้การขนส่ง GRPC ในสถานการณ์ที่โหลดสูงอาจต้องการสำรวจรายการแอ็คชั่นเพิ่มเติมที่อยู่นอกขอบเขตของห้องสมุดที่สนับสนุนชุมชนอย่างง่ายนี้:
ผู้ใช้ทั่วไปควรใช้ RestTransport สำหรับสถานการณ์ที่มีความเร็วสูงและ/หรือสถานการณ์พร้อมกันสูงแทนเว้นแต่การประเมิน GrpcTransport ในสภาพแวดล้อมเฉพาะของพวกเขาจะให้ผลลัพธ์ที่ดีกว่า
ณ ตอนนี้ RestTransport และ System.Text.Json ที่ใช้สำหรับการทำให้เป็นอนุกรมดูเหมือนจะมีประสิทธิภาพมากกว่าหน่วยความจำมากกว่า GrpcTransport และ Protobuf นี่ไม่ใช่ข้อ จำกัด โดยธรรมชาติของ GRPC แต่เป็นผลมาจากการใช้งานปัจจุบันของ grpc-dotnet System.Text.Json ได้รับการปรับให้เหมาะสมอย่างมากเกี่ยวกับการจัดสรรทราฟฟิกและส่งผลให้การใช้หน่วยความจำที่ยั่งยืนลดลงอย่างมีนัยสำคัญภายใต้แสงและหนัก ด้วยสถานะปัจจุบันของการใช้งาน grpc-dotnet ฉันไม่คาดหวังว่าจะมีการเปลี่ยนแปลงในอนาคตอันใกล้ มันเป็น "ดีพอ" สำหรับแอปพลิเคชันส่วนใหญ่ แต่ความแตกต่างของขนาดฮีปที่ยั่งยืนภายใต้โหลดมีความสำคัญเพียงพอที่จะรับประกันการระบุสิ่งนี้อย่างชัดเจน
โปรดทราบว่า Pinecone.NET ดำเนินการก่อสร้าง/อ่านซ้ำของ RepeatedField<float> ที่เก็บค่าเวกเตอร์เพื่อบรรเทาความดันการจัดสรร แต่ก็ไม่เพียงพอที่จะชดเชยความได้เปรียบของการใช้ System.Text.Json Serialization
ยินดีต้อนรับ! อย่าลังเลที่จะเปิดปัญหาหรือการประชาสัมพันธ์