Я столкнулся с простой (как мне изначально показалось – даже очень) задачкой. Мне в последнее время потребовалось часто проводить поиск в 4 словарях. Государство мне их дало в виде пяти PDF файлов, выложенных онлайн. Это нормативные словари русского языка, слова из которых можно использовать в публичном пространстве после 1 марта 2026 г.
Например, caсhe - можно использовать на русском как кэш, а не переводить как тайник или склад (не путать с cash как наличные), поскольку в Словарь иностранных слов это слово уже включено. И это слово нам еще пригодится далее по тексту)

Один раз в 10 лет я призываю силу Хабра на помощь. Прошлый раз мне сильно помогли в моей попытке сделать захабренный договор. Надеюсь сейчас тоже сработает.
Итак, открыл я все файлы сначала в браузере, потом в Adobe Acrobat и стал заводить поисковые запросы в каждом окне. Подустал уже после второго запроса и подумал, что должен же быть способ объединить их в один массив и выдавать результат сразу по всем словарям.
При этом мне нужно, чтобы в результатах выдачи по каждому совпадению показывался фрагмент текста с найденным словом, название словаря (оно же название файла) и номер страницы в файле, где найдено совпадение.
В идеале – быстрый переход по ссылке сразу на ту страницу, где найдено совпадение. Это нужно, чтобы доказывать проверяющим органам, что имеешь право юзать англицизм, вошедший в употребление, а точнее в один из 4 нормативных словарей, утвержденных Правительством РФ.
Я посмотрел кучу роликов в интернете как легко можно делать с помощью ИИ решения и подумал – справлюсь сам и навайбкодю. Ко второму дню начал подозревать, что в роликах про настройку агентов за 2 минуты немного обманывают.
Попытка привлечь 15-летнего сына, который ходит на олимпиады по программированию, не увенчалась успехом. Не дослушав задачу до конца, он сказал, что вообще ни разу не программист и мне следует привлечь профессионала. Но мы-то не ищем легких путей.
Вайбкодинг – день первый
Сразу же решил делать решение доступным онлайн, чтобы команда и клиенты тоже могли пользоваться таким удобным поиском. Сайт у меня на Тильде, поэтому решение заключалось в разработке html-кода для вставки в блок T123.
В помощники я взял себе ChatGPT, Gemini и Claude. Все в лоб дали вот такой вариант (с небольшими вариациями) – ниже цитата из GPT
Для того чтобы добавить поиск по нескольким PDF-документам на сайте...
, собранном на Тильде, можно использовать несколько подходов. Вот шаги для реализации:
1. Загрузка PDF в облако
Загрузи свои PDF-документы на облачный сервис (например, Google Drive, Dropbox или любой другой сервис для хранения файлов). Обрати внимание, что лучше использовать ссылку с возможностью общего доступа, чтобы все могли видеть файлы.
2. Создание индекса для поиска
Чтобы пользователь мог искать по содержимому документов, можно использовать сервисы, которые позволяют индексировать PDF-файлы и строить поисковый функционал:
-
Google Custom Search:
Создаешь поисковую систему в Google, указывая ссылку на файлы, расположенные в облаке.
Получаешь код для встраивания на страницу Тильды.
Встраиваешь код на нужную страницу в Тильде через HTML-блок.
Searchable PDF: Есть сервисы и инструменты, которые могут конвертировать PDF-документы в индексируемый текст. Ты можешь использовать такие инструменты, чтобы создать индекс или текстовую базу данных для поиска по этим документам.
3. Добавление формы поиска на Тильде
Чтобы разместить поиск на странице Тильды, нужно добавить HTML/JavaScript код:
На Тильде выбери блок с HTML-кодом.
Вставь туда код для поиска, который ты получишь после настройки поисковой системы в Google или другого сервиса.
Чем меня не устроил этот вариант – после публикации не было никаких результатов поиска. На вопрос: "Где результаты?" – ИИ ответил, что нужно время на индексацию документов и это займет от нескольких часов до нескольких дней. Кстати, на второй день результаты стали появляться, но пока точно не все совпадения ищет. В этой части эксперимент продолжается.
Вайбкодинг — день второй
Вторым решением, которое пока остается рабочим, было сделать собственный поиск по документам, размещенным онлайн.
Claude дал мне полный код, который заработал сразу после устранения пары ошибок.
Код
<style> *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } #pdf-search-widget { width: 100%; max-width: 780px; margin: 0 auto; font-family: 'Georgia', serif; } .psw-header { margin-bottom: 28px; text-align: center; } .psw-header h2 { font-size: clamp(22px, 4vw, 34px); font-weight: normal; color: #1a1a1a; letter-spacing: -0.5px; } .psw-header p { margin-top: 6px; font-size: 14px; color: #888; font-family: 'Courier New', monospace; } .psw-search-wrap { position: relative; margin-bottom: 10px; } .psw-search-wrap input { width: 100%; padding: 16px 56px 16px 20px; font-family: 'Georgia', serif; font-size: 17px; border: 2px solid #1a1a1a; background: #fff; color: #1a1a1a; outline: none; transition: border-color 0.2s, box-shadow 0.2s; } .psw-search-wrap input::placeholder { color: #bbb; } .psw-search-wrap input:focus { border-color: #c8502a; box-shadow: 4px 4px 0 #c8502a; } .psw-search-icon { position: absolute; right: 18px; top: 50%; transform: translateY(-50%); color: #bbb; pointer-events: none; font-size: 20px; } .psw-clear-btn { position: absolute; right: 16px; top: 50%; transform: translateY(-50%); background: none; border: none; font-size: 22px; cursor: pointer; color: #999; line-height: 1; display: none; padding: 2px 4px; } .psw-clear-btn:hover { color: #c8502a; } .psw-status { font-family: 'Courier New', monospace; font-size: 12px; color: #999; margin-bottom: 18px; min-height: 18px; display: flex; align-items: center; gap: 8px; } .psw-dot { width: 8px; height: 8px; border-radius: 50%; background: #ddd; flex-shrink: 0; } .psw-dot.loading { background: #f0a830; animation: psw-pulse 0.9s ease-in-out infinite; } .psw-dot.ready { background: #4caf7d; } .psw-dot.error { background: #e05a5a; } @keyframes psw-pulse { 0%,100%{opacity:1} 50%{opacity:0.3} } .psw-progress-bar { height: 2px; background: #eee; margin-bottom: 18px; overflow: hidden; display: none; } .psw-progress-fill { height: 100%; background: linear-gradient(90deg, #c8502a, #f0a830); width: 0%; transition: width 0.3s ease; } .psw-results { display: flex; flex-direction: column; gap: 12px; } .psw-result-card { background: #fff; border: 1.5px solid #e0dcd4; padding: 18px 20px; cursor: pointer; transition: border-color 0.15s, transform 0.1s, box-shadow 0.15s; } .psw-result-card:hover { border-color: #c8502a; box-shadow: 4px 4px 0 rgba(200,80,42,0.13); transform: translateX(-2px); } .psw-card-top { display: flex; justify-content: space-between; align-items: flex-start; gap: 12px; margin-bottom: 8px; } .psw-doc-name { font-family: 'Courier New', monospace; font-size: 12px; font-weight: bold; color: #c8502a; text-transform: uppercase; letter-spacing: 0.5px; flex: 1; } .psw-page-badge { background: #1a1a1a; color: #f4f1eb; font-family: 'Courier New', monospace; font-size: 11px; padding: 2px 8px; white-space: nowrap; flex-shrink: 0; } .psw-snippet { font-family: 'Georgia', serif; font-size: 14px; color: #444; line-height: 1.65; } .psw-snippet mark { background: #fff0a0; color: #1a1a1a; padding: 0 2px; border-radius: 2px; } .psw-card-footer { margin-top: 12px; display: flex; align-items: center; gap: 12px; } .psw-dl-link { display: inline-flex; align-items: center; gap: 5px; font-family: 'Courier New', monospace; font-size: 12px; color: #1a1a1a; text-decoration: none; border-bottom: 1px solid #ccc; padding-bottom: 1px; transition: color 0.15s, border-color 0.15s; } .psw-dl-link:hover { color: #c8502a; border-color: #c8502a; } .psw-more-count { font-family: 'Courier New', monospace; font-size: 11px; color: #aaa; } .psw-empty { text-align: center; padding: 40px 20px; color: #bbb; font-family: 'Courier New', monospace; font-size: 13px; border: 1.5px dashed #ddd; } </style> <div id="pdf-search-widget"> <div class="psw-header"> <h2>Поиск по документам</h2> <p id="psw-doc-count-label">инициализация...</p> </div> <div class="psw-search-wrap"> <input type="text" id="psw-input" placeholder="Введите слово или фразу..." autocomplete="off" /> <span class="psw-search-icon" id="psw-icon">⌕</span> <button class="psw-clear-btn" id="psw-clear" title="Очистить">×</button> </div> <div class="psw-progress-bar" id="psw-progress-bar"> <div class="psw-progress-fill" id="psw-progress-fill"></div> </div> <div class="psw-status" id="psw-status"> <span class="psw-dot loading" id="psw-dot"></span> <span id="psw-status-text">Загружаем документы...</span> </div> <div class="psw-results" id="psw-results"></div> </div> <script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.min.js"></script> <script> // ================================================ // НАСТРОЙКИ — замени на свои ссылки и названия // ================================================ var PDF_SOURCES = [ { name: 'Орфографический словарь', url: 'https://5b6cun312m.ucarecd.net/d0775608-a981-40e9-9699-f412433c40cc/orfograficheskij_slovar.pdf' }, { name: 'Орфоэпический словарь', url: 'https://5b6cun312m.ucarecd.net/9e5bbd55-48b3-467a-bbf2-328351ccf695/orfoepicheskij_slovar.pdf' }, { name: 'Словарь иностранных слов', url: 'https://5b6cun312m.ucarecd.net/2416bd08-c569-4f7f-a396-0e2617538988/slovar_inostr_slov.pdf' }, { name: 'Толковый словарь А-Н', url: 'https://5b6cun312m.ucarecd.net/6fb87d14-05f8-409a-983a-21b71808afb4/tolkovyj_slovar_chast1_AN.pdf' }, { name: 'Толковый словарь О-Я', url: 'https://5b6cun312m.ucarecd.net/8791e39d-ed5d-48be-a9d8-4122825c5e98/tolkovyj_slovar_chast2_OJa.pdf' }, ]; var MAX_RESULTS = 30; var SNIPPET_RADIUS = 120; // ================================================ pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.worker.min.js'; var input = document.getElementById('psw-input'); var resultsEl = document.getElementById('psw-results'); var statusText = document.getElementById('psw-status-text'); var statusDot = document.getElementById('psw-dot'); var clearBtn = document.getElementById('psw-clear'); var iconEl = document.getElementById('psw-icon'); var progressBar = document.getElementById('psw-progress-bar'); var progressFill = document.getElementById('psw-progress-fill'); var docLabel = document.getElementById('psw-doc-count-label'); var index = []; var ready = false; function setStatus(msg, state) { statusText.textContent = msg; statusDot.className = 'psw-dot ' + (state || 'loading'); } function escHtml(str) { return String(str).replace(/[&<>"']/g, function(c) { return {'&':'&','<':'<','>':'>','"':'"',"'":'''}[c]; }); } function highlight(text, query) { var esc = query.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); return escHtml(text).replace(new RegExp('(' + esc + ')', 'gi'), '<mark>$1</mark>'); } function getSnippet(text, query) { var idx = text.toLowerCase().indexOf(query.toLowerCase()); if (idx === -1) return escHtml(text.slice(0, SNIPPET_RADIUS * 2)) + '…'; var start = Math.max(0, idx - SNIPPET_RADIUS); var end = Math.min(text.length, idx + query.length + SNIPPET_RADIUS); var snippet = text.slice(start, end); if (start > 0) snippet = '…' + snippet; if (end < text.length) snippet = snippet + '…'; return highlight(snippet, query); } function loadAllPDFs() { progressBar.style.display = 'block'; var loaded = 0; function loadNext(i) { if (i >= PDF_SOURCES.length) { ready = true; progressBar.style.display = 'none'; var totalPages = index.filter(function(e){ return e.page > 0; }).length; setStatus('Проиндексировано ' + totalPages + ' стр. в ' + PDF_SOURCES.length + ' докум.', 'ready'); docLabel.textContent = PDF_SOURCES.length + ' документ' + (PDF_SOURCES.length === 1 ? '' : PDF_SOURCES.length < 5 ? 'а' : 'ов') + ' · ' + totalPages + ' страниц'; return; } var source = PDF_SOURCES[i]; setStatus('Загружаем «' + source.name + '»...', 'loading'); pdfjsLib.getDocument({ url: source.url, withCredentials: false }).promise .then(function(pdf) { var pageNum = 1; function nextPage() { if (pageNum > pdf.numPages) { loaded++; progressFill.style.width = (loaded / PDF_SOURCES.length * 100) + '%'; loadNext(i + 1); return; } pdf.getPage(pageNum).then(function(page) { page.getTextContent().then(function(content) { var text = content.items.map(function(it){ return it.str; }).join(' ').trim(); var textNoSpaces = text.replace(/\s+/g, ''); if (text.length > 10) { index.push({ docName: source.name, url: source.url, page: pageNum, text: text, textNoSpaces: textNoSpaces }); } pageNum++; nextPage(); }); }); } nextPage(); }) .catch(function(e) { console.warn('Ошибка загрузки ' + source.name + ':', e); index.push({ docName: source.name, url: source.url, page: 0, text: '[Не удалось загрузить]' }); loaded++; progressFill.style.width = (loaded / PDF_SOURCES.length * 100) + '%'; loadNext(i + 1); }); } loadNext(0); } function search(query) { resultsEl.innerHTML = ''; if (!query.trim()) return; if (!ready) { setStatus('Подождите, индексируем...', 'loading'); return; } var q = query.trim().toLowerCase(); var qNoSpaces = q.replace(/\s+/g, ''); var hits = index.filter(function(e){ return e.text.toLowerCase().indexOf(q) !== -1 || e.textNoSpaces.toLowerCase().indexOf(qNoSpaces) !== -1; }); if (hits.length === 0) { resultsEl.innerHTML = '<div class="psw-empty">Ничего не найдено по запросу «' + escHtml(query) + '»</div>'; setStatus('0 совпадений', 'ready'); return; } var grouped = {}; hits.forEach(function(h) { if (!grouped[h.docName]) grouped[h.docName] = []; grouped[h.docName].push(h); }); var cardCount = 0; var docNames = Object.keys(grouped); docNames.forEach(function(docName) { if (cardCount >= MAX_RESULTS) return; var docHits = grouped[docName]; var shown = docHits.slice(0, 3); var extra = docHits.length - shown.length; shown.forEach(function(hit, idx2) { if (cardCount >= MAX_RESULTS) return; cardCount++; var card = document.createElement('div'); card.className = 'psw-result-card'; var extraHtml = (extra > 0 && idx2 === shown.length - 1) ? '<span class="psw-more-count">+ ещё ' + extra + ' совпад. в этом документе</span>' : ''; card.innerHTML = '<div class="psw-card-top">' + '<span class="psw-doc-name">' + escHtml(docName) + '</span>' + (hit.page > 0 ? '<span class="psw-page-badge">стр. ' + hit.page + '</span>' : '') + '</div>' + '<div class="psw-snippet">' + getSnippet(hit.text, query.trim()) + '</div>' + '<div class="psw-card-footer">' + '<a class="psw-dl-link" href="' + escHtml(hit.url) + '" target="_blank" download>↓ Скачать PDF</a>' + extraHtml + '</div>'; (function(h) { card.addEventListener('click', function(e) { if (e.target.closest('.psw-dl-link')) return; var pageHash = h.page > 1 ? '#page=' + h.page : ''; window.open(h.url + pageHash, '_blank'); }); })(hit); resultsEl.appendChild(card); }); }); setStatus(hits.length + ' совпад. в ' + docNames.length + ' докум.', 'ready'); } var debounceTimer; input.addEventListener('input', function() { var val = input.value; clearBtn.style.display = val ? 'block' : 'none'; iconEl.style.display = val ? 'none' : 'block'; clearTimeout(debounceTimer); debounceTimer = setTimeout(function(){ search(val); }, 250); }); clearBtn.addEventListener('click', function() { input.value = ''; clearBtn.style.display = 'none'; iconEl.style.display = 'block'; resultsEl.innerHTML = ''; if (ready) setStatus('Готов к поиску', 'ready'); input.focus(); }); input.addEventListener('keydown', function(e) { if (e.key === 'Escape') clearBtn.click(); }); loadAllPDFs(); </script>
Но обнаружилась несколько проблем.
1. Чтобы запустить поиск первый раз нужно подождать около минуты. И так при каждой новой загрузке страницы, поскольку идет "инициализация" и загрузка файлов.

