feat: automatische Wort-Kategorisierung (Batches API + Sofort-Backfill)

Feste ~20er-Taxonomie geseedet (de/en/sv, published; bestehende
Kategorien werden wiederverwendet) + Tabelle category_batches.

src/lib/classifyWords.js: findet in Pairs verwendete Wörter ohne
Kategorie und klassifiziert sie per Haiku gegen die feste Liste.
- Stundenjob über die Message Batches API (asynchron, ~50% günstiger):
  submit/collect-Ticks, in index.js nach Boot + stündlich.
- Sofortiger synchroner One-Shot-Backfill (classifyWordsSync) für
  Live-Test ohne 24h-Verzug.
Beides materialisiert pair_categories via derivePairCategories.

POST /api/categories/auto-assign (admin): ?sync=true = Sofort-Backfill,
sonst ein Batch-Tick. Entkoppelt von generate-words und Publish.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-15 14:27:09 +02:00
parent 9738d3e35a
commit d66cff3f61
4 changed files with 365 additions and 0 deletions

View File

@@ -1,8 +1,20 @@
const router = require('express').Router();
const { query } = require('../db');
const { runCategorizationTick, classifyWordsSync } = require('../lib/classifyWords');
const STATUSES = ['requested', 'blocked', 'published'];
// POST /api/categories/auto-assign — Kategorisierung anstoßen.
// ?sync=true → sofortiger One-Shot-Backfill bestehender Wörter (synchron, kein 24h-Verzug)
// sonst → ein asynchroner Batch-Tick (submit/collect über die Message Batches API)
router.post('/auto-assign', async (req, res, next) => {
try {
const sync = req.query.sync === 'true' || req.body?.sync === true;
const result = sync ? await classifyWordsSync({}) : await runCategorizationTick();
res.json(result);
} catch (err) { next(err); }
});
const STATUS_TIMESTAMP = {
requested: 'requested_at',
published: 'published_at',