From 0c3fc53f9b2fb6bfc635476d660863c075b280e5 Mon Sep 17 00:00:00 2001 From: Florian Neuhuber Date: Mon, 16 Mar 2026 22:00:03 +0100 Subject: [PATCH] fix(rag): scan full NOMAD_DATA_PATH for PDFs, not only 10_EIGENE_PDFS_RAG Made-with: Cursor --- admin/app/services/rag_service.ts | 33 ++++++++++++++++++++++++++----- install/NOMAD-DATA-DOWNLOADS.md | 20 ++++++++++++++++--- 2 files changed, 45 insertions(+), 8 deletions(-) diff --git a/admin/app/services/rag_service.ts b/admin/app/services/rag_service.ts index e6ac043..ae023e2 100644 --- a/admin/app/services/rag_service.ts +++ b/admin/app/services/rag_service.ts @@ -4,6 +4,7 @@ import { inject } from '@adonisjs/core' import logger from '@adonisjs/core/services/logger' import { TokenChunker } from '@chonkiejs/core' import sharp from 'sharp' +import env from '@adonisjs/core/services/env' import { deleteFileIfExists, determineFileType, getFile, getFileStatsIfExists, listDirectoryContentsRecursive, ZIM_STORAGE_PATH } from '../utils/fs.js' import { PDFParse } from 'pdf-parse' import { createWorker } from 'tesseract.js' @@ -988,17 +989,16 @@ export class RagService { logger.info(`[RAG] Deleted all points for source: ${source}`) /** Delete the physical file only if it lives inside the uploads directory. - * resolve() normalises path traversal sequences (e.g. "/../..") before the - * check to prevent path traversal vulns - * The trailing sep is to ensure a prefix like "kb_uploads_{something_incorrect}" can't slip through. + * For NOMAD_DATA files we only remove from the index; we do not delete the file on disk (user-owned data). + * resolve() normalises path traversal sequences (e.g. "/../..") before the check to prevent path traversal vulns. */ const uploadsAbsPath = join(process.cwd(), RagService.UPLOADS_STORAGE_PATH) const resolvedSource = resolve(source) - if (resolvedSource.startsWith(uploadsAbsPath + sep)) { + if (resolvedSource.startsWith(resolve(uploadsAbsPath) + sep)) { await deleteFileIfExists(resolvedSource) logger.info(`[RAG] Deleted uploaded file from disk: ${resolvedSource}`) } else { - logger.warn(`[RAG] File was removed from knowledge base but doesn't live in Nomad's uploads directory, so it can't be safely removed. Skipping deletion of physical file...`) + logger.debug(`[RAG] Removed from index only (file not in uploads dir): ${resolvedSource}`) } return { success: true, message: 'File removed from knowledge base.' } @@ -1125,6 +1125,29 @@ export class RagService { } } + // Scan NOMAD-DATA (ganzer Ordner: 01_MEDIZIN, 04_SURVIVAL, 10_EIGENE_PDFS_RAG, etc.) für RAG + const nomadDataPath = env.get('NOMAD_DATA_PATH') + if (nomadDataPath) { + const nomadDataAbs = nomadDataPath.startsWith(sep) ? resolve(nomadDataPath) : join(process.cwd(), nomadDataPath) + try { + const nomadContents = await listDirectoryContentsRecursive(nomadDataAbs) + let nomadCount = 0 + nomadContents.forEach((entry) => { + if (entry.type === 'file' && determineFileType(entry.name) !== 'unknown') { + filesInStorage.push(entry.key) + nomadCount++ + } + }) + logger.debug(`[RAG] Found ${nomadCount} supported files in NOMAD-DATA`) + } catch (error) { + if (error.code === 'ENOENT') { + logger.debug(`[RAG] NOMAD-DATA path ${nomadDataAbs} does not exist, skipping`) + } else { + logger.warn(`[RAG] Error scanning NOMAD-DATA:`, error) + } + } + } + logger.info(`[RAG] Found ${filesInStorage.length} total files in storage directories`) // Get all stored sources from Qdrant diff --git a/install/NOMAD-DATA-DOWNLOADS.md b/install/NOMAD-DATA-DOWNLOADS.md index 441a6af..5b48b06 100644 --- a/install/NOMAD-DATA-DOWNLOADS.md +++ b/install/NOMAD-DATA-DOWNLOADS.md @@ -2,6 +2,21 @@ Dieses Skript lädt alle in `nomad-data-pdf-urls.txt` eingetragenen PDFs und Ressourcen in eine NOMAD-DATA-Ordnerstruktur. +## Warum sehe ich die neuen ZIM-Kategorien / PDFs nicht? + +- **ZIM-Kategorien (Deutsch & Österreich, Klexikon, Koch-Wiki, …):** Die App lädt die Collection-Dateien von einer URL. Standard ist der **main**-Branch von Crosstalk-Solutions – dort sind die neuen Kategorien erst nach Merge des PRs. Damit du sie **sofort** siehst, muss die laufende NOMAD-Instanz die Umgebungsvariable **`NOMAD_COLLECTIONS_BASE_URL`** setzen (z.B. in der Docker-/Compose-Umgebung): + ```bash + NOMAD_COLLECTIONS_BASE_URL=https://raw.githubusercontent.com/neuhubereco/project-nomad/refs/heads/feature/collections-german-austria-zim + ``` + Danach in der Oberfläche unter Einstellungen / Content Explorer die Collections neu laden („Collections aktualisieren“ o.ä.). + **Hinweis:** Die App-Version muss den Code für `NOMAD_COLLECTIONS_BASE_URL` enthalten (z.B. Build von deinem Fork oder nach Merge des PRs). + +- **PDFs in der Knowledge Base:** Die App muss **`NOMAD_DATA_PATH`** auf den Ordner setzen, in dem deine NOMAD-DATA-Struktur liegt (z.B. wo die heruntergeladenen PDFs in 01_MEDIZIN, 04_SURVIVAL, … liegen). Dieser Pfad muss **im Container** erreichbar sein (z.B. Volume-Mount): + ```bash + NOMAD_DATA_PATH=/storage/nomad_data + ``` + Wenn die PDFs auf dem Host unter `/home/nomad/nomad_data` liegen, muss dieses Verzeichnis z.B. als `/storage/nomad_data` in den Admin-Container gemountet sein. Anschließend in der App: **Knowledge Base → Scan and Sync** ausführen. + ## 1. Live: Neue ZIM-Kategorien Die neuen ZIM-Kategorien (Deutsch & Österreich, Militär & Taktik, Kommunikation, Energie & Off-Grid) sind in `collections/kiwix-categories.json` eingetragen. @@ -43,12 +58,11 @@ Es werden u.a. geladen: ## 3. RAG (Knowledge Base) -Die App indexiert nur Inhalte unter **`NOMAD_DATA_PATH/10_EIGENE_PDFS_RAG`**. +Die App indexiert alle unterstützten Dateien (PDF, Text, Bilder) **im gesamten Ordner** `NOMAD_DATA_PATH` (also auch 01_MEDIZIN, 04_SURVIVAL, 07_FUNK, 08_VORRAT, 10_EIGENE_PDFS_RAG usw.). Wenn du die heruntergeladenen PDFs auch in der Knowledge Base nutzen willst: -- Entweder **Kopien/Symlinks** der gewünschten PDFs nach `NOMAD-DATA/10_EIGENE_PDFS_RAG/` legen (z.B. Unterordner `Survival`, `Funk`, `Medizin`), -- oder `NOMAD_DATA_PATH` auf deinen NOMAD-DATA-Root setzen und in der App nur diesen einen Baum nutzen; dann müsste die RAG-Logik um weitere Ordner (z.B. 04_SURVIVAL, 07_FUNK) erweitert werden. +- `NOMAD_DATA_PATH` auf deinen NOMAD-DATA-Root setzen (z.B. `/opt/project-nomad/storage/nomad_data` oder `/home/nomad/nomad_data`). Die RAG-Sync durchsucht dann **alle** Unterordner (01_MEDIZIN, 04_SURVIVAL, 07_FUNK, …). Anschließend in der App: **Knowledge Base → Scan and Sync**.