
Принято считать, что экосистема SAP — это закрытый клуб, где вендор намеренно ограничивает доступ к знаниям. В свое время я даже делал доклад «SAP Support Launchpad и другие инструменты, которые облегчают жизнь консультанта», в котором основной темой было — где и как искать необходимую информацию. Но сейчас кажется, что настоящая проблема консультанта кроется не в дефиците информации, а в ее переизбытке. Мы тонем в данных, и нам нужны не новые доступы, а четкие алгоритмы поиска.
SAP — это большая платформа, которая рождает огромный «шум»: талмуды документации, которые лежат прямо в системе (и которые зачастую никто не читает), книги, курсы, разрозненные вики. А еще в нагрузку на каждом новом предприятии ты получаешь свой параллельный мир — множество кастомных «уникальных объектов и решений», которые приходится понять и освоить. И вот тут, как мне кажется, можно найти область, где LLM может принести практическую пользу. А именно — помогать структурировать, упаковывать и связывать знания так, чтобы их можно было находить и переиспользовать быстрее. При этом с существующими технологиями каждый может выстраивать свою базу знаний со своей привычной концепцией, не полагаясь на корпоративные практики, которые могут кардинально отличаться от места к месту.
В статье я покажу 3 сценария, которые я опробовал для личного пользования. Сначала мы применим LLM для навигации по стандартным настройкам, затем — для описания кода, и наконец — для суммаризации внешних знаний из чатов. В целом все эти подходы уже не раз были описаны ранее, но я постарался адаптировать их именно под SAP-реалии, и, возможно, кому-то они будут полезными.
Сценарий 1. Выносим знания из монолита: как сделать закрытую справку доступной и "поископригодной"
В этом примере в качестве базы я использовал уже готовую документацию, зашитую в каждую SAP ERP. А именно — нашу «мега-админку» настроек — SAP Reference IMG, также известную по имени транзакции SPRO.
Если опытный консультант интуитивно уже представляет, где примерно искать нужную информацию, то для новичка это настоящий «лабиринт Минотавра» (хотя, если область не твоя, то и опытному консультанту придётся попыхтеть). Ты либо бродишь по веткам, либо идёшь через «Обратный поиск» (от поля транзакции к SPRO). При этом для поиска доступны только заголовки веток, а поиск по самому содержимому документации вовсе не предусмотрен.

Я решил поэкспериментировать с решением этой задачи, а именно — сделать расширенный «гуглоподобный» поиск, в том числе и по тексту документации.
Получение документации
Первое решение — вынести документацию из SAP и обрабатывать ее независимыми от экосистемы инструментами. В теории подобный поиск можно было бы реализовать на базе встроенной программы (ABAP), но это явно вышло бы дольше, а о кастомизации под свои «хотелки» не было бы и речи.
Поэтому сначала надо решить вопрос с выгрузкой. Все карточки документации хранятся в таблицах DOKIL (заголовки) и DOKTL (строки текста). После выгрузки получился «сырой» дамп в CSV формате: около 500 МБ текста на английском языке (русский для IMG отсутствует), примерно следующего вида:
|OBJECT |LINE |DOKFORMAT|DOKTEXT |
------------------------------------------------------------------------------------------------------------------------------------
|BCST/CEEISUT/IUUA_LOSS |000001|* |You need to activate this BC Set for using the ISU - Power Loss |
|BCST/IAM/OBJECT_ACCESS |000001|U2 |Use |
|BCST/IAM/OBJECT_ACCESS |000002|AS |This BC Set contains Customizing data... |
Далее из этой таблицы генерируем отдельные листки документации. Технически здесь ничего сложного: почти любой LLM-агент без проблем создаёт программу для парсинга и генерации .md‑карточек. В результате получаем примерно такие файлы:

