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: consulting-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 installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceA pluggable, observable modular RAG service framework that exposes tool interfaces via the MCP protocol, enabling AI assistants like Copilot and Claude to directly invoke knowledge retrieval and reasoning capabilities.MIT
- AlicenseNot gradedqualityBmaintenanceExposes RAG and document intelligence pipelines as 8 composable tools for MCP-compatible clients, enabling querying, indexing, classifying, extracting, and assessing documents.1MIT
- FlicenseNot gradedqualityCmaintenanceProvides RAG-based knowledge retrieval and document management as MCP tools, supporting hybrid search, reranking, and retrieval process visualization.
- AlicenseNot gradedqualityCmaintenanceEnables AI assistants to query documents in a Bedrock Knowledge Base through the MCP protocol, with tools for semantic search and agentic retrieval.MIT
Related MCP Connectors
Real-time Amazon, WIPO & PACER data for AI agents — 19 tools via the MCP protocol.
100+ MCP tools for AI agents: content metadata, trade intelligence, business-expertise analysis.
Reddit & X data for AI agents over MCP. Semantic search, hosted, no Reddit API.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/shreyaschhabra/two-tower-recsys-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server