Photon: creazione di un motore di recupero e ranking da zero

Scopri come formati di dati specializzati, letture in batch e la separazione della creazione dell'indice dall'elaborazione delle query migliorano la ricerca nativa per l'IA.

AutoriPerplexity Engineering

Introduzione

Lo stack di ricerca nativo per l'IA di Perplexity recupera e classifica le pagine candidate, facendo emergere il contenuto più rilevante affinché il modello fondi le sue risposte. Originariamente, questa fase veniva eseguita su un motore open source che avevamo adattato al nostro sistema. Tuttavia, man mano che il nostro indice e i nostri carichi di lavoro crescevano, abbiamo raggiunto limiti insormontabili in termini di costi, latenza di coda e tempo di recupero dei nodi che non potevamo risolvere all'interno della piattaforma di terze parti esistente.

Per superare queste sfide, abbiamo realizzato Photon, un nuovo motore di recupero e ranking interno. Ciò continua il nostro approccio di costruzione di un'infrastruttura di ricerca nativa per l'IA da zero, come abbiamo fatto con CobbleDB, il nostro archivio chiave-valore distribuito per la gestione dei record di pagina, e la nostra Search API.

Photon utilizza formati di dati compatti per leggere e decodificare solo ciò di cui ogni query ha bisogno, con caching consapevole dei batch e letture asincrone per ridurre l'accesso al disco e sovrapporre le attese. La creazione dell'indice viene eseguita separatamente dall'elaborazione delle query, aggiornando un gruppo di servizio alla volta e riscaldandone le cache prima di instradare le query attive.

Photon ora alimenta la nostra pipeline di ricerca ed è anche la base di un nuovo preset rapido per la nostra API di Search, con una latenza per singola chiamata di ricerca di 160 ms al p50 e 230 ms al p95. In sei benchmark pubblici, il preset rapido ha ridotto il costo stimato di modello più ricerca per attività del 68%, mantenendo una qualità complessiva delle attività comparabile a quella del preset predefinito. Lo rilasciamo oggi affinché gli sviluppatori possano accedere a questi miglioramenti.

Latenza per singola chiamata di ricerca auto-dichiarata. PPLX Fast riporta una latenza al p50 di 160 ms e al p95 di 230 ms. Exa Instant riporta il p90, anziché il p95, per il suo valore di coda alta; i valori di coda alta di Parallel non sono pubblicati. I percentili riportati e le configurazioni di misurazione non costituiscono un confronto controllato alla pari.
Qualità complessiva delle attività rispetto al costo totale stimato di modello più ricerca per le stesse 3.554 attività selezionate. I punteggi sono ponderati per conteggio delle attività e i costi coprono l'intero set di attività. PPLX Fast ottiene il 64,3% a 59,73 $, rispetto al 64,0% a 187,60 $ per il preset PPLX predefinito, con un costo stimato inferiore di circa il 68% a parità di numero di attività.

Requisiti del motore di recupero e ranking

Per ogni query, il motore di recupero e ranking cerca in un indice ampio e distribuito per selezionare e ordinare un piccolo insieme di pagine rilevanti entro il budget di latenza dello stack di ricerca. Il sistema deve anche mantenere l'indice aggiornato man mano che arrivano nuove pagine e quelle esistenti cambiano, senza consentire a tale lavoro di rallentare le query attive.

Abbiamo valutato diverse opzioni open source e scelto un motore di recupero e ranking generale e maturo che soddisfaceva le nostre esigenze iniziali. Lo abbiamo quindi adattato alla nostra architettura e ai nostri carichi di lavoro, mantenendo latenza e throughput stabili su scala di produzione.

Dove il nostro sistema precedente si è dimostrato carente

Abbiamo mantenuto il nostro fork per adattare il motore al nostro indice in crescita, ma la risoluzione di limitazioni chiave richiedeva sempre più spesso la ridisegnazione di grandi parti della piattaforma. Diversi vincoli si sono rivelati difficili da risolvere senza modifiche architetturali fondamentali:

1. Costi di scalabilità. Sia il numero di documenti che memorizziamo sia la quantità di dati per documento che dobbiamo recuperare e classificare sono cresciuti nel tempo. Questa scalabilità ha esercitato pressione sul nostro hardware, in particolare sulla quantità di RAM disponibile. Per controllare i costi, avevamo bisogno di rappresentazioni di dati più compatte e di un controllo più fine su ciò che rimane in memoria e ciò che viene letto da disco su richiesta.

