Photon: Een ophaal- en rangschikkingsengine vanaf de grond opbouwen

Hoe gespecialiseerde dataformaten, batch-reads en de scheiding van indexbouwen en querybediening AI-native zoeken verbeteren.

AuteursPerplexity Engineering

Inleiding

De AI-native zoekstack van Perplexity haalt kandidaat-pagina's op en rangschikt ze, waarbij de meest relevante inhoud naar voren wordt gebracht zodat het model zijn antwoorden kan onderbouwen. Oorspronkelijk draaide deze fase op een open-source engine die we aanpasten aan ons systeem. Naarmate onze index en workloads groeiden, liepen we echter tegen harde limieten aan op het gebied van kosten, staartlatentie en hersteltijd van knooppunten die we binnen het bestaande platform van derden niet konden oplossen.

Om deze uitdagingen te overwinnen, hebben we Photon gebouwd, een nieuwe eigen ophaal- en rangschikkingsengine. Dit zet onze benadering voort van het vanaf de grond af aan bouwen van AI-first zoekinfrastructuur, zoals we deden met CobbleDB, onze gedistribueerde sleutel-waardewinkel voor het bedienen van paginarecords, en onze Search API.

Photon gebruikt compacte data-formaten om alleen te lezen en te decoderen wat elke query nodig heeft, met batch-bewuste caching en asynchrone reads om schijftoegang te verminderen en wachttijden te overlappen. Het bouwen van indexen loopt apart van het bedienen van queries, waarbij één bedieningsgroep tegelijk wordt bijgewerkt en de caches worden opgewarmd voordat live queries erheen worden gerouteerd.

Photon stuurt nu onze zoekpipeline aan en vormt tevens de basis voor een nieuwe snelle preset voor onze Search API, met een latentie van een enkele zoekaanroep van 160 ms op p50 en 230 ms op p95. Over zes openbare benchmarks verlaagde de snelle preset de geschatte kosten per taak voor model-plus-zoeken met 68% met behoud van een totale taakkwaliteit die vergelijkbaar is met de standaardpreset. We brengen deze vandaag uit zodat ontwikkelaars toegang hebben tot deze verbeteringen.

Zelfgerapporteerde latentie van een enkele zoekaanroep. PPLX Fast rapporteert een p50-latentie van 160 ms en een p95-latentie van 230 ms. Exa Instant rapporteert p90, niet p95, voor zijn hoge-staartwaarde; de hoge-staartwaarden van Parallel zijn niet gepubliceerd. De gerapporteerde percentielen en meetopstellingen zijn geen gecontroleerde vergelijking op basis van gelijke eenheden.
Totale taakkwaliteit versus geschatte totale kosten van model-plus-zoeken voor dezelfde 3.554 geselecteerde taken. Scores zijn gewogen naar taaktelling en de kosten dekken de volledige taakset. PPLX Fast scoort 64,3% op $59,73, versus 64,0% op $187,60 voor de standaard PPLX-preset, ongeveer 68% lagere geschatte kosten voor hetzelfde aantal taken.

Wat de ophaal- en rangschikkingsengine vereist

Voor elke query doorzoekt de ophaal- en rangschikkingsengine een grote, gedistribueerde index om een kleine set relevante pagina's te selecteren en te ordenen binnen het latentiebudget van de zoekstack. Het systeem moet de index ook up-to-date houden naarmate nieuwe pagina's arriveren en bestaande pagina's veranderen, zonder dat dat werk live queries vertraagt.

We hebben verschillende open-source opties geëvalueerd en kozen voor een volwassen, voor generieke doeleinden geschikte ophaal- en rangschikkingsengine die aan onze initiële behoeften voldeed. Vervolgens hebben we deze aangepast aan onze architectuur en workloads, waarbij we stabiele latentie en doorvoer handhaafden op productschaal.

Waar ons vorige systeem te kort schoot

We onderhielden onze eigen fork om de engine aan te passen aan onze groeiende index, maar het aanpakken van belangrijke beperkingen vereiste in toenemende mate het herontwerpen van grote delen van het platform. Verschillende beperkingen bleken moeilijk op te lossen zonder fundamentele architecturale wijzigingen:

