two-tower-recsys-mcp
Two-Tower Recsys MCP — Neuronales Retrieval, bereitgestellt über MCP
Ein Deep-Learning-Zwei-Turm-Empfehlungsmodell, trainiert auf dem eigenen Review-Korpus von Amazon aus 2023, bereitgestellt als MCP (Model Context Protocol) Tool-Server, mit einem Streamlit-Chat-Frontend, das es einem Gemini-Agenten ermöglicht, diese Tools in Ihrem Namen aufzurufen.
Dieses README führt durch die gesamte Pipeline von Anfang bis Ende: was das Modell ist, wie es trainiert wurde, wie gut es tatsächlich abschneidet (gemessen, nicht geschätzt), wie der MCP-Server es bereitstellt und wie Sie das Frontend ausführen oder bereitstellen können.
1. Was das ist
Zwei-Turm-Modelle sind die Standardarchitektur hinter groß angelegten industriellen Empfehlungssystemen (dieses Muster – getrennte „Türme“, die einen Benutzer und einen Artikel in denselben Vektorraum einbetten, trainiert, damit relevante Paare nahe beieinander liegen – ist dieselbe Form, die in Produktion von YouTube, Pinterest und den eigenen Retrieval-Systemen von Amazon verwendet wird). Dieses Projekt implementiert eines von Grund auf, trainiert es auf echten Amazon-Interaktionsdaten und verpackt es für die agentische Nutzung über MCP statt über eine typische REST-API.
Warum MCP statt einer REST-API? MCP ist das Protokoll, das Anthropic für
die Verbindung von LLM-Agenten mit Tools und Daten eingeführt hat. Ein
trainiertes Modell als MCP-Tools zu verpacken (statt etwa als Flask-Endpunkt)
bedeutet, dass jeder MCP-kompatible Agent – Claude Desktop, das eigene
Streamlit+Gemini-Frontend dieses Projekts oder jeder andere MCP-Client –
recommend_for_user, similar_items usw. direkt aufrufen kann, wobei der
LLM anhand natürlicher Sprache entscheidet, wann und wie sie aufgerufen werden.
Related MCP server: Modular RAG MCP Server
2. Architektur
Benutzer-Turm: eine gelernte Benutzer-ID-Einbettung (64-dim) → 2-Schicht-MLP → 64-dim Ausgabe.
Artikel-Turm: eine gelernte Artikel-ID-Einbettung (64-dim), verkettet mit einer eingefrorenen
all-MiniLM-L6-v2-Satz-Einbettung des Produkttitels (384-dim, projiziert auf 64-dim) → 2-Schicht-MLP → 64-dim Ausgabe. Die eingefrorene Texteinbettung verleiht dem Modell Cold-Start-Fähigkeit – es kann einen Artikel auch ohne Interaktionshistorie allein anhand seines Titels sinnvoll im Vektorraum platzieren.Beide Türme geben L2-normalisierte Vektoren aus; die Ähnlichkeit ist ein Skalarprodukt (äquivalent zur Kosinus-Ähnlichkeit).
Trainingsverlust: In-Batch-Sampled-Softmax – für einen Batch von B (Benutzer, Artikel)-Positivpaaren fungiert jeder andere Artikel im Batch als Negativbeispiel für jeden Benutzer, und die Kreuzentropie wird über die resultierende B×B-Ähnlichkeitsmatrix angewendet. Dies ist der Standard-, recheneffiziente Weg, um Retrieval-Türme ohne explizites Negativ-Sampling zu trainieren.
Bereitstellung: Artikeleinbettungen werden einmal vorberechnet und in FAISS (
IndexFlatIP) für schnelle Nearest-Neighbor-Suche indiziert. Ein zweiter FAISS-Index, der über die rohen (untrainierten) MiniLM-Titeleinbettungen erstellt wird, ermöglicht eine Cold-Start-Textsuche, die unabhängig vom trainierten kollaborativen Signal funktioniert.
┌────────────┐ ┌────────────┐
│ User ID │ │ Item ID │
└─────┬──────┘ └─────┬──────┘
│ embed(64) │ embed(64)
▼ ▼
┌────────────┐ ┌──────────────────────────┐
│ MLP (128) │ │ Item title → MiniLM(384) │
└─────┬──────┘ └─────────────┬─────────────┘
│ │ project(64)
│ ▼
│ concat(128) → MLP(128)
▼ ▼
user vector (64, L2-norm) item vector (64, L2-norm)
└──────────────┬───────────────────────────┘
▼
dot product = relevance score3. Datensatz
McAuley-Lab/Amazon-Reviews-2023
(UC San Diego McAuley Lab), Kategorie Video_Games – rohe Rezensionen +
Artikeldaten, direkt von HuggingFace heruntergeladen.
Schritt | Anzahl |
Rohe Rezensionen | 4.624.615 |
Rohe Benutzer / Artikel | 2.766.656 / 137.249 |
Nach 5-Core-Filterung (Benutzer & Artikel mit ≥5 Interaktionen) | 857.505 Interaktionen |
Benutzer / Artikel (nach Filter) | 98.906 / 26.354 |
Trainings- / Validierungs- / Test-Interaktionen | 659.693 / 98.906 / 98.906 |
Split-Protokoll – Leave-last-two-out pro Benutzer, nach Zeitstempel sortiert: die jüngste Interaktion jedes Benutzers → Test, die zweitjüngste → Validierung, der Rest → Training. Dies ist ein zeitlicher Split, sodass das Modell darauf bewertet wird, tatsächlich zukünftiges Verhalten relativ zu dem, worauf es trainiert wurde, vorherzusagen, nicht auf zufällig zurückgehaltenen Interaktionen (was zukünftige Informationen in das Training einsickern lassen und die Zahlen aufblähen würde).
4. Evaluierung (echte, gemessene Zahlen)
Die Evaluierung verwendet Full-Catalog-Ranking – jeder Kandidat wird gegen alle 26.354 Artikel bewertet, nicht gegen eine kleine Stichprobe von Negativbeispielen. Die Evaluierung mit Stichproben-Negativen (in älteren RecSys-Papieren üblich, z. B. Ranking nur gegen 99 zufällige Negative) ist bekannt dafür, Offline-Metriken erheblich aufzublähen, daher ist dies das schwierigere, ehrlichere Protokoll. Die bereits gesehenen Artikel jedes Benutzers werden aus seiner eigenen Kandidaten-Rangliste ausgeschlossen.
Testsatz – 98.906 Benutzer, die zurückgehaltene letzte Interaktion jedes Benutzers:
Metrik | Wert |
Recall@10 | 1,40 % |
NDCG@10 | 0,70 % |
HitRate@10 | 1,40 % (identisch mit Recall@10 unter Leave-one-out: genau ein relevanter Artikel pro Benutzer) |
Zur Einordnung: Die Zufallswahrscheinlichkeit bei einem Katalog mit 26.354 Artikeln und k=10 beträgt 10/26.354 = 0,038 %. Das trainierte Modell ist ~37-mal besser als der Zufall unter Full-Catalog-Ranking.
Der Validierungs-Recall@10 erreichte während des Trainings einen Spitzenwert von 2,43 % (Epoche 142/150) – die Testzahl ist niedriger, weil die Testinteraktion die am weitesten in der Zukunft liegende Interaktion jedes Benutzers relativ zu seiner Trainingshistorie ist, was inhärent die schwierigere Vorhersage ist. Diese Lücke ist erwartetes Verhalten bei einem zeitlichen Split, kein Fehler. Die Testzahl (1,40 %) ist die, die überall zitiert werden sollte – die Validierung wurde nur verwendet, um den besten Checkpoint während des Trainings auszuwählen, daher wäre die Berichterstattung als Endergebnis eine Form von Cherry-Picking.
Vollständige Trainingskurve: models/train_history.csv.
Rohe Ergebnisse: models/test_results.json.
5. MCP-Tools (mcp_server.py)
Tool | Beschreibung |
| Top-k personalisierte Empfehlungen, schließt Artikel aus, mit denen der Benutzer bereits interagiert hat |
| Artikel-zu-Artikel-Ähnlichkeit über die trainierten Artikel-Turm-Einbettungen |
| Cold-Start-semantische Suche über Artikeltitel (nur MiniLM – funktioniert für Artikel, bei denen das kollaborative Modell schwache Signale hat) |
| Ähnlichkeitswert plus die früheren Artikel des Benutzers, die dem Ziel am ähnlichsten sind, für Interpretierbarkeit |
6. Frontend (streamlit_app.py)
Eine Chat-Oberfläche im gleichen Stil wie weather-mcp-server: Sie startet den MCP-Server als Unterprozess über stdio, ruft dessen Tool-Schemas ab, konvertiert sie in Gemini-Funktionsaufruf-Deklarationen und führt eine agentische Schleife aus – Gemini entscheidet anhand Ihrer Nachricht, welches der 4 Tools (falls überhaupt) aufgerufen werden soll, das Tool führt gegen das echte trainierte Modell aus, und das Ergebnis wird für eine finale Antwort in natürlicher Sprache zurückgeführt. Die Seitenleiste zeigt die Beschreibung jedes Tools sowie ein Beispiel mit einem Klick, das echte IDs aus dem trainierten Katalog verwendet, und einen Expander mit den Evaluierungsstatistiken des Modells.
7. Lokal ausführen
uv venv --python 3.11 .venv
uv pip install -p .venv/bin/python -r requirements.txt
# one-time: reproduce the trained model from scratch
.venv/bin/python src/data_prep.py # downloads + filters the dataset
.venv/bin/python src/precompute_text_embeddings.py
.venv/bin/python src/train.py # ~150 epochs, ~40s/epoch on an M2 CPU
.venv/bin/python src/evaluate.py # writes models/test_results.json
.venv/bin/python src/build_index.py # builds FAISS indices for serving
# run the MCP server standalone (stdio transport)
.venv/bin/python mcp_server.py
# or run the chat frontend (spawns the MCP server itself)
cp .streamlit/secrets.toml.example .streamlit/secrets.toml # then fill in your key
.venv/bin/streamlit run streamlit_app.pyWenn .streamlit/secrets.toml (oder eine GEMINI_API_KEY-Umgebungsvariable)
nicht gesetzt ist, fällt die App darauf zurück, zur Laufzeit in der
Seitenleiste nach einem Schlüssel zu fragen.
macOS-Hinweis
faiss und torch kollidieren auf macOS bei der OpenMP-Laufzeitinitialisierung,
was FAISS-Suchaufrufe zum Absturz bringt, es sei denn, torch/numpy werden
vor faiss importiert, mit KMP_DUPLICATE_LIB_OK=TRUE und OMP_NUM_THREADS=1
gesetzt. Beides ist bereits in mcp_server.py und src/build_index.py behandelt.
8. Bereitstellung auf Streamlit Community Cloud
Pushen Sie dieses Repository zu GitHub (öffentlich oder privat – Community Cloud kann für ein persönliches Konto beides bereitstellen).
Gehen Sie zu share.streamlit.io, klicken Sie auf New app und zeigen Sie auf dieses Repository mit
streamlit_app.pyals Einstiegspunkt.Fügen Sie in den Settings → Secrets der App Folgendes hinzu:
GEMINI_API_KEY = "your_gemini_api_key_here"Dies ist derselbe Mechanismus, den
.streamlit/secrets.tomllokal verwendet – der Schlüssel lebt nur im Secrets-Speicher von Streamlit, nie im Repository oder in der Git-Historie, und die App liest ihn automatisch, sodass Besucher nie einen Schlüssel eingeben müssen.Bereitstellen. Der erste Start wird langsam sein (~1-2 Min), während das MiniLM-Modell heruntergeladen und die FAISS-Indizes geladen werden; nachfolgende Ladevorgänge sind schnell.
Hinweis zur Repository-Größe: models/ (~110 MB: der trainierte Checkpoint
FAISS-Indizes) ist eingecheckt, damit die bereitgestellte App nicht bei jedem Kaltstart neu trainieren muss.
data/raw/(~2,9 GB rohe HuggingFace-Downloads) ist gitignored und nur nötig, wenn Sie das Training von Grund auf reproduzieren möchten.
9. Technologie-Stack
Python, PyTorch, FAISS, Sentence-Transformers (MiniLM), FastMCP, MCP Python SDK, Google Gemini API, Streamlit, pandas, HuggingFace datasets/huggingface_hub.
This server cannot be deployed
Maintenance
Related MCP Connectors
Cloud or self-hosted knowledge for AI agents: hybrid search, reranking, GraphRAG, scoped MCP tools.
Real-time Amazon, WIPO & PACER data for AI agents — 19 tools via the MCP protocol.
- WauldoOAuthcom.wauldo
Stateless agentic tools over MCP: concept extraction, long-context, knowledge graph, planning.
- geoOAuthco.thinair
Geocoding, routing, isochrones, traffic, weather, and place search for AI agents. 19 MCP tools.
Related MCP Servers
- FlicenseNot gradedqualityCmaintenanceProvides RAG-based knowledge retrieval and document management as MCP tools, supporting hybrid search, reranking, and retrieval process visualization.-
- AlicenseNot gradedqualityCmaintenanceA modular RAG framework exposing knowledge retrieval tools via MCP, enabling AI assistants to perform hybrid search, reranking, and multimodal document queries with full observability and evaluation.MIT
- AlicenseNot gradedqualityCmaintenanceEnables AI assistants to perform retrieval-augmented generation with hybrid search, reranking, multi-modal image processing, and RAG evaluation through standardized MCP tools.MIT
- AlicenseNot gradedqualityBmaintenanceEnables agents to turn documents into vectors, perform approximate nearest neighbor search with HNSW, and filter by metadata via MCP tools for RAG workflows.MIT