2. Scarsa latenza di coda. Sul traffico di produzione, il tempo di risposta al p99 del vecchio sistema era di circa 800 ms. Il set di dati superava la RAM disponibile, quindi non potevamo usare mlock per mantenerlo interamente in memoria. L'accesso a dati non residenti poteva attivare importanti page fault, bloccando l'esecuzione delle query mentre il sistema operativo leggeva dal disco.

Il motore univa inoltre periodicamente il suo indice su disco principale con indici più piccoli svuotati dalla memoria. Durante questo processo di fusione dell'indice su disco, il numero di page fault aumentava ulteriormente, con una latenza al p99 che raggiungeva circa 1,2 s per 10-15 minuti. Man mano che le cache si riscaldavano, sia la frequenza dei page fault che la latenza diminuivano, suggerendo che le letture a freddo fossero un importante fattore determinante per i picchi. Il precaricamento dei dati e il riscaldamento dell'indice hanno ridotto i picchi ma non hanno affrontato adeguatamente l'elevata latenza di coda.

3. Recupero e sincronizzazione lenti. Nel sistema precedente, il deployment di un cluster aggiuntivo e la sincronizzazione dei suoi dati potevano richiedere più di una settimana. La sincronizzazione era necessaria anche quando si aggiungevano gruppi di nodi per contenere copie di dati aggiuntive o per il ripristino da guasti dei nodi. Durante il ripristino, una quota maggiore di risposte di ricerca era parziale, il che abbassava i punteggi di qualità della risposta finale.

Alla fine, abbiamo concluso che sarebbe stato più semplice ed economico creare una soluzione da zero piuttosto che continuare ad adattare e mantenere il nostro fork. Facendo tesoro della nostra esperienza con il sistema precedente, un piccolo team di ingegneri ha lavorato insieme a uno sciame di agenti di codifica persistenti per sviluppare Photon.

Dove si colloca Photon nello stack di ricerca

Photon è progettato per due flussi di lavoro principali: l'elaborazione delle richieste di ricerca e l'acquisizione degli aggiornamenti dalla pipeline di elaborazione.

Una richiesta dal servizio di ricerca di livello superiore raggiunge il broker di Photon tramite un bilanciatore del carico. Il broker seleziona un gruppo di shard e inoltra la richiesta a ciascuno shard, monitorando i timeout ed emettendo richieste aggiuntive quando necessario.

Ciascuno shard esegue il recupero, il ranking iniziale e il ranking di seconda fase, per poi restituire i suoi candidati migliori al broker. Il broker combina questi candidati in un'unica lista classificata e recupera i campi chiave dei documenti per le pagine selezionate dagli shard pertinenti. Restituisce quindi questi risultati al servizio di ricerca di livello superiore, il quale raccoglie il contenuto della pagina necessario affinché l'agente generi una risposta fondata.

Gli aggiornamenti dell'indice seguono un percorso separato. Pillar, il nostro livello di pubblicazione, prepara i dati e li memorizza nelle tabelle di YTsaurus. Gli indicizzatori convertono queste tabelle in strutture di indice che gli shard possono caricare per la ricerca. Il controller coordina la preparazione dei dati, la creazione dell'indice e il deployment delle nuove versioni dell'indice nei gruppi di servizio. Prima di gestire il traffico attivo, ogni shard ripete le query di ricerca reali per riscaldare le proprie cache.

Una query passa dal servizio di ricerca di livello superiore attraverso il bilanciatore del carico e il broker a un gruppo di shard selezionato. Ciascuno shard recupera e classifica i candidati; il broker unisce i risultati, recupera i campi dei documenti per le pagine selezionate e li restituisce al servizio di ricerca di livello superiore. I passaggi numerati mostrano l'ordine. Le frecce continue trasportano le richieste e le frecce tratteggiate restituiscono i risultati. Le etichette delle fasi sul lato sinistro distinguono la selezione dei candidati dalle letture dei sommari.

Progettazione di Photon per i nostri flussi di lavoro

Tre scelte di design rendono Photon particolarmente adatto al nostro flusso di lavoro: rappresentazioni di dati compatte, caching e letture da disco asincrone, e la separazione degli aggiornamenti dell'indice dall'elaborazione delle query.

Rappresentazioni dei dati per il recupero e il ranking