1. Schaalkosten. Zowel het aantal documenten dat we opslaan als de hoeveelheid per-document data die we moeten ophalen en rangschikken is in de loop der tijd gegroeid. Deze schaling zette druk op onze hardware, met name de hoeveelheid beschikbaar RAM. Om de kosten te beheersen hadden we compactere datarepresentaties nodig en fijnere controle over wat in het geheugen blijft en wat op aanvraag van schijf wordt gelezen.

2. Slechte staartlatentie. Bij productieverkeer was de p99-responstijd van het oude systeem ongeveer 800 ms. De dataset overschreed het beschikbare RAM, dus we konden mlock niet gebruiken om deze volledig in het geheugen te houden. Het benaderen van niet-residente data kon grote paginastoringen veroorzaken, waardoor de uitvoering van queries stagneerde terwijl het besturingssysteem van schijf las.

De engine voegde ook periodiek zijn hoofdschijfindex samen met kleinere indexen die vanuit het geheugen werden weggespoeld. Tijdens dit schijfindex-fusieproces steeg het aantal paginastoringen nog verder, waarbij de p99-latentie gedurende 10-15 minuten ongeveer 1,2 s bereikte. Naarmate de caches opwarmden, namen zowel de frequentie van paginastoringen als de latentie af, wat suggereert dat koude reads een belangrijke bijdrage leverden aan de pieken. Het vooraf laden van data en het opwarmen van de index verminderde de pieken, maar pakte hoge staartlatentie niet adequaat aan.

3. Langdurig herstel en synchronisatie. In het vorige systeem kon het implementeren van een extra cluster en het synchroniseren van de data meer dan een week duren. Synchronisatie was ook vereist bij het toevoegen van groepen knooppunten om extra datakopieën te bevatten of bij het herstellen van knooppuntfouten. Tijdens herstel was een groter deel van de zoekreacties gedeeltelijk, wat de scores voor de kwaliteit van het uiteindelijke antwoord verlaagde.

Uiteindelijk concludeerden we dat het eenvoudiger en goedkoper zou zijn om vanaf de grond af aan te bouwen in plaats van onze fork te blijven aanpassen en onderhouden. Puttend uit onze ervaring met het bedienen van het vorige systeem, werkte een klein engineeringteam samen met een zwerm persistente programmeer-agenten om Photon te bouwen.

Waar Photon past in de zoekstack

Photon is ontworpen voor twee primaire workflows: het bedienen van zoekverzoeken en het opnemen van updates uit de verwerkingspipeline.

Een verzoek van de zoekservice op een hoger niveau bereikt de Photon-broker via een load balancer. De broker selecteert een shard-groep en stuurt het verzoek door naar elke shard, waarbij timeouts worden bewaakt en extra verzoeken worden ingediend wanneer dat nodig is.

Elke shard voert ophalen, initiële rangschikking en rangschikking in de tweede fase uit, en retourneert vervolgens de beste kandidaten naar de broker. De broker combineert deze kandidaten tot één gerangschikte lijst en haalt belangrijke documentvelden op voor de geselecteerde pagina's uit de relevante shards. Vervolgens retourneert het deze resultaten naar de zoekservice op hoger niveau, die de paginainhoud verzamelt die nodig is voor de agent om een onderbouwd antwoord te genereren.

Indexupdates volgen een apart pad. Pillar, onze publicatielaag, bereidt de data voor en slaat deze op in YTsaurustabellen. Indexers converteren deze tabellen naar indexstructuren die shards kunnen laden voor zoeken. De controller coördineert datavoorbereiding, het bouwen van indexen en de implementatie van nieuwe indexversies naar bedieningsgroepen. Voordat live verkeer wordt afgehandeld, speelt elke shard echte zoekqueries af om zijn caches op te warmen.

Een query beweegt zich van de zoekservice op hoger niveau via de load balancer en broker naar een geselecteerde shard-groep. Elke shard haalt kandidaten op en rangschikt ze; de broker voegt de resultaten samen, haalt documentvelden op voor de geselecteerde pagina's en retourneert deze naar de zoekservice op hoger niveau. Genummerde stappen tonen de volgorde. Doorgetrokken pijlen dragen verzoeken en onderbroken pijlen dragen resultaten terug. De faselabels aan de linkerkant onderscheiden kandidaatselectie van samenvatting-reads.

Photon ontwerpen voor onze workflows

Drie ontwerppunten maken Photon zeer geschikt voor onze workload: compacte datarepresentaties, caching en asynchrone schijf-reads, en het scheiden van indexupdates van het bedienen van queries.

