From c804b051e0c30fb1637d08b9ba4abadf44dc4f06 Mon Sep 17 00:00:00 2001 From: Marc Mintel Date: Sun, 8 Mar 2026 01:36:14 +0100 Subject: [PATCH] fix: qdrant --- package.json | 2 +- src/lib/qdrant.ts | 25 ---------- src/payload/collections/Media.ts | 77 ------------------------------- src/scripts/error.png | Bin 0 -> 33567 bytes src/scripts/upload-pdfs.ts | 58 ----------------------- 5 files changed, 1 insertion(+), 161 deletions(-) create mode 100644 src/scripts/error.png delete mode 100644 src/scripts/upload-pdfs.ts diff --git a/package.json b/package.json index f4683932..6cdda423 100644 --- a/package.json +++ b/package.json @@ -106,7 +106,7 @@ }, "scripts": { "dev": "bash -c '[ -f .env ] || (cp .env.example .env && sed -i.bak \"s/TRAEFIK_HOST=klz-cables.com/TRAEFIK_HOST=klz.localhost/\" .env && rm -f .env.bak && echo \"✅ Created .env from .env.example\"); trap \"COMPOSE_PROJECT_NAME=klz-2026 docker-compose -f docker-compose.dev.yml down\" EXIT INT TERM; docker network create infra 2>/dev/null || true && COMPOSE_PROJECT_NAME=klz-2026 docker-compose -f docker-compose.dev.yml down && COMPOSE_PROJECT_NAME=klz-2026 docker-compose -f docker-compose.dev.yml up klz-app klz-db klz-proxy klz-qdrant klz-redis --remove-orphans'", - "dev:local": "bash -c 'trap \"COMPOSE_PROJECT_NAME=klz-2026 docker-compose -f docker-compose.dev.yml down\" EXIT INT TERM; COMPOSE_PROJECT_NAME=klz-2026 docker-compose -f docker-compose.dev.yml up -d klz-db klz-proxy klz-qdrant klz-redis && POSTGRES_URI=\"\" NODE_ENV=development next dev --webpack --port 3100 --hostname 0.0.0.0'", + "dev:local": "bash -c 'trap \"COMPOSE_PROJECT_NAME=klz-2026 docker-compose -f docker-compose.dev.yml down\" EXIT INT TERM; COMPOSE_PROJECT_NAME=klz-2026 docker-compose -f docker-compose.dev.yml up -d klz-db klz-proxy klz-qdrant klz-redis && POSTGRES_URI=NODE_ENV=development next dev --webpack --port 3100 --hostname 0.0.0.0'", "dev:infra": "COMPOSE_PROJECT_NAME=klz-2026 docker-compose -f docker-compose.dev.yml up -d klz-db klz-proxy", "build": "next build", "start": "next start", diff --git a/src/lib/qdrant.ts b/src/lib/qdrant.ts index 31477344..c477e920 100644 --- a/src/lib/qdrant.ts +++ b/src/lib/qdrant.ts @@ -152,31 +152,6 @@ export async function deleteProductVector(id: string | number) { } } -/** - * Delete knowledge chunks by their source Media ID - */ -export async function deleteKnowledgeByMediaId(mediaId: string | number) { - try { - await ensureCollection(); - await qdrant.delete(COLLECTION_NAME, { - wait: true, - filter: { - must: [ - { - key: 'mediaId', - match: { - value: mediaId, - }, - }, - ], - }, - }); - console.log(`Successfully deleted Qdrant chunks for Media ID: ${mediaId}`); - } catch (error) { - console.error('Error deleting knowledge by Media ID from Qdrant:', error); - } -} - /** * Search products in Qdrant. * Results are cached in Redis for 30 minutes keyed by query text. diff --git a/src/payload/collections/Media.ts b/src/payload/collections/Media.ts index 9ba3865b..dd4a6244 100644 --- a/src/payload/collections/Media.ts +++ b/src/payload/collections/Media.ts @@ -45,81 +45,4 @@ export const Media: CollectionConfig = { type: 'text', }, ], - hooks: { - afterChange: [ - async ({ doc, req }) => { - // Only process PDF files - if (doc.mimeType === 'application/pdf') { - try { - const fs = require('fs'); - const path = require('path'); - const crypto = require('crypto'); - const pdfParse = require('pdf-parse'); - const { upsertProductVector, deleteKnowledgeByMediaId } = require('../../lib/qdrant'); - - const filePath = path.join(process.cwd(), 'public/media', doc.filename); - - if (fs.existsSync(filePath)) { - req.payload.logger.info(`Extracting text from PDF: ${doc.filename}`); - - const dataBuffer = fs.readFileSync(filePath); - const data = await pdfParse(dataBuffer); - - // Clear any previously indexed chunks for this file just in case it's an update - await deleteKnowledgeByMediaId(doc.id); - - // Chunk the text like we did in the ingest script - const chunks = data.text - .split(/\n\s*\n/) - .map((c: string) => c.trim()) - .filter((c: string) => c.length > 50); - - let successCount = 0; - for (let i = 0; i < chunks.length; i++) { - // Generate a deterministic UUID based on doc ID and chunk index - const hash = crypto.createHash('md5').update(`${doc.id}-${i}`).digest('hex'); - // Qdrant strictly requires UUID: 8-4-4-4-12 - const uuid = [ - hash.substring(0, 8), - hash.substring(8, 12), - hash.substring(12, 16), - hash.substring(16, 20), - hash.substring(20, 32), - ].join('-'); - - await upsertProductVector(uuid, chunks[i], { - type: 'knowledge', - title: `${doc.filename} - Teil ${i + 1}`, - content: chunks[i], - source: doc.filename, - mediaId: doc.id, - }); - successCount++; - } - req.payload.logger.info( - `Successfully ingested ${successCount} chunks from ${doc.filename} into Qdrant`, - ); - } - } catch (e: any) { - req.payload.logger.error(`Error parsing PDF ${doc.filename}: ${e.message}`); - } - } - }, - ], - afterDelete: [ - async ({ id, doc, req }) => { - if (doc.mimeType === 'application/pdf') { - try { - const { deleteKnowledgeByMediaId } = require('../../lib/qdrant'); - await deleteKnowledgeByMediaId(id); - req.payload.logger.info(`Removed Qdrant chunks for deleted PDF: ${doc.filename}`); - } catch (e: any) { - req.payload.logger.error( - `Error removing Qdrant chunks for ${doc.filename}: ${e.message}`, - ); - } - } - }, - ], - }, }; diff --git a/src/scripts/error.png b/src/scripts/error.png new file mode 100644 index 0000000000000000000000000000000000000000..f9674c9b510df2992bf74b12c36d6bfa3e04a5d3 GIT binary patch literal 33567 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 f.endsWith('.pdf')); - - console.log(`Found ${files.length} PDFs in Downloads folder.`); - - for (const file of files) { - const filePath = path.join(downloadDir, file); - try { - const stats = fs.statSync(filePath); - - // Check if it already exists - const existing = await payload.find({ - collection: 'media', - where: { - filename: { - equals: file, - }, - }, - }); - - if (existing.docs.length > 0) { - console.log(`Skipping ${file} - already exists in CMS`); - continue; - } - - console.log(`Uploading ${file}...`); - await payload.create({ - collection: 'media', - data: { - alt: file, - }, - file: { - data: fs.readFileSync(filePath), - mimetype: 'application/pdf', - name: file, - size: stats.size, - }, - }); - console.log(`✅ Uploaded ${file}`); - } catch (err) { - console.error(`❌ Failed to upload ${file}:`, err); - } - } - - console.log('Done uploading PDFs to Payload CMS. Payload hooks have synced them to Qdrant.'); - process.exit(0); -} - -uploadPDFs();