Forked from mindstudio/big-rag
Project Files
.clinerules
# Big RAG Plugin — Правила проекта
## Обзор
LM Studio плагин для RAG (Retrieval-Augmented Generation). Индексирует большие объёмы документов (GB–TB), выполняет векторный поиск и инъекцию контекста в промпт.
## Технический стек
- **Язык**: TypeScript 5.9 (strict mode)
- **Runtime**: Node.js (CommonJS, target ES2021)
- **Сборка**: `tsc` → `dist/`
- **Тесты**: Node.js built-in test runner (`node:test` + `node:assert/strict`)
- **Плагинный SDK**: `@lmstudio/sdk` ^1.5.0
- **Векторное хранилище**: Vectra (шардированные индексы)
- **Парсинг**: cheerio (HTML), pdf-parse/pdfjs-dist (PDF), epub2 (EPUB), tesseract.js (OCR)
## Команды
```bash
npm run build # tsc → dist/ (основная команда компиляции)
npm run test # build + node --test dist/tests/parseDocument.test.js
npm run dev # lms dev (горячая перезагрузка в LM Studio)
npm run index:cli # node dist/cliIndex.js (автономная индексация)
lms push -y --write-revision # опубликовать плагин на https://lmstudio.ai/<owner>/<name>
```
### Что означает «опубликуй проект»
Когда пользователь просит «опубликуй» — это значит запустить:
```bash
lms push -y --write-revision
```
Эта команда собирает tarball и загружает его на lmstudio.ai, обновляя ревизию плагина.
## Структура файлов
```
src/
├── index.ts # Точка входа плагина: main(context)
├── config.ts # Все настройки плагина (createConfigSchematics)
├── promptPreprocessor.ts # RAG: поиск + инъекция контекста в промпт
├── cliIndex.ts # CLI-версия для автономной индексации
├── ingestion/
│ ├── fileScanner.ts # Рекурсивное сканирование директорий
│ ├── indexManager.ts # Оркестрация индексации (504 строки — самый большой файл)
│ └── runIndexing.ts # Запуск индексации из препроцессора
├── parsers/
│ ├── documentParser.ts # Маршрутизатор парсеров по расширению файла
│ ├── htmlParser.ts # HTML → текст (cheerio)
│ ├── pdfParser.ts # PDF → текст (pdf-parse)
│ ├── epubParser.ts # EPUB → текст (epub2)
│ ├── textParser.ts # TXT/MD → текст (с опциональной очисткой Markdown)
│ └── imageParser.ts # Изображения → текст (OCR, tesseract.js)
├── vectorstore/
│ └── vectorStore.ts # Vectra: шардированные индексы, CRUD, поиск
├── utils/
│ ├── fileHash.ts # SHA-256 хеширование файлов
│ ├── textChunker.ts # Разбивка текста на чанки с перекрытием
│ ├── supportedExtensions.ts # Поддерживаемые расширения файлов
│ ├── failedFileRegistry.ts # Реестр ошибок индексации
│ ├── indexingLock.ts # Блокировка параллельной индексации
│ └── sanityChecks.ts # Проверки здоровья системы
└── tests/
└── parseDocument.test.ts # Smoke-тесты парсеров (HTML, MD, TXT)
test-fixtures/ # Файлы для тестов (sample.html, sample.md, sample.txt)
stubs/napi-rs-canvas/ # Заглушка для @napi-rs/canvas (не нужна на Windows)
```
## Конвенции кода
### Стиль
- **Строгий TypeScript**: `strict: true`, `noImplicitOverride: true`
- **CommonJS**: `export`/`import` компилируются в `require`/`module.exports`
- **Отступы**: 2 пробела
- **Точка с запятой**: обязательно
- **Строки**: двойные кавычки (согласно tsconfig `esModuleInterop`)
- **Асинхронность**: `async/await` (не коллбэки)
### Именование
- **Файлы**: camelCase (`fileScanner.ts`, `indexManager.ts`)
- **Классы**: PascalCase (`IndexManager`, `VectorStore`)
- **Функции**: camelCase (`parseDocument`, `scanDirectory`)
- **Интерфейсы/Типы**: PascalCase (`ScannedFile`, `IndexingResult`)
- **Константы**: UPPER_SNAKE_CASE или camelCase
### Паттерны
- **Result pattern**: функции возвращают `{ success: true, ...data } | { success: false, reason: string }`
- **Прогресс**: через callback `onProgress?: (progress: IndexingProgress) => void`
- **Конфигурация**: через `createConfigSchematics()` из LM Studio SDK
- **Логирование**: `console.log("[BigRAG] ...")` с префиксом
### Парсеры
- Каждый парсер принимает `filePath: string` и возвращает `ParseResult`
- `documentParser.ts` маршрутизирует по расширению файла
- При ошибке парсер возвращает `{ success: false, reason: "..." }`, не бросает исключение
### Векторное хранилище
- Vectra с шардированием (один шард в памяти за раз)
- Методы: `addChunks`, `search`, `deleteByFileHash`, `getFileHashInventory`, `getStats`, `hasFile`
- Методы поиска по имени файла: `searchByFilenames`, `searchInFiles`, `getChunksForFiles`, `getChunkCountForFile`
- Типы: `DocumentChunk`, `SearchResult`, `FilenameSearchResult`
### Поиск по именам файлов
- Определяется намерение пользователя через regex-паттерны (русские + английские)
- Функция `extractFilenameSearchIntent()` извлекает ключевые слова для поиска по имени и по контенту
- Функция `extractMeaningfulWords()` фильтрует стоп-слова (русские + английские)
- Функция `hasContentDisplayIntent()` определяет, хочет ли пользователь увидеть контент файла (а не только список имён)
- Четыре сценария: только имя, имя + отображение контента, имя + контент, обычный векторный поиск
- При обнаружении намерения отобразить контент — извлекаются ВСЕ чанки найденных файлов через `getChunksForFiles()`
- Настройка: `enableFilenameSearch` (boolean, по умолчанию true)
### Локализация RAG-инструкций (язык ответа)
- Настройка `responseLanguage` (первое поле в конфиге, по умолчанию `"ru"`)
- Тип: `ResponseLanguage = "ru" | "en"` (экспортируется из `config.ts`)
- Все inline-инструкции, отправляемые модели, локализованы через функцию `getPromptStrings(lang)`
- Интерфейс `PromptStrings` определяет все строки: заголовки цитат, инструкции поиска, сообщения об ошибках
- Шаблон промпта по умолчанию выбирается через `getDefaultPromptTemplate(lang)` — русский или английский
- При добавлении новых inline-строк в `promptPreprocessor.ts` — обязательно добавить их в `PromptStrings` и `getPromptStrings()`
## Рабочий цикл
1. **Прочитать релевантные файлы** перед изменением
2. **Внести правки** в `src/**/*.ts`
3. **Собрать**: `npm run build` — не должно быть ошибок TypeScript
4. **Протестировать**: `npm run test` — все 13 тестов должны пройти (HTML, XHTML, MD, MDX, TXT, DOCX, XLSX, CSV, PPTX, EPUB, OCR-eng, OCR-rus, OCR-eng+rus)
5. **Если добавлен новый парсер/функция**: добавить тест в `src/tests/`
## Правило тестирования после изменений
- **Серьёзные изменения** (парсеры, индексация, OCR, векторное хранилище, конфигурация, утилиты используемые при индексации) → **обязательно** прогонять `npm run test` (все 13 тестов по всем типам файлов)
- **Несерьёзные изменения** (README, комментарии, логирование, не влияющее на логику) → достаточно `npm run build`
- **Если сомневаешься** — спроси пользователя, нужно ли прогонять тесты
## Ключевые зависимости и их роли
| Зависимость | Роль | Где используется |
|---|---|---|
| `@lmstudio/sdk` | SDK для плагинов LM Studio | `index.ts`, `config.ts`, `promptPreprocessor.ts`, `indexManager.ts` |
| `vectra` | Локальное векторное хранилище | `vectorstore/vectorStore.ts` |
| `cheerio` | HTML-парсинг | `parsers/htmlParser.ts` |
| `pdf-parse` | PDF-парсинг | `parsers/pdfParser.ts` |
| `epub2` | EPUB-парсинг | `parsers/epubParser.ts` |
| `tesseract.js` | OCR | `parsers/imageParser.ts` |
| `p-queue` | Ограничение конкурентности | `ingestion/indexManager.ts` |
| `zod` | Валидация схем | `promptPreprocessor.ts` |
| `mime-types` | Определение MIME-типов | `ingestion/fileScanner.ts` |
| `pngjs` | Чтение PNG для OCR | `parsers/imageParser.ts` |
## Поддерживаемые форматы файлов
`.htm`, `.html`, `.xhtml`, `.pdf`, `.epub`, `.txt`, `.text`, `.md`, `.mdx`, `.markdown`, `.mdown`, `.mkd`, `.mkdn`, `.bmp`, `.jpeg`, `.jpg`, `.png`
## Обязательные правила при внесении изменений
1. **Обновлять README.md**: При добавлении нового функционала или изменении существующего, затрагивающего описание в README, — обязательно обновить соответствующие секции README.md
2. **Обновлять .clinerules**: При изменении архитектуры, структуры файлов, зависимостей, паттернов или рабочих процессов — обновлять соответствующие секции этого файла, чтобы поддерживать актуальное описание проекта
3. **Синхронность**: README и .clinerules должны отражать текущее состояние кодовой базы
## Что нельзя делать
- ❌ Не удалять и не переименовывать существующие файлы без явного запроса
- ❌ Не менять `tsconfig.json` без веской причины
- ❌ Не менять версию в `package.json` без запроса
- ❌ Не трогать `stubs/napi-rs-canvas/` — это заглушка для Windows
- ❌ Не добавлять новые зависимости без обсуждения
- ❌ Не использовать `import()` dynamic imports — CommonJS совместимость
- ❌ Не использовать костыли, хаки, обходные пути — только проверенные методики
- ❌ Не пытаться решить проблему «любым способом» — качество важнее скорости
## Правило 3 попыток
Если решение не получается с первой попытки:
1. **Попытка 1** — стандартный подход
2. **Попытка 2** — альтернативный проверенный подход
3. **Попытка 3** — последний вариант с анализом причин неудачи
**После 3 неудачных попыток — остановиться и задать вопрос пользователю.** Возможно, пользователь сможет решить проблему быстрее и проще. Честно описать, что именно не получается и почему.
## Особенности окружения
- **ОС**: Windows 10
- **Путь**: `c:\Users\Александр\.lmstudio\extensions\plugins\falcons\big-rag`
- **@napi-rs/canvas**: заменён на локальную заглушку (override в package.json)
- **Embedding-модель**: `nomic-ai/nomic-embed-text-v1.5-GGUF` (должна быть загружена в LM Studio)
- **CLI-индексация**: `node dist/cliIndex.js <docsDir> <vectorStoreDir>` — нужна запущенная LM Studio для эмбеддингов