Il recupero e il ranking accedono ai dati dei documenti in modo diverso. Il recupero lessicale inizia con i termini di ricerca e trova i documenti che li contengono. Il ranking richiede quindi informazioni dettagliate su ciascun documento selezionato, incluse le frequenze dei termini e le posizioni.

Photon utilizza due rappresentazioni complementari per supportare questi pattern di accesso. Un indice invertito memorizza una lista di documenti corrispondenti per ciascun termine, chiamata lista di posting, per supportare la selezione dei candidati. Record separati per documento forniscono i dati necessari per il ranking. Ottimizziamo anche il modo in cui le liste di posting vengono memorizzate e attraversate per migliorare la selezione entro un budget di lavoro fisso.

Rappresentazioni di dati specializzate ci consentono di memorizzare i dati chiave in modo più efficiente. Un indice invertito più compatto riduce la quantità di dati letti o spostati per query, migliorando la latenza eliminando le operazioni di I/O non necessari. Questi formati consentono inoltre di verificare se un documento compare in una lista senza decodificarla completamente, una proprietà su cui la nostra logica di attraversamento fa affidamento per controllare quanto lavoro svolge una query entro un budget fisso. L'ottimizzazione dei record per documento consente di memorizzare più dati per documento ai fini del ranking, riducendo al contempo i costi di scalabilità associati al nostro sistema precedente.

L'indice invertito

Per ciascun termine, l'indice invertito memorizza una lista di posting. Queste liste possono variare da una manciata di documenti a milioni, quindi nessun singolo formato funziona bene per ogni lista. Photon sceglie il formato in base al numero di documenti contenenti il termine.

Le liste brevi utilizzano una rappresentazione in-line che rientra in una singola pagina e non richiede alcuna tabella dei blocchi. Le liste più lunghe che non rientrano nel formato in-line sono suddivise in blocchi che coprono intervalli fissi di identificatori di documento. La rappresentazione di ciascun blocco dipende dalla sua densità: i blocchi sparsi memorizzano array ordinati di offset di ID documento, mentre i blocchi densi utilizzano bitmap. I blocchi sparsi utilizzano la ricerca a galloppo (galloping search), che procede con passi progressivamente più ampi per saltare regioni della lista. I blocchi densi consentono il controllo dell'appartenenza cercando il bit corrispondente a un documento.

La frequenza delle query di un termine determina dove la sua lista di posting viene inserita sul disco. Le liste interrogate di frequente vengono memorizzate vicine tra loro, concentrando i dati attdi in una regione di archiviazione più piccola. All'interno di ciascuna lista, i documenti sono ordinati in base a un segnale di utilità separato, in modo che i candidati più promettenti vengano incontrati prima.

Photon sceglie una rappresentazione della lista di posting in base alla lunghezza e alla densità dei blocchi. Le liste brevi si inseriscono in-line all'interno di una pagina. Le liste più lunghe sono suddivise in intervalli di ID documento fissi, con array di offset ordinati per i blocchi sparsi e bitmap per i blocchi densi.

Attraversamento delle liste entro un budget di lavoro

La selezione dei candidati richiede l'attraversamento delle liste di posting per trovare documenti potenzialmente rilevanti. La scansione esaustiva di ogni lista è costosa, quindi Photon utilizza un algoritmo simile a WAND che attraversa solo alcune liste pur tenendo conto delle corrispondenze nelle altre.

L'algoritmo divide le liste in due gruppi. Le liste di guida avanzano nell'attraversamento e propongono i documenti candidati. Le liste di sondaggio contribuiscono ai punteggi di tali candidati ma non generano direttamente candidati.

Il punteggio dei candidati combina la copertura ponderata dei termini della query e un contributo di frequenza, con normalizzazione della lunghezza del documento e un limite massimo sui guadagni derivanti dai termini ripetuti. Photon verifica prima la presenza dei termini negli array e nelle bitmap per delimitare il punteggio massimo possibile di ciascun candidato. Legge le frequenze esatte dei termini solo per i candidati che potrebbero comunque soddisfare la soglia di selezione.

La selezione procede quindi in tre fasi:

  • Attraversamento: iniziare con un requisito di copertura della query rigoroso. Se vengono trovati troppo pochi candidati, ripetere con un requisito rilassato.
  • Conservazione: i candidati vengono mantenuti in un insieme limitato utilizzando un punteggio che combina copertura e frequenza. Man mano che i migliori candidati raccolti migliorano, la soglia di ammissione sale.
  • Selezione finale: i risultati finali per il passaggio vengono scelti dall'insieme conservato in base ai punteggi di frequenza. Ciascun campo esegue il proprio passaggio e i risultati vengono uniti utilizzando i pesi dei campi.

