Представьте: вы спрашиваете у ИИ "где у нас обработка платежей", а он в ответ кидает вам три файла с функциями, названными по-разному, без понимания, как они связаны. Обычный RAG для кода работает примерно так — как слепой, пытающийся описать слона по одному хоботу.
Ragex ломает эту парадигму. Это MCP-сервер, который смотрит на код не как на текст, а как на структурированную вселенную. AST, векторы и графы — три кита, на которых стоит эта система. И да, она написана на Elixir, что для некоторых уже достаточная причина её попробовать.
Почему обычный RAG для кода — это провал
Возьмите стандартную RAG-систему из нашего руководства по созданию RAG за 15 минут. Она отлично работает с документацией, статьями, даже с правилами настольных игр (как в агенте для объяснения настолок). Но код — это другой зверь.
Проблема в контексте. Функция process_payment может вызывать validate_card, которая тянет за собой log_transaction, а та зависит от конфигурации в payment_config.ex. Обычный RAG видит только куски. Ragex видит связи.
Если вы уже работали с гибридным поиском для RAG, знаете: BM25 + векторы дают прирост точности. Но для кода этого недостаточно. Нужна третья ось — структурная.
Три головы одного дракона: архитектура Ragex
Ragex не выбирает один подход. Он использует все три одновременно:
1 AST-парсер: код как дерево
Elixir отлично парсит сам себя. Ragex использует это для разбора кода на узлы:
# Вот как выглядит разбор функции
defmodule PaymentProcessor do
def process(%{card: card, amount: amount}) do
# AST узел: функция process с двумя аргументами
# Вложенные узлы: паттерн-матчинг, вызовы функций
validate_card(card)
|> charge(amount)
|> log_transaction()
end
end
Каждый узел получает уникальный идентификатор, тип (function, module, variable) и метаданные. Это не просто текст — это структура.
2 Векторные эмбеддинги: семантический поиск
Здесь Ragex делает хитрость: эмбеддинг строится не только из текста функции, но и из её сигнатуры, типов аргументов, возвращаемого значения. process_payment/1 и handle_payment/1 получат близкие векторы, даже если названия разные.
Под капотом — модель наподобие тех, что используются в мультимодальном RAG, но адаптированная для кода.
3 Граф знаний: карта зависимостей
Это самая мощная часть. Каждый узел AST становится вершиной графа. Рёбра — это связи:
PaymentProcessor.process/1→calls→CardValidator.validate/1PaymentProcessor→imports→LoggerTransaction→has_field→amount
Когда вы спрашиваете "покажи цепочку обработки платежа", Ragex не ищет текст. Он идёт по графу.
Установка: не так страшно, как кажется
Если вы думаете, что настройка MCP-сервера — это ад из конфигов, расслабьтесь. Ragex работает как обычное Elixir-приложение:
# Клонируем
git clone https://github.com/yourusername/ragex.git
cd ragex
# Ставим зависимости
mix deps.get
mix compile
# Индексируем проект
mix ragex.index /path/to/your/elixir/project
# Запускаем MCP-сервер
mix ragex.serve
Сервер поднимается на порту 8080 и предоставляет три основных инструмента через MCP:
| Инструмент | Что делает |
|---|---|
search_code |
Гибридный поиск по AST + векторам |
trace_dependencies |
Построение цепочек вызовов через граф |
find_similar |
Поиск семантически похожего кода |
Пример: как это работает на реальном коде
Допустим, у вас есть проект на 200 файлов. Вы подключаете Ragex к Claude через MCP (как в production-ready AI-агенте) и спрашиваете:
"Где у нас логируются ошибки валидации платежей?"
Обычный RAG нашёл бы все файлы со словами "log", "error", "validation". Ragex делает иначе:
- Находит через AST все вызовы функций валидации
- Ищет в графе, какие из них вызывают функции логирования
- Возвращает не просто файлы, а конкретные цепочки:
validate_payment → log_validation_error → Logger.error
Вот как выглядит запрос через MCP:
{
"tool": "trace_dependencies",
"params": {
"function_name": "PaymentValidator.validate/1",
"depth": 3,
"direction": "forward"
}
}
И ответ:
{
"path": [
{
"node": "PaymentValidator.validate/1",
"type": "function",
"file": "lib/payment/validator.ex"
},
{
"edge": "calls",
"node": "ErrorLogger.log_validation/2",
"type": "function",
"file": "lib/utils/logger.ex"
},
{
"edge": "calls",
"node": "Logger.error/1",
"type": "function",
"file": "deps/logger/lib/logger.ex"
}
]
}
Сравнение с альтернативами: почему именно Ragex?
Есть другие инструменты для анализа кода. Но у каждого свои грабли:
| Инструмент | Плюсы | Минусы | Для кого |
|---|---|---|---|
| Ragex | Гибридный поиск, графы знаний, интеграция с Claude через MCP | Только Elixir, требует настройки | Команды Elixir с большими проектами |
| Sourcegraph | Многоподдержка языков, продвинутый поиск | Только текстовый поиск, нет семантики | Большие компании с разными языками |
| CodeQL | Статический анализ, поиск уязвимостей | Сложный язык запросов, не для повседневного поиска | Команды безопасности |
| Обычный RAG | Простая настройка, работает с любым текстом | Не понимает структуру кода, теряет контекст | Для документации, не для кода |
Ragex занимает нишу: он для разработчиков, которые хотят не просто искать код, а понимать его связи. Это как разница между поиском по словам в книге и навигацией по её оглавлению с перекрёстными ссылками.
Если ваш проект на 10 файлов — Ragex overkill. Но если у вас 100+ файлов, микросервисы, и вы тратите полдня на поиск "где же эта функция вызывается", он окупится за неделю.
Под капотом: как устроена индексация
Ragex не работает в реальном времени. Сначала нужно проиндексировать проект. Процесс трёхэтапный:
# 1. Парсинг AST
ast_nodes = Code.string_to_quoted!(file_content)
|> Ragex.ASTParser.parse()
# 2. Построение графа
graph = Ragex.GraphBuilder.build(ast_nodes)
# 3. Генерация эмбеддингов
embeddings = ast_nodes
|> Enum.map(&Ragex.Embedder.encode/1)
|> Enum.into(%{})
Индексация среднего проекта (50K строк кода) занимает 2-3 минуты. Зато потом поиск работает за миллисекунды.
Хранилище — комбинация ETS для графа и векторов + PostgreSQL для метаданных. Можно заменить на что-то своё, если хочется боли.
Интеграция с Claude и другими ИИ
MCP (Model Context Protocol) — это стандарт от Anthropic для подключения инструментов к ИИ. Ragex реализует MCP-сервер, поэтому работает с Claude Desktop из коробки.
Конфиг для Claude Desktop:
{
"mcpServers": {
"ragex": {
"command": "/path/to/ragex/_build/dev/rel/ragex/bin/ragex",
"args": ["start"],
"env": {
"RAGEX_PROJECT_PATH": "/path/to/your/project"
}
}
}
}
После этого в Claude можно спрашивать прямо в чате: "Найди все места, где мы используем Redis для кэширования" или "Покажи цепочку вызовов от контроллера пользователя до отправки email".
Технически, можно подключить и к другим ИИ через MCP, но Claude пока самый удобный вариант.
Ограничения и подводные камни
Идеальных инструментов не бывает. Вот что бесит в Ragex:
- Только Elixir. Если у вас микросервисная архитектура на пяти языках — Ragex покрывает только Elixir-часть. Для остального придётся использовать что-то ещё (или ждать, пока кто-то портирует идею).
- Индексация при каждом изменении. Не инкрементальная. Добавили файл — переиндексируйте весь проект. Для CI/CD это нормально, для локальной разработки — раздражает.
- Память. Граф для большого проекта жрёт RAM. 100K строк кода — около 500MB. Не критично, но учитывайте.
- Сложность отладки. Если поиск выдаёт странные результаты, понять почему сложно. Логов маловато.
Но главное ограничение — ментальное. Ragex меняет подход к поиску кода. Вместо "найди файл с этим текстом" вы начинаете думать "найди все функции, которые вызывают эту функцию и логируют ошибки". Это требует перестройки мышления.
Кому подойдёт Ragex (а кому нет)
Берите Ragex, если:
- Ваш проект на Elixir больше 50 файлов
- У вас есть legacy-код, который никто полностью не понимает
- Вы интегрируете Claude в разработку и хотите дать ему "зрение" по кодовой базе
- Вы устали объяснять новичкам "а вот эта функция вызывается отсюда, а та — отсюда"
Не тратьте время, если:
- Проект маленький или на другом языке
- Вам нужен только текстовый поиск по коду (Ctrl+F достаточно)
- Вы не используете ИИ-ассистентов в разработке
- У вас нет времени на настройку и обучение команды
Что дальше? Будущее гибридных RAG для кода
Ragex — не конечная точка. Это эксперимент, который показывает: код нужно анализировать структурно. Что можно улучшить:
- Инкрементальная индексация. Watch за файлами, обновление графа на лету.
- Поддержка больше языков. TypeScript, Python, Go — те же принципы работают везде.
- Интеграция с IDE. Плагин для VS Code, который показывает граф зависимостей на ховере.
- Предсказание рефакторинга. Анализ графа для поиска "пахучих мест".
Самая интересная возможность — использовать Ragex для обучения ИИ-агентов работе с кодом. Представьте агента, который не просто читает файлы, а понимает архитектуру проекта. Как в production-ready агенте, но со знанием структуры.
Пока большинство RAG-систем бьются над улучшением поиска по документации (как в Skill Seekers), Ragex идёт в другую сторону: глубина вместо широты. Лучше понимать один язык идеально, чем все языки поверхностно.
Если вы работаете с большими Elixir-проектами — попробуйте. Первые полчаса будете ругаться на настройку. Потом зададите вопрос "покажи все места, где мы обрабатываем ошибки этого типа" и поймёте, что назад пути нет.