Von Oktober 2021 bis April 2022 war ich CTO eines Ventures für Geschenkempfehlungen. Man wählte einen Anlass, wählte ein paar Tags über die Person und bekam Vorschläge. Das Unternehmen hörte auf, bevor die Empfehlungsschicht gebaut war. Was hier steht, ist also das Problem, wie ich es vorfand, und was ich heute damit machen würde, kein ausgeliefertes System.
Die Randbedingung, die alles bestimmt: Der Beschenkte ist nie Nutzer. Wer das Geschenk bekommt, hat kein Konto, keine Historie, keine früheren Käufe. Collaborative Filtering fällt per Konstruktion aus, nicht aus Datenmangel. Das ist Cold Start in seiner härtesten Form, und genau deshalb greift man zuerst nach einem Modell.
Der Reflex war falsch. Das Schwierige war ein Kalender.
Ein Anlass ist mehr als ein Name
Wir wollten auf Englisch starten, größerer Zielmarkt war Spanien. Die Anlassliste brauchte also eine zweite Region, und ich nahm an, das hieße übersetzen.
Tut es nicht. Die Menge ist eine andere, die Termine sind andere, und in einem Fall enthält der Anlass die Produktkategorie.
- In Spanien wird am 6. Januar geschenkt. Día de Reyes ist der traditionelle Schenktag, nicht Heiligabend. Die ganze Dezemberspitze verschiebt sich um zwölf Tage, mit ihr Lager, Affiliate-Deals und Marketingkalender.
- Sant Jordi am 23. April ist ein Buch und eine Rose. Der Anlass ist die Kategorie. Und er gilt in Katalonien, nicht in ganz Spanien, die Taxonomie braucht also eine Ebene unterhalb des Landes.
- Muttertag ist ein anderer Sonntag. In Spanien der erste, in Deutschland der zweite, gleicher Name. Und es ist ein detalle, ein kleineres Geschenk als zum Geburtstag, also verschiebt sich auch das Preisband.
- Den Namenstag gibt es in Deutschland so nicht. Ein kompletter Schenkanlass existiert im einen Markt und im anderen nicht.
Nichts davon ist ein Übersetzungsproblem. Ein Anlass ist ein Datum, ein Preisband und eine Menge erlaubter Kategorien, und alle drei hängen an der Region.
Was das System wirklich brauchte
Die Eingabe war eine Auswahl von Tags plus ein Anlass. Strukturiert, kein Freitext. Das ist wichtig, denn eine strukturierte Eingabe braucht keine Vektorsuche, und trotzdem eine zu bauen ist eine gute Art, als kleines Team seine Landebahn aufzubrauchen.
OCCASIONS = {
# occasion, region date price band allowed categories
("mothers_day", "DE"): ("2nd Sunday in May", (20, 60), {"flowers", "jewellery", "books"}),
("mothers_day", "ES"): ("1st Sunday in May", (10, 30), {"flowers", "sweets", "books"}),
("reyes", "ES"): ("6 January", (20, 80), {"toys", "books", "clothing"}),
("sant_jordi", "ES-CT"): ("23 April", (10, 40), {"books", "flowers"}),
("name_day", "ES"): ("varies by name", (5, 25), {"sweets", "flowers", "small_gifts"}),
}
def candidates(products, chosen_tags, occasion):
date, (low, high), allowed = OCCASIONS[occasion]
for p in products:
if p["category"] not in allowed: # Sant Jordi is books and roses.
continue # Nothing else is a gift that day.
if not low <= p["price"] <= high: # A detalle is not a birthday present.
continue
shared = chosen_tags & p["tags"]
if shared:
yield p, len(shared) / len(chosen_tags | p["tags"])
def popularity_baseline(products, occasion, k=5):
_, _, allowed = OCCASIONS[occasion]
eligible = [p for p in products if p["category"] in allowed]
return sorted(eligible, key=lambda p: -p["sales_30d"])[:k]
Regeln, eine Schnittmenge, eine Sortierung. Kein Modell, keine Embeddings, keine Vektordatenbank. Es ist erklärbar, und das zählt in dem Moment, in dem jemand fragt, warum ihm ein Buch angezeigt wird, und es ist schnell genug, dass der ganze Katalog in eine Schleife passt.
Die letzte Funktion ist kein Notnagel. Sie ist das, was jedes Empfehlungssystem schlagen muss, und darauf komme ich zurück.
Januar 2022, und der Umstieg als falsche Frage
Drei Monate nach Projektstart, am 25. Januar 2022, veröffentlicht OpenAI einen Embeddings-Endpunkt. Die naheliegende Frage war, ob man umsteigt. Ich bin die archivierten Seiten inzwischen durchgegangen, und die Antwort ist heute klarer, als sie sich damals anfühlte.
Ihre eigenen Zahlen, Preise von der am 1. März 2022 archivierten Preisseite, Genauigkeit aus der Ankündigung:
- Vorheriger Stand der Technik, kostenlos: 50,2 % im Mittel über elf BEIR-Suchaufgaben
text-search-ada-001, $0,0080 je 1K Tokens: 49,0 %text-search-babbage-001, $0,0120: 50,4 %text-search-curie-001, $0,0600: 50,9 %text-search-davinci-001, $0,6000: 52,8 %
Die Stufe, die man sich leisten konnte, lag unter dem Stand der Technik, den sie ersetzen sollte. Die Stufe, die ihn schlug, kostete das Fünfundsiebzigfache. Bei hunderttausend Produkten à rund hundert Tokens sind das etwa sechstausend Dollar für einen einzigen Durchlauf, bei einem Katalog, der sich täglich änderte. Zum Vergleich: ada-002 kam im Dezember 2022 für $0,0001, ein Achtzigstel dessen, was Ada in jenem Frühjahr kostete.
Der Preis allein entscheidet die Sache. Zwei weitere Dinge entscheiden sie zusätzlich.
Textähnlichkeit löst kein Tag-Matching. BEIR misst, wie gut Dokumente zu einer Textanfrage gefunden werden. Das war nicht die Aufgabe. Eine bessere Antwort auf eine Frage zu kaufen, die niemand gestellt hat, ist eine verbreitete Art, ein Quartal auszugeben.
Die Ankündigung sagt kein Wort zu anderen Sprachen als Englisch. Keine Aussage zu Mehrsprachigkeit, kein Benchmark außerhalb englischer Aufgaben. Das ist kein Beweis, dass Spanisch schlecht war. Es ist der Beweis, dass ein Team mit Zielmarkt Spanien keine veröffentlichte Grundlage hatte, gutes Spanisch zu erwarten, und für eine Technologieentscheidung läuft das aufs Gleiche hinaus.
Was das Modell ohnehin nicht hätte liefern können, war genau das, was uns fehlte. Die Lücke war kulturell, nicht semantisch. Kein Embedding wusste 2022, dass man in Katalonien am 23. April Bücher schenkt, weil diese Tatsache in einem Kalender steht und nicht im Abstand zweier Sätze.
Die Machbarkeitsstudie, die richtig gewesen wäre
Wir haben nie eine gemacht, und darauf würde ich heute bestehen.
Hundert bis dreihundert Paare aus Anlass und Tags von Hand labeln, zwei Personen unabhängig, damit man sieht, wie weit sie übereinstimmen. Precision@5 und nDCG messen. Und dann das eine, was darüber entscheidet, ob sich der Bau überhaupt gelohnt hat:
Schlägt es Popularität? Also das meistgekaufte Produkt der zulässigen Kategorie, die Funktion von oben. Wer das nicht schlägt, hat nichts produziert außer Latenz und einer Rechnung. An dieser Baseline sterben Empfehlungsprojekte, und sie sterben leise, weil Teams ihr Modell gegen kein Modell vergleichen statt gegen die billige Antwort. Das ist derselbe grüne Haken, der nichts beweist, nur in einer anderen Domäne.
Es ist dasselbe Argument, das ich über bewertete Agentenschleifen mache, nur vier Jahre älter. Eine Zahl ohne Vergleichswert sagt gar nichts.
Was ich heute bauen würde
Embeddings kosten inzwischen fast nichts, und ein Modell kann einen Katalog in einem Durchlauf normalisieren, was Wochen an Arbeit erspart. Das ändert die zweite Hälfte des Problems und an der ersten nichts.
Ich würde weiterhin mit der Anlasstabelle anfangen. Ich würde weiterhin zuerst gegen Popularität messen. Ein Modell würde ich für das einsetzen, worin es tatsächlich gut ist: aus unordentlichem Affiliate-Produkttext saubere Kategorien und Tags machen, damit der deterministische Abgleich oben überhaupt etwas Brauchbares zum Abgleichen hat.
Und ich würde die Anlass-Taxonomie zuerst schreiben, vor jeder Zeile Code, weil das der Teil ist, für den man jemanden braucht, der weiß, dass der zweite Sonntag im Mai in Spanien der falsche Sonntag ist.
Next
Was fehlt, ist die Zahl. Ich habe den Entwurf und das Argument, aber keine Messung gegen einen echten Katalog, weil es keinen mehr gab, sobald das Unternehmen aufhörte. Ordentlich gemacht braucht das einen offenen Produktdatensatz und einen zweisprachig gelabelten Testsatz, also ein Wochenende und keinen Absatz.
Falls du Empfehlungen über mehr als ein Land gebaut hast: Wie hast du die Anlässe behandelt, die es im einen Markt gibt und im anderen nicht? Mich interessiert, ob das jemand als Daten modelliert oder ob am Ende alle bei einer Fallunterscheidung pro Region landen, was ich vermutlich ausgeliefert hätte.
Preise stammen von OpenAIs Preisseite in der Fassung vom 1. März 2022, die Genauigkeitswerte aus ihrer Ankündigung vom 25. Januar 2022. Die hier beschriebene Empfehlungsschicht wurde nie gebaut; das Unternehmen endete im April 2022.
Baust du an etwas Ähnlichem?
Ich schreibe hier über Setups, die ich selbst benutze. Wenn du an etwas Vergleichbarem arbeitest, würde mich interessieren, wie dein Workflow aussieht.