L'algoritmo produce un insieme di candidati di documenti rilevanti da utilizzare per un ulteriore ranking.

Attraversamento illustrativo dei candidati limitati. Le liste di guida propongono i documenti, mentre i limiti superiori consentono di effettuare il pruning dei candidati al di sotto dell'attuale soglia di ammissione senza leggere le liste di sondaggio o le frequenze esatte. La soglia aumenta man mano che l'insieme conservato migliora. I punteggi sono inventati a scopo illustrativo e i candidati conservati non costituiscono un top-k esatto garantito.

Docblob

Dopo aver selezionato le pagine candidate, la fase di ranking richiede le frequenze dei termini, la copertura dei campi e le posizioni e la prossimità delle occorrenze. Ottenere questi dati tramite l'indice invertito richiederebbe accessi sparsi tra molte coppie termine-documento. In Photon, memorizziamo un record compatto per documento chiamato docblob che contiene le frequenze dei termini, i campi in cui è apparso un termine e la sua posizione all'interno del documento. Di conseguenza, il ranking di un candidato richiede una sola ricerca per documento.

Il formato è strutturato per evitare di decodificare più del necessario. All'interno di un docblob, i campi sono raggruppati per analizzatore di testo. Ciascun gruppo memorizza una lista di termini ordinata e codificata con Elias-Fano, in modo che un termine di query possa essere cercato direttamente senza prima espandere l'intera lista. Una maschera di campo contrassegna la posizione in cui è comparso un termine, un conteggio di frequenza traccia la frequenza e le posizioni effettive si trovano in blocchi separati per ogni coppia termine-campo codificati come differenze di posizione. Vengono decodificati solo i blocchi per i termini che hanno effettivamente generato una corrispondenza, mentre tutto il resto nel record rimane nel formato compresso.

Questa decodifica selettiva consente a docblob di supportare la memorizzazione di una quantità maggiore di dati per documento senza un aumento proporzionale dei costi. L'aumento delle dimensioni del record non impone ulteriore lavoro per ricerca, poiché il ranking tocca solo le parti rilevanti per i termini corrispondenti anziché l'intero record.

Un docblob raggruppa i dati di ranking in un record compatto per documento. I termini della query vengono cercati in una lista di termini codificata con Elias-Fano; le maschere di campo, le frequenze e i blocchi di posizione forniscono i dati necessari per i termini corrispondenti, mentre i termini non correlati rimangono compressi. Gli ID dei termini e le posizioni sono puramente illustrativi.

Letture in batch e gestione della memoria

Anche con rappresentazioni dei dati più efficienti, la RAM si esaurisce comunque prima delle altre risorse, quindi abbiamo spesso bisogno di accedere ai dati memorizzati su disco. Photon utilizza letture da disco asincrone e una cache ottimizzata per le letture in batch per velocizzare questi accessi, riducendo il tempo di attesa per richiesta. Ciò contribuisce a un miglioramento significativo della latenza di coda rispetto al sistema precedente.

Photon verifica la presenza di un batch di offset di record noti nella sua cache prima di emettere le letture su disco. Gli hit della cache vengono copiati in un buffer preparato; i miss vengono inviati tramite io_uring in modo che le attese del disco possano sovrapporsi e i dati restituiti popolano la cache. I record e le linee temporali sono schematici, non latenze misurate.

Sovrapposizione delle attese del disco

Il ranking richiede l'ottenimento delle feature di un centinaio di documenti situati in diverse parti di un file. Il nostro sistema precedente utilizzava mmap per mappare il file nello Spazio degli indirizzi virtuali in modo che potesse essere letto tramite puntatori di memoria. Tuttavia, l'accesso a una pagina assente dalla memoria richiedeva comunque una lettura su disco. Il thread doveva attendere i dati prima di continuare il calcolo, e questo tempo di attesa si accumulava quando il processo doveva leggere record a freddo in sequenza.