Создание дерева IMG
На основе полученных документов уже можно делать поиск, но без иерархии мы лишаемся быстрой и понятной навигации. Также названия веток имеют большую значимость при поиске, поэтому нам необходимо воссоздать структуру дерева. Для этого используем следующий SQL-запрос:
SELECT
i.NODE_ID,
i.PARENT_ID,
n.REF_OBJECT,
c.DOCU_ID,
c.TCODE,
c.ATTRIBUTES,
c.C_ACTIVITY,
a.SPRAS,
a.TEXT
FROM TNODEIMG i
LEFT JOIN TNODEIMGR n
ON i.NODE_ID = n.NODE_ID
LEFT JOIN CUS_IMGACH c
ON c.ACTIVITY = n.REF_OBJECT
LEFT JOIN CUS_IMGACT a
ON a.ACTIVITY = c.ACTIVITY
AND a.SPRAS = 'E';
Запрос строит полное дерево SPRO (IMG) и для каждого узла, где это возможно, добавляет связанную IMG-активность с её транзакцией, документацией (это, по сути, и есть ссылка на созданные нами ранее карточки) и английским описанием, не отбрасывая узлы без кастомизации. По результатам данной выборки мы можем восстановить дерево IMG, например, в формате YAML.
Поиск
Теперь, имея все данные на руках, можно создать свою Google‑подобную поисковую систему на базе Python-скрипта.
Суть программы: в качестве файлового поискового движка используется консольная утилита ugrep, в которой уже есть множество встроенных функций поиска. Поверх этого добавляется логика восстановления SPRO-пути, ранжирование результатов и несколько вариантов вывода — JSON либо, по умолчанию, «красивый» CLI-формат с кликабельными ссылками.
Ниже пример поиска по фразе "assign division" + sales, в режиме поиска по заголовку и по документации. Видна ветка запросов и первые несколько предложений из документации. По клику на ссылку документация открывается в редакторе, а по клику на транзакцию — генерируется и вызывается ярлык SAP GUI с открытием нужной транзакции.

Итог. Поиск был перенесён из SAP во внешние инструменты. Базовый результат уже есть, но пространство для экспериментов здесь практически бесконечно. Например, на первом шаге можно подключить вызов LLM, который бы преобразовывал простой текстовый запрос на любом языке в формат правильной поисковой команды на английском.
Сценарий 2. Концепция «Карточки кода»: как за 5 минут понять, что делает отчет десятилетней давности
В любой системе, которая живёт больше пары лет, возникает классическая ситуация: ABAP-код есть, а понимания, что он делает — уже нет. Документация либо не писалась вовсе, либо безнадёжно устарела, либо существуют только в устной форме и теряются при ротации кадров.Это приводит к принудительному реверс-инжинирингу: разработчик тратит ресурсы не на создание нового, а на дешифровку старого.
Есть и другая проблема, связанная с отсутствием нормального поиска — невозможность переиспользования существующих решений. В системе почти наверняка уже лежат готовые куски кода: логирование, работа с классификацией, парсинг Excel. Формально они есть, фактически — их не найти, поэтому их никто и не ищет.
В итоге система обрастает «зоопарком»:
10 вариантов чтения констант,
5 разных способов получить характеристики партии,
бесконечные копии одной и той же утилиты, написанные разными людьми в разные годы.
Получается что мы пишем «велосипеды» не потому, что любим это делать, а потому что зачастую сделать с нуля получается быстрее, чем найти готовое.
Концепция «карточки программы»
Решением здесь может стать создание слоя метаданных — «карточки программы». Это, по сути, технический паспорт объекта, который на человеческом языке объясняет: что это, для чего создано и как это вызвать.
С��абдив код такими «паспортами», мы превращаем хаос легаси в понятную базу знаний. Это позволяет вернуть в процесс разработки этап, который мы часто пропускаем: проверку наличия. Сначала ищем готовое, и только если не нашли — пишем свое.
Полигон для тестов: почему DEMO-программы?
Для валидации подхода я выбрал стандартный пакет примеров SAP ABAP (пакет SABAPDEMOS). Демо-программы SAP подошли идеально. Их много (почти 7 сотен), и они покрывают многие концепции ABAP — от "Hello World" до сложных примеров работы с данными и UI.
Но главная причина — это возможность самопроверки. У каждой демо-программы есть официальное описание от SAP в ABAP Keyword Documentation. Это не просто снимает вопрос субъективности, но и открывает крутую перспективу: имея эталон, мы можем автоматизировать оценку с помошью того же LLM. Например автоматически сравнивать ответ LLM с документацией вендора и оценивать, насколько точно модель "поняла" код. В системе стандартные описания выглядят примерно так

