Photon: Construint un motor de recuperació i jerarquització des de zero
Com els formats de dades especialitzats, les lectures per lots i la separació de la construcció d'índexs de la prestació milloren la cerca nativa d'IA.
Introducció
La pila de cerca nativa d'IA de Perplexity recupera i jerarquitza pàgines candidates, aflorant el contingut més rellevant perquè el model fonamenti les seves respostes. Originalment, aquesta etapa s'executava en un motor de codi obert que vam adaptar al nostre sistema. No obstante, a mesura que el nostre índex i les nostres càrregues de treball creixien, vam arribar a límits estrictes en costos, latència de cua i temps de recuperació de nodes que no vam poder resoldre dins de la plataforma de tercers existent.
Per superar aquests reptes, vam construir Photon, un nou motor de recuperació i jerarquització propi. Això continua el nostre enfocament de construir infraestructura de cerca primerament amb IA des de zero, tal com vam fer amb CobbleDB, la nostra botiga clau-valor distribuïda per servir registres de pàgina, i la nostra API de cerca.
Photon utilitza formats de dades compactes per llegir i descodificar només allò que cada consulta necessita, amb memòria cau conscient dels lots i lectures asíncrones per reduir l'accés al disc i solapar les esperes. La construcció d'índexs s'executa separadament de la prestació de consultes, actualitzant un grup de servei a la vegada i escalfant les seves memòries cau abans d'encaminar-hi les consultes en directe.
Photon ara impulsa la nostra canonada de cerca i és també la base d'una nova preconfiguració ràpida per a la nostra API de cerca, amb una latència d'una sola crida de cerca de 160 ms a p50 i 230 ms a p95. A través de sis punts de referència públics, la preconfiguració ràpida va reduir el cost estimat de model més cerca per tasca en un 68% mantenint una qualitat de tasca agregada comparable a la preconfiguració predeterminada. L'estem llançant avui perquè els desenvolupadors puguin accedir a aquestes millores.
Què requereix el motor de recuperació i jerarquització
Per a cada consulta, el motor de recuperació i jerarquització cerca un índex gran i distribuït per seleccionar i ordenar un petit conjunt de pàgines rellevants dins del pressupost de latència de la pila de cerca. El sistema també ha de mantenir l'índex actualitzat a mesura que arriben noves pàgines i canvien les existents, sense permetre que aquesta feina încideixi alentint les consultes en directe.
Vam avaluar diverses opcions de codi obert i vam triar un motor de recuperació i jerarquització madur i de propòsit general que satisfeia les nostres necessitats inicials. Després el vam adaptar a la nostra arquitectura i càrregues de treball, mantenint una latència i un rendiment estables a escala de producció.
On es quedava curt el nostre sistema anterior
Vam mantenir la nostra pròpia bifurcació per adaptar el motor al nostre índex creixent, però abordar limitacions clau requeria cada vegada més el redisseny de gran part de la plataforma. Diverses restriccions van resultar difícils de resoldre sense canvis arquitectònics fonamentals:
1. Costos d'escalat. Tant el nombre de documents que emmagatzemem com la quantitat de dades per document que necessitem recuperar i jerarquitzar han anat creixent amb el temps. Aquest escalat va exercir pressió sobre el nostre maquinari, especialment la quantitat de RAM disponible. Per controlar els costos, necessitàvem representacions de dades més compactes i un control més fi sobre què roman a la memòria i què es llegeix del disc sota demanda.
2. Latència de cua deficient. En el trànsit de producció, el temps de resposta p99 del sistema antic era d'uns 800 ms. El conjunt de dades superava la RAM disponible, de manera que no vam poder utilitzar mlock per mantenir-lo íntegrament a la memòria. L'accés a dades no residents podia provocar errors de pàgina importants, bloquejant l'execució de consultes mentre el sistema operatiu llegia del disc.
El motor també fusionava periòdicament el seu índex de disc principal amb índexs més petits buidats de la memòria. Durant aquest procés de fusió d'índexs de disc, el nombre d'errors de pàgina augmentava encara més, amb la latència p99 arribant aproximadament a 1,2 s durant 10-15 minuts. A mesura que les memòries cau s'escalfaven, la freqüència dels errors de pàgina i la latència disminuïen, suggerint que les lectures fredes eren un contribuent important als pics. Precarregar dades i escalfar l'índex va reduir els pics però no va abordar adequadament la latència de cua alta.
3. Recuperació i sincronització lentes. En el sistema anterior, desplegar un clúster addicional i sincronitzar les seves dades podia trigar més d'una setmana. La sincronització també era necessària en afegir grups de nodes per contenir còpies de dades addicionals o en recuperar-se de fallades de nodes. Durant la recuperació, una part més gran de les respostes de cerca eren parcials, la qual cosa rebaixava les puntuacions de qualitat de la resposta final.
En última instància, vam concloure que seria més senzill i econòmic construir des de zero en lloc de continuar adaptant i mantenint la nostra bifurcació. Basant-se en la nostra experiència operant el sistema anterior, un petit equip d'enginyeria va treballar al costat d'un eixam d'agents de codificació persistents per construir Photon.
On encaixa Photon a la pila de cerca
Photon està dissenyat per a dos fluxos de treball primaris: servir sol·licituds de cerca i ingesta d'actualitzacions de la canonada de processament.
Una sol·licitud del servei de cerca de nivell superior arriba al bróker de Photon a través d'un equilibrador de càrrega. El bróker selecciona un grup de fragments i reenvia la sol·licitud a cada fragment, monitorant els temps d'espera i emetent sol·licituds addicionals quan calgui.
Cada fragment realitza la recuperació, la jerarquització inicial i la jerarquització de segona etapa, i després retorna els seus millors candidats al bróker. El bróker combina aquests candidats en una sola llista jerarquitzada i recupera els camps de document clau per a les pàgines seleccionades dels fragments rellevants. A continuació, retorna aquests resultats al servei de cerca de nivell superior, que recopila el contingut de pàgina necessari perquè l'agent generi una resposta fundamentada.
Les actualitzacions d'índex segueixen un camí separat. Pillar, la nostra capa de publicació, prepara les dades i les emmagatzema en taules de YTsaurus. Els indexadors converteixen aquestes taules en estructures d'índex que els fragments poden carregar per a la cerca. El controlador coordina la preparació de dades, la construcció d'índexs i el desplegament de noves versions d'índexs als grups de servei. Abans de gestionar el trànsit en directe, cada fragment reprodueix consultes de cerca reals per escalfar les seves memòries cau.
Dissenyant Photon per als nostres fluxos de treball
Tres decisions de disseny fan que Photon s'adapti bé al nostre flux de treball: representacions de dades compactes, memòria cau i lectures de disc asíncrones, i la separació de les actualitzacions d'índexs de la prestació de consultes.
Representacions de dades per a la recuperació i la jerarquització
La recuperació i la jerarquització accedeixen a les dades dels documents de manera diferent. La recuperació lèxica comença amb termes de cerca i troba documents que els contenen. La jerarquització necessita llavors informació detallada sobre cada document seleccionat, incloent-hi les freqüències de termes i les posicions.
Photon utilitza dues representacions complementàries per admetre aquests patrons d'accés. Un índex invertit emmagatzema una llista de documents coincidents per a cada terme, anomenada llista d'inserció, per admetre la selecció de candidats. Registres per document separats proporcionen les dades necessàries per a la jerarquització. També optimitzem com s'emmagatzemen i recorren les llistes d'inserció per millorar la selecció dins d'un pressupost de treball fix.
Les representacions de dades especialitzades ens permeten emmagatzemar dades clau de manera més eficient. Un índex invertit més compacte redueix la quantitat de dades llegides o mogudes per consulta, millorant la latència en eliminar operacions d'I/O innecessàries. Aquests formats també fan possible comprovar si un document apareix en una llista sense descodificar-lo completament, una propietat en la qual es basa la nostra lògica de recorregut per controlar quanta feina fa una consulta sota un pressupost fix. Optimitzar els registres per document ens permet emmagatzemar més dades per document per a la jerarquització, alhora que redueix els costos d'escalat associats al nostre sistema anterior.
L'índex invertit
Per a cada terme, l'índex invertit emmagatzema una llista d'inserció. Aquestes llistes poden variar des d'un grapat de documents fins a milions, de manera que cap format únic funciona bé per a totes les llistes. Photon tria el format basant-se en el nombre de documents que contenen el terme.
Les llistes curtes utilitzen una representació en línia que cap dins d'una sola pàgina i no requereix cap taula de blocs. Les llistes més llargues que no s'ajusten al format en línia es divideixen en blocs que cobreixen intervals fixos d'identificadors de documents. La representació de cada bloc depèn de la seva densitat: els blocs dispersos emmagatzemen matrius ordenades de desplaçaments d'ID de document, mentre que els blocs densos utilitzen mapes de bits. Els blocs dispersos utilitzen la cerca galopant, que avança en passos cada vegada més grans per saltar regions de la llista. Els blocs densos permeten comprovacions de pertinença cercant el bit corresponent a un document.
La freqüència de consulta d'un terme determina on es col·loca la seva llista d'inserció al disc. Les llistes consultades amb freqüència s'emmagatzemen a prop les unes de les altres, concentrant les dades calentes en una regió d'emmagatzematge més petita. Dins de cada llista, els documents s'ordenen per un senyal d'utilitat separat de manera que els candidats més prometedors es trobin abans.
Recorregut de llistes dins d'un pressupost de treball
La selecció de candidats requereix recórrer llistes d'inserció per trobar documents potencialment rellevants. Escanejar exhaustivament cada llista és costós, de manera que Photon utilitza un algoritme similar a WAND que recorre només algunes llistes tot tenint en compte les coincidències de les altres.
L'algoritme divideix les llistes en dos grups. Les llistes directores fan avançar el recorregut i proposen documents candidats. Les llistes de sondeig contribueixen a les puntuacions d'aquests candidats però no generen candidats per si mateixes.
La puntuació de candidats combina la cobertura ponderada de termes de cerca i una contribució de freqüència, amb la normalització de la longitud del document i un límit en els guanys dels termes repetits. Photon comprova primer la presència de termes a les matrius i mapes de bits per limitar la puntuació màxima possible de cada manifestació. Llegeix les freqüències de termes exactes només per als candidats que encara podrien complir el llindar de selecció.
La selecció procedeix llavors en tres passos:
- Recorregut: Comenceu amb un requisit estricte de cobertura de consultes. Si es troben massa pocs candidats, torneu a provar amb un requisit més relaxat.
- Retenció: Els candidats es mantenen en un conjunt fitat utilitzant una puntuació que combina cobertura i freqüència. A mesura que els millors candidats recollits milloren, el llindar d'admissió puja.
- Selecció final: Els resultats finals per a la passada s'escullen del conjunt retingut basant-se en les puntuacions de freqüència. Cada camp executa la seva pròpia passada, i els resultats es fusionen utilitzant pesos de camp.
L'algoritme produeix un conjunt de candidats de documents rellevants per ser utilitzats en una jerarquització posterior.
Docblob
Un cop seleccionades les pàgines candidates, la fase de jerarquització necessita freqüències de termes, cobertura de camps, i les ubicacions i proximitat de les aparicions. Obtenir aquestes dades a través de l'índex invertit requeriria accessos dispersos a través de molts parells de terme-document. A Photon, emmagatzemem un registre compacte per document anomenat docblob que conté freqüències de termes, en quins camps ha aparegut un terme i on s'ha produït al document. Com a resultat, jerarquitzar un candidat només requereix una cerca per document.
El format està construït per evitar descodificar més del necessari. Dins d'un docblob, els camps s'agrupen per analitzador de text. Cada grup emmagatzema una llista de termes ordenada codificada amb Elias-Fano, de manera que es pot cercar un terme de consulta directament sense expandir tota la llista primer. Una màscara de camp marca on s'ha produït un terme, un recompte de freqüència fa un seguiment de la freqüència, i les posicions reals resideixen en blocs separats per parell de terme-camp codificats com a diferències de posició. Només es descodifiquen els blocs dels termes que realment han coincidit, mentre que la resta del registre es manté en el format comprimit.
Aquesta descodificació selectiva permet que docblob admeti l'emmagatzematge de més dades per document sense un augment de cost proporcional. Fer créixer el registre no força més feina per cerca, perquè la jerarquització només toca les parts rellevants per als termes coincidents en lloc de tot el registre.
Lectures per lots i treball amb la memòria
Fins i tot amb les representacions de dades més eficients, la RAM s'acaba abans que altres recursos, de manera que sovint necessitem accedir a dades emmagatzemades al disc. Photon utilitza lectures de disc asíncrones i una memòria cau optimitzada per a lectures per lots per accelerar aquests accessos, reduint el temps d'espera per sol·licitud. Això contribueix a una millora significativa en la latència de cua en comparació amb el sistema anterior.
Solapament d'esperes de disc
La jerarquització requereix obtenir les característiques d'un centenar de documents situats en diferents parts d'un fitxer. El nostre sistema anterior utilitzava mmap per assignar el fitxer a l'espai d'adreces virtuals de manera que es pogués llegir a través de punters de memòria. No obstant això, accedir a una pàgina que estava absent de la memòria encara requeria una lectura de disc. El fil havia d'esperar les dades abans de continuar el càlcul, i aquest temps d'espera s'acumulava quan el procés necessitava llegir registres freds seqüencialment.
Photon aprofita el fet que els desplaçaments de registres es coneixen per avançat, de manera que podem enviar diverses lectures alhora. Això ho gestiona el reactor: fils de treball dedicats envien lots a través de io_uring i passen les dades que llegeixen al codi de crida. Cada fil manté el seu propi io_uring; els lots s'envien al reactor amb menys càrrega. Els descriptors de fitxers prèviament registrats i els conjunts de memòria intermèdia redueixen la sobrecàrrega de les lectures repetides. Aquesta execució asíncrona permet que les esperes de diverses operacions se solapin, la qual cosa redueix la latència de cua.
Reducció del nombre d'accessos a la unitat
Abans d'enviar lectures, Photon comprova tot el lot a la memòria cau en memòria. Només les sol·licituds de registres que falten van al disc; les dades llegides omplen llavors la memòria cau.
La memòria cau està dissenyada per a lectures per lots. Específicament:
- No hi ha cap assignació separada en un encerts. En canvi, les dades es copien en una memòria intermèdia preparada per avançat pel codi de crida.
- No hi ha cap adquisició de bloqueig per part del lector. En canvi, comprova la versió de dades i torna a intentar-ho si entra en conflicte amb una escriptura.
- Utilitza l'evicció CLOCK, en lloc de requerir actualitzacions a una llista LRU compartida a cada lectura.
- Utilitza la prefetch de la memòria cau de la CPU, on les metadades i les dades per als registres futurs es sol·liciten per avançat.
Aquestes optimitzacions redueixen la latència sense perjudicar el rendiment en les càrregues de treball que ens importen.
Construir i actualitzar l'índex separadament de la prestació
A Photon, la construcció d'índexs i la prestació de consultes s'executen en nodes diferents. Els indexadors transformen dades en estructures d'emmagatzematge llestes, mentre que els nodes de servei les llegeixen i realitzen la recuperació i la jerarquització. Com a resultat, la construcció d'índexs no competeix amb les consultes de cerca per la CPU, i els recursos per a aquestes tasques es poden escalar de manera independent.
Aquesta separació aborda els colls d'ampolla de recuperació i sincronització presents en la implementació anterior. Com que la construcció d'índexs s'executava dins del mateix clúster que servia consultes, recuperar un node fallit o afegir una nova còpia de les dades podia significar reindexar documents 'in situ', un procés que trigava dies i augmentava les respostes parcials durant la recuperació. Photon elimina aquest acoblament; els indexadors s'executen com a treballs distribuïts que produeixen estructures d'índex versionades i llestes per servir independentment dels nodes de servei, de manera que construir la següent versió de l'índex ja no competeix amb el trànsit en directe.
Preparació i construcció distribuïda
Una construcció comença seleccionant documents per a l'índex actiu i produint l'exportació d'origen. El controlador registra la versió d'origen, les taules d'entrada i el nombre esperat de fragments. Els treballs de MapReduce a YTsaurus preparen text, metadades, fragments, característiques i incrustacions precomputades en taules versionades partides per fragment. Cada indexador transmet la taula preparada, construeix les estructures per al seu fragment i fusiona els segments de text. L'índex llest, juntament amb una descripció dels seus components, es puja a l'emmagatzematge d'objectes.
El recompte de fragments i el nombre d'indexadors que s'executen concurrentment es configuren de manera independent, de manera que una construcció es pot executar en diverses onades, o es poden assignar més màquines per treballar en paral·lel. La preparació distribuïda i els indexadors paral·lels permeten construir tot l'índex web en un nombre d'hores d'un sol dígit, una millora significativa respecte al sistema anterior.
Desplegament d'una nova versió
Abans del desplegament, el controlador comprova que el nou índex estigui a punt. Si les dades estan incompletes, el desplegament es bloqueja automàticament.
Quan hi ha diversos grups de servei, el controlador els actualitza un a un. Primer elimina un grup de l'encaminament del bróker i l'inicia amb la nova versió de l'índex. Abans de servir sol·licituds, els fragments passen per una etapa d'escalfament independent basada en registres de cerca, la qual cosa prepopula l'estat inicial i fa que la transició al trànsit real sigui més suau. Després de l'escalfament, el controlador comprova l'estat de l'índex i la disponibilitat, i després torna el grup a l'encaminament. Els altres grups continuen servint sol·licituds durant aquest temps. Com que l'estat de l'operació és persistent, un reinici no força una construcció a començar de nou; el controlador pot reenganxar-se a la preparació ja en curs, reutilitzar un resultat preparat o continuar una rotació interrompuda des del pas desat.
Els temps d'actualització de dades difereixen entre verticals de cerca. Per a verticals amb altes exigències de frescor, el lliurament de documents triga un nombre de minuts d'un sol dígit. Es pot desplegar una còpia addicional de les dades en aproximadament mitja hora; els índexs preparats es carreguen i s'adjunten als fragments sense reindexar els documents d'origen.
Migració i validació dins de la nostra pila de cerca
El nostre primer objectiu era substituir el sistema antic per un motor que preservés la funcionalitat i la qualitat de cerca alhora que reduïa els temps de resposta. Vam validar Photon per etapes, començant amb proves de càrrega reproduïbles i avaluacions de qualitat fora de línia abans de passar al trànsit en directe. Photon ara impulsa la recuperació i la jerarquització en la nostra pila de cerca de producció, amb temps de resposta substancialment inferiors als del sistema antic.
Proves de càrrega i avaluacions
Per a les proves de rendiment, vam construir una eina de proves de càrrega que reprodueix consultes dels nostres registres de cerca a taxes d'arribada configurables. Compara resultats entre execucions i aplica proves estadístiques per avaluar si les diferències de rendiment observades són consistents. Per separat, vam avaluar Photon i el sistema antic en els mateixos conjunts de dades als nostres sistemes d'avaluació fora de línia interns per comprovar regressions de qualitat.
Després d'aquestes comprovacions, vam enviar consultes en directe a tots dos motors simultàniament utilitzant trànsit fantasma. Això ens va permetre comparar el seu rendiment i resultats en càrregues de treball de producció abans de canviar quin motor servia els usuaris. A continuació, vam habilitar Photon per a subconjunts petits d'usuaris i vam ampliar gradualment el desplegament, monitorant la qualitat i el rendiment durant tot el procés. La primera versió va superar les proves d'acceptació sense regressions de qualitat, i vam continuar el desplegament fins que Photon va servir tot el trànsit de producció.
Millores mesurades en producció
En el nostre flux de treball de producció, el temps de resposta p99 va baixar d'aproximadament 800 ms en el sistema antic a aproximadament 65 ms a Photon. Aquesta mesura cobreix totes les etapes dins de Photon, però exclou etapes posteriors a la pila de cerca de nivell superior. Tampoc observem ja els pics de latència associats prèviament al canvi de versions d'índexs.
Photon utilitza aproximadament un 20% menys de màquines de servei equivalents que els nodes de contingut del sistema antic alhora que emmagatzema aproximadament 2,5 vegades més dades per document. Després de la migració, vam utilitzar aquestes dades addicionals per millorar la qualitat de la jerarquització més enllà de la del sistema antic.
Photon també redueix la quantitat de dades que han de romandre a la memòria. Fixar el mateix conjunt de dades de Photon a la RAM amb mlock requeriria aproximadament 4,6 vegades tanta memòria resident com la que utilitza actualment Photon.
Avaluació de la preconfiguració ràpida de l'API de cerca
També vam utilitzar Photon com a base per a una nova preconfiguració ràpida per a la nostra API de cerca, dissenyada per a càrregues de treball sensibles a la latència. Segons les nostres mesures, la latència d'una sola crida de cerca per a la preconfiguració ràpida és de 160 ms a p50 i 230 ms a p95, inferior o comparable als números autoinformats d'altres proveïdors de l'API de cerca, tot i que els percentils de cua informats difereixen.
Vam avaluar la preconfiguració ràpida en sis punts de referència d'agents: WideSearch, BrowseComp, DSQA, FRAMES, SEAL-0 i SEAL-Hard. Al llarg d'aquestes avaluacions, va tenir el cost total estimat de model més cerca més baix i la puntuació de tasca agregada més alta entre les configuracions provades.
La preconfiguració ràpida emparella Photon amb la jerarquització optimitzada per a fluxos de treball d'agents, oferint un rendiment comparable a la preconfiguració predeterminada a un cost substancialment inferior. No obstant això, comporta un compromís en la qualitat de cerca més àmplia. La preconfiguració ràpida utilitza menys càlcul per a la jerarquització que la preconfiguració predeterminada. En punts de referència interns que cobreixen consultes de cua llarga, cobertura àmplia i diversitat de resultats, puntua 0,24 punts menys en rellevància i aproximadament 3 punts percentuals menys en disponibilitat de respostes. Creiem que aquest és un compromís sensat per als fluxos de treball d'agents, ja que el raonament i el coneixement propis del model poden ajudar a compensar la diferència.
Recomanem la preconfiguració ràpida per a les tasques d'agents del dia a dia. Per a preguntes més desafiants o ambigües que menys depenen del temps, la preconfiguració predeterminada ofereix una qualitat més robusta, justificant la seva latència i cost més elevats.
Conclusió
Estem movent constantment la nostra pila de cerca a una infraestructura pròpia basada en Rust. Substituir el motor de codi obert per Photon, el nostre motor de recuperació i jerarquització personalitzat, és l'últim pas. Photon ens dóna el control total sobre les representacions de dades, com s'organitzen les lectures i com es despleguen els nous índexs, permetent-nos optimitzar cada capa per a les nostres càrregues de treball.
Photon ha permès una cerca més ràpida a través dels productes de Perplexity i proporciona la base per a la nostra nova preconfiguració ràpida a l'API de cerca. Després de la migració, la latència de recuperació i jerarquització p99 va baixar d'aproximadament 800 ms a 65 ms. Els nostres formats de dades compactes també ens permeten emmagatzemar 2,5 vegades més dades per document, donant a la recuperació i la jerarquització accés a informació de documents més rica.
La preconfiguració ràpida ofereix una latència d'una sola crida de cerca de 160 ms a p50 i 230 ms a p95. En els sis punts de referència d'agents avaluats, va reduir el cost estimat de model més cerca per tasca en un 68% en relació amb la preconfiguració predeterminada, mantenint alhora una qualitat de tasca agregada comparable. Aquests resultats demostren els beneficis pràctics de la infraestructura dissenyada al voltant de les nostres càrregues de treball de cerca, tant per als productes de Perplexity com per als desenvolupadors que construeixen amb la nostra API.
Continuem millorant el rendiment i l'eficiència d'emmagatzematge de Photon. El nostre objectiu és admetre un índex més gran i dades de documents més riques en el mateix maquinari alhora que mantenim la cerca ràpida a mesura que creixen les nostres càrregues de treball.
Citació
@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}
}