حزمة hnsw تنفذ الرسوم البيانية العالمية الصغيرة الصالحة للملاحة في GO. يمكنك قراءة كيفية عملهم هنا. في جوهرها ، فإنها تسمح بإجراء عمليات بحث تقريبية تقريبية تقريبية مع بيانات متجه عالية الأبعاد.
يمكن اعتبار هذه الحزمة بديلاً في الذاكرة لقاعدة بيانات المتجه المفضلة لديك (مثل Pinecone ، Weaviate). ينفذ فقط العمليات الأساسية:
| عملية | تعقيد | وصف |
|---|---|---|
| أدخل | أدخل ناقل في الرسم البياني | |
| يمسح | حذف ناقل من الرسم البياني | |
| يبحث | ابحث عن أقرب جيران المتجه | |
| ابحث عن | استرداد ناقل بالمعرف |
ملحوظة
التعقيدات تقريبية أين
go get github.com/coder/hnsw@main
g := hnsw . NewGraph [ int ]()
g . Add (
hnsw . MakeNode ( 1 , [] float32 { 1 , 1 , 1 }),
hnsw . MakeNode ( 2 , [] float32 { 1 , - 1 , 0.999 }),
hnsw . MakeNode ( 3 , [] float32 { 1 , 0 , - 0.5 }),
)
neighbors := g . Search (
[] float32 { 0.5 , 0.5 , 0.5 },
1 ,
)
fmt . Printf ( "best friend: %v n " , neighbors [ 0 ]. Vec )
// Output: best friend: [1 1 1] في حين أن جميع عمليات الرسم البياني في الذاكرة ، hnsw يوفر مرافق للتحميل/الادخار من التخزين المستمر.
لواجهة io.Reader / io.Writer ، استخدم Graph.Export و Graph.Import .
إذا كنت تستخدم ملفًا واحدًا كواجهة خلفية ، فإن HNSW يوفر نوعًا مناسبًا SavedGraph بدلاً من ذلك:
path := "some.graph"
g1 , err := LoadSavedGraph [ int ]( path )
if err != nil {
panic ( err )
}
// Insert some vectors
for i := 0 ; i < 128 ; i ++ {
g1 . Add ( hnsw . MakeNode ( i , [] float32 { float32 ( i )}))
}
// Save to disk
err = g1 . Save ()
if err != nil {
panic ( err )
}
// Later...
// g2 is a copy of g1
g2 , err := LoadSavedGraph [ int ]( path )
if err != nil {
panic ( err )
}انظر المزيد:
نستخدم ترميزًا ثنائيًا سريعًا للرسم البياني ، حتى تتوقع حفظ/تحميل تقريبًا بسرعة القرص. على جهاز M3 MacBook الخاص بي ، أحصل على هذه النتائج القياسية:
goos: darwin
goarch: arm64
pkg: github.com/coder/hnsw
BenchmarkGraph_Import-16 4029 259927 ns/op 796.85 MB/s 496022 B/op 3212 allocs/op
BenchmarkGraph_Export-16 7042 168028 ns/op 1232.49 MB/s 239886 B/op 2388 allocs/op
PASS
ok github.com/coder/hnsw 2.624s
عند حفظ/تحميل رسم بياني من 100 متجهات مع 256 أبعاد.
إلى حد كبير ، فإن أكبر تأثير يمكن أن يكون له على أداء الرسم البياني يقلل من أبعاد بياناتك. في 1536 أبعاد (Openai Default) ، يتم إنفاق 70 ٪ من عملية الاستعلام تحت المعلمات الافتراضية في وظيفة المسافة.
إذا كنت تكافح مع البطء / الكمون ، فكر في:
وإذا كنت تكافح مع استخدام الذاكرة الزائدة ، ففكر:
Graph.M (الحد الأقصى لعدد الجيران يمكن أن يكون لكل عقدة)Graph.Ml (معلمة توليد المستوى) تبدو الذاكرة العلوية للرسم البياني مثل:
أين:
يمكنك أن تستنتج ما يلي:
في مثال الرسم البياني مع 256 أبعاد ، و
ونمو الذاكرة خطي في الغالب.