1
0
Files
ollama/rag/README.md
2025-08-27 00:20:10 +08:00

13 KiB
Raw Blame History

Базовый RAG для локального запуска

Этот проект представляет собой систему RAG, которая позволяет преобразовывать документацию из Confluence или других источников в формат, пригодный для работы с локальной Ollama, и задавать вопросы по содержимому документов.

Быстрый старт

cd ..; ./up; cd -
python3 -m venv .venv
source ./venv/bin/activate
pip install beautifulsoup4 markdownify sentence-transformers qdrant-client langchain transformers hashlib
pip install torch torchvision --index-url https://download.pytorch.org/whl/cpu
./download.sh 123456789
python3 convert.py
python3 vectorize.py
python3 rag.py --interactive

Что такое RAG?

RAG (Retrieval-Augmented Generation) — это архитектура, которая расширяет возможности генеративных языковых моделей (LLM) за счет интеграции внешних источников знаний. Вместо того, чтобы полагаться исключительно на информацию, полученную во время обучения, RAG сначала извлекает релевантные фрагменты из внешней базы знаний, а затем использует их для генерации более точных и информативных ответов.

Основные шаги подготовки RAG:

  • Индексация: Документы преобразуются в векторные представления (эмбеддинги) и сохраняются в векторной базе данных
  • Поиск: При поступлении запроса система ищет наиболее релевантные фрагменты из индексированной базы
  • Генерация: Найденные фрагменты используются как контекст для генерации ответа с помощью языковой модели

Преимущества RAG:

  • Повышает точность ответов засчёт использования актуальной и специфической информации
  • Позволяет отвечать на вопросы, требующих знаний, не входящих в обучающие данные модели
  • Дает возможность проверить источник информации в сгенерированном ответе
  • Может работать с проприетарными или конфиденциальными данными без дообучения модели

Структура проекта

rag/
├── input_html/         # Входные файлы HTML, загруженные из Confluence
├── input_md/           # Входные (конвертированные) файлы Markdown
├── chats/              # Директория для сохранения чатов
├── download.sh         # Скрипт для загрузки страниц из Confluence
├── convert.py          # Скрипт конвертации HTML в Markdown
├── vectorize.py        # Скрипт векторизации Markdown
├── rag.py              # Основной скрипт RAG системы
├── clear.sh            # Скрипт очистки html/md файлов
└── README.md           # Этот файл

Стек

Предварительные требования

  1. Запустить среду из корня репозитория: ../README.md
  2. Установить ПО: curl, jq, python3, pip
  3. Установить зависимости python:
python3 -m venv .venv
source ./venv/bin/activate
pip install beautifulsoup4 markdownify sentence-transformers qdrant-client langchain transformers
pip install torch torchvision --index-url https://download.pytorch.org/whl/cpu
  1. Установить в ollama генеративную модель -- читай ниже.

Подготовка данных

1. Выгрузка из Confluence

Открыть одну или несколько страниц (разделов) Confluence, которые необходимо получить, и обратить внимание на наличие pageId, например:

https://conf.company.ltd/pages/viewpage.action?pageId=123456789
https://conf.company.ltd/pages/viewpage.action?pageId=987654321

Если URL страницы не содержит pageId, можно открыть историю изменений этой страницы, например:

https://conf.company.ltd/pages/viewpreviousversions.action?pageId=123456789
https://conf.company.ltd/pages/viewpreviousversions.action?pageId=987654321

Скопировать значения pageId и подставить в команду ./download.sh <pageId1> [<pageId2>...], например:

./download.sh 123456789 987654321

В результате указанные страницы и все их дочерние будут сохранены в директорию ./input_html/. Файлы будут названы по заголовкам страниц.

Important

В начале каждого файла будет сохранена исходная ссылка в формате @@https://conf.company.ltd/pages/viewpage.action?pageId=123456789@@. Это сделано для того, чтобы в диалоге с моделью источники информации отображались в виде ссылок, а не названий файлов.

Important

Confluence не позволяет получить готовые макросы в HTML-виде. Хотя в макросах часто есть очень полезная информация, но её приходится выбрасывать просто потому, что загрузка макросов происходит при загрузке страницы браузером. В файлах будет находиться HTML-текст с готовыми к загрузке макросами, но не загруженными. Поэтому, например, содержания, списки дочерних страниц, встраиваемые диаграммы и пр. плюшечки будут вырезаны.