2. В файлах слова указаны с ударением и при поиске ударная гласная не воспринимается как обычная буква. В результатах поиска она как будто отделена пробелами. Соответственно полное слово не выдается в поиске.
Пример – ищем ОВЕРСАЙЗ

Видите Оверсайза?
- Нет.
- И я не вижу.
- А он есть.


ИИ говорит, вообще не проблема – перепиши код, пробелы будем учитывать при поиске. Вот тебе новый код на замену. Переписал, но что-то все равно не получается. Хочется, чтобы поиск был с учетом ударений и не исключал слова.
Вайбкодинг – день третий. Пока последний. Продолжение следует...
Спрашиваю у ИИ: а можно как-то побыстрее? Ну, говорит, можно и по-взрослому, но для этого нужен Python. Тогда все будет летать за секунды. Далее опять цитата
Вместо того чтобы парсить PDF в браузере — один раз извлечь текст заранее и сохранить как лёгкий JSON-файл.
Браузер грузит не 163 МБ PDF, а 2-5 МБ чистого текста.
Как это работает: я пишу тебе Python-скрипт, ты запускаешь его один раз на своём компьютере, он вытаскивает весь текст из PDF и сохраняет в index.json. Этот файл кладёшь на Uploadcare, виджет грузит только его.
Плюсы: загрузка за 1-2 секунды вместо минуты, работает без кэша. Минус: при обновлении PDF нужно перегенерировать JSON заново.
И затем убойный вопрос: Python есть на твоём компьютере? Если да — за 5 минут настроим. Ага, спросил он у гуманитария. Тут настал предел моим компетенция и терпению.
Вопрос к силе неискусственного интеллекта
Скажите, стоит мне дальше мучать ИИ и продолжать описывать свои мучения (подозреваю, что для специалистов может выглядеть смешно) или подросток, не верящий в силу интеллекта родителя и искусственных интеллектов был прав?
Если есть у вас желание помочь и дать дельный совет, буду рад увидеть в комментариях.
P.S. Пост буду дописывать.
P.P.S. Боюсь публиковать ссылку на поиск - забанят.
Комментарии (43)

