Москва: проверенные б/у ноутбуки с гарантией и проверкой перед оплатой
+7 906 722-94-45

Главная → Статьи → Локальный RAG на ноутбуке: эмбеддинги и векторные базы без облака

Локальный RAG на ноутбуке: поиск по своим документам без облака — эмбеддинги, векторные базы, RAM

Как собрать приватный RAG-пайплайн на ноутбуке: выбор эмбеддинг-модели, Chroma/Qdrant/FAISS, чанкинг, требования к ОЗУ и связка с Ollama. Пошаговая схема и ограничения.

Прямой ответ

RAG (retrieval-augmented generation) — это «сначала найдём релевантные фрагменты ваших документов, потом дадим их модели как контекст». Полностью локальная версия на ноутбуке собирается из четырёх компонентов, и все они бесплатны:

  1. Эмбеддинг-модель — превращает текст в векторы (например, nomic-embed-text через Ollama или bge-m3 через sentence-transformers): ~0,3–1,5 ГБ RAM.
  2. Векторная база — хранит и ищет векторы: Chroma (проще всего), Qdrant (масштабируемее) или FAISS (библиотека без сервера).
  3. Локальная LLM для генерации ответа — та же Ollama (7–8B Q4).
  4. Оркестрация — Python-скрипт или LlamaIndex/LangChain.

Ресурсы: для базы на 10–50 тыс. документов достаточно 16 ГБ ОЗУ без дискретной GPU; эмбеддинги считаются на CPU приемлемо быстро (сотни страниц в минуту).

Требования к железу: считаем честно

  • Векторы почти не требуют памяти. 100 000 фрагментов × 768 измерений × 4 байта ≈ 300 МБ. Векторная база — не узкое место даже на ноутбуке.
  • Память ест LLM. Ответы генерирует чат-модель: 7–8B Q4 — это 5–6 ГБ. Расчёт VRAM/RAM — в статье про Ollama и LM Studio.
  • Индексация документов (первичный прогон эмбеддингов) — разовая операция: CPU справляется, GPU ускоряет в разы, если есть.
  • Диск: исходные документы + индексы обычно вдвое больше самой базы документов; NVMe ускоряет холодный старт.

Практический вывод: RAG-стек повторяет требования локального чата (+1–2 ГБ на векторную базу), а не требования обучения моделей.

Шаг 1. Эмбеддинги локально

Простейший путь — через Ollama:

ollama pull nomic-embed-text     # ~275 МБ, 768 измерений
import requests
def embed(text: str) -> list[float]:
    r = requests.post("",
                      json={"model": "nomic-embed-text", "input": text})
    return r.json()["embeddings"][0]

Альтернатива — sentence-transformers с моделями семейства BGE (bge-small-ru для русского, bge-m3 для мультиязычности): работает полностью офлайн, качество для русского текста у специализированных RU-моделей выше.

Шаг 2. Векторная база: Chroma или Qdrant

Chroma — минимум кода, хранение в локальной папке:

import chromadb
client = chromadb.PersistentClient(path="./chroma_db")
col = client.get_or_create_collection("docs")
col.add(ids=["d1"], documents=["текст..."], embeddings=[embed("текст...")])
res = col.query(query_embeddings=[embed("запрос")], n_results=5)

Qdrant — отдельный сервис (удобно в Docker), фильтрация по метаданным, лучше на больших объёмах. FAISS — когда база это просто индекс в памяти процесса, без сервера.

Выбор для ноутбука: до ~100 тыс. фрагментов — Chroma; больше или нужны сложные фильтры — Qdrant.

Шаг 3. Чанкинг — важнее, чем кажется

Качество RAG на 70% определяется нарезкой документов:

  • Фрагменты 500–1000 символов с перекрытием 10–15% — стартовая точка.
  • Режьте по смысловым границам (абзацы, заголовки markdown), а не по символам.
  • В каждый фрагмент добавляйте контекст: заголовок раздела, имя файла — это заметно улучшает поиск.
  • Таблицы и код не режьте пополам: отдельный фрагмент целиком.

Шаг 4. Сборка ответа

Классический цикл: запрос → эмбеддинг → топ-5 фрагментов из базы → промпт «ответь, используя только контекст: {фрагменты}» → локальная LLM. Готовые обёртки: LlamaIndex (llama_index + OllamaEmbedding/Ollama) или LangChain — обе работают с Ollama из коробки и не отправляют данные наружу.