Выгрузка и обработка
Первым делом нужно извлечь код из системы. Единого стандарта выгрузки в SAP-мире нет,поэтому я воспользовался open-source решением:
https://github.com/palermo-consulting/sap-mass-abap-download-program
На выходе получилась папка с ~660 файлами .abap, по которым и будем запускать генерацию карточек. Для этого используем программу на Python. Скрипт итерируется по файлам .abap и скармливает их содержимое языковой модели (в данном кейсе — Qwen-Max). Задача модели — вернуть YAML с метаданными. В зависимости от нужной информации, можно использовать и тестировать разные промты. В моем случае это был примерно следующий образец
Промпт для генерации (упрощенно):
"Ты — эксперт SAP ABAP. Проанализируй этот код. Создай YAML-карточку с полями:
title: Краткий заголовок на русском.
faq_id: ID категории (из справочника).
questions_it_answers: На какие вопросы отвечает этот код? (например, 'Как удалить дубликаты из таблицы?').
dependencies: Какие таблицы/классы используются.
На выходе для каждого DEMO_XX.abap появляется его — DEMO_XX.meta.md.Это позволяет быстро навигироваться по проекту, не открывая исходный код каждого отчета. Пример такой карточки можно посмотреть ниже
Карточка демо программы в формате YAML
---
"id": "demo_corresponding_table_exp"
"title": "Пример использования CORRESPONDING для извлечения строки из внутренней таблицы\
\ в структуру"
"faq_id": "0014"
"keywords":
- "CORRESPONDING"
- "внутренняя таблица"
- "hashed table"
- "spfli"
- "cl_demo_output"
- "cl_demo_input"
- "исключение cx_sy_itab_line_not_found"
- "уникальный ключ"
"questions_it_answers":
- "Как использовать оператор CORRESPONDING для копирования полей из строки внутренней\
\ таблицы в структуру?"
- "Что происходит, если строка с указанным ключом не найдена в хешированной таблице?"
- "Как инициализировать внутреннюю таблицу данными из базы при старте программы?"
- "Как организовать ввод параметров через cl_demo_input?"
- "Почему используется hashed table с уникальным ключом carrid и connid?"
- "Как обработать исключение cx_sy_itab_line_not_found при доступе к таблице по ключу?"
- "Можно ли использовать CORRESPONDING без указания BASE или других опций?"
- "Как отобразить результат выполнения в демонстрационном выводе SAP?"
"features_used":
"syntax":
- "CORRESPONDING"
- "HASHED TABLE WITH UNIQUE KEY"
- "TRY ... CATCH cx_sy_itab_line_not_found"
- "SELECT ... INTO TABLE @itab"
- "CLASS-METHODS main и class_constructor"
- "cl_demo_input=>add_field / request"
- "cl_demo_output=>display"
"dependencies":
"ddic_tables":
- "spfli"
"classes":
- "cl_demo_output"
- "cl_demo_input"
"screens": []
---
Имея такие карточки, мы можем не только ориентироваться самостоятельно, но и запускать на них автоматический поиск. Например локальный RAG, построенный на этих карточках, позволит искать код не по имени (которое часто ничего не значит), а по смыслу решаемой задачи.
Итог. Эксперимент с демо-пакетом — это лишь Proof of Concept. В старых системах, где годами копился технический долг, такой подход позволяет за пару часов создать актуальную карту функциональности, на ручное написание которой ушли бы месяцы.
Сценарий 3. «Кто-то уже спрашивал»: достаем полезные решения из ленты Telegram-чата
Мне близка идея знаний, разложенных не по главам, а по вопросам. Когда каждый рецепт — это самостоятельная точка входа. Ты не листаешь книгу подряд, а находишь нужный вопрос и сразу работаешь с решением. Особенно хорошо такой формат заходит в SAP — когда система большая, задач много, а тебе нужен быстрый и точный ответ на конкретный вопрос.
Такие форматы действительно пользовались популярностью. Регулярно выходили ( и наверное до сих пор выходят) книги и сборники в духе «100 вещей которые ты должен знать о ...», «ABAP Cookbook» итп, ориентированные на конкретные роли: SD-консультантов, ABAP-разработчиков, специалистов по настройке и полномочиям. Ниже - несколько примеров такого формата