anonymous
26.02.2026 17:22
aborouhin
26.02.2026 17:22Это задача на 15 минут для новичка.
Ну точно не на 15 минут. Словари толком не структурированы, кроме собственно словарной части ещё всякие введения/сокращения/пр., которые надо отбрасывать, причём в 4 разных словарях эта структура разная. Разбиение на словарные статьи делать придётся только по форматированию (PDF же), тоже 4 разных алгоритма. Есть статьи, где несколько вариантов слова в одной статье (в словаре "выставля́ть(ся)", надо чтобы находил по поисковой строке "выставляться", наверняка ещё и другие подобные нюансы найдутся) Ударения не проверял, но их обычно в кириллице делают двумя способами - правильным (два юникодных символа) и простым (один символ из латиницы, пишущийся аналогично), надо учитывать обе возможности. А ещё бы по всем словоформам потом искать... и обновлять как-то это всё, если словари на оф. сайте обновятся.
P.S. Повеселило в официально (!) опубликованном словаре 32 вхождения фразы "Error! Bookmark not defined". Делали в Ворде, публиковали не приходя в сознание... мда.

PashtetMedved
26.02.2026 17:22А Elasticsearch с asciifolding, не закроет эту задачу, при условии что поиск должен быть именно на сайте ?

aborouhin
26.02.2026 17:22Opensearch (в пень Elasticsearch с их новой лицензией...) закроет простой поиск, но если мы захотим отфильтровать именно термины, то тут уже надо парсить текст похитрее. А мы, наверное, захотим в итоге и функционал "проверить наличие несловарных слов в произвольном тексте" (ну напрашивается же), так что лучше сразу готовить нормальную БД.

