DiskANN: una soluzione ANNS basata su disco con alto richiamo e QPS elevato su dataset su scala di miliardi
“DiskANN: Fast Accurate Billion-point Nearest Neighbor Search on a Single Node” è un articolo pubblicato su NeurIPS nel 2019. L’articolo introduce un metodo all’avanguardia per eseguire la costruzione dell’indice e la ricerca su dataset su scala di miliardi utilizzando una singola macchina con soli 64GB di RAM e un SSD sufficientemente capiente. Inoltre, soddisfa i tre requisiti dell’ANNS (Approximate Nearest Neighbor Search) su dataset su larga scala: alto recall, bassa latenza e alta densità (numero di nodi in una singola macchina). Questo metodo costruisce un indice basato su grafo su un dataset su scala di miliardi SIFT-1B utilizzando una singola macchina con 64GB di RAM e una CPU a 16 core, raggiungendo 5000 QPS (query al secondo) con oltre il 95 % di recall@1, e una latenza media inferiore a 3ms.
Autori
Suhas Jayaram Subramanya: Ex dipendente del Microsoft India Research Institute, dottorando della CMU. I principali interessi di ricerca sono il calcolo ad alte prestazioni e gli algoritmi di machine learning per dati su larga scala.
Devvrit: Assistente di ricerca laureato presso The University of Texas at Austin. I suoi interessi di ricerca sono l’informatica teorica, il machine learning e il deep learning.
Rohan Kadekodi: Dottorando presso l’University of Texas. La sua direzione di ricerca è sistemi e storage, includendo principalmente storage persistente, file system e storage kV.
Ravishankar Krishaswamy: Principal researcher del Microsoft Indian research institute. Dottore della CMU. La direzione di ricerca è l’algoritmo di approssimazione basato su grafi e clustering.
Harsha Vardhan Simhadri: Principal researcher del Microsoft Indian research institute. Dottore della CMU. In passato, ha studiato algoritmi paralleli e sistemi runtime. Ora il suo lavoro principale è sviluppare nuovi algoritmi e scrivere modelli di programmazione.
Motivazioni
La maggior parte degli algoritmi ANNS più diffusi compie alcuni compromessi tra prestazioni di costruzione dell’indice, prestazioni di ricerca e recall. Gli algoritmi basati su grafo come HNSW e NSG sono attualmente metodi allo stato dell’arte in termini di prestazioni di ricerca e recall. Poiché il metodo di indicizzazione basato su grafo residente in memoria occupa troppa memoria, è relativamente difficile indicizzare e cercare un dataset su larga scala utilizzando una singola macchina con risorse di memoria limitate.
Molte applicazioni richiedono risposte rapide di ANNS basata sulla distanza euclidea su dataset su scala di miliardi. Di seguito sono riportate due soluzioni principali:
Indice invertito + quantizzazione: raggruppare il dataset in M partizioni e comprimere il dataset utilizzando schemi di quantizzazione come PQ (Product Quantization). Questa soluzione produce un basso recall a causa di una perdita di precisione causata dalla compressione dei dati. Aumentare il topk aiuta a migliorare il recall, mentre il QPS diminuirebbe di conseguenza.
Dividere e indicizzare: dividere il dataset in diversi shard disgiunti e costruire un indice in memoria per ciascuno shard. Quando arrivano richieste di query, la ricerca verrà eseguita sugli indici di ciascuno shard e i risultati verranno restituiti dopo il merge. Questa soluzione causa la sovra-espansione della scala del dataset, e quindi sono necessarie più macchine a causa della restrizione delle risorse di memoria in una singola macchina, portando a un QPS basso.
Entrambe le soluzioni menzionate sopra sono limitate dalla restrizione di memoria di una singola macchina. Questo articolo propone la progettazione di un meccanismo di indicizzazione residente su SSD per risolvere questo problema. La sfida dell’indicizzazione residente su SSD è ridurre il numero di accessi casuali al disco e il numero di richieste di accesso al disco.
Contributi
Questo articolo presenta uno schema ANNS residente su SSD chiamato DiskANN, che può supportare efficacemente la ricerca su dataset su larga scala. Questo schema si basa su un algoritmo basato su grafo presentato in questo articolo: Vamana. I contributi di questo articolo includono:
DiskANN può indicizzare e cercare un dataset su scala di miliardi di oltre 100 dimensioni su una singola macchina con 64GB RAM, fornendo oltre il 95% di recall@1 con latenze inferiori a 5 millisecondi.
È stato proposto un nuovo algoritmo basato su grafi chiamato Vamana, con un raggio di ricerca inferiore rispetto a quelli di NSG e HNSW, per minimizzare il numero di accessi al disco.
Vamana può funzionare in memoria e le sue prestazioni non sono inferiori a quelle di NSG e HNSW.
Indici Vamana più piccoli, costruiti su partizioni sovrapposte del grande dataset, possono essere uniti in un unico grafo senza perdere connettività.
Vamana può essere combinato con schemi di quantizzazione come PQ. La struttura del grafo e i dati originali sono archiviati sul disco, mentre i dati compressi sono mantenuti in memoria.
Vamana
Questo algoritmo è simile all’idea di NSG[2][4] (per chi non comprende NSG, fare riferimento al Riferimento [2], e se non si vogliono leggere articoli, si può fare riferimento al Riferimento [4]). La loro principale differenza risiede nella strategia di trimming. Per essere precisi, alla strategia di trimming di NSG è stato aggiunto uno switch alpha. L’idea principale della strategia di trimming di NSG è che la scelta dei vicini del punto target sia il più diversificata possibile. Se il nuovo vicino è più vicino a un vicino del punto target che al punto target, non è necessario aggiungere questo punto all’insieme dei punti vicini. In altre parole, per ogni vicino del punto target, non possono esserci altri punti vicini entro il raggio circostante dist (punto target, punto vicino). Questa strategia di trimming controlla efficacemente il grado uscente del grafo ed è relativamente radicale. Riduce l’occupazione di memoria dell’indice, migliora la velocità di ricerca, ma riduce anche l’accuratezza della ricerca. La strategia di trimming di Vamana consiste nel controllare liberamente la scala del trimming tramite il parametro alpha. Il principio di funzionamento consiste nel moltiplicare la dist (un punto vicino, punto candidato) nella condizione di trimming per un parametro alpha (non inferiore a 1). Solo quando la dist (punto target, un determinato punto candidato) è maggiore della distanza di riferimento ampliata viene adottata la strategia di trimming, aumentando la tolleranza dell’esclusione reciproca tra i vicini del punto target.
Il processo di indicizzazione di Vamana è relativamente semplice:
Inizializzare un grafo casuale;
Calcolare il punto di partenza, che è simile al punto di navigazione di NSG. Innanzitutto, trovare il centroide globale, quindi trovare il punto più vicino al centroide globale come punto di navigazione. La differenza tra Vamana e NSG è che l’input di NSG è già un grafo dei vicini più prossimi, quindi gli utenti possono semplicemente eseguire una ricerca approssimata del vicino più prossimo sul punto centroide direttamente sul grafo dei vicini iniziale. Tuttavia, Vamana inizializza un grafo casuale dei vicini più prossimi, quindi gli utenti non possono condurre una ricerca approssimata direttamente sul grafo casuale. Devono effettuare un confronto globale per ottenere un punto di navigazione come punto di partenza delle iterazioni successive. Lo scopo di questo punto è minimizzare il raggio medio di ricerca;
Eseguire la ricerca approssimata del vicino più prossimo su ciascun punto in base al grafo casuale dei vicini inizializzato e al punto di partenza della ricerca determinato nel passaggio 2, rendere tutti i punti sul percorso di ricerca gli insiemi di vicini candidati ed eseguire la strategia di trimming degli archi usando alpha = 1. Analogamente a NSG, selezionare l’insieme di punti sul percorso di ricerca a partire dal punto di navigazione come insieme di vicini candidati aumenterà alcuni archi lunghi e ridurrà efficacemente il raggio di ricerca.
Regolare alpha > 1 (l’articolo raccomanda 1.2) e ripetere il passaggio 3. Poiché il passaggio 3 si basa su un grafo casuale dei vicini più prossimi, il grafo è di bassa qualità dopo la prima iterazione. Pertanto, è necessaria un’altra iterazione per migliorare la qualità del grafo, il che è molto importante per il tasso di recall.
Questo articolo confronta i tre indici a grafo, ovvero Vamana, NSG e HNSW. In termini di prestazioni di indicizzazione e query, Vamana e NSG sono relativamente vicini, ed entrambi superano leggermente HNSW. Fare riferimento alla sezione Esperimenti qui sotto per i dati.
Figura 1.
Per visualizzare il processo di costruzione dell'indice Vamana, il paper fornisce un grafo, in cui 200 punti bidimensionali vengono utilizzati per simulare due cicli di iterazione. La prima riga usa alpha = 1 per potare gli archi. Si può vedere che la strategia di potatura è relativamente radicale, e viene potato un gran numero di archi. Dopo aver aumentato il valore alpha e allentato le condizioni di potatura, molti archi vengono ovviamente aggiunti di nuovo. Nel grafo finale, vengono aggiunti parecchi archi lunghi. Ciò può ridurre efficacemente il raggio di ricerca.
DiskANN
Un personal computer con solo 64GB di memoria non riuscirebbe nemmeno a contenere un miliardo di dati grezzi, per non parlare dell'indice costruito su di essi. Ci sono due sfide da affrontare: 1. Come indicizzare un set di dati di così larga scala con risorse di memoria limitate? 2. Come calcolare la distanza durante la ricerca se i dati originali non possono essere caricati in memoria?
Il paper ha proposto le seguenti soluzioni:
Per la prima sfida: innanzitutto, dividere i dati in k cluster usando k-means, quindi allocare ogni punto negli i cluster più vicini. Generalmente, 2 è sufficiente per il numero i. Costruire un indice Vamana basato su memoria per ciascun cluster, e infine fondere k indici Vamana in uno solo.
Per la seconda sfida: costruire l'indice sui vettori originali e interrogare i vettori compressi. Costruire gli indici sul vettore originale garantisce la qualità del grafo, mentre il vettore compresso può essere caricato in memoria per una ricerca a grana grossa. Sebbene la ricerca con i vettori compressi possa causare una perdita di accuratezza, la direzione generale sarà corretta purché la qualità del grafo sia sufficientemente alta. Il risultato finale della distanza sarà calcolato usando il vettore originale.
Il layout dell'indice di DiskANN è simile a quello degli indici grafici generali. L'insieme dei vicini di ogni punto e i dati del vettore originale vengono memorizzati insieme. Questo sfrutta meglio la località dei dati.
Come menzionato in precedenza, se i dati dell'indice sono memorizzati sull'SSD, il numero di accessi al disco e le richieste di lettura e scrittura del disco devono essere ridotti il più possibile per garantire una bassa latenza di ricerca. Pertanto DiskANN propone due strategie di ottimizzazione:
Cache hotspot: memorizzare in cache in memoria tutti i punti entro C salti dal punto di partenza. Il valore di C è meglio impostarlo entro 3 o 4.
Beam search: In parole semplici, consiste nel precaricare le informazioni sui vicini. Quando si cerca il punto p, il punto vicino di p deve essere caricato dal disco se non è in memoria. Poiché una piccola quantità di operazioni di accesso casuale all'SSD richiede circa lo stesso tempo di un'operazione di accesso a un singolo settore dell'SSD, le informazioni sui vicini di W punti non accessi possono essere caricate alla volta. W non può essere impostato né troppo grande né troppo piccolo. Un W grande sprecherà risorse di calcolo e larghezza di banda dell'SSD, mentre uno piccolo aumenterà la latenza di ricerca.
Esperimento
L'esperimento consiste in tre gruppi:
Confronto tra indici basati su memoria: Vamana VS. NSG VS. HNSW
Set di dati: SIFT1M (128 dimensioni), GIST1M (960 dimensioni), DEEP1M (96 dimensioni) e un set di dati da 1M campionato casualmente da DEEP1B.
Parametri dell'indice (tutti i set di dati usano lo stesso insieme di parametri):
HNSW:M = 128, efc = 512.
Vamana: R = 70, L = 75, alpha = 1.2.
NSG: R = 60, L = 70, C= 500.
I parametri di ricerca non sono forniti nel paper, il che potrebbe essere coerente con i parametri di indicizzazione. Per la selezione dei parametri, i parametri di NSG menzionati nell'articolo si basano sui parametri elencati nel repository GitHub di NSG per selezionare il gruppo con prestazioni migliori. Vamana e NSG sono relativamente vicini, quindi anche i parametri sono impostati in modo simile. Tuttavia, il motivo della selezione dei parametri di HNSW non è fornito. Riteniamo che il parametro M di HNSW sia impostato relativamente grande. Ciò potrebbe portare a un confronto meno convincente tra indici basati su grafo se i loro gradi uscenti non sono impostati allo stesso livello.
Con i parametri di indicizzazione sopra indicati, il tempo di indicizzazione di Vamana, HNSW e NSG è rispettivamente di 129s, 219s e 480s. Il tempo di indicizzazione di NSG include il tempo per costruire il grafo iniziale dei vicini con EFANN [3].
Curva Recall-QPS:
Figure 2.
Dalla Figura 3 si può vedere che Vamana ha prestazioni eccellenti sui tre set di dati, simili a NSG e leggermente migliori di HNSW.
Confronto del raggio di ricerca:
Dalla Figura 2.c, possiamo vedere che Vamana ha il percorso di ricerca medio più breve a parità di tasso di recall rispetto a quelli di NSG e HNSW.
Confronto tra un indice costruito in una sola volta e un grande indice fuso
Set di dati: SIFT1B
Parametri dell’indice costruito in una sola volta: L = 50, R = 128, alpha = 1.2. Dopo l’esecuzione per 2 giorni su una macchina DDR3 da 1800G, il picco di memoria è di circa 1100 G e l’out-degree medio è 113.9.
Procedura di indicizzazione basata sulla fusione:
Addestrare 40 cluster sul dataset usando kmeans;
Ogni punto viene distribuito nei 2 cluster più vicini;
Costruire un indice Vamana con L = 50, R = 64 e alpha = 1.2 per ciascun cluster;
Fondere gli indici di ciascun cluster.
Questo indice ha generato un indice da 384GB con un out-of-degree medio di 92.1. Questo indice è stato eseguito per 5 giorni su una macchina DDR4 da 64GB.
I risultati del confronto sono i seguenti (Figura 2a):
Figure 3.
In conclusione:
L’indice costruito in una sola volta è significativamente migliore dell’indice basato sulla fusione;
Anche l’indice basato sulla fusione è eccellente;
Lo schema di indicizzazione basato sulla fusione è applicabile anche al set di dati DEEP1B (Figura 2b).
Indice basato su disco: DiskANN VS. FAISS VS. IVF-OADC+G+P
IVFOADC+G+P è un algoritmo proposto nel Riferimento [5].
Questo articolo confronta DiskANN solo con IVFOADC+G+P, poiché il riferimento [5] ha dimostrato che IVFOADC+G+P è migliore di FAISS. Inoltre, FAISS richiede risorse GPU, che non sono supportate da tutte le piattaforme.
IVF-OADC+G+P sembra essere una combinazione di HNSW e IVF-PQ. Determina i cluster usando HNSW ed esegue la ricerca aggiungendo alcune strategie di pruning al cluster target.
Il risultato è nella Figura 2a. I 16 e 32 nella figura sono la dimensione del codebook. Il dataset è SIFT1B, quantizzato da OPQ.
Dettagli di implementazione del codice
Il codice sorgente di DiskANN è open-source su https://github.com/microsoft/DiskANN
Nel gennaio 2021, il codice sorgente della soluzione su disco è stato reso open-source.
Di seguito vengono introdotti principalmente il processo di indicizzazione e il processo di ricerca.
Costruzione dell’indice
Ci sono 8 parametri per costruire l’indice:
data_type: le opzioni includono float/int8/uint8.
data_file.bin: Il file binario dei dati originali. I primi due interi nel file rappresentano rispettivamente il numero totale n del vettore del dataset e la dimensione del vettore dim. Gli ultimi n * dim * sizeof(data_type) byte sono dati vettoriali continui.
index_prefix_path: Il prefisso del percorso del file di output. Dopo la costruzione dell’indice, verranno generati diversi file relativi all’indice. Questo parametro è il prefisso comune della directory in cui vengono archiviati.
R: L’out-degree massimo dell’indice globale.
L: Il parametro L dell’indice Vamana, il limite superiore della dimensione del set di candidati.
B: La soglia di memoria durante le query. Controlla la dimensione del codebook PQ, in GB.
M: La soglia di memoria durante la costruzione di un indice. Determina la dimensione del frammento, in GB.
T: Il numero di thread.
Processo di indicizzazione (funzione di ingresso: aux_utils.cpp::build_disk_index):
Generare vari nomi di file di output secondo index_prefix_path.
Controllo dei parametri.
Leggere i meta di data_file.bin per ottenere n e dim. Determinare il numero di sottospazi del codebook m di PQ secondo B e n.
generate_pq_pivots: Campionare il punto centrale del set di addestramento PQ usando uniformemente il tasso di campionamento p = 1500000/n per addestrare PQ globalmente.
generate_pq_data_from_pivots: Generare il codebook PQ globale e salvare separatamente il punto centrale e il codebook.
build_merged_vamana_index: suddividere il set di dati originale, costruire indici Vamana in segmenti e infine unire gli indici in uno.
partition_with_ram_budget: Determinare il numero di frammenti k in base al parametro M. Campionare il set di dati usando kmeans, distribuendo ogni punto ai due cluster più vicini. Frammentare il dataset, e ogni frammento produce due file: un file di dati e un file ID. Il file ID e il file di dati corrispondono l’uno all’altro, e ogni ID nel file ID corrisponde a un vettore nel file di dati. Gli ID sono ottenuti numerando ogni vettore dei dati originali da 0 a n-1. L’ID è relativamente importante ed è correlato al merge.
Campionare uniformemente a livello globale il training set con un tasso di campionamento di 1500000 / n;
Inizializzare num_parts = 3. Iterare da 3:
- Eseguire num_parts-means++ sul training set nel passaggio i;
- Usare un tasso di campionamento di 0.01 per campionare uniformemente a livello globale un test set e dividere il test set nei 2 cluster più vicini;
- Contare il numero di punti in ciascun cluster e dividerlo per il tasso di campionamento per stimare il numero di punti in ciascun cluster;
- Stimare la memoria richiesta dal cluster più grande nel passaggio 3 in base alla dimensione dell’indice Vamana; se non supera il parametro M, passare al passaggio iii, altrimenti num_parts ++ tornare al passaggio 2;
Dividere il set di dati originale in num_parts file di gruppo, ogni gruppo di file include file di dati frammentati e file ID corrispondenti ai dati frammentati.
Creare indici Vamana separatamente per tutte le slice nel passaggio a e salvarli su disco;
merge_shards: unire num_parts shard Vamana in un indice globale:
Leggere il file ID di num_parts frammenti in idmap. Questo idmap equivale a stabilire una mappatura diretta di frammento->id;
Stabilire una mappatura inversa di id-> frammenti secondo idmap e sapere in quali due frammenti si trova ogni vettore;
Usare un reader con cache da 1GB per aprire num_parts indici Vamana di slice, e usare un writer con cache da 1GB per aprire il file di output, pronto per il merge;
Posizionare num_parts punti di navigazione dell’indice Vamana nel file dei punti centrali, che sarà usato durante la ricerca;
Iniziare il merge secondo l’ID dal più piccolo al più grande, leggere a turno il set di punti vicini di ogni vettore originale in ciascun frammento secondo la mappatura inversa, deduplicare, fare shuffle, troncare e scrivere nel file di output. Poiché lo slicing era originariamente ordinato globalmente, e ora anche il merge è in ordine, l’ID nell’indice finale flushato e l’ID dei dati originali sono in corrispondenza uno-a-uno.
Eliminare i file temporanei, inclusi file di frammento, indici di frammento e file ID di frammento.
7.create_disk_layout: L’indice globale generato nel passaggio 6 ha solo una tabella di adiacenza compatta. Questo passaggio serve ad allineare l’indice. La tabella di adiacenza e i dati originali sono memorizzati insieme. Durante la ricerca, caricare la tabella di adiacenza e leggere insieme il vettore originale per un calcolo accurato della distanza. Esiste anche il concetto di SECTOR, con dimensione predefinita di 4096. Ogni SECTOR contiene solo 4096 / node_size elementi di informazione vettoriale. node_size = dimensione di un singolo vettore + dimensione della tabella di adiacenza di un singolo nodo.
8.Infine, eseguire un campionamento uniforme globale di 150000 / n, salvarlo e usarlo per il warmup durante la ricerca.
Ricerca
Ci sono 10 parametri di ricerca:
index_type: Le opzioni includono Float/int8/uint8, simile al primo parametro data_type durante la costruzione di un indice.
index_prefix_path: Fare riferimento al parametro dell’indice index_prefix_path.
num_nodes_to_cache: Numero di hotspot della cache.
num_threads: Numero di thread di ricerca.
beamwidth: Limite superiore del numero di punti di preload. Il sistema determina se è impostato a 0.
query_file.bin: File del query set.
truthset.bin: File del result set, "null" significa che il result set non è fornito, il programma lo calcola autonomamente;
K: topk;
result_output_prefix: Percorso per salvare i risultati della ricerca;
L*: Elenco dei parametri di ricerca. È possibile aggiungere più valori. Per ogni L, verranno fornite informazioni statistiche durante la ricerca con diverse L.
Processo di ricerca:
Caricare i dati correlati: caricare il set di query, i dati dei punti centrali PQ, i dati del codebook, il punto di partenza della ricerca e altri dati, e leggere i metadati dell'indice.
Utilizzare il set di dati campionato durante l'indicizzazione per eseguire cached_beam_search, contare i tempi di accesso di ciascun punto e caricare nella cache num_nodes_to_cache punti con la frequenza di accesso più alta.
Per impostazione predefinita è presente un'operazione di WARMUP. Come nello step 2, anche questo set di dati di esempio viene utilizzato per eseguire una cached_beam_search.
In base al numero di parametri L forniti, ogni L verrà eseguita di nuovo con cached_beam_search con il set di query, e verranno prodotte statistiche come tasso di recall e QPS. Il processo di warmup e i dati hotspot delle statistiche non vengono conteggiati nel tempo di query.
Informazioni su cached_beam_search:
Trovare il candidato più vicino al punto di query dal punto di partenza candidato. Qui viene utilizzata la distanza PQ, e il punto di partenza viene aggiunto alla coda di ricerca.
Iniziare la ricerca:
Dalla coda di ricerca, ci sono non più di beam_width + 2 punti non visitati. Se questi punti sono nella cache, aggiungerli alla coda degli hit della cache. Se non sono hit, aggiungerli alla coda dei miss. Assicurarsi che la dimensione della coda dei miss non superi beam_width.
Inviare richieste asincrone di accesso al disco ai punti nella coda dei miss.
Per i punti colpiti dalla cache, utilizzare i dati originali e i dati della query per calcolare la distanza esatta, aggiungerli alla coda dei risultati, quindi utilizzare PQ per calcolare la distanza dai punti vicini che non sono stati visitati prima di aggiungerli alla coda di ricerca. La lunghezza della coda di ricerca è limitata dai parametri.
Elaborare i punti di miss della cache nello step a, in modo simile allo step c.
Quando la coda di ricerca è vuota, la ricerca termina e viene restituito il topk della coda dei risultati.
Riepilogo
Sebbene si tratti di un lavoro relativamente lungo, nel complesso è eccellente. Le idee del paper e del codice sono chiare: dividere un certo numero di bucket sovrapposti tramite k-means, quindi dividere i bucket per costruire un indice a mappa, e infine unire gli indici, che è un'idea relativamente nuova. Per quanto riguarda l'indice a grafo basato su memoria Vamana, è essenzialmente una versione inizializzata casualmente di NSG che può controllare la granularità del trimming. Durante la query, sfrutta appieno cache + pipeline, maschera parte del tempo di io e migliora il QPS. Tuttavia, secondo il paper, anche se le condizioni della macchina non sono straordinarie, il tempo di training richiede fino a 5 giorni, e l'usabilità è relativamente bassa. Ottimizzazioni del training saranno sicuramente necessarie in futuro. Dal punto di vista del codice, la qualità è relativamente alta e può essere utilizzato direttamente nell'ambiente di produzione.
Riferimenti
[Cong Fu, Chao Xiang, Changxu Wang, and Deng Cai. Fast approximate nearest neighbor search with the navigating spreading-out graphs. PVLDB, 12(5):461 – 474, 2019. doi: 10.14778/3303753.3303754.] (http://www.vldb.org/pvldb/vol12/p461-fu.pdf)
Cong Fu and Deng Cai. GitHub - ZJULearning/efanna: fast library for ANN search and KNN graph construction.
Continua a leggere

How to Build an Enterprise-Ready RAG Pipeline on AWS with Bedrock, Zilliz Cloud, and LangChain
Build production-ready enterprise RAG with AWS Bedrock, Nova models, Zilliz Cloud, and LangChain. Complete tutorial with deployable code.

Announcing the General Availability of Zilliz Cloud BYOC on Google Cloud Platform
Zilliz Cloud BYOC on GCP offers enterprise vector search with full data sovereignty and seamless integration.

OpenAI o1: What Developers Need to Know
In this article, we will talk about the o1 series from a developer's perspective, exploring how these models can be implemented for sophisticated use cases.



