Photon: Entwicklung einer Abruf- und Ranking-Engine von Grund auf
Wie spezialisierte Datenformate, stapelweise Lesevorgänge und die Trennung von Indexerstellung und Abfragebearbeitung die KI-native Suche verbessern.
Einleitung
Der KI-native Such-Stack von Perplexity ruft Kandidatenseitenvorgänge ab und rankt sie, um die relevantesten Inhalte für das Modell zur Untermauerung seiner Antworten bereitzustellen. Ursprünglich lief diese Phase auf einer Open-Source-Engine, die wir an unser System angepasst hatten. Als jedoch unser Index und unsere Workloads wuchsen, stießen wir an harte Grenzen bei Kosten, Tail-Latenz und Knotenwiederherstellungszeit, die wir innerhalb der bestehenden Drittanbieter-Plattform nicht lösen konnten.
Um diese Herausforderungen zu bewältigen, haben wir Photon entwickelt, eine neue hausinterne Abruf- und Ranking-Engine. Dies setzt unseren Ansatz fort, KI-erste Suchinfrastruktur von Grund auf neu zu bauen, so wie wir es mit CobbleDB getan haben, unserem verteilten Key-Value-Store für das Ausliefern von Seitendatensätzen, sowie unserer Search API.
Photon verwendet kompakte Datenformate, um nur das zu lesen und zu decodieren, was die jeweilige Abfrage benötigt. Dabei kommen stapelbewusstes Caching und asynchrone Lesevorgänge zum Einsatz, um den Festplattenzugriff zu reduzieren und Wartezeiten zu überlappen. Die Indexerstellung läuft getrennt von der Abfragebearbeitung ab, wobei jeweils eine Serving-Gruppe aktualisiert und deren Caches aufgewärmt werden, bevor Live-Abfragen dorthin weitergeleitet werden.
Photon treibt nun unsere Suchpipeline an und ist zudem die Grundlage für ein neues schnelles Preset für unsere Search API, mit einer Latenz für einzelne Suchaufrufe von 160 ms bei p50 und 230 ms bei p95. Über sechs öffentliche Benchmarks hinweg reduzierte das schnelle Preset die geschätzten Kosten pro Aufgabe (Modell plus Suche) um 68 %, während eine aggregierte Aufgabenqualität aufrechterhalten wurde, die mit dem Standard-Preset vergleichbar ist. Wir veröffentlichen es heute, damit Entwickler auf diese Verbesserungen zugreifen können.
Anforderungen an die Abruf- und Ranking-Engine
Für jede Abfrage durchsucht die Abruf- und Ranking-Engine einen großen, verteilten Index, um eine kleine Menge relevanter Seiten innerhalb des Latenzbudgets des Such-Stacks auszuwählen und zu sortieren. Das System muss den Index auch aktuell halten, während neue Seiten eintreffen und bestehende Seiten sich ändern, ohne dass diese Arbeit Live-Abfragen verlangsamt.
Wir haben mehrere Open-Source-Optionen evaluiert und uns für eine ausgereifte Allzweck-Abruf- und Ranking-Engine entschieden, die unsere anfänglichen Anforderungen erfüllte. Wir haben sie dann an unsere Architektur und Workloads angepasst und dabei eine stabile Latenz und einen stabilen Durchsatz im Produktionsmaßstab aufrechterhalten.
Wo unser bisheriges System Mängel aufwies
Wir haben unseren eigenen Fork beibehalten, um die Engine an unseren wachsenden Index anzupassen, aber die Behebung wichtiger Einschränkungen erforderte zunehmend die Neugestaltung großer Teile der Plattform. Mehrere Einschränkungen erwiesen sich als schwer zu lösen ohne grundlegende architektonische Änderungen:
1. Skalierungskosten. Sowohl die Anzahl der von uns gespeicherten Dokumente als auch die Menge an Daten pro Dokument, die wir abrufen und ranken müssen, sind im Laufe der Zeit gewachsen. Diese Skalierung übte Druck auf unsere Hardware aus, insbesondere auf den verfügbaren RAM. Um die Kosten zu kontrollieren, benötigten wir kompaktere Datenrepräsentationen und eine feinere Kontrolle darüber, was im Speicher verbleibt und was bei Bedarf von der Festplatte gelesen wird.
2. Schlechte Tail-Latenz. Bei Produktionsdatenverkehr betrug die p99-Antwortzeit des alten Systems etwa 800 ms. Der Datensatz überstieg den verfügbaren RAM, sodass wir mlock nicht verwenden konnten, um ihn vollständig im Arbeitsspeicher zu halten. Der Zugriff auf nicht-residente Daten konnte schwere Seitenfehler (Page Faults) auslösen, wodurch die Abfrageausführung ins Stocken geriet, während das Betriebssystem von der Festplatte las.
Die Engine führte zudem regelmäßig ihren Haupt-Festplattenindex mit kleineren, aus dem Speicher gefushiten Indizes zusammen. Während dieses Festplattenindex-Zusammenführungsprozesses stieg die Anzahl der Seitenfehler (Page Faults) noch weiter an, wobei die p99-Latenz für 10 bis 15 Minuten etwa 1,2 s erreichte. Während sich die Caches aufwärmenten, nahmen sowohl die Häufigkeit von Seitenfehlern als auch die Latenz ab, was darauf hindeutet, dass kalte Lesevorgänge maßgeblich zu den Spitzen beigetragen haben. Das Vorladen von Daten und das Aufwärmen des Index reduzierten die Spitzen, behoben jedoch die hohe Tail-Latenz nicht adäquat.
3. Langwierige Wiederherstellung und Synchronisierung. Im vorherigen System konnte die Bereitstellung eines zusätzlichen Clusters und die Synchronisierung seiner Daten mehr als eine Woche dauern. Eine Synchronisierung war auch erforderlich, wenn Knotengruppen hinzugefügt wurden, um zusätzliche Datenkopien vorzuhalten, oder bei der Wiederherstellung nach Knotenausfällen. Während der Wiederherstellung war ein größerer Anteil der Suchantworten partiell, was die Qualitätsbewertungen der Endergebnisse verschlechterte.
Schließlich kamen wir zu dem Schluss, dass es einfacher und kostengünstiger wäre, von Grund auf neu zu bauen, anstatt unseren Fork weiter anzupassen und zu pflegen. Gestützt auf unsere Erfahrungen beim Betrieb des vorherigen Systems arbeitete ein kleines Engineering-Team zusammen mit einem Schwarm persistenter Coding-Agenten an der Entwicklung von Photon.
Wo sich Photon in den Such-Stack einfügt
Photon ist für zwei primäre Workflows konzipiert: das Bedienen von Suchanfragen und das Ingestieren von Aktualisierungen aus der Verarbeitungspipeline.
Eine Anfrage des höherstufigen Suchdienstes erreicht den Photon-Broker über einen Load Balancer. Der Broker wählt eine Shard-Gruppe aus und leitet die Anfrage an jeden Shard weiter, wobei Timeouts überwacht und bei Bedarf zusätzliche Anfragen ausgestellt werden.
Jeder Shard führt Abruf, Erst-Ranking und Zweitstufen-Ranking durch und gibt dann seine besten Kandidaten an den Broker zurück. Der Broker fasst diese Kandidaten zu einer einzigen gerankten Liste zusammen und ruft wichtige Dokumentfelder für die ausgewählten Seiten von den relevanten Shards ab. Er gibt diese Ergebnisse dann an den höherstufigen Suchdienst zurück, der die für den Agenten erforderlichen Seiteninhalte sammelt, um eine fundierte Antwort zu generieren.
Indexaktualisierungen folgen einem separaten Pfad. Pillar, unsere Veröffentlichungsschicht, bereitet die Daten vor und speichert sie in YTsaurus-Tabellen. Indexer konvertieren diese Tabellen in Indexstrukturen, die Shards für die Suche laden können. Der Controller koordiniert die Datenvorbereitung, die Indexerstellung und die Bereitstellung neuer Indexversionen für Serving-Gruppen. Bevor Live-Datenverkehr verarbeitet wird, spielt jeder Shard reale Suchabfragen ab, um seine Caches aufzuwärmen.
Entwurf von Photon für unsere Workflows
Drei Designentscheidungen machen Photon gut geeignet für unseren Workflow: kompakte Datenrepräsentationen, Caching und asynchrone Festplattenlesevorgänge sowie die Trennung von Indexaktualisierungen und Abfragebearbeitung.
Datenrepräsentationen für Abruf und Ranking
Abruf und Ranking greifen unterschiedlich auf Dokumentdaten zu. Der lexikalische Abruf beginnt mit Abfragebegriffen und findet Dokumente, die diese enthalten. Das Ranking benötigt dann detaillierte Informationen über jedes ausgewählte Dokument, einschließlich Begriffshäufigkeiten und Positionen.
Photon verwendet zwei komplementäre Darstellungen, um diese Zugriffsmuster zu unterstützen. Ein invertierter Index speichert eine Liste passender Dokumente für jeden Begriff, eine sogenannte Posting-Liste, um die Kandidatenauswahl zu unterstützen. Separate Datensätze pro Dokument liefern die für das Ranking benötigten Daten. Wir optimieren zudem die Speicherung und Traversierung von Posting-Listen, um die Auswahl innerhalb eines festen Arbeitsbudgets zu verbessern.
Spezialisierte Datenrepräsentationen ermöglichen es uns, Schlüsseldaten effizienter zu speichern. Ein kompakterer invertierter Index reduziert die pro Abfrage gelesene oder verschobene Datenmenge und verbessert die Latenz durch Eliminierung unnötiger E/A-Operationen. Diese Formate ermöglichen es auch zu überprüfen, ob ein Dokument in einer Liste erscheint, ohne es vollständig zu decodieren – eine Eigenschaft, auf die unsere Traversierungslogik vertraut, um zu steuern, wie viel Arbeit eine Abfrage unter einem festen Budget verrichtet. Die Optimierung von Datensätzen pro Dokument ermöglicht es uns, mehr Daten pro Dokument für das Ranking zu speichern und gleichzeitig die Skalierungskosten im Zusammenhang mit unserem bisherigen System zu senken.
Der invertierte Index
Für jeden Begriff speichert der invertierte Index eine Posting-Liste. Diese Listen können von einer Handvoll Dokumenten bis zu Millionen reichen, sodass kein einzelnes Format für jede Liste gleichermaßen gut funktioniert. Photon wählt das Format basierend auf der Anzahl der Dokumente aus, die den Begriff enthalten.
Kurze Listen verwenden eine Inline-Darstellung, die in eine einzelne Seite passt und keine Blocktabelle erfordert. Längere Listen, die nicht in das Inline-Format passen, werden in Blöcke unterteilt, die feste Bereiche von Dokumentkennungen abdecken. Die Darstellung jedes Blocks hängt von seiner Dichte ab: Sparse-Blöcke speichern sortierte Arrays von Dokument-ID-Offsets, während Dense-Blöcke Bitmaps verwenden. Sparse-Blöcke verwenden die Galloping-Suche, die in immer größeren Schritten vorrückt, um Bereiche der Liste zu überspringen. Dense-Blöcke ermöglichen Mitgliedschaftsprüfungen durch Nachschlagen des Bits, das einem Dokument entspricht.
Die Abfragehäufigkeit eines Begriffs bestimmt, wo seine Posting-Liste auf der Festplatte platziert wird. Häufig abgefragte Listen werden nahe beieinander gespeichert, wodurch heiße Daten in einem kleineren Speicherbereich konzentriert werden. Innerhalb jeder Liste sind Dokumente nach einem separaten Nützlichkeitssignal geordnet, sodass vielversprechendere Kandidaten früher angetroffen werden.
Traversieren von Listen innerhalb eines Arbeitsbudgets
Die Kandidatenauswahl erfordert das Traversieren von Posting-Listen, um potenziell relevante Dokumente zu finden. Das erschöpfende Scannen jeder Liste ist teuer, weshalb Photon einen WAND-ähnlichen Algorithmus verwendet, der nur einige Listen traversiert und dabei dennoch Übereinstimmungen in den anderen berücksichtigt.
Der Algorithmus unterteilt Listen in zwei Gruppen. Treibende Listen treiben die Traversierung voran und schlagen Kandidatendokumente vor. Probenabelisten tragen zu den Bewertungen dieser Kandidaten bei, erzeugen jedoch selbst keine Kandidaten.
Die Kandidatenbewertung kombiniert gewichtete Abfragebegriffsabdeckung und einen Häufigkeitsbeitrag, mit Dokumentlängenormalisierung und einer Obergrenze für Gewinne aus wiederholten Begriffen. Photon überprüft zunächst das Vorhandensein von Begriffen in den Arrays und Bitmaps, um die maximal mögliche Punktzahl jedes Kandidaten zu begrenzen. Es liest exakte Begriffshäufigkeiten nur für Kandidaten, die die Auswahlschwelle noch erreichen könnten.
Die Auswahl erfolgt dann in drei Schritten:
- Traversierung: Beginnen Sie mit einer strengen Abfrageabdeckungsanforderung. Wenn zu wenige Kandidaten gefunden werden, wiederholen Sie den Vorgang mit einer gelockerten Anforderung.
- Aufnahme (Retention): Kandidaten werden in einer begrenzten Menge gehalten, wobei eine Bewertung verwendet wird, die Abdeckung und Häufigkeit kombiniert. Wenn sich die gesammelten Top-Kandidaten verbessern, steigt die Aufnahmeschwelle.
- Endgültige Auswahl: Die Endergebnisse für den Durchlauf werden basierend auf den Häufigkeitswertem aus der beibehaltenen Menge ausgewählt. Jedes Feld führt einen eigenen Durchlauf aus, und die Ergebnisse werden anhand von Feldgewichten zusammengeführt.
Der Algorithmus erzeugt eine Kandidatenmenge relevanter Dokumente, die im weiteren Ranking verwendet werden soll.
Docblob
Nachdem Kandidatenseiten ausgewählt wurden, benötigt die Ranking-Phase Begriffshäufigkeiten, Feldabdeckung sowie die Speicherorte und die Nähe von Vorkommen. Das Abrufen dieser Daten über den invertierten Index würde verstreute Zugriffe über viele Begriff-Dokument-Paare hinweg erfordern. In Photon speichern wir einen kompakten Datensatz pro Dokument namens Docblob, der Begriffshäufigkeiten enthält, in welchen Feldern ein Begriff vorkam und wo im Dokument er auftrat. Infolgedessen erfordert das Ranking eines Kandidaten nur ein Nachschlagen pro Dokument.
Das Format ist so aufgebaut, dass eine Decodierung über das Notwendige hinaus vermieden wird. Innerhalb eines Docblobs sind Felder nach Textanalysator gruppiert. Jede Gruppe speichert eine sortierte Begriffsliste, die mit Elias-Fano codiert ist, sodass ein Abfragebegriff direkt nachgeschlagen werden kann, ohne zuerst die gesamte Liste zu expandieren. Eine Feldmaske markiert, wo ein Begriff aufgetreten ist, ein Häufigkeitszähler verfolgt, wie oft, und tatsächliche Positionen befinden sich in separaten Blöcken pro Begriff-Feld-Paar, codiert als Positionsdifferenzen. Nur die Blöcke für Begriffe, die tatsächlich übereinstimmten, werden decodiert, während alles andere im Datensatz im komprimierten Format verbleibt.
Diese selektive Decodierung ermöglicht es Docblob, das Speichern von mehr Daten pro Dokument ohne proportionalen Kostenanstieg zu unterstützen. Das Vergrößern des Datensatzes erzwingt keine zusätzliche Arbeit pro Abruf, da das Ranking immer nur die Teile berührt, die für die übereinstimmenden Begriffe relevant sind, anstatt des gesamten Datensatzes.
Stapelweise Lesevorgänge und der Umgang mit dem Speicher
Selbst mit den effizienteren Datenrepräsentationen geht der RAM vor anderen Ressourcen zur Neige, sodass wir häufig auf auf der Festplatte gespeicherte Daten zugreifen müssen. Photon verwendet asynchrone Festplattenlesevorgänge und einen für Stapellesevorgänge optimierten Cache, um diese Zugriffe zu beschleunigen und die Wartezeit pro Anfrage zu verkürzen. Dies trägt zu einer signifikanten Verbesserung der Tail-Latenz im Vergleich zum vorherigen System bei.
Überlappende Festplatten-Wartezeiten
Das Ranking erfordert das Beschaffen der Merkmale von hundert Dokumenten, die sich an verschiedenen Teilen einer Datei befinden. Unser früheres System verwendete mmap, um die Datei in den virtuellen Adressraum abzubilden, damit sie über Speicherzeiger gelesen werden konnte. Der Zugriff auf eine Seite, die im Speicher fehlte, erforderte jedoch dennoch einen Festplattenlesevorgang. Der Thread musste auf die Daten warten, bevor die Berechnung fortgesetzt werden konnte, und diese Wartezeit summierte sich, wenn der Prozess kalte Datensätze sequenziell lesen musste.
Photon macht sich zunutze, dass Datensatz-Offsets im Voraus bekannt sind, sodass wir mehrere Lesevorgänge auf einmal senden können. Dies wird vom Reaktor verwaltet: Dedizierte Worker-Threads übermitteln Stapel über io_uring und leiten die gelesenen Daten an den aufrufenden Code weiter. Jeder Thread unterhält sein eigenes io_uring; Stapel werden an den am wenigsten ausgelasteten Reaktor gesendet. Vorregistrierte Dateideskriptoren und Pufferpools reduzieren den Overhead wiederholter Lesevorgänge. Diese asynchrone Ausführung ermöglicht es, dass sich die Wartezeiten für mehrere Operationen überschneiden, wodurch Tail-Latenz reduziert wird.
Reduzierung der Laufwerkszugriffe
Bevor Lesevorgänge übermittelt werden, überprüft Photon den gesamten Stapel im In-Memory-Cache. Nur Anfragen für fehlende Datensätze gehen an die Festplatte; die gelesenen Daten füllen dann den Cache.
Der Cache ist für stapelweise Lesevorgänge ausgelegt. Insbesondere:
- Bei einem Treffer erfolgt keine separate Allokation. Stattdessen werden Daten in einen Puffer kopiert, der im Voraus vom aufrufenden Code vorbereitet wurde.
- Es erfolgt keine Sperrenakquise (Lock Acquisition) durch den Leser. Stattdessen überprüft dieser die Datenversion und unternimmt bei einem Konflikt mit einem Schreibvorgang einen erneuten Versuch.
- Es verwendet CLOCK-Verdrängung, anstatt Aktualisierungen einer gemeinsam genutzten LRU-Liste bei jedem Lesevorgang zu erfordern.
- Es nutzt CPU-Cache-Prefetching, bei dem Metadaten und Daten für kommende Datensätze im Voraus angefordert werden.
Diese Optimierungen verringern die Latenz, ohne die Leistung bei den für uns wichtigen Workloads zu beeinträchtigen.
Erstellung und Aktualisierung des Index getrennt vom Serving
In Photon laufen Indexerstellung und Abfragebearbeitung auf unterschiedlichen Knoten. Indexer transformieren Daten in einsatzbereite Speicherstrukturen, während Serving-Knoten diese lesen und Abruf sowie Ranking durchführen. Infolgedessen konkurriert die Indexerstellung nicht mit Suchabfragen um die CPU, und Ressourcen für diese Aufgaben können unabhängig voneinander skaliert werden.
Diese Trennung adressiert die Wiederherstellungs- und Synchronisierungsengpässe der vorherigen Implementierung. Da die Indexerstellung innerhalb desselben Clusters ablief, das Abfragen bediente, konnte die Wiederherstellung eines ausgefallenen Knotens oder das Hinzufügen einer neuen Datenkopie bedeuten, Dokumente an Ort und Stelle neu zu indizieren – ein Prozess, der Tage dauerte und partielle Antworten während der Wiederherstellung erhöhte. Photon hebt diese Kopplung auf; Indexer laufen als verteilte Jobs, die versionierte, einsatzbereite Indexstrukturen unabhängig von den Serving-Knoten erstellen, sodass das Erstellen der nächsten Version des Index nicht mehr mit dem Live-Datenverkehr konkurriert.
Vorbereitung und verteilte Erstellung
Ein Build beginnt mit der Auswahl von Dokumenten für den aktiven Index und der Erstellung des Quell-Exports. Der Controller zeichnet die Quellenversion, die Eingangstabellen und die erwartete Anzahl von Shards auf. MapReduce-Jobs in YTsaurus bereiten Text, Metadaten, Fragmente, Merkmale und vorab berechnete Embeddings in versionierten Tabellen auf, die nach Shard partitioniert sind. Jeder Indexer streamt die vorbereitete Tabelle, erstellt die Strukturen für seinen Shard und führt Textsegmente zusammen. Der bereite Index wird zusammen mit einer Beschreibung seiner Komponenten in den Objektspeicher hochgeladen.
Die Shard-Anzahl und die Anzahl der gleichzeitig laufenden Indexer werden unabhängig voneinander konfiguriert, sodass ein Build in mehreren Wellen laufen oder mehr Maschinen für die parallele Arbeit zugewiesen werden können. Verteilte Vorbereitung und parallele Indexer ermöglichen es, den vollständigen Web-Index in einer einstelligen Anzahl von Stunden zu erstellen, eine signifikante Verbesserung gegenüber dem vorherigen System.
Bereitstellung einer neuen Version
Vor der Bereitstellung überprüft der Controller, ob der neue Index bereit ist. Wenn die Daten unvollständig sind, wird die Bereitstellung automatisch blockiert.
Wenn es mehrere Serving-Gruppen gibt, aktualisiert der Controller diese nacheinander. Er entfernt zunächst eine Gruppe aus dem Broker-Routing und startet sie auf der neuen Indexversion. Bevor Anfragen bedient werden, durchlaufen die Shards eine separate Aufwärmphase basierend auf Suchprotokollen, die den anfänglichen Zustand vorab füllt und den Übergang zum echten Datenverkehr reibungsloser gestaltet. Nach dem Aufwärmen überprüft der Controller den Indexstatus und die Bereitschaft und gibt die Gruppe dann an das Routing zurück. Die anderen Gruppen bedienen während dieser Zeit weiterhin Anfragen. Da der Betriebsstatus persistiert wird, erzwingt ein Neustart keinen Neustart des Builds; der Controller kann sich an eine bereits laufende Vorbereitung anhängen, ein bereites Ergebnis wiederverwenden oder eine unterbrochene Rotation ab dem gespeicherten Schritt fortsetzen.
Die Aktualisierungszeiten für Daten unterscheiden sich je nach Suchbereich (Vertical). Bei Bereichen mit hohen Anforderungen an die Aktualität dauert die Dokumentbereitstellung eine einstellige Anzahl von Minuten. Eine zusätzliche Kopie der Daten kann in etwa einer halben Stunde bereitgestellt werden; bereite Indizes werden geladen und an Shards angehängt, ohne die Quelldokumente erneut zu indizieren.
Migration und Validierung in unserem Such-Stack
Unser erstes Ziel war es, das alte System durch eine Engine zu ersetzen, die Funktionalität und Suchqualität bewahrt und gleichzeitig die Antwortzeiten verkürzt. Wir haben Photon in Phasen validiert, beginnend mit reproduzierbaren Lasttests und Offline-Qualitätsevaluierungen, bevor wir zum Live-Datenverkehr übergingen. Photon treibt nun Abruf und Ranking in unserem Produktions-Such-Stack an, mit wesentlich geringeren Antwortzeiten als das alte System.
Lasttests und Evaluierungen
Für Leistungstests haben wir ein Lasttest-Tool entwickelt, das Abfragen aus unseren Suchprotokollen mit konfigurierbaren Ankunftsraten wiedergibt. Es vergleicht Ergebnisse über Durchläufe hinweg und wendet statistische Tests an, um zu bewerten, ob beobachtete Leistungsunterschiede konsistent sind. Unabhängig davon haben wir Photon und das alte System anhand derselben Datensätze in unseren internen Offline-Evaluierungssystemen evaluiert, um nach Qualitätsregressionen zu suchen.
Nach diesen Prüfungen haben wir mithilfe von Shadow-Traffic Live-Abfragen gleichzeitig an beide Engines gesendet. Dies ermöglichte es uns, deren Leistung und Ergebnisse bei Produktions-Workloads zu vergleichen, bevor wir änderten, welche Engine die Benutzer bediente. Anschließend haben wir Photon für kleine Benutzeruntergruppen aktiviert und den Rollout schrittweise erweitert, wobei Qualität und Leistung kontinuierlich überwacht wurden. Die erste Version bestand die Abnahmetests ohne Qualitätsregressionen, und wir setzten den Rollout fort, bis Photon den gesamten Produktionsdatenverkehr bediente.
Gemessene Verbesserungen in der Produktion
In unserem Produktions-Workflow sank die p99-Antwortzeit im alten System von etwa 800 ms auf etwa 65 ms in Photon. Diese Messung deckt alle Phasen innerhalb von Photon ab, schließt jedoch nachfolgende Phasen im höherstufigen Such-Stack aus. Zudem beobachten wir keine Latenzspitzen mehr, die zuvor mit dem Umschalten von Indexversionen verbunden waren.
Photon verwendet im Vergleich zu den Inhaltsknoten des alten Systems ungefähr 20 % weniger äquivalente Serving-Maschinen und speichert dabei ungefähr die 2,5-fache Datenmenge pro Dokument. Nach der Migration haben wir diese zusätzlichen Daten verwendet, um die Ranking-Qualität über das Niveau des alten Systems hinaus zu verbessern.
Photon reduziert zudem die Datenmenge, die im Arbeitsspeicher verbleiben muss. Das Pinnen desselben Photon-Datensatzes im RAM mit mlock würde schätzungsweise das 4,6-Fache des residenten Speichers erfordern, den Photon derzeit nutzt.
Evaluierung des schnellen Search API-Presets
Wir haben Photon auch als Basis für ein neues schnelles Preset für unsere Search API verwendet, das für Latenzsensitive Workloads entwickelt wurde. Unseren Messungen zufolge beträgt die Latenz für einzelne Suchaufrufe für das schnelle Preset 160 ms bei p50 und 230 ms bei p95, was niedriger oder vergleichbar mit den von anderen Search API-Anbietern selbst gemeldeten Werten ist, obwohl sich die gemeldeten Tail-Perzentile unterscheiden.
Wir haben das Preset „Schnell“ anhand von sechs agentenbasierten Benchmarks evaluiert: WideSearch, BrowseComp, DSQA, FRAMES, SEAL-0 und SEAL-Hard. Über diese Evaluierungen hinweg wies es unter den getesteten Konfigurationen die geringsten geschätzten Gesamtkosten (Modell plus Suche) und die höchste aggregierte Aufgabenpunktzahl auf.
Das schnelle Preset kombiniert Photon mit einem für agentische Workflows optimierten Ranking und bietet eine vergleichbare Leistung wie das Standard-Preset bei deutlich geringeren Kosten. Allerdings geht dies mit Abstrichen bei der breiteren Suchqualität einher. Das schnelle Preset verwendet für das Ranking weniger Rechenleistung als das Standard-Preset. Bei internen Benchmarks zu Long-Tail-Abfragen, breiter Abdeckung und Ergebnisdiversität erzielt es bei der Relevanz 0.24 Punkte weniger und bei der Antwortverfügbarkeit etwa 3 Prozentpunkte weniger. Wir glauben, dass dies ein sinnvoller Kompromiss für agentische Workflows ist, da das eigene Reasoning und Wissen des Modells helfen können, den Unterschied auszugleichen.
Wir empfehlen das Preset „Schnell“ für alltägliche agentenbasierte Aufgaben. Für anspruchsvollere oder mehrdeutige Fragen, die weniger zeitkritisch sind, bietet das Standard-Preset eine robustere Qualität, was die höhere Latenz und die höheren Kosten rechtfertigt.
Fazit
Wir migrieren unseren Such-Stack kontinuierlich auf eine auf Rust basierende, hausinterne Infrastruktur. Das Ersetzen der Open-Source-Engine durch Photon, unsere benutzerdefinierte Abruf- und Ranking-Engine, ist der jüngste Schritt. Photon gibt uns die volle Kontrolle über Datenrepräsentationen, die Organisation von Lesevorgängen und die Bereitstellung neuer Indizes, sodass wir jede Schicht für unsere Workloads optimieren können.
Photon hat eine schnellere Suche über die Produkte von Perplexity hinweg ermöglicht und bildet die Grundlage für unser neues schnelles Preset in der Search API. Nach der Migration sank die p99-Latenz für Abruf und Ranking von etwa 800 ms auf 65 ms. Unsere kompakten Datenformate ermöglichen es uns zudem, die 2,5-fache Datenmenge pro Dokument zu speichern, wodurch Abruf und Ranking Zugriff auf reichhaltigere Dokumentinformationen erhalten.
Das Preset „Schnell“ liefert eine Latenz für einzelne Suchaufrufe von 160 ms bei p50 und 230 ms bei p95. Über die sechs evaluierten agentenbasierten Benchmarks hinweg reduzierte es die geschätzten Kosten pro Aufgabe (Modell plus Suche) um 68 % im Vergleich zum Standard-Preset, während es eine vergleichbare aggregierte Aufgabenqualität aufrechterhielt. Diese Ergebnisse demonstrieren die praktischen Vorteile einer Infrastruktur, die auf unsere Such-Workloads ausgelegt ist – sowohl für die Produkte von Perplexity als auch für Entwickler, die mit unserer API arbeiten.
Wir arbeiten kontinuierlich daran, Photons Leistung und Speichereffizienz zu verbessern. Unser Ziel ist es, einen größeren Index und reichhaltigere Dokumentdaten auf derselben Hardware zu unterstützen und gleichzeitig die Suche schnell zu halten, während unsere Workloads wachsen.
Zitat
@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}
}