FetTroll
26.02.2026 17:22Даже Elasticsearch может быть дорогим и избыточным. Есть прекрасный FTS в PostgreSQL и какой-нибудь Apache PDFBox для чтения и индексирования.

Anti2024
26.02.2026 17:22Для своего пет проекта я преобразовал около 500 PDF в текстовый формат, оттуда в векторную базу данных.
Питон ставится самой ллм за три минуты, дальше она же скачет какую-нибудь уже готовую библиотеку - и преобразование PDF в json займёт ещё пару минут.
Что дальше делать с текстом вопрос уже к автору, в каком виде ему нужно.
Но это реально задача на пару часов максимум, без знания кода вообще.
Главное не использовать какой-нибудь дипсик или композер, а потратить 20 баксов на подписку и пользоваться платной моделью (хотя на самом деле с такой простой задачей даже авто в курсоре справится).

oeditus
26.02.2026 17:22Векторную базу? Зачем тут векторная, не поде́литесь?
В условии задачи — самое главное — показать ссылку на справочник (на страницу в печатном издании, оно же PDF) и текст оттуда. Как вы планируете из джейсона обратно в PDF прилинковываться?
В общем, камни в этой задаче ворочать — немного сложнее, чем языком чесать.

aborouhin
26.02.2026 17:22P.S. Всё уже написано до Вас :) Кэш и оверсайз успешно ищутся. Нет ссылок на страницы, правда.