Примерно в таком же формате долгое время работали и популярные форумы. Например один из самых известных русскоязычных ресурсов по SAP — SAPboard. Концепция "Вопрос → обсуждение → найденное решение" — и дальше этот тред годами служиnm верой и правдой для тех, кто сталкивался с той же задачей. Конечно это тоже было не идеально, но при этом очень практично.
К сожалению, со временем наметилась устойчивая тенденция: значительная часть профессиональной информации начала перетекать в Telegram-каналы и другие более популярные площадки. К этому добавились и LLM-чаты — всё чаще за ответами идут не на специализированные сайты, а напрямую к ним. В результате классические форумы стали постепенно пустеть. Обсуждения вопросов, которые раньше оформлялись в виде законченных тредов с найденным решением, теперь либо теряются в чатах, либо остаются внутри диалогов с LLM. Если посмотреть на активность форумов, то видно — иногда за месяц набирается всего несколько сообщений. По сути, это уже не стагнация, а финальная стадия угасания формата.
И что делать, когда привык работать с контентом в старом формате, который сейчас не в тренде? Перевести его в нужный тебе формат, и как раз LLM здесь нам так же поможет.
Я попробовал реализовать данную концепцию на основе популярного русскоязычного Telegram канала SAP ABAP.
Идея следущая - превратить историю чата в подобие форума с рецептами, где в качестве конечных тредов будут выступать md карточки, а просматривать их мы будем через Obsidian.
Чтобы было более понятно, сразу покажу пример конечного результата

Вот отформатированный вариант:
Слева — тематическое дерево папок. Внутри каждой конечной темы лежат минимум два файла:
Рецепт (
.md) — это карточка с решением, которая пытается ответить на определенный вопрос на основе существующего обсуждения в чате.Лог чата (
.md) — исходное обсуждение. Это критически важно для верификации: мы всегда можем проверить, что LLM не «сочинила» решение, а взяла его из контекста.