Photon sfrutta il fatto che gli offset dei record sono noti in anticipo, consentendoci di inviare più letture in una sola volta. Questo processo è gestito dal reactor: thread di lavoro dedicati inviano batch tramite io_uring e passano i dati letti al codice chiamante. Ciascun thread gestisce il proprio io_uring; i batch vengono inviati al reactor con il carico minore. I descrittori di file pre-registrati e i pool di buffer riducono il sovraccarico delle letture ripetute. Questa esecuzione asincrona consente di sovrapporre le attese per più operazioni, riducendo la latenza di coda.

Riduzione del numero di accessi all'unità disco

Prima di inviare le letture, Photon verifica l'intero batch nella cache in memoria. Solo le richieste per i record mancanti vanno sul disco; i dati letti popolano quindi la cache.

La cache è progettata per letture in batch. Nello specifico:

  • Non vi è alcuna allocazione separata in caso di hit. I dati vengono invece copiati in un buffer preparato in anticipo dal codice chiamante.
  • Non vi è alcuna acquisizione di lock da parte del lettore. Viene invece controllata la versione dei dati e viene effettuato un nuovo tentativo in caso di conflitto con una scrittura.
  • Utilizza l'eviction CLOCK, anziché richiedere aggiornamenti a una lista LRU condivisa a ogni lettura.
  • Sfrutta il prefetching della cache della CPU, in cui i metadati e i dati per i record futuri vengono richiesti in anticipo.

Queste ottimizzazioni riducono la latenza senza compromettere le prestazioni sui carichi di lavoro che ci interessano.

Creazione e aggiornamento dell'indice separatamente dall'elaborazione delle query

In Photon, la creazione dell'indice e l'elaborazione delle query vengono eseguite su nodi diversi. Gli indicizzatori trasformano i dati in strutture di archiviazione pronte, mentre i nodi di servizio li leggono ed eseguono il recupero e il ranking. Di conseguenza, la creazione dell'indice non entra in competizione con le query di ricerca per la CPU e le risorse per queste attività possono essere scalate in modo indipendente.

Questa separazione risolve i colli di bottiglia di ripristino e sincronizzazione presenti nella precedente implementazione. Poiché la creazione dell'indice veniva eseguita all'interno dello stesso cluster che serviva le query, il ripristino di un nodo guasto o l'aggiunta di una nuova copia dei dati poteva comportare la re-indicizzazione dei documenti in-place, un processo che richiedeva giorni e aumentava le risposte parziali durante il recupero. Photon rimuove tale accoppiamento; gli indicizzatori vengono eseguiti come job distribuiti che producono strutture di indice versionate e pronte all'uso indipendentemente dai nodi di servizio, per cui la compilazione della versione successiva dell'indice non entra più in conflitto con il traffico attivo.

La creazione dell'indice viene eseguita separatamente dall'elaborazione delle query in tempo reale. Pillar esporta i dati di origine, YTsaurus prepara le tabelle versionate per shard e gli indicizzatori paralleli scrivono strutture di indice pronte all'uso nell'archiviazione a oggetti. I nodi di servizio caricano tali strutture per il recupero e il ranking; la concorrenza degli indicizzatori e il conteggio degli shard sono configurati in modo indipendente.

Preparazione e compilazione distribuita

Una compilazione inizia selezionando i documenti per l'indice attivo e producendo l'esportazione di origine. Il controller registra la versione di origine, le tabelle di input e il numero atteso di shard. I job MapReduce in YTsaurus preparano testo, metadati, frammenti, feature e embedding precalcolati in tabelle versionate partizionate per shard. Ciascun indicizzatore esegue lo streaming della tabella preparata, compila le strutture per il proprio shard e unisce i segmenti di testo. L'indice pronto, insieme a una descrizione dei suoi componenti, viene caricato nell'archiviazione a oggetti.

Il conteggio degli shard e il numero di indicizzatori in esecuzione simultanea sono configurati in modo indipendente, pertanto una compilazione può essere eseguita in più ondate oppure è possibile allocare più macchine per lavorare in parallelo. La preparazione distribuita e gli indicizzatori paralleli consentono di compilare l'intero indice web in un numero di ore a una sola cifra, un miglioramento significativo rispetto al sistema precedente.

Deployment di una nuova versione

Prima del deployment, il controller verifica che il nuovo indice sia pronto. Se i dati sono incompleti, il deployment viene bloccato automaticamente.