Newskylaw Автор
26.02.2026 17:22Спасибо за ваше участие.
По этому решению - да, сделано, но работает криво. И видимо по тем причинам, как описано в статье и комментариях выше.
Попробуем найти слово «кэшбэк»

Скриншот с Грамота.ру А слово есть в словаре

Орфоэпический словарь Видимо из-за используемых в файле символов скобок и ударений ищет только вариант кЕшбэк через Е, хотя в словаре есть два варианта слова - через Е и Э.
А вопрос в юридической плоскости означает - оштрафуют юрлицо на полмиллиона или нет? Переделывать вывески или оставить?
Хочется найти решение, чтобы поиск работал корректно.
В моем временном решении кэшбэк нашелся


aborouhin
26.02.2026 17:22Конкретно с кэшбэком я вижу ошибку в словаре. В именительном падеже Е, в родительном почему-то Э (второе Э после \\ относится в произношению, а не написанию, с ним всё ОК). Хотя во введении к словарю прямо написано, что через запятую до \\ указываются только словоформы, в которых ударение может падать по-разному, но никак не разные варианты написания.
Если бы я делал свой поиск - у меня бы кэшбэк через Э тоже не нашёлся by design.
P.S. Я особо не погружался в эту тему, но, насколько я понимаю, ответственность наступает за использование слов, отсутствующих в словарях, а не за написание имеющихся в словарях слов с орфографическими ошибками. Поэтому, даже если бы в словаре был везде только кешбэк через Е - за написание кэшбэк через Э ответственности нет. А отсюда вытекает ещё одно требование к ТЗ для поиска - неплохо бы находить не только буквальные вхождения искомых слов, но и все похожие слова...

Zippy
26.02.2026 17:22а негуманитариям (технарям то есть) зачем вайбкодинг если они могут научится программировать? ну кроме каких то набросок кусков кода чтобы в стековерфлов не искать - типа примера поиска по pdf

Gedeonych
26.02.2026 17:22Скажите, стоит мне дальше мучать ИИ и продолжать описывать свои мучения (подозреваю, что для специалистов может выглядеть смешно) или подросток, не верящий в силу интеллекта родителя и искусственных интеллектов был прав?
То что вы написали, это вовсе не смешно, а в некоторой степени даже грустно. К сожалению, это весьма распространённое сейчас заблуждение, то есть типичный современный пользователь думает так: "Это второй мозг, он даст мне экспертные ответы на мои вопросы" и т.п. Сейчас я работаю над книгой по теме продуктивного использования нейросетей, и в процессе сбора материала и интервью с пользователями, постоянно сталкиваюсь с таким крайне порочным и ошибочным мышлением. В реальности, продуктивное использование моделей сводится приблизительно к следующему: оператор-эксперт делает работу, модель помогает решать рутинные задачи, например быстро набрать материал для исследования, предложить структуру, черновик, версии... Эксперт анализирует полученную информацию и на основании своего (ключевое слово "своего") опыта и уровня, делает выводы и итоговое заключение. Если проще, то могу вам дать что-то типа "аксиомы", которую всегда стоит помнить при общении с любой моделью нейросети: "Мусор на входе=мусор на выходе". В профессиональной среде, это выражение используется несколько в другом контексте, но в этом ответе я использую его в самом широком смысле. Просто помните это и любая сессия работы с моделью будет проходить продуктивней. Конкретный ответ на Ваш вопрос: "ИИ имело бы смысл помучать в том случае, если бы у вас был технический бэкграунд для того, чтобы решить эту задачу вручную". Желаю Вам достигнуть своей цели. Лучший вариант для вас это привлечь специалиста (быстро), или самому "учить матчасть", как некоторые любят говорить (долго). По поводу того, что вы гуманитарий, можете нисколько не расстраиваться, из среды гуманитариев есть много прекрасных программистов и ИТ-инженеров. Вопрос только в желании.

SCode
26.02.2026 17:22Заинтриговали книгой. Где следить за релизом? Может черновик уже есть в доступе?

Gedeonych
26.02.2026 17:22Честно говоря даже не знаю, как ответить на ваш вопрос. Думаю к лету закончить вычитку, "вылежку" и редактуру, а вот где и в каком виде выпускать - будет зависеть от того, что будет происходить в этой стране к тому времени. Думаю, вы понимаете о чём я. Изначально планировалась "цифра" для Amazon, а вот что будет теперь....вопрос даже для меня пока открытый.

acsent1
26.02.2026 17:22К тому времени как книга выйдет она может и устареть. Слишком все быстро меняется

FSmile
26.02.2026 17:22Так человек был обманут. Введение в заблуждение от производителей LLM, но всем плевать

Gedeonych
26.02.2026 17:22Странная какая-то у вас логика. Представьте себе, что например, машинисту паровоза, дали в руки скальпель и всё необходимое самое лучшее и реально работающее медицинское оборудование, и сказали провести операцию по пересадке сердца. Как вы думаете чем такой подход закончится, и можно ли это считать обманом машиниста? LLM это всего лишь инструмент. Модель никоим образом не "эксперт" и не "специалист". Специалистом должен быть оператор модели.