Datarepresentaties voor ophalen en rangschikken

Het ophalen en rangschikken benaderen documentdata op verschillende manieren. Lexicaal ophalen begint met querytermen en vindt documenten die deze bevatten. Rangschikking heeft vervolgens gedetailleerde informatie nodig over elk geselecteerd document, inclusief termfrequenties en posities.

Photon gebruikt twee complementaire representaties om deze toegangsronde te ondersteunen. Een geïnverteerde index slaat een lijst van matchende documenten op voor elke term, een postinglijst genoemd, om kandidaatselectie te ondersteunen. Aparte per-document records leveren de data die nodig is voor rangschikking. We optimaliseren ook hoe postinglijsten worden opgeslagen en doorlopen om de selectie te verbeteren binnen een vast werkbudget.

Gespecialiseerde datarepresentaties stellen ons in staat om sleuteldata efficiënter op te slaan. Een compactere geïnverteerde index vermindert de hoeveelheid data die per query wordt gelezen of verplaatst, wat de latentie verbetert doordat onnodige I/O-bewerkingen worden geëlimineerd. Deze formaten maken het ook mogelijk om te controleren of een document in een lijst voorkomt zonder het volledig te decoderen, een eigenschap waarop onze traversatielogica vertrouwt om te controleren hoeveel werk een query verricht onder een vast budget. Het optimaliseren van per-document records stelt ons in staat om meer data per document op te slaan voor rangschikking, terwijl het ook de schaalkosten verlaagt die geassocieerd zijn met ons vorige systeem.

De geïnverteerde index

Voor elke term slaat de geïnverteerde index een postinglijst op. Deze lijsten kunnen variëren van een handvol documenten tot miljoenen, dus geen enkele indeling werkt goed voor elke lijst. Photon kiest de indeling op basis van het aantal documenten dat de term bevat.

Korte lijsten gebruiken een inline representatie die binnen één pagina past en geen bloktabel vereist. Langere lijsten die niet in het inline formaat passen, worden opgedeeld in blokken die vaste bereiken van documentidentificaties omvatten. De representatie van elk blok hangt af van de dichtheid: schaarse blokken slaan gesorteerde arrays van document-ID-offsets op, terwijl dichte blokken bitmaps gebruiken. Schaarse blokken gebruiken galloping search, die vordert in steeds grotere stappen om regio's van de lijst over te slaan. Dichte blokken maken lidmaatschapschecks mogelijk door de bit op te zoeken die overeenkomt met een document.

De queryfrequentie van een term bepaalt waar de postinglijst op de schijf wordt geplaatst. Vaak opgevraagde lijsten worden dicht bij elkaar opgeslagen, waardoor hete data in een kleinere opslagregio wordt geconcentreerd. Binnen elke lijst worden documenten geordend op een apart bruikbaarheidssignaal, zodat meer veelbelovende kandidaten eerder worden aangetroffen.

Photon kiest een postinglijst-representatie op basis van lengte en blokdichtheid. Korte lijsten passen inline binnen een pagina. Langere lijsten worden opgedeeld in vaste document-ID-bereiken, met gesorteerde offset-arrays voor schaarse blokken en bitmaps voor dichte blokken.

Lijsten doorlopen binnen een werkbudget

Kandidaatselectie vereist het doorlopen van postinglijsten om potentieel relevante documenten te vinden. Het exhaustief scannen van elke lijst is duur, dus Photon gebruikt een WAND-achtig algoritme dat slechts sommige lijsten doorloopt terwijl het toch rekening houdt met matches in de andere.

Het algoritme verdeelt lijsten in twee groepen. Sturende lijsten bevorderen de traverse en stellen kandidaat-documenten voor. Probe-lijsten dragen bij aan de scores van die kandidaten, maar genereren zelf geen kandidaten.

Kandidaatscoring combineert gewogen querytermedekking en een frequentiebijdrage, met documentlengtenormalisatie en een limiet op winst door herhaalde termen. Photon controleert eerst de aanwezigheid van termen in de arrays en bitmaps om de maximaal mogelijke score van elke kandidaat te begrenzen. Het leest exacte termfrequenties alleen voor kandidaten die nog steeds aan de selectiedrempel kunnen voldoen.