Quando sono presenti più gruppi di servizio, il controller li aggiorna uno alla volta. Rimuove prima un gruppo dall'instradamento del broker e lo avvia sulla nuova versione dell'indice. Prima di servire le richieste, gli shard attraversano una fase di riscaldamento separata basata sui log di ricerca, che pre-popola lo stato iniziale e rende più fluida la transizione al traffico reale. Dopo il riscaldamento, il controller verifica lo stato dell'indice e la prontezza, quindi restituisce il gruppo all'instradamento. Gli altri gruppi continuano a servire le richieste durante questo periodo. Poiché lo stato operativo viene salvato in modo persistente, un riavvio non costringe una compilazione a ricominciare da capo; il controller può ricollegarsi alla preparazione già in corso, riutilizzare un risultato pronto o continuare una rotazione interrotta dal passaggio salvato.

I tempi di aggiornamento dei dati differiscono a seconda dei verticali di ricerca. Per i verticali con elevate esigenze di freschezza, la consegna dei documenti richiede un numero di minuti a una sola cifra. È possibile effettuare il deployment di una copia aggiuntiva dei dati in circa mezz'ora; gli indici pronti vengono caricati e collegati agli shard senza indicizzare nuovamente i documenti di origine.

Il controller verifica che un nuovo indice sia completo, quindi ruota un gruppo di servizio alla volta. Un gruppo esce dall'instradamento del broker, carica la nuova versione, riscalda le proprie cache con le query dei log di ricerca e supera i controlli di prontezza prima di tornare a gestire il traffico. Gli altri gruppi continuano a fornire il servizio e lo stato del controller salvato in modo persistente consente a una rotazione interrotta di riprendere.

Migrazione e convalida all'interno del nostro stack di ricerca

Il nostro primo obiettivo era sostituire il vecchio sistema con un motore che preservasse la funzionalità e la qualità della ricerca riducendo al contempo i tempi di risposta. Abbiamo convalidato Photon per fasi, iniziando con test di carico riproducibili e valutazioni di qualità offline prima di passare al traffico live. Photon ora alimenta il recupero e il ranking nel nostro stack di ricerca di produzione, con tempi di risposta notevolmente inferiori rispetto al vecchio sistema.

Test di carico e valutazioni

Per i test delle prestazioni, abbiamo creato uno strumento di test di carico che ripete le query dai nostri log di ricerca a tassi di arrivo configurabili. Confronta i risultati tra le esecuzioni e applica test statistici per valutare se le differenze di prestazioni osservate siano coerenti. Separatamente, abbiamo valutato Photon e il vecchio sistema sugli stessi dati nei nostri sistemi di valutazione offline interni per verificare la presenza di regressioni di qualità.

Dopo questi controlli, abbiamo inviato query in tempo reale a entrambi i motori contemporaneamente utilizzando il traffico di shadow. Ciò ci ha permesso di confrontare le prestazioni e i risultati sui carichi di lavoro di produzione prima di modificare quale motore servisse gli utenti. Abbiamo quindi abilitato Photon per piccoli subset di utenti e ampliato gradualmente il rollout, monitorando costantemente la qualità e le prestazioni. La prima versione ha superato i test di accettazione senza regressioni di qualità e abbiamo continuato il rollout fino a quando Photon ha gestito tutto il traffico di produzione.

Miglioramenti misurati in produzione

Nel nostro flusso di lavoro di produzione, il tempo di risposta al p99 è sceso da circa 800 ms nel vecchio sistema a circa 65 ms in Photon. Questa misurazione copre tutte le fasi all'interno di Photon, ma esclude le fasi successive nello stack di ricerca di livello superiore. Non osserviamo inoltre più i picchi di latenza precedentemente associati al cambio di versione dell'indice.

Photon utilizza circa il 20% di macchine di servizio equivalenti in meno rispetto ai nodi di contenuto del vecchio sistema, pur memorizzando una quantità di dati per documento pari a circa 2,5 volte superiore. Dopo la migrazione, abbiamo utilizzato questi dati aggiuntivi per migliorare la qualità del ranking oltre quella del sistema precedente.

Photon riduce anche la quantità di dati che devono rimanere in memoria. Bloccare lo stesso set di dati di Photon nella RAM con mlock richiederebbe una quantità di memoria residente stimata pari a 4,6 volte quella attualmente utilizzata da Photon.

Valutazione del preset rapido per la Search API