Vydra77
26.02.2026 17:22Вот только самое лучшее и реально работающее медицинское оборудование крайне редко совершает ошибки, а вот LLM галлюцинирует очень часто. Тут и у "практикующего опытного хирурга" операция выйдет сомнительная. У машиниста, конечно, вообще без шансов.

Foreststander
26.02.2026 17:22Можно попробовать загрузить pdf прямо в чат или в "базу знаний" (может, придётся кусочками) и попросить 1) написать парсер pdf , распознающий ударения 2) протестировать на фактическом pdf 3) спрарсить pdf в json 4) выдать json

DaneSoul
26.02.2026 17:22Например, cash - можно использовать на русском как кэш, а не переводить как тайник или склад, поскольку в Словарь иностранных слов это слово уже включено.
Есть два слова в английском с одинаковым звучанием, но разным написанием и смыслом.
У Вас в этом абзаце и на последующем скриншоте РАЗНЫЕ слова.cash - наличные деньги, больше сленговый термин в русском языке, но достаточно распространен
cache - вот тот самый "склад" и распространённый компьютерный термин о котором шла речь.

avshkol
26.02.2026 17:22О! Ага!
Я недавно решал задачу парсинга одного из этих pdf -- Орфографического словаря -- выбирал термины для обучения microgpt (и уже начал писать статью на Хабре на эту тему -- название "Чудим по-русски: как я c нуля обучал microgpt придумывать «русские слова»").
Код для парсинга писали Qwen и DeepSeek, в т.ч. сделать список с ударениями и без ударений. Написал код в несколько заходов, однако, как протестировать на то, все ли слова корректно выбрались, пока не придумал (но мне и не нужны были абсолютно все слова, спарсил около 140 тысяч, по количеству листов и слов на листе, прикинул, что очень близко к реальному количеству). Единственное, я ограничивал все слова и сочетания слов 16 символами, а то там есть очень длинные...

avshkol
26.02.2026 17:22Кстати, если кто не знает, что такое microgpt - вот моя статья на Хабре на эту тему...

BobovorTheCommentBeast
26.02.2026 17:22Я вброшу не совсем по теме, но как из того, что понял, проблема в изначально не верном подходе.
Не имея экспертизы, вы принялись решать "что-то", "каким-то" способом, который вам первый пришел на ум. Это стандарт ная проблема начинающих и людей со стороны. И это то, от чего я пытаюсь уже с пол года отучить подконтрольного мне джуна.
Нейронка же с радостью взялась реализовывать ваши задачи.
Подход должен быть с максимальной высоты - вниз, не наоборот и не с середины. Какая проблема? Когда она считается решенной? Что я имею из ресурсов? Какие есть подходы к решению? Их плюсы минусы? Вот только где то тут начинается выбор технологий для решения.

koreychenko
26.02.2026 17:22Можно загрузить в какую-нить базу данных и работать уже с индексированным текстом. В Postgres (скорее всего в MySQL тоже) можно настроить collation таким образом, чтобы он при поиске считал буквы с ударениями и без ударений одинаковыми. Тут даже замены никакой при вставке в базу делать не нужно. Ну и с базой работать можно будет уже удобными инструментами.

oeditus
26.02.2026 17:22Не поде́литесь, как можно несколько гигантских PDF с разным (в общем случае) форматированием — загрузить в базу? Где эта база будет физически размещена?

koreychenko
26.02.2026 17:22В зависимости от того, где вам надо искать там базу и размещать. Хоть локально в докере поднять.
poppler tools помогут вам ваш pdf в текст сконвертировать быстро и эффективно. Есть как консольная команда, так и пакеты для любого языка программирования.
Понятно, что нужно будет делать препроцессинг. Но это уже не ко мне, а к вайб-кодерам.

xSVPx
26.02.2026 17:22Если это реально нужно - должно быть готовое, просто поищите.
Если готового нету - надо пилить и как-то монетизировать потом. Задача для упорного школьника вполне посильная. Яб когда был школьником смог бы.
Но, боюсь, чатботы лучше вообще не использовать на текущем этапе. Они с большим энтузиазмом изготавливают какой-то адский треш.
И да, вариант тут только один: единожды всё распарсить в свою базу и потом уже по ней искать.
Серьезный вопрос тут только один: как будете проверять, что спарсили всё верно...
Если на кону пол миллиона, может проще всё-таки пять раз поискать :)?

Anfisapi
26.02.2026 17:22Смотрите, можно было обойтись вообще без этого, объединить 5 пдф в один через конвектор, и спокойно пользоваться запрограммированым задолго до вас встроеным поиском (сайты конвекторов, бесплатны и лежат в открытом доступе). По поводу кодинга, лучше если есть тяга, его осваивать. Тем более вам, как юристу возможно придётся сталкиваться со смарт контрактами и т.д. Держитесь вообщем ❤️

DmitryOlkhovoi
26.02.2026 17:22у меня из коробки макоси ищет по контенту пдф в файле в папке. Еще и подставляет поиск из папки в открытый пдф превью. И по фоткам документов даже.
В посте изобретение уровня приложение поиска авто на парковке - блокнот