Selectie verloopt vervolgens in drie stappen:

  • Traverse: Begin met een strikte eis voor query-dekking. Als er te weinig kandidaten worden gevonden, herhaal dan met een soepelere eis.
  • Retentie: Kandidaten worden in een begrensde set gehouden met behulp van een score die dekking en frequentie combineert. Naarmate de verzamelde topkandidaten verbeteren, stijgt de toelatingsdrempel.
  • Uiteindelijke selectie: De uiteindelijke resultaten voor de ronde worden gekozen uit de behouden set op basis van de frequentiescores. Elk veld doorloopt zijn eigen ronde en de resultaten worden samengevoegd met behulp van veldgewichten.

Het algoritme produceert een kandidaatset van relevante documenten die in verdere rangschikking zal worden gebruikt.

Illustratieve begrensde kandidaattraverse. Sturende lijsten stellen documenten voor, terwijl bovengrenzen het mogelijk maken om kandidaten onder de huidige toelatingsdrempel te snoeien zonder probe-lijsten of exacte frequenties te lezen. De drempel stijgt naarmate de behouden set verbetert. Scores zijn uitgevonden ter illustratie en de behouden kandidaten zijn geen gegarandeerde exacte top-k.

Docblob

Nadat kandidaat-pagina's zijn geselecteerd, heeft de rangschikkingsfase termfrequenties, velddekkingsgraad en de locaties en nabijheid van voorkomens nodig. Het verkrijgen van deze data via de geïnverteerde index zou verspreide toegangen over vele term-document-paren vereisen. In Photon slaan we een compact per-document record op dat docblob wordt genoemd en dat termfrequenties bevat, in welke velden een term verscheen en waar in het document deze voorkwam. Als gevolg hiervan vereist het rangschikken van een kandidaat slechts één opzoeking per document.

Het formaat is gebouwd om te voorkomen dat er meer wordt gedecodeerd dan nodig is. Binnen een docblob zijn velden gegroepeerd op tekstanalyse. Elke groep slaat een gesorteerde termlijst op die is gecodeerd met Elias-Fano, zodat een queryterm direct kan worden opgezocht zonder eerst de hele lijst uit te breiden. Een veldmasker markeert waar een term voorkomt, een frequentietelling houdt bij hoe vaak, en werkelijke posities bevinden zich in aparte blokken per term-veld-paar gecodeerd als positieverschillen. Alleen de blokken voor termen die daadwerkelijk matchen worden gedecodeerd, terwijl al het andere in het record in het gecomprimeerde formaat blijft.

Dankzij die selectieve decodering ondersteunt docblob het opslaan van meer data per document zonder proportionele kostenstijging. Het laten groeien van het record dwingt niet meer werk per opzoeking af, omdat de rangschikking altijd alleen de onderdelen aanraakt die relevant zijn voor de gematchte termen in plaats van het hele record.

Een docblob groepeert rangschikkingsdata in een compact per-document record. Querytermen worden opgezocht in een met Elias-Fano gecodeerde termlijst; veldmaskers, frequenties en positieblokken leveren de data die nodig is voor gematchte termen, terwijl ongerelateerde termen gecomprimeerd blijven. Term-ID's en posities zijn illustratief.

Reads in batches en werken met geheugen

Zelfs met de efficiëntere datarepresentaties raakt het RAM nog steeds op voor andere resources, dus we moeten regelmatig data benaderen die op schijf is opgeslagen. Photon gebruikt asynchrone schijf-reads en een cache die is geoptimaliseerd voor batch-reads om deze toegangen te versnellen, waardoor de wachttijd per verzoek wordt verkort. Dit draagt bij aan een aanzienlijke verbetering van de staartlatentie in vergelijking met het vorige systeem.

Photon controleert een batch bekende recordoffsets in zijn cache voordat schijf-reads worden uitgevaardigd. Cachehits worden gekopieerd naar een voorbereide buffer; missers worden ingediend via io_uring zodat schijfwachttijden kunnen overlappen, en geretourneerde data vult de cache. De records en tijdlijnen zijn schematisch, geen gemeten latenties.

Overlappende schijfwachttijden

Rangschikking vereist het verkrijgen van de kenmerken van honderd documenten die zich in verschillende delen van een bestand bevinden. Ons vorige systeem gebruikte mmap om het bestand toe te wijzen aan de virtuele adresruimte zodat het kon worden gelezen via geheugenwijzers. Het benaderen van een pagina die afwezig was uit het geheugen vereiste echter nog steeds een schijf-read. De draad moest wachten op de data voordat de berekening werd voortgezet, en deze wachttijd liep op toen het proces koude records opeenvolgend moest lezen.

