# RAG / LightRAG для анализа чертежей Этот модуль добавляет **Retrieval-Augmented Generation (RAG)** поверх существующего OCR-pipeline. Он превращает распознанный текст из `full_ocr_results.json` в **граф знаний** и позволяет задавать вопросы по чертежам на естественном языке. ## Архитектура ``` PDF -> PyMuPDF + RapidOCR -> full_ocr_results.json | v rag_indexer.py (LightRAG) | v lightrag_cache/ (граф знаний) | v rag_query.py (вопросы) ``` **Почему LightRAG?** - Строит **граф сущностей и отношений** (этажи, оси, размеры, помещения) - Поддерживает 4 режима поиска: `naive`, `local`, `global`, `hybrid` - Для чертежей рекомендуется **`hybrid`** — объединяет локальный поиск по соседним сущностям и глобальный контекст проекта ## Установка ```bash # 1. Установите зависимости pip install -r requirements.txt # 2. Выберите LLM backend: ``` ### Вариант A: OpenAI (быстро, требует интернет) ```bash export OPENAI_API_KEY="sk-..." # или в Windows: set OPENAI_API_KEY=sk-... ``` ### Вариант B: Ollama (локально, приватно, требует RAM/VRAM) ```bash # Установите Ollama: https://ollama.com # Скачайте модели (пример) ollama pull qwen2.5:14b # LLM для ответов ollama pull nomic-embed-text # embeddings # Запустите сервер ollama serve ``` ### Вариант C: LM Studio (локальный GUI, подходит для VLM) ```bash # Установите LM Studio: https://lmstudio.ai # 1. Загрузите VLM модель (например, qwen3-vl-4b) и запустите Local Server # 2. Убедитесь, что сервер доступен: http://127.0.0.1:1234/v1 # Переменные окружения (при необходимости) export LMSTUDIO_URL="http://127.0.0.1:1234/v1" export LMSTUDIO_API_KEY="lm-studio" ``` ### Вариант D: OpenCode API (DeepSeek V4 Flash Free) ```bash # Требуется API-ключ OpenCode (бесплатный тариф) # 1. Получите ключ на https://opencode.ai # 2. Экспортируйте переменные: export OPENCODE_API_KEY="ваш-ключ" export OPENCODE_URL="https://opencode.ai/zen/v1" # опционально, уже задан по умолчанию ``` ## Использование ### Шаг 1: OCR (если еще не сделано) ```bash python process_any_pdf.py "Кронштадтский 16-18 НК1_ОСК (v3).pdf" output_kronshtadt ``` Результат: папка `output_kronshtadt/` с `full_ocr_results.json`. ### Шаг 2: Построение индекса **OpenAI:** ```bash python rag_indexer.py output_kronshtadt --backend openai --model gpt-4o-mini ``` **Ollama (локально):** ```bash python rag_indexer.py output_kronshtadt --backend ollama --model qwen2.5:14b --embed-model nomic-embed-text ``` Результат: папка `output_kronshtadt/lightrag_cache/` с графом знаний. **LM Studio (VLM для описаний):** ```bash # Сгенерировать VLM-описания PNG (локальная Qwen) python vlm_describer.py output_kronshtadt --model qwen/qwen3-vl-4b # Построить индекс через OpenCode API (LLM) python rag_indexer.py output_kronshtadt --backend opencode --vlm-desc ``` **OpenCode API (DeepSeek V4 Flash Free):** ```bash # Построение индекса через бесплатный DeepSeek python rag_indexer.py output_kronshtadt --backend opencode --model opencode/deepseek-v4-flash-free # С VLM-описаниями (локальная Qwen + бесплатный DeepSeek) python rag_indexer.py output_kronshtadt --backend opencode --vlm-desc ``` ### Шаг 3 (опционально): VLM-описания через LM Studio Если у вас в LM Studio загружена **VLM модель** (например, `qwen3-vl-4b`), можно сгенерировать текстовые описания PNG перед индексацией: ```bash python vlm_describer.py output_kronshtadt --model qwen/qwen3-vl-4b ``` Это создаст `output_kronshtadt/vlm_descriptions.json` — текстовое описание каждой страницы. При `--vlm-desc` в `rag_indexer.py` эти описания добавятся к OCR-тексту, давая RAG понимание пространственной компоновки. **Важно:** 4B VLM хороша для базовых описаний, но на сложных А0-чертежах может галлюцинировать. Для лучшего качества используйте 7B+ VLM (Qwen2-VL 7B, InternVL 8B). ### Шаг 4: Запросы ```bash # Через OpenCode API (рекомендуется — бесплатно) python rag_query.py output_kronshtadt "На каких страницах показан план 3-го этажа?" --backend opencode --mode hybrid python rag_query.py output_kronshtadt "Какие размеры указаны между осями А и Б?" --backend opencode --mode hybrid python rag_query.py output_kronshtadt "Какие квартиры есть на этаже 2?" --backend opencode --mode hybrid # Режим local — ищет соседей сущностей в графе python rag_query.py output_kronshtadt "Что находится рядом с осью В?" --backend opencode --mode local # Режим global — общий контекст проекта python rag_query.py output_kronshtadt "Опиши общую структуру здания по чертежам." --backend opencode --mode global ``` ## Как это работает под капотом ### 1. Формирование документов `rag_indexer.py` читает `full_ocr_results.json` и для каждой страницы создает текстовый документ вида: ``` === Чертеж: страница 5 из 120 === Изображение: page_005.png --- Текстовый слой PDF --- План 3-го этажа... --- Распознанный текст (OCR) --- "3-й этаж" (confidence=0.95, bbox=[100, 200, 150, 220]) "Ось А" (confidence=0.88, bbox=[300, 400, 350, 420]) "5400 мм" (confidence=0.92, bbox=[500, 600, 580, 620]) --- Извлеченные сущности --- Этажи: 3-й этаж Оси: А Размеры: 5400 мм ``` ### 2. Построение графа (LightRAG) LightRAG пропускает каждый документ через LLM и извлекает: - **Entities**: `3-й этаж`, `Ось А`, `5400 мм` - **Relationships**: `3-й этаж -> содержит -> Ось А`, `Ось А -> имеет размер -> 5400 мм` Это сохраняется в `lightrag_cache/` как граф + векторные эмбеддинги. ### 3. Поиск ответа При запросе `"Какие размеры между осями А и Б?"`: - **Hybrid** = Local (ищет узлы "Ось А", "Ось Б" и их соседей) + Global (общий контекст "размеры между осями") - LLM генерирует ответ на основе найденных фрагментов ## Советы по использованию для чертежей 1. **Качество OCR критично** — если RapidOCR пропускает цифры размеров, RAG не найдет их. Проверяйте `full_ocr_results.json`. 2. **Структурируйте сущности** — в `rag_indexer.py` уже встроен парсер этажей, осей, размеров. При необходимости расширьте регулярные выражения под ваши ГОСТ-овские обозначения. 3. **Страницы как узлы** — если чертеж очень большой (А0), можно разбить PNG на фрагменты и индексировать их отдельно. 4. **VLM для сложных схем** — если нужно понимать геометрию (а не только текст), добавьте описания от зрительной модели (Qwen2-VL, LLaVA) в текст документов перед индексацией. ## Расширение: добавление VLM-описаний Если у вас есть GPU, можно улучшить понимание чертежей: ```python # Псевдокод — добавить в rag_indexer.py перед insert from transformers import Qwen2VLForConditionalGeneration, AutoProcessor vlm = Qwen2VLForConditionalGeneration.from_pretrained("Qwen/Qwen2-VL-7B-Instruct") processor = AutoProcessor.from_pretrained("Qwen/Qwen2-VL-7B-Instruct") desc = vlm_describe_image(page_image_path, "Опиши этот чертеж: этажи, оси, размеры, помещения.") doc_text += f"\n--- Описание модели зрения ---\n{desc}\n" await rag.ainsert(doc_text) ``` Это даст RAG понимание пространственной компоновки, даже если OCR плохо распознал текст. ## Файлы | Файл | Назначение | |------|-----------| | `rag_indexer.py` | Построение индекса LightRAG из OCR-результатов | | `rag_query.py` | Запросы к индексу | | `requirements.txt` | Зависимости (lightrag-hku, openai, etc.) |