Foreststander
26.02.2026 17:22Собственно, вот. Инструменты и сконвертированный первый словарь здесь: https://disk.yandex.ru/d/et01_1yfBkBaPQ . Промпт и ответ GPT (5.2 thinking):
Ты - опытный программист на Pyton Проанализируй этот Pdf. Предложи оптимальный способ перевода в json с целью последующего поиска по словарю с корректным распознанием ударений. Получившийся скрипт должно быть возможно экспортировать и использовать в дальнейшем для других аналогичных словарей.
Думал на протяжении 10m 24s
По этому PDF видно, что это текстовый (не сканированный) орфографический словарь: извлекается “живой” Unicode-текст, а ударения нанесены диакритикой (в извлечённом тексте это, как правило,
COMBINING ACUTE ACCENTU+0301 после гласной). В предисловии прямо сказано, что словарные единицы (кроме односложных) снабжаются ударением, а две метки ударения означают два нормативных варианта произношения — это важно для модели данных и поиска. 311a22ef-beab-4358-b2cc-7a5d662…Ниже — оптимальная схема “PDF → JSON → поиск” и готовый экспортируемый Python-скрипт (плюс простой поиск), рассчитанные на повторное использование для аналогичных словарей.
Оптимальная схема конвертации в JSON под поиск с ударениями
1) Извлечение текста из PDF (с сохранением ударений)
Рекомендация: PyMuPDF (pymupdf) — на таких словарях обычно лучше сохраняет:
порядок строк,
Unicode-диакритику ударений,
скобки/пометы.
(Если словарь будет “сканом”, тогда нужен OCR, но здесь это не требуется.)
2) Нормализация “глюков” извлечения
Типовая проблема в словарных PDF: пробел внутри слова после знака ударения (пример вида
абази́ нкавместоабази́нка). Это чинится очень безопасным правилом:удалить пробел, если он стоит сразу после U+0301/U+0300 и перед буквой.
Также стоит:
привести дефисы/тире к
-,удалить soft hyphen/zero-width,
схлопнуть множественные пробелы.
3) Разбор строк на записи (entries)
Минимально практичная стратегия (устойчивая к разным словарям):
каждая строка PDF → кандидат на словарную статью,
если строка начинается с
(/,/;/:— это перенос (continuation), приклеить к предыдущей,если строка содержит несколько лемм в одной статье (“… , -а и … , -а (помета)”) — развернуть в несколько записей.
4) Модель данных JSON (под быстрый поиск)
Лучший “универсальный” формат — JSONL (одна запись на строку), потому что словарь большой.
Рекомендуемые поля записи:
lemma— лемма как в словаре (с ударениями)lemma_plain— лемма без ударений (но с сохранениемё)lemma_key— поисковый ключ (casefold + без ударений + нормализованные дефисы)lemma_key_ye— ключ сё→е(удобно для пользовательского ввода)stresses— позиции ударных гласных вlemma(индексы по строке без combining-знаков)homonym,lemma_base— для случаев типаа1,а2(поиск поадолжен находить оба)rest— хвост статьи (грамматика/пометы/пояснения)page— номер страницы (для отладки и трассировки)
5) Индекс для поиска
Поверх JSONL можно построить:
index.json:key -> [id, id, ...]
Это самый простой переносимый вариант (без БД). Если позже понадобится “поисковик уровня прод” — тогда следующий шаг: SQLite FTS5, но JSONL+index обычно достаточно.
Готовые экспортируемые скрипты
Я подготовил два файла:
Конвертер PDF → JSONL (+ опциональный индекс)
Download pdf_dict_to_jsonl.pyПростой CLI-поиск по JSONL (с индексом или без)
Download search_dict.py
Мини-README с командами:
Download README_pdf_dict_tools.mdУстановка
pip install pymupdfКонвертация
python pdf_dict_to_jsonl.py INPUT.pdf entries.jsonl --build-index index.jsonДля других словарей (если авто-детект старта не сработает):
python pdf_dict_to_jsonl.py INPUT.pdf entries.jsonl --start-page 10 --end-page 200 --build-index index.jsonПоиск
python search_dict.py entries.jsonl --index index.json "творог"python search_dict.py entries.jsonl "абажур"Почему это решение хорошо переносится на “аналогичные словари”
Отделены извлечение, нормализация, парсинг, индексация.
Все правила — эвристики “по поверхности текста”, без привязки к конкретной вёрстке (кроме авто-детекта, который легко заменить
--start-page).-
Поиск устойчив к:
вводу без ударений,
вводу с
ё/е,омографам
а1/а2,словам с двойным ударением (хранится как список позиций).

aborouhin
26.02.2026 17:22сконвертированный первый словарь здесь: https://disk.yandex.ru/d/et01_1yfBkBaPQ .
Раз:
{"lemma": "я́стреб", "lemma_plain": "ястреб", "lemma_key": "ястреб", "lemma_key_ye": "ястреб", "lemma_base": null, "homonym": null, "stresses": [0], "rest": ", -а, мн. -а́, -о́в (птица)", "id": 167250, "page": 3186} {"lemma": "-ы", "lemma_plain": "-ы", "lemma_key": "-ы", "lemma_key_ye": "-ы", "lemma_base": null, "homonym": null, "stresses": [], "rest": ", -ов (птица)", "id": 167251, "page": 3186}Два:
{"lemma": "яровизи́ровать(ся)", "lemma_plain": "яровизировать(ся)", "lemma_key": "яровизировать(ся)", "lemma_key_ye": "яровизировать(ся)", "lemma_base": null, "homonym": null, "stresses": [6], "rest": ", -рую, -рует(ся)", "id": 167176, "page": 3185}Главное, непонятно, как тестировать на наличие таких нюансов, кроме как вручную просматривая весь результат.
И для перехода к определению в PDF файле неплохо бы не только страницу сохранять, но и как минимум вертикальную позицию на ней (а лучше конкретные текстовые блоки, чтобы подсветить можно было).