Abbiamo anche utilizzato Photon come base per un nuovo preset rapido per la nostra API di Search, progettato per carichi di lavoro sensibili alla latenza. In base alle nostre misurazioni, la latenza per singola chiamata di ricerca per il preset rapido è di 160 ms al p50 e 230 ms al p95, inferiore o comparabile ai valori auto-dichiarati di altri provider di Search API, sebbene i percentili di coda riportati differiscano.

Abbiamo valutato il preset rapido su sei benchmark basati su agenti: WideSearch, BrowseComp, DSQA, FRAMES, SEAL-0 e SEAL-Hard. Tra queste valutazioni, ha ottenuto il costo totale stimato di modello più ricerca più basso e il punteggio complessivo di attività più alto tra le configurazioni testate.

Il preset rapido unisce Photon a un ranking ottimizzato per i flussi di lavoro basati su agenti, offrendo prestazioni comparabili a quelle del preset predefinito a un costo notevolmente inferiore. Tuttavia, comporta un compromesso sulla qualità di ricerca più ampia. Il preset rapido utilizza una capacità di calcolo inferiore per il ranking rispetto al preset predefinito. Sui benchmark interni che coprono query a coda lunga, copertura ampia e diversità dei risultati, ottiene un punteggio inferiore di 0,24 punti sulla rilevanza e di circa 3 punti percentuali in meno sulla disponibilità delle risposte. Riteniamo che questo sia un compromesso ragionevole per i flussi di lavoro basati su agenti, poiché il ragionamento e la conoscenza del modello stesso possono aiutare a compensare la differenza.

Confronto interno della qualità di recupero tra il preset PPLX predefinito e PPLX Fast. La rilevanza (DCG) scende da 2,45 a 2,21, con una diminuzione di 0,24 punti; la disponibilità delle risposte scende da 0,596 a 0,567, con una diminuzione di 2,9 punti percentuali. I due riquadri utilizzano linee di base degli assi diverse e diverse da zero, per cui le altezze delle barre enfatizzano i divari anziché le differenze proporzionali.

Consigliamo il preset rapido per le attività quotidiane basate su agenti. Per domande più complesse o ambigue che sono meno sensibili al tempo, il preset predefinito offre una qualità più robusta, giustificando la maggiore latenza e i costi superiori.

Conclusione

Stiamo trasferendo costantemente il nostro stack di ricerca su un'infrastruttura interna basata su Rust. La sostituzione del motore open source con Photon, il nostro motore personalizzato di recupero e ranking, è l'ultimo passo. Photon ci offre il controllo completo sulle rappresentazioni dei dati, su come vengono organizzate le letture e su come vengono distribuiti i nuovi indici, consentendoci di ottimizzare ciascun livello per i nostri carichi di lavoro.

Photon ha consentito una ricerca più rapida tra i prodotti di Perplexity e costituisce la base per il nostro nuovo preset rapido nella Search API. A seguito della migrazione, la latenza di recupero e ranking al p99 è scesa da circa 800 ms a 65 ms. I nostri formati di dati compatti ci consentono anche di memorizzare una quantità di dati per documento pari a 2,5 volte superiore, offrendo al recupero e al ranking l'accesso a informazioni sui documenti più ricche.

Il preset rapido offre una latenza per singola chiamata di ricerca di 160 ms al p50 e 230 ms al p95. Tra i sei benchmark basati su agenti valutati, ha ridotto il costo stimato di modello più ricerca per attività del 68% rispetto al preset predefinito, mantenendo una qualità complessiva delle attività comparabile. Questi risultati dimostrano i benefici pratici di un'infrastruttura progettata attorno ai nostri carichi di lavoro di ricerca, sia per i prodotti di Perplexity sia per gli sviluppatori che utilizzano la nostra API.

Continuiamo a migliorare le prestazioni e l'efficienza di archiviazione di Photon. Il nostro obiettivo è supportare un indice più ampio e dati di documenti più ricchi sullo stesso hardware, mantenendo la ricerca veloce man mano che i nostri carichi di lavoro crescono.

Citazione

BibTeX
@online{perplexity2026Photon,
  author = {{Perplexity} and Maksim Morozov and Bogdan Savko and Ruslan Kovalev and Aleksei Bykov and Artur Zayats and Denis Bykov and Nikita Kireev and Jarrod Bryan and Claire Beamer and Jeremy Yang},
  title = {{Photon: Building a retrieval and ranking engine from scratch}},
  date = {2026-09-24},
  url = {https://www.perplexity.ai/hub/blog/photon}
}