Photon maakt gebruik van het feit dat recordoffsets van tevoren bekend zijn, zodat we meerdere reads tegelijk kunnen indienen. Dit wordt beheerd door de reactor: toegewijde worker-draden dienen batches in via io_uring en geven de gelezen data door aan de aanroepende code. Elke draad onderhoudt zijn eigen io_uring; batches worden naar de minst belastte reactor gestuurd. Vooraf geregistreerde bestandsdescriptors en bufferpools verlagen de overhead van herhaalde reads. Deze asynchrone uitvoering zorgt ervoor dat het wachten op meerdere bewerkingen elkaar kan overlappen, waardoor de staartlatentie wordt verminderd.

Het aantal schijftoegangen verminderen

Voordat reads worden ingediend, controleert Photon de hele batch in de in-memory cache. Alleen verzoeken om ontbrekende records gaan naar de schijf; de gelezen data vult vervolgens de cache.

De cache is ontworpen voor reads in batches. Specifiek:

  • Er is geen afzonderlijke toewijzing bij een hit. In plaats daarvan wordt data gekopieerd naar een buffer die vooraf is voorbereid door de aanroepende code.
  • Er is geen vergrendelingsverwerving door de lezer. In plaats daarvan controleert deze de dataversie en probeert het opnieuw als deze conflicteert met een schrijfactie.
  • Het maakt gebruik van CLOCK-evictie, in plaats van updates van een gedeelde LRU-lijst bij elke read te vereisen.
  • Het maakt gebruik van CPU-cache-prefetching, waarbij metadata en data voor toekomstige records van tevoren worden aangevraagd.

Deze optimalisaties verlagen de latentie zonder de prestaties te schaden op de workloads die voor ons belangrijk zijn.

Het bouwen en bijwerken van de index los van het bedienen

In Photon draaien het bouwen van indexen en het bedienen van queries op verschillende knooppunten. Indexers transformeren data in kant-en-klare opslagstructuren, terwijl bedienende knooppunten deze lezen en ophalen en rangschikken uitvoeren. Hierdoor concurreert het bouwen van indexen niet met zoekqueries om CPU, en kunnen resources voor deze taken onafhankelijk worden geschaald.

Deze scheiding pakt de herstel- en synchronisatieknelpunten aan die aanwezig waren in de vorige implementatie. Omdat het bouwen van indexen plaatsvond binnen hetzelfde cluster dat queries bediende, kon het herstellen van een mislukt knooppunt of het toevoegen van een nieuwe kopie van de data betekenen dat documenten ter plekke opnieuw moesten worden geïndexeerd, een proces dat dagen duurde en gedeeltelijke reacties tijdens het herstel verhoogde. Photon verwijdert die koppeling; indexers draaien als gedistribueerde taken die geversioneerde, kant-en-klare indexstructuren produceren onafhankelijk van de bedienende knooppunten, zodat het bouwen van de volgende versie van de index niet langer concurreert met live verkeer.

Het bouwen van indexen loopt apart van het bedienen van live queries. Pillar exporteert brondata, YTsaurus bereidt geversioneerde tabellen per shard voor en parallelle indexers schrijven kant-en-klare indexstructuren naar objectopslag. Bedienende knooppunten laden die strukturen voor ophalen en rangschikken; de concurrency van de indexer en het shard-aantal worden onafhankelijk geconfigureerd.

Voorbereiding en gedistribueerd bouwen

Een bouwstart begint met het selecteren van documenten voor de actieve index en het produceren van de bronexport. De controller legt de bronversie, inputtabellen en het verwachte aantal shards vast. MapReduce-taken in YTsaurus bereiden tekst, metadata, fragmenten, kenmerken en vooraf berekende embeddings voor in geversioneerde tabellen die per shard zijn gepartitioneerd. Elke indexer streamt de voorbereide tabel, bouwt de structuren voor zijn shard en voegt tekstsegmenten samen. De kant-en-klare index, samen met een beschrijving van de componenten, wordt geüpload naar objectopslag.

Het shard-aantal en het aantal gelijktijdig draaiende indexers worden onafhankelijk geconfigureerd, zodat een bouw in meerdere golven kan draaien of meer machines kunnen worden toegewezen om parallel te werken. Gedistribueerde voorbereiding en parallelle indexers maken het mogelijk om de volledige webindex te bouwen in een enkel cijfer aantal uren, een significante verbetering ten opzichte van het vorige systeem.