amedvedev88
26.02.2026 17:22Закиньте все нужные справочники и документы в NotionLM и работайте там. Судя по запросу, это то что вам нужно.
Предварительно правда нужно пройти увлекательный квест "как получить доступ к google ai studio из России".

Newskylaw Автор
26.02.2026 17:22Спасибо за ваше участие.
Под NotionLM Вы имеете в виду https://notebooklm.google/ ?

Byker
26.02.2026 17:22А чем не устраивает поиск через Adobe Acrobat по "Shift + Ctrl + F"?.. Ну и простенький RAG можно сделать, через связку Ollama и Obsidian, например.

aborouhin
26.02.2026 17:22Классический кейс, когда RAG противопоказан на 100%. Нам нужны только точные вхождения, а не поиск по смыслу.

Newskylaw Автор
26.02.2026 17:22А чем не устраивает поиск через Adobe Acrobat по "Shift + Ctrl + F"?..
Объединил все 5 pdf-файлов в один - 7755 страниц в сумме. Поиск одного слова занимает примерно 105 секунд (запускал несколько раз - может это у меня такой тормозной ноут, конечно). И предварительно нужно еще все файлы скачать себе. Изначально хотелось сделать поиск доступным онлайн (без скачивания файлов) и быстрым.
Ну и простенький RAG можно сделать, через связку Ollama и Obsidian, например.
А вот это попробую, спасибо.

Anarchist
26.02.2026 17:22А почему бы эти словари попросту не скормить иишечке и не пользовать ее как поиск, а не пытаться изобретать велосипеды?

aborouhin
26.02.2026 17:22Потому что нужен поиск по точным вхождениям. Даже если бы словари влезли в контекст, это не гарантирует точности. А поскольку они не влезут - надо городить RAG, а это ещё более гадательная история. Для поиска точных вхождений мы делаем гибридный RAG (добавляя BM25 к векторному поиску), а в этом случае нам только BM25 и нужен, для чего никакой "иишечки" не требуется.
Ну это не говоря уж про то, что всё, что может быть сделано без нейросети, должно быть сделано без нейросети... А то привыкли гвозди микроскопом :)

aborouhin
26.02.2026 17:22Кстати, меня заинтересовала эта задачка, попробовал написать сам, упёрся в неочевидные нюансы. Проверил, как у существующих сервисов проверки на иностранные слова дела с этими граничными случаями. Резюме - всё плохо.
normaslov.ru - ложноположительные обнаружения (указывает как запрещённые) для составных слов из двух словарных ("стрелок-помощник"), для включённых в словарь префиксов, пишущихся слитно ("автохимия"), географических названий, фамилий; плюс - ловит названия компаний (из ЕГРЮЛ подтягивает?) и отдельно подсвечивает как таковые (с именами собственными то же самое бы делать);
mslov.ru - фамилии (но не всегда, видимо NER глючит), составные слова и префиксы (тут ошибочно ловит не только пишущиеся слитно, но и через дефис - "лейб-гвардия");
gosslovar.ru - только фамилии, географические названия и названия компаний, - в целом лучший результат, если сразу оговаривать, что имена собственные не ловим;
sendev.ru - вообще для моего итогового тестового текста со всеми заковыристыми кейсами выдал самый точный результат; но на промежуточных вариантах текста работал как-то рандомно - при небольшом изменении текста слова, не затронутые этим изменением, то находил, то нет.
В общем, даже те, кто не стесняется брать за это деньги, в решении задачи отнюдь не до идеала продвинулись. И да, задача прям конкретно далека от простой.
И это я только те кейсы, которые по результатам быстрого поверхностного анализа нашёл, проверил, а сколько их ещё... Как минимум товарные знаки я не проверял. Информацию о разрешённых словах (ссылка на словарь и текст вхождения в нём) никто не выводит. Функционалом выявления орфографических ошибок/опечаток или подсказки разрешённых синонимов никто не озаботился.
P.S. В контексте вайбкодинга эта попытка оказалась очень интересным примером, как SDD-фреймворки обрабатывают ситуацию "в процессе релизации изначальных планов выяснилось, что не учли некоторые концептуальные вещи" (в данном случае описанные выше нюансы стали понятны, когда вся логика загрузки и парсинга словарей и складывания словоформ в БД была уже написана). Прямо захотелось прогнать на этом примере Spec-Kit, Openspec, GSD (в своей попытке я как раз использовал его) и BMAD все по очереди и сравнить, но на такой эксперимент даже 200-баксового тарифа CC не хватит :(
aborouhin
Уже не первый раз наблюдаю, что восторг от использования ИИ возникает у пользователей на ровном месте от того, что они не в курсе возможностей, которые давно существуют без всякого ИИ.
Открыл справку Acrobat - прекрасно он ищет по нескольким файлам одновременно, решая Вашу задачу (у меня не Acrobat, а PDF-XChange, там такое тоже, само собой, есть) Единственное в Вашем случае надо посмотреть, будет ли он гласные с ударениями искать по запросу, в котором эти же гласные без ударений (если нет - самым простым решением кажется создать копии словарей для поиска, в которых простым поиском-заменой все ударения убрать).
Ну а если уж кодить своё - PDFки там с текстовым слоем, загнать всё в одну БД элементарно, искать будет как угодно гибко и быстро. Но учитывая Ваши вопросы... лучше попросите кого-то помочь. ИИ нынче замечательно умел, но навык постановки корректного ТЗ никто не отменял.
FSmile
Вы портите вайб)