Ниже я опишу свой пайплайн получения такого результата.
Берем JSON-выгрузку истории Telegram-чата. На Хабре про это написаны десятки статей, поэтому подробно останавливаться не буду. Самый простой вариант — сделать выгрузку через десктопное приложение, где эта функция встроена штатно.
Вычленяем отдельные диалоги (треды). Сначала я пытался решить это алгоритмически, опираясь на метаданные: паузы между сообщениями, цепочки reply_to, пересечение участников. К сожалению, стабильного результата получить не удалось: было слишком много шума. Поэтому пришлось подключать LLM. Это был, наверное, самый затратный этап по «пожиранию» токенов, так как истории чата почти 10 лет. Здесь я использовал Gemini 2.5 Pro с её большим контекстным окном. На вход я подавал инструкцию (см. под катом) и чанк выгрузки, не превышающий 200 тысяч токенов.
Системный промт для выделения диалогов
[Системная роль и контекст]
Ты — опытный системный аналитик, специализирующийся на анализе коммуникаций в IT-командах. Твоя задача — проанализировать лог сообщений из технического чата и сгруппировать их в осмысленные диалоги (треды). Ты должен действовать как человек, который читает чат и понимает, где заканчивается одна тема и начинается другая, даже если они переплетаются.
[Входные данные]
Ниже будет предоставлен массив JSON-объектов, где каждый объект — это сообщение из чата. Каждое сообщение имеет следующие поля: id, datetime, sender_user_name, text, а также опциональные is_reply и reply_to_message_id.
[Основная задача]
Твоя задача — выполнить два шага:
Сгруппировать сообщения: Разделить все сообщения на логические группы (диалоги, треды). Каждая группа должна представлять собой единое обсуждение одной темы.
Озаглавить каждую группу: Для каждой созданной группы придумать короткий, но емкий заголовок (4-7 слов), который точно отражает суть обсуждаемой темы.
[Критерии и правила для группировки]
При группировке сообщений руководствуйся следующими правилами в порядке приоритета:
Прямые ответы (Высший приоритет): Если сообщение A является ответом на сообщение B (через поле reply_to_message_id), они обязаны находиться в одной группе. Все сообщения, связанные цепочкой ответов, формируют неразрывный "скелет" диалога.
Тематическая близость и продолжение диалога: Сообщения, не связанные прямыми ответами, должны объединяться, если они очевидно продолжают одну и ту же тему. Используй следующие эвристики:
Продолжение мысли автора: Если несколько сообщений подряд от одного автора развивают одну идею, они должны быть в одной группе.
Быстрый обмен мнениями: Если несколько разных участников отвечают друг другу с небольшими временными интервалами (1-5 минут) на одну и ту же тему, объединяй их.
Возврат к теме: Если участник возвращается к обсуждению спустя некоторое время (до 30-40 минут), и в его сообщении явно прослеживается связь с предыдущей темой (например, используются те же ключевые слова, имена или технологии), присоединяй его сообщение к соответствующей группе.
Смена контекста (Разделитель групп): Новая группа должна начинаться, когда происходит явная смена темы. Признаки смены темы:
Новый участник задает совершенно новый, не связанный с предыдущим обсуждением вопрос.
Проходит значительное время (более часа) без сообщений по текущей теме.
В итоге получим множество групп такого формата
{
"title": "Решение проблемы с ошибкой 'Memory limit exceeded' в отчете",
"message_ids": [
14419,
14420,
14421,
14422,
14423,
14425,
14426
]
}
Фильтрация и структурирование. На этом этапе у нас есть список названий всех бесед. Это позволяет работать с облегченным контекстом, не теряя общей картины. Используя только список заголовков, делаем еще два прогона через LLM:
а) Очистка. Просим модель вернуть список заголовков, не относящихся к SAP ERP (флуд, оффтоп), и исключаем их из выборки.
б) Кластеризация. Оставшиеся релевантные темы подаем на вход LLM с просьбой построить глубокую иерархию (структуру книги/справочника).
Генерация контента. Теперь для каждого сохраненного треда создаем карточку рецепта. Это второй ресурсоемкий этап («пожиратель токенов»). На вход модели (здесь я использовал Qwen-Max) подаем JSON с отдельной завершенной беседой и специальную инструкцию (см. ниже).
Системный промт для генерации рецепта
Ты — строгий технический редактор и архивариус, работающий над базой знаний по SAP (ABAP/Functional),
чтобы потом добавить его в книгу рецептов "SAP Recipes".
Твоя задача — проанализировать сырой лог чата и конвертировать его в структурированный JSON-объект.
### ВХОДНЫЕ ДАННЫЕ:
Текст чата между специалистами, который может содержать фрагменты кода.
### ТВОИ ЗАДАЧИ:
1. ОЦЕНКА ПОЛЕЗНОСТИ (Relevance):
Определи, содержит ли этот чат полезный кейс для книги.
- Если это флуд — is_relevant: false.
- Если есть обсуждение проблемы и кода — is_relevant: true.
2. ВЫДЕЛЕНИЕ ТЕМ (Topics):
Сформулируй поисковые запросы (темы), по которым можно найти эту беседу.
3. ИЗВЛЕЧЕНИЕ РЕШЕНИЯ (Extraction):
Напиши "Рецепт" на основе чата. Используй Markdown.
- Используй ТОЛЬКО информацию из чата. Не выдумывай и не добавляй от себя.
- Если решение не найдено, опиши саму проблему и предложенные гипотезы.
4. ОБРАБОТКА КОДА (CRITICAL!):
- Если в чате встречается код, ты должен извлечь его ДОСЛОВНО (verbatim).
- ЗАПРЕЩЕНО исправлять ошибки, дописывать пропущенные скобки или менять форматирование, если этого не было в исходнике.
- Код должен быть помещен в массив code_snippets.
### ФОРМАТ ВЫВОДА (JSON STRUCTURE):
Ты обязан вернуть только валидный JSON объект следующей структуры:
{
"is_relevant": true/false,
"reason": "Почему этот чат важен или почему нет",
"title_options": ["Заголовок 1", "Заголовок 2"],
"problem_description": "Описание проблемы",
"solution_content": "Текст статьи в Markdown. Включая блоки кода.",
"code_snippets": [
{
"language": "abap",
"code": "Код точь-в-точь как в чате (экранируй переносы строк как \\n)"
}
],
"key_entities": ["T-code", "Table", "Method"],
"warning": "Предупреждение, если решение сомнительно (иначе null)"
}
Ну и последний, завершающий этап - Организация файловой системы. На основе полученной иерархии создаем структуру папок. Скрипт автоматически распределяет пары .md файлов (чат + рецепт) по соответствующим директориям, завершая формирование базы для Obsidian.
Итог. В этом сценарии важен не столько конкретный Telegram чат, сколько сама возможность превращению любого неструктурированного потока сообщений в базу знаний. Если у вас есть история переписки, этот сценарий возможно сможет превратит её в полезный справочник.
Если кому то будет интересно ознакомиться, то все файлы, сгенерированные в ходе экспериментов (база SPRO, метаданные SABAPDEMOS и архив чата для Obsidian), доступны для скачивания с Сбердиска - https://files.sberdisk.ru/s/skDUkHvjXOL2U9L
Спасибо, что дочитали!
