# LlamaIndex с Ollama: локальный RAG и проверка ответа по документам

Источник: https://modelium.tech/zhurnal/llamaindex-s-ollama/

Для локального RAG в LlamaIndex задайте и генеративную модель Ollama, и отдельную модель embeddings Ollama: без явной настройки framework может выбрать облачные модели по умолчанию. Индексируйте небольшие тестовые документы, задайте вопрос и сопоставьте ответ с `source_nodes` и исходными файлами. Найденный фрагмент не доказывает истинность ответа или отсутствие сетевых вызовов: оба свойства проверяются отдельно.

**Данные сверены с официальными страницами 6 октября 2026 года.** Это протокол для собственного теста читателя, а не утверждение, что Modelium запускал Ollama, LlamaIndex или проверял сеть. Версии Python-пакетов здесь не закреплены; прежде чем переносить демонстрацию в рабочую среду, зафиксируйте установленные версии и digest тегов моделей. [s1](#src-s1) [s2](#src-s2) [s6](#src-s6) [s7](#src-s7)

## Что решает связка LlamaIndex и Ollama?

Представьте папку из нескольких текстовых регламентов. Задача — спросить локальную модель об одном факте и увидеть, какой фрагмент попал в контекст ответа. LlamaIndex загружает документы, дробит их на узлы и строит векторный индекс; Ollama обслуживает модель для ответа и **отдельную** модель для векторизации. Это не один универсальный вызов: генерация и поиск используют разные роли моделей. [s1](#src-s1) [s2](#src-s2) [s3](#src-s3) [s4](#src-s4)

В этой демонстрации генератор — тег `qwen3:0.6b`, а векторизатор — `embeddinggemma:300m` в Ollama Library. По карточкам на дату проверки их идентификаторы digest начинаются соответственно с `7df6b6e09427` и `85462619ee72`; сверяйте фактические локальные теги после загрузки. Малый вариант Qwen3 служит только для проверки проводки, не является рекомендацией для длинных договоров или обещанием точных русских ответов. EmbeddingGemma требует Ollama версии не старее `v0.11.10`; её карточка содержит отдельные Gemma Terms of Use, тогда как у выбранного тега Qwen3 указана Apache-2.0. Право на использование каждого компонента проверяйте отдельно. Указанные в карточках объёмы файлов нельзя превращать в минимальную RAM/VRAM. [s6](#src-s6) [s7](#src-s7)

## Что подготовить до индексации?

Установите Ollama по [проверенному вводному материалу](/zapusk/ollama/) и убедитесь, что локальный сервер отвечает на `http://127.0.0.1:11434/api/tags` и что у вас достаточно места и ресурсов для двух выбранных тегов. API на loopback отличается от прямого облачного `https://ollama.com/api`; облачный endpoint требует иной маршрут и ключ, а возможность облачных моделей через локальный сервер проверяется отдельно. Не публикуйте локальный порт в сеть и не подставляйте реальные документы до проверки маршрута. Команды `ollama pull qwen3:0.6b`, `ollama pull embeddinggemma:300m` и `ollama list` загрузят и покажут теги; загрузка весов требует сети. [s5](#src-s5) [s6](#src-s6) [s7](#src-s7)

Создайте отдельное виртуальное окружение проекта. По официальной схеме раздельной установки достаточно `llama-index-core`, `llama-index-readers-file`, `llama-index-llms-ollama` и `llama-index-embeddings-ollama`: установите их через `python -m pip install llama-index-core llama-index-readers-file llama-index-llms-ollama llama-index-embeddings-ollama` в этом окружении. Не ограничивайтесь метапакетом `llama-index`: его стартовый набор включает облачные интеграции, а настройки по умолчанию могут ожидать OpenAI. В коде ниже **обе** модели указаны явно; отдельного платного API для этого маршрута не требуется. [s1](#src-s1) [s2](#src-s2) [s3](#src-s3)

Для первой проверки подготовьте папку `docs` с двумя **вымышленными** текстовыми файлами `.txt`. Пусть `rule-a.txt` содержит ровно «В тестовом регламенте А срок согласования — два дня», а `rule-b.txt` — «В тестовом регламенте Б срок согласования — пять дней». Не загружайте в папку посторонние файлы: `SimpleDirectoryReader` читает файлы каталога, а для больших документов и нестандартных форматов может понадобиться отдельная интеграция. Такой маленький набор проверяет трассировку ответа, но не качество поиска по реальным PDF. [s4](#src-s4)

## Как собрать локальный запрос и увидеть источник?

В активированном виртуальном окружении из каталога, где лежит `docs`, выполните одну команду (весь текст внутри одинарных кавычек — **одна строка**, без переносов): `python -c 'from llama_index.core import Settings, SimpleDirectoryReader, VectorStoreIndex; from llama_index.llms.ollama import Ollama; from llama_index.embeddings.ollama import OllamaEmbedding; Settings.llm=Ollama(model="qwen3:0.6b",request_timeout=120.0); Settings.embed_model=OllamaEmbedding(model_name="embeddinggemma:300m",base_url="http://127.0.0.1:11434"); docs=SimpleDirectoryReader(input_dir="docs",required_exts=[".txt"]).load_data(); index=VectorStoreIndex.from_documents(docs); response=index.as_query_engine(similarity_top_k=2).query("Каков срок согласования в регламенте А?"); print(response); print([(n.node.metadata.get("file_name"),n.node.get_content()) for n in response.source_nodes])'`. Это краткий одноразовый индекс в памяти; перезапуск создаст его заново. Установки `Settings.llm` и `Settings.embed_model` нужны именно для того, чтобы случайно не задействовать облачные настройки по умолчанию. [s1](#src-s1) [s2](#src-s2) [s3](#src-s3) [s4](#src-s4)

Полученный `response` содержит сформулированный моделью ответ, а `source_nodes` — узлы, извлечённые поиском; код выводит имя файла и содержание каждого найденного узла. Найденный источник **не** является автоматически проверенной цитатой: в примере оба файла могут попасть в `top_k=2`. Отдельно прочитайте текст `rule-a.txt` и сравните «два дня» с ответом; если модель ответила «пять дней» или не различила А и Б, тест не пройден. Смотрите также, не противоречит ли ответ первоисточнику при правильной выдаче — это уже ошибка генерации. [s8](#src-s8) [s4](#src-s4)

Второй контрольный вопрос — о регламенте В, которого в папке нет. Система без дополнительного порога уверенности может всё равно вернуть соседние узлы и сгенерировать уверенный ответ. Поэтому ожидаемый **критерий читателя**, а не обещанный результат LlamaIndex: отсутствие утверждения о несуществующем сроке и явная передача вопроса на ручную проверку. Для автоматического отказа по недостаточным данным потребуется отдельно настроить оценку релевантности и формат ответа. [s3](#src-s3)

## Как отличить локальный пилот от ложного ощущения приватности?

Указание `localhost` для embeddings и локальной модели — необходимая часть этого маршрута, но не доказательство отсутствия внешних запросов во всём процессе. Загрузка моделей и Python-пакетов обращается наружу; плагины чтения, трассировка, сторонний векторный сервис и конфигурация приложения тоже требуют собственного аудита. Перед реальными документами проведите [сетевой тест закрытого контура](/zhurnal/proverka-offline-kontura-ii/), зафиксируйте процессы и обращения, запретите внешние маршруты и повторите ответ после подготовки кешей. Подпись «локальный» не заменяет этот тест. [s4](#src-s4) [s5](#src-s5)

Временный индекс по умолчанию находится в памяти процесса; это удобно для небольшого теста, но не заменяет резервное копирование, обновление документов, контроль доступа и постоянное хранилище. Замена модели embeddings требует переиндексации документов согласованной моделью, иначе сравнение векторов теряет смысл. Для рабочих документов отдельно задайте размер фрагмента, сохраняемые метаданные и политику удаления старых версий; файл с чувствительным содержимым не должен попадать в индекс без разрешения. [s2](#src-s2) [s3](#src-s3) [s4](#src-s4)

Если запрос к модели падает, проверьте локальный `/api/tags`, наличие **обоих** тегов через `ollama list`, версию Ollama для EmbeddingGemma и адрес `base_url`. Если найден не тот файл — сначала проверьте содержимое `docs`, `source_nodes` и точную формулировку вопроса, а затем уже меняйте модель. Если `response.source_nodes` пусты, не описывайте выдуманный источник. Скорость и качество на русском языке в этом материале не измерены; аппаратные требования зависят от выбранных вариантов и окружения, а не только от размера файлов весов. [s2](#src-s2) [s3](#src-s3) [s4](#src-s4) [s6](#src-s6) [s7](#src-s7)

**Следующий шаг:** примените [протокол оценки качества RAG](/zhurnal/ocenka-kachestva-rag/) к собственным *разрешённым* документам: приготовьте вопросы с известным фрагментом-источником и вопросы без ответа, сохраните версии моделей/пакетов, долю правильных найденных фрагментов и число неподтверждённых утверждений. Только такой прогон на ваших данных позволит решать, подходит ли конкретная конфигурация. Modelium этого прогона не проводил. [s3](#src-s3) [s4](#src-s4)

## Источники

1. [LlamaIndex — Ollama LLM integration](https://developers.llamaindex.ai/python/framework/integrations/llm/ollama/) — получено 2026-10-06
2. [LlamaIndex — Ollama Embeddings integration](https://developers.llamaindex.ai/python/framework/integrations/embeddings/ollama_embedding/) — получено 2026-10-06
3. [LlamaIndex — Using VectorStoreIndex](https://developers.llamaindex.ai/python/framework/module_guides/indexing/vector_store_index/) — получено 2026-10-06
4. [LlamaIndex — SimpleDirectoryReader](https://developers.llamaindex.ai/python/framework/module_guides/loading/simpledirectoryreader/) — получено 2026-10-06
5. [Ollama — API introduction and local/cloud base URLs](https://docs.ollama.com/api/introduction) — получено 2026-10-06
6. [Ollama Library — qwen3:0.6b](https://ollama.com/library/qwen3:0.6b) — получено 2026-10-06
7. [Ollama Library — embeddinggemma:300m](https://ollama.com/library/embeddinggemma:300m) — получено 2026-10-06
8. [LlamaIndex — Response Synthesizer and response.source_nodes](https://developers.llamaindex.ai/python/framework/module_guides/querying/response_synthesizers/) — получено 2026-10-06