Een nieuwe versie implementeren

Voor de implementatie controleert de controller of de nieuwe index gereed is. Als de data onvolledig is, wordt de implementatie automatisch geblokkeerd.

Wanneer er meerdere bedieningsgroepen zijn, werkt de controller ze één voor één bij. Eerst verwijdert het een groep uit de brokerrouting en start deze op de nieuwe indexversie. Voordat verzoeken worden bediend, doorlopen de shards een afzonderlijke opwarmfase op basis van zoeklogs, wat de initiële status vooraf vult en de overgang naar echt verkeer soepeler maakt. Na het opwarmen controleert de controller de indexstatus en gereedheid en retourneert vervolgens de groep naar de routing. De andere groepen blijven gedurende deze tijd verzoeken bedienen. Omdat de operationele status wordt bewaard, dwingt een herstart niet af dat een bouw helemaal opnieuw begint; de controller kan opnieuw koppelen aan de voorbereiding die al aan de gang is, een kant-en-klaar resultaat hergebruiken of een onderbroken rotatie voortzetten vanaf de opgeslagen stap.

Data-updatetijden verschillen per zoekvertical. Voor verticalen met hoge versheidseisen duurt de documentlevering een enkel cijfer aantal minuten. Een extra kopie van de data kan in ongeveer een half uur worden geïmplementeerd; kant-en-klare indexen worden geladen en gekoppeld aan shards zonder de brondocumenten opnieuw te indexeren.

De controller controleert of een nieuwe index compleet is en roteert vervolgens één bedieningsgroep tegelijk. Een groep verlaat de brokerrouting, laadt de nieuwe versie, warmt de caches op met zoeklogqueries en slaagt voor de gereedheidschecks voordat deze terugkeert naar het verkeer. Andere groepen blijven bedienen en de bewaarde controllerstatus zorgt ervoor dat een onderbroken rotatie kan worden hervat.

Migratie en validatie binnen onze zoekstack

Ons eerste doel was om het oude systeem te vervangen door een engine die functionaliteit en zoekkwaliteit behield en tegelijkertijd de responstijden verkortte. We hebben Photon in fasen gevalideerd, te beginnen met reproduceerbare belastingtests en offline kwaliteitsevaluaties voordat we overstapten op live verkeer. Photon stuurt nu het ophalen en rangschikken aan in onze productiezoekstack, met aanzienlijk lagere responstijden dan het oude systeem.

Belastingtests en evaluaties

Voor prestatietests hebben we een belastingtesttool gebouwd die queries uit onze zoeklogs afspeelt tegen configureerbare aankomstsnelheden. Deze vergelijkt resultaten over runs heen en past statistische tests toe om te beoordelen of waargenomen prestatieverschillen consistent zijn. Afzonderlijk hebben we Photon en het oude systeem geëvalueerd op dezelfde datasets in onze interne offline evaluatiesystemen om te controleren op kwaliteitsregressies.

Na deze controles stuurden we gelijktijdig live queries naar beide engines met behulp van schaduwverkeer. Hierdoor konden we hun prestaties en resultaten op productieworkloads vergelijken voordat we veranderden welke engine gebruikers bediende. Vervolgens schakelden we Photon in voor kleine subsets van gebruikers en breidden we de uitrol geleidelijk uit, waarbij we de kwaliteit en prestaties voortdurend bewaakten. De eerste versie doorliep acceptatietests zonder kwaliteitsregressies en we vervolgden de uitrol totdat Photon al het productieverkeer bediende.

Gemeten verbeteringen in productie

In onze productieworkflow daalde de p99-responstijd van ongeveer 800 ms in het oude systeem tot ongeveer 65 ms in Photon. Deze meting omvat alle fasen binnen Photon, maar sluit volgende fasen in de zoekstack op een hoger niveau uit. We observeren ook niet langer de latentiepieken die voorheen geassocieerd werden met het wisselen van indexversies.

Photon gebruikt ongeveer 20% minder equivalente bedieningsmachines dan de inhoudsknooppunten van het oude systeem, terwijl het ongeveer 2,5 keer zoveel data per document opslaat. Na de migratie gebruikten we deze extra data om de rangschikkingskwaliteit te verbeteren tot boven die van het oude systeem.