Критичное правило приватности: весь цикл должен оставаться локальным. Проверьте, что в коде нет облачных API-ключей (OpenAI, Cohere) — популярная случайная утечка в туториалах, где локальным заявлен только чат.

Мини-пайплайн целиком: 20 строк на Python

Скелет рабочего локального RAG без фреймворков — удобно, чтобы понять механику:

import chromadb, requests, json

def embed(text):
    r = requests.post("",
        json={"model": "nomic-embed-text", "input": text})
    return r.json()["embeddings"][0]

def ask(question, db, col):
    found = db.get_collection(col).query(
        query_embeddings=[embed(question)], n_results=4)
    ctx = "\n---\n".join(found["documents"][0])
    r = requests.post("",
        json={"model": "llama3.1:8b", "stream": False,
              "prompt": f"Ответь только по контексту.\nКонтекст:\n{ctx}\n\nВопрос: {question}"})
    return json.loads(r.text)["response"]

Индексация — цикл col.add() по фрагментам с идентификатором файл:номер_чанка. Для продакшена добавьте LlamaIndex: он берёт на себя загрузчики форматов (PDF, DOCX, HTML), чанкинг и кэш эмбеддингов.

Оценка качества: как понять, что RAG работает

Три быстрых проверки перед тем, как доверять системе:

  1. Retrieval-тест: возьмите 10 вопросов с известными ответами в базе и проверьте, попадает ли нужный фрагмент в топ-4. Попадание ниже 8/10 — правьте чанкинг и эмбеддинги, а не промпт.
  2. Проверка на «нет ответа»: задайте вопрос, которого в базе нет — корректная система отвечает «в документах этого нет», а не фантазирует.
  3. Цитируемость: просите модель указывать идентификатор фрагмента — ответы без ссылок трудно проверять.

Логируйте вопросы и найденные фрагменты в файл: через неделю вы увидите системные провалы (например, все ошибки — на таблицах) и почините именно их.

Ограничения, о которых честно предупреждаем

  1. Качество 7–8B-модели ограничено: она хуже фронтирных моделей следует инструкциям и чаще «додумывает». Помогает строгий промпт и n_results с запасом.
  2. Эмбеддинги не решают всё: точные совпадения (артикулы, коды ошибок) ищите гибридно — вектор + полнотекстовый поиск (BM25).
  3. Обновление базы: при изменении документов переиндексация обязательна; заведите привычку хранить хэш документа в метаданных.
  4. PDF-парсинг — отдельная боль: сканы требуют OCR, таблицы ломаются; для технических документов надёжнее markdown/текстовые источники.

Для аналитиков, у которых «документы» — это витрины и отчёты, RAG дополняет, а не заменяет SQL: связка «SQL к данным + RAG к регламентам» описана в материале про стек Power BI/SQL/Pandas.

Приватность: что именно остаётся на устройстве

Проверьте свой стек по списку: документы не покидают диск (индексация локальная), эмбеддинги считаются локальной моделью (Ollama/sentence-transformers, а не API OpenAI), векторная база лежит в папке проекта (Chroma) или в локальном контейнере (Qdrant), генерация идёт через локальную LLM. Если все четыре пункта выполнены — запросы не уходят в интернет физически; это единственная схема, допустимая для конфиденциальных договоров, медицинских и персональных данных без отдельного согласия. Быстрая самопроверка: отключите Wi-Fi и повторите типовой запрос — рабочий локальный RAG этого не заметит.

FAQ

Хватит ли 16 ГБ без видеокарты? Да: эмбеддинги на CPU, LLM 7–8B Q4 на CPU (медленно, 3–8 ток/с, но приватно), векторная база почти бесплатна по памяти.

Можно ли держать базу в облаке, а модель локально? Можно, но тогда приватность определяется облачным провайдером векторной БД. Полностью локальная схема — Chroma/Qdrant на своём диске.

Какой размер базы имеет смысл для RAG? От нескольких десятков документов (регламенты проекта) до сотен тысяч фрагментов — на ноутбуке оба сценария рабочи; разница только во времени индексации.

Нужен ли GPU? Для инференса 7–8B — желателен, но не обязателен. Для переиндексации больших библиотек GPU экономит часы; требования — в статье про PyTorch и CUDA.

Источники: документация Chroma, Qdrant, FAISS и Ollama (ссылки в шапке).