Да, можно запросить страницы простым curl/wget, но (1) будет сложнее получить мета-инфу о странице и (2) даже после очистки HTML-тегов в тексте останется очень много мусора (меню, футер, навигация...)

Да, можно комбинировать разные подходы и всё сильно усложнить, но я не хочу.

2. Конвертация страниц в Markdown

Этот формат наиболее хорошо подходит для цитирования, потому что не содержит лишних символов, которые будут мешать хорошей токенизации и векторизации.

Для конвертации следует выполнить команду:

python3 convert.py

В результате все html-файлы будут сохранены в директорию ./input_md/. Файлы будут названы по заголовкам страниц, внутри также сохранится ссылка на исходную страницу @@...@@.

Для получения справки по скрипту выполни команду:

python3 convert.py --help

3. Векторизация (индексирование)

Файлы ./input_md/*.md должны быть проиндексированы.

Для того, чтобы проиндексировать Markdown-документы, выполнить команду:

python3 vectorize.py

Весь текст делится на отрезки (чанки) с некоторым перекрытием. Это делается для оптимизации количества информации, которое будет делиться на токены. Перекрытие обеспечивает смысловую связь между чанками.

Каждый чанк разбивается на токены, которые в виде векторов сохраняются в векторную СУБД Qdrant. При работе RAG, близость векторов токенов обеспечивает наибольшее смысловое совпадение разных слов => чанков => предложений => абзацев => документов. Как следствие:

  • наибольшее смысловое совпадение с вопросом пользователя;
  • молниеносный поиск по индексу чанков (частям документов);
  • корректное насыщение контекста для генеративной модели.

Впоследствии embedding-модель будет встраивать эти данные в диалог с генеративной моделью. Каждый запрос сначала будет обрабатывать именно она, находя подходящие по векторам документы, и подставлять их в контекст генеративной модели. Последняя будет всего лишь генерировать ответ, опираясь на предоставленные из документов данные, ссылаясь на них в ответе.

Для получения справки по скрипту выполни команду:

python3 vectorize.py --help

4. Запуск

Для работы с RAG в интерактивном режиме (симуляция диалога) следует выполнить команду:

python3 rag.py --interactive

Important

Модель не запоминает ничего, поскольку сам диалог не попадает в контекст! В целом, это похоже на гуглёж.

Для разового запуска RAG следует выполнить команду:

python3 rag.py --query "твой запрос здесь"

Для получения справки по скрипту выполни команду:

python3 rag.py --help

Кастомный системный промпт

Если хочется уточнить роль генеративной модели, можно создать файл sys_prompt.txt и прописать туда всё необходимое, учитывая следующие правила:

  1. Шаблон {{sources}} будет заменён на цитаты документов, найденные в qdrant
  2. Шаблон {{query}} будет заменён на запрос пользователя
  3. Если этих двух шаблонов не будет в промпте, результаты будут непредсказуемыми
  4. Каждая цитата в списке цитат формируется в формате:
    --- Source X ---
    Lorem ipsum dolor sit amet
    <пустая строка>
    
  5. Если в этой директории нет файла sys_prompt.txt, то будет применён промпт по умолчанию (см. функцию generate_answer()).

Посмотреть полный промпт можно указав аргумент --show_prompt при вызове rag.py.

Неплохие лёгкие модели

Для эмбеддинга:

  • sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2 (по умолчанию, хорошо адаптирована под русский язык)
  • nomad-embed-text (популярная)
  • ...

Для генерации ответов:

  • qwen2.5:3b (по умолчанию)
  • gemma3n:e2b
  • phi4-mini:3.8b
  • qwen2.5:1.5b
  • ...

Дисклеймер

Проект родился на энтузиазме из личного любопытства.

Цель: изучить современные технологии.

Задачи:

  1. облегчить поиск информации о проекте среди почти 2000 тысяч документов в корпоративной Confluence, относящихся к нему;
  2. обеспечить минимум телодвижений для развёртывания RAG с нуля внутри команды.

Здесь не было задачи сделать всё сложно и по красоте.

Частично (в качестве агентов) в проекте участвовали модели семейств qwen, clause и chatgpt.