Photon vermindert ook de hoeveelheid data die in het geheugen moet blijven. Het vastpinnen van dezelfde Photon-dataset in RAM met mlock zou naar schatting 4,6 keer zoveel resident geheugen vereisen als Photon momenteel gebruikt.

Evaluatie van de snelle Search API-preset

We hebben Photon ook gebruikt als basis voor een nieuwe snelle preset voor onze Search API, ontworpen voor latentiegevoelige workloads. Volgens onze metingen is de latentie van een enkele zoekaanroep voor de snelle preset 160 ms op p50 en 230 ms op p95, lager dan of vergelijkbaar met de zelfgerapporteerde getallen van andere Search API-providers, hoewel de gerapporteerde staartpercentielen verschillen.

We hebben de snelle preset geëvalueerd op zes agentische benchmarks: WideSearch, BrowseComp, DSQA, FRAMES, SEAL-0 en SEAL-Hard. Over deze evaluaties heen had deze de laagste geschatte totale kosten van model-plus-zoeken en de hoogste totale taakscore van de geteste configuraties.

De snelle preset koppelt Photon aan rangschikking die is geoptimaliseerd voor agentische workflows, wat vergelijkbare prestaties levert als de standaardpreset tegen aanzienlijk lagere kosten. Het brengt echter wel een afweging met zich mee in de bredere zoekkwaliteit. De snelle preset gebruikt minder berekening voor rangschikking dan de standaardpreset. Op interne benchmarks die long-tail-queries, brede dekking en resultaatsdiversiteit omvatten, scoort deze 0,24 punten lager op relevantie en ongeveer 3 procentpunten lager op antwoordbeschikbaarheid. Wij zijn van mening dat dit een zinvolle afweging is voor agentische workflows, aangezien de eigen redenering en kennis van het model kunnen helpen om het verschil te compenseren.

Interne vergelijking van ophaalkwaliteit tussen de standaard PPLX-preset en PPLX Fast. Relevantie (DCG) daalt van 2,45 naar 2,21, een afname van 0,24 punten; de beschikbaarheid van antwoorden daalt van 0,596 naar 0,567, een afname van 2,9 procentpunten. De twee panelen gebruiken verschillende, niet-nul-asbasislijnen, dus staafhoogtes benadrukken hiaten in plaats van proportionele verschillen.

We raden de snelle preset aan voor dagelijkse agentische taken. Voor uitdagendere of ambigue vragen die minder tijdgevoelig zijn, biedt de standaardpreset robuustere kwaliteit, wat de hogere latentie en kosten rechtvaardigt.

Conclusie

We verplaatsen onze zoekstack gestaag naar op Rust gebaseerde, eigen infrastructuur. Het vervangen van de open-source engine door Photon, onze aangepaste ophaal- en rangschikkingsengine, is de laatste stap. Photon geeft ons volledige controle over datarepresentaties, hoe reads worden georganiseerd en hoe nieuwe indexen worden geïmplementeerd, zodat we elke laag kunnen optimaliseren voor onze workloads.

Photon heeft sneller zoeken mogelijk gemaakt in de producten van Perplexity en biedt de basis voor onze nieuwe snelle preset in de Search API. Na de migratie daalde de latentie voor ophalen en rangschikken van p99 van ongeveer 800 ms tot 65 ms. Onze compacte data-formaten stellen ons ook in staat om 2,5 keer zoveel data per document op te slaan, waardoor ophalen en rangschikken toegang krijgen tot rijkere documentinformatie.

De snelle preset levert een latentie van een enkele zoekaanroep van 160 ms op p50 en 230 ms op p95. Over de zes geëvalueerde agentische benchmarks verlaagde het de geschatte kosten per taak voor model-plus-zoeken met 68% ten opzichte van de standaardpreset met behoud van vergelijkbare aggregaten voor taakkwaliteit. Deze resultaten tonen de praktische voordelen aan van infrastructuur die is ontworpen rond onze zoekworkloads, zowel voor de producten van Perplexity als voor ontwikkelaars die bouwen met onze API.

We blijven de prestaties en opslagefficiëntie van Photon verbeteren. Ons doel is om een grotere index en rijkere documentdata te ondersteunen op dezelfde hardware, terwijl we het zoeken snel houden naarmate onze workloads groeien.

Citatie

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}
}