Install
openclaw skills install @dariaakimov/ai-summary-ope-page-v2Одностраничное резюме на русском языке PDF-отчёта или документа Word (DOCX) (A4, ключевые выводы и открытые вопросы для обсуждения). Определяет сектор отчёта и выписывает факты по отраслевым правилам; иностранные отчёты пересказывает по-русски языком профессионального переводчика
openclaw skills install @dariaakimov/ai-summary-ope-page-v2Навык превращает PDF-отчёт в одну страницу A4 в фиксированном оформлении: шапка, заголовок,
короткая преамбула, ключевые выводы, открытые вопросы для обсуждения, источник. Читатель — правление крупной
российской технологической компании, выросшей из банка. Результат — PDF; HTML-копия рядом
отдаётся только по прямой просьбе. Сканы читаются встроенным OCR (pdf.py ocr, без сети).
Язык резюме — русский, независимо от языка документа: навык сделан для правления Сбера, и все проверки текста (калька, непереведённый английский, типографика) рассчитаны на русский. Если пользователь просит резюме на другом языке, до начала работы скажи, что этот навык делает только русское резюме, и спроси, подходит ли это.
Думаешь и пишешь ты — как ведущий аналитик сектора, о котором написан отчёт, и как профессиональный переводчик. Скрипты хранят прочитанное вне твоего контекста, выдают отраслевые правила, сверяют числа с текстом указанной страницы, проверяют твои цитаты при сверке фактов, верстают страницу и говорят, что исправить. Смысл утверждений сверяешь ты: скрипт проверяет только, что цитата и числа действительно есть на странице. Не пропускай шаги и не пиши «из головы».
Если скрипты не запускаются — не собирай резюме сам: скажи, что навык не работает, и приведи ошибку.
skill_exec(skill="ai-summary-one-page-ver-2", script="pdf.py", args=["open", "/путь/к/файлу.pdf"])
args — список строк; JSON — одной строкой после --json или файлом --file <путь.json>.ok: true — лишь «отработал»: смотри rejected, verdict,
errors, warnings, field_notes и подсказку next. При ok: false — error и hint.complete: false — повтори вызов.pdf.py open <путь> | ocr <job> [--pages 1-8] [--force] | pages <job> [--pages 1-8]
| render <job> --pages 3 [--dpi 110] | jobs | purge <job>
facts_rules.py list | detect <job> | set <job> --sector <id> [--secondary <id>] [--why '…'] | show <job>
facts.py add <job> --json '<JSON-массив>' | --file <путь> | skip <job> --pages 1,2 [--reason '…']
| list <job> [--relevance high,medium] [--offset N] | stats <job> | drop <job> --ids f003
summary.py schema | check <job> --json '<summary.json>' | build <job> --json '<summary.json>'
[--density compact --user-request '<слова>'] [--reset]
| factcheck <job> --json '<отчёт сверки>'
context.py consent <job> --decision allow|deny --user-request '<слова>' | add <job> --json '…' | list <job>
sber_kb.py topics | search <job> --slot q1 --scope company|country --query '…'
guide.py summary | translation | humanize | factcheck
Вне Ouroboros / ГигаАгента запускай скрипты из папки навыка с переменной PDF_SKILL_STATE_DIR:
PDF_SKILL_STATE_DIR="$HOME/pdf-skill-state" python3 {baseDir}/scripts/pdf.py open /путь/к/файлу.pdf.
pdf.py open <путь> — PDF или документ Word (.docx). DOCX скрипт сначала переводит в
PDF (source_format: "docx", сводка — converted_from_docx), дальше всё как с PDF: номера страниц
в фактах и резюме — страницы этого PDF, а не Word. Старый .doc и DOCX с паролем не принимаются —
попроси у пользователя .docx без пароля или PDF. При needs_ocr — сразу pdf.py ocr <job> до
complete: true.
doc_language — язык документа.guide.py summary — всегда; guide.py translation — если doc_language не ru.
Один раз, до чтения.facts_rules.py detect <job> отдаёт полный текст первых 5 страниц, каталог секторов
и границы между соседними секторами. Прочитай эти страницы и реши сам, о какой отрасли документ
и чьи показатели в нём главные, и закрепи: facts_rules.py set <job> --sector <id> --why '…'.
Документ про две отрасли — --secondary <id>; подходящего сектора нет или документ межотраслевой —
--sector general. Ответ set — правила извлечения фактов: оптика аналитика, пункты focus
(F1…Fn), метрики, ловушки, словарь, семь правил. Работай по ним до конца задания. Без set
facts.py add факты не примет. Правила длинные и в долгом задании уходят из внимания — перед
сбором содержания (п. 7) перечитай их: facts_rules.py show <job>.pdf.py pages <job> --pages 1-8, 9-16… Читай каждую страницу.facts.py add <job> --json '[{"page": 3, "kind": "precedent", "topic": "Расчёты в токенах",
"claim": "Впервые три банка из разных юрисдикций провели расчёт по одной сделке в общем реестре.",
"numbers": [], "quote": "the first time three banks from different jurisdictions",
"relevance": "high", "focus": ["F6"], "status": "pilot", "modality": null,
"why": "прецедент — причина, по которой материал важен"}]'
page — одно число; claim — сразу на хорошем русском (стандарт перевода); quote — дословно.kind: fact | trend | forecast | estimate | opinion | recommendation | term | mechanism
(шаг нового порядка работы) | gap (чего нет для внедрения) | precedent (первое в своём
роде) | beneficiary (что получает сторона; поле party).status — стадия инициативы: proposed | studied | announced | agreed | decided | pilot |
operating | completed | cancelled. Дата объявления — не дата запуска.modality — модальная формула источника по-русски («предлагается рассмотреть», «изучают»).focus — номера пунктов отраслевых правил.page (соседние не засчитываются; если
числа на разных страницах — два факта); с графика — "from_image": true; факт без своих чисел
на странице будет отклонён. relevance=high — то, что правление должно знать для решения.skip — только обложка, оглавление, сноски, дисклеймер.facts.py stats <job>. focus_uncovered — пункты правил без фактов;
rules_check — нет механизма, недостающего, прецедента или бенефициаров. Если в документе это
есть — вернись к страницам и сдай факты; если нет — ничего не добавляй.facts.py list <job>, отбери лучшее по канону, напиши summary.json
(summary.py schema). У каждого пункта — source_pages и fact_ids. Преамбула — одно
предложение, как можно короче (ориентир до 160 знаков, предел 200): кто, когда и о чём; скрипт
наберёт её 10 pt с интервалом 1. Сначала все выводы, потом вопросы.
7а. Контекст до вопроса. Модель не знает, что Сбер уже делает и кто работает в отрасли, и без
этого задаёт вопросы невпопад: «кредитуем ли мы компании беспилотного транспорта», когда одна из
двух таких компаний — бывшая «дочка» Сбера (Navio), а вторая — прямой конкурент (Яндекс). Поэтому
для каждого будущего вопроса (slot q1, q2, q3), до того как его писать:
company — о нашей компании; country — о стране;data/sber_knowledge_base.json), обязательно для company:
sber_kb.py search <job> --slot q1 --scope company --query '<тема вопроса>' — что Сбер уже делает,
какие компании отрасли входят в группу, какие проданы (former), что опровергнуто
(rumor_denied); запись в реестр контекста — автоматически. Тематики — sber_kb.py topics;context.py consent <job> --decision allow|deny --user-request '<его слова дословно>'. Без
allow context.py add не примет результаты; нет ответа или отказ — вопросы только по базе
знаний и документу, поиск не делай;context.py add <job> --json '{"slot": "q1", "scope": "company", "query": "…", "provider": "…", "results": [{"title", "url", "date", "snippet"}], "error": ""}';summary.json: scope, context_ids (id записей базы и поиска этого slot), known
(что уже известно и почему ответа ещё нет) и players — компании отрасли и их связь со Сбером
(own / related / competitor / neutral, с источником).
Вопрос — открытый, без «или» и без «да/нет» («Стоит ли…»), начинается с вопросительного слова,
о Сбере, на него у правления ещё нет ответа; три вопроса — о разных предметах, без общих ключевых
слов. Нельзя предлагать кредитовать или покупать нашу, связанную или конкурирующую компанию как
постороннюю. Печатается только q; в нём можно назвать актив или проект Сбера и конкурента из
базы и поиска, числа — только из документа. Подробно — канон, «Канон вопроса для обсуждения».
Поиск недоступен или не разрешён — опирайся на базу знаний и одной строкой скажи об этом
пользователю. Подвал резюме сам говорит, что учтено при вопросах: только отчёт, база знаний или
поиск в интернете.summary.py check <job> --json '<summary.json>' — канон, числа и
семь правил. Исправь errors. Естественность здесь не проверяется и не правится: для неё
будет отдельный шаг после вёрстки (п. 9в), один раз.summary.py build <job> --json '<summary.json>'.
Скрипт сам считает страницы и ведёт этапы (phase).
verdict: "shorten_required" — резюме больше одной страницы. Сократи текст по shorten.rules
(не меньше shorten.cut_chars знаков; начни с shorten.cheapest_cuts) и снова build.
Сокращай смыслом, а не телеграфным стилем, но естественность на этом этапе не проверяется и не
правится. Попыток сокращения — не больше 5.build вернёт verdict: "humanize_required".humanize: инструкцию instruction
(её же печатает guide.py humanize), признаки машинного текста, найденные скриптом (signs),
весь текст (text), памятку reader_review и предел длины max_body_chars. Прочитай text
целиком, перепиши summary.json по инструкции (числа, fact_ids, source_pages, число пунктов,
статус и модальность не меняются) и вызови build. Естественность повторно не проверяется.verdict: "factcheck_required". Ответ содержит factcheck:
инструкцию (guide.py factcheck), утверждения резюме (claims: заголовок, преамбула, тезисы,
каждое предложение выводов и обоснований вопросов) с фрагментами страниц (excerpts) и фактами
реестра. Для каждого утверждения проверь по тексту страницы: тот ли показатель, период, единица,
предмет, чья оценка, статус, модальность, нет ли обобщения или причинной связи, которых нет в
документе. Отправь отчёт summary.py factcheck <job> --json '{"claims": [...]}': для каждого id
— ok | fix | unsupported, дословная цитата со страницы (evidence), при ошибке — problem
и correction. Скрипт отклонит отчёт, если цитаты нет на странице или числа нет в цитатах.
Найденные ошибки впиши в summary.json и вызови build: исправления, вписанные дословно, уже
подтверждены; на новый раунд уходят только предложения, изменённые иначе (раундов — до 3).
Пропуск слов внутри цитаты — только многоточием; скрипт не примет цитату, из которой без
многоточия выпало отрицание, оговорка, модальность или число. Если после 3 раундов
утверждения не подтверждены, готовое резюме не выдаётся: fix_required с этими утверждениями —
удали их (или замени дословно на correction) и собери снова; новых формулировок не пиши.
Если не подтверждены только заголовок, преамбула, тезисы или вопросы (их удалить нельзя), скрипт
даст ещё до 2 раундов сверки.ready (одна страница) или ready_as_is (больше страницы после 5
сокращений). Если правка вывела помещавшийся текст за страницу — trim_required: подрежь по
shorten.rules (до 2 раз), не возвращая машинных оборотов, и снова build; изменённые при
подрезке предложения снова уйдут на сверку.verdict: "fix_required" — на любом этапе: исправь все errors канона, сверки чисел и семи правил
(«вывод 1», «вопрос 2» — с единицы) и собери снова; этап не меняется. Ошибки семи правил
исправляются текстом, а не удалением fact_ids. Ориентир длины пункта («N знаков при ориентире»)
после исчерпания сокращений и на финальной сборке становится замечанием: критерий — страница.
Шрифт не меняется; --density compact — только по прямой просьбе пользователя.warnings исправляй, если это не ломает страницу. Сборки считает сам скрипт: build.attempt из
build.max_attempts (18). Ответ с builds_exhausted: true — больше не собирай: отправь
ЧЕРНОВИК-PDF с пометкой и прямо напиши, что не сошлось. --reset начинает этапы и счёт сборок
заново (pdf.py open делает это сам).ready или ready_as_is outputs.pdf под именем file_name (только эти два
verdict; файлы с другими verdict — черновики). В сообщении —
одна-две фразы о документе, выбранный сектор, число попыток сокращения (если были), что поправила
проверка на человечность (одной фразой), сколько фактических ошибок нашла сверка и какие (коротко) и
оставшиеся warnings; при ready_as_is — число страниц. Текст резюме в чат не дублируй.Как отправлять файл. В ГигаАгенте скопируй PDF без изменений в /data/user/Deliverables/ и
отправляй копию (send_file); если скопировать нельзя — отправляй напрямую.
Хранение. Папка задания хранит копию документа, его текст, факты и найденный контекст. После
выдачи одной фразой предложи удалить их; если пользователь согласен или документ конфиденциальный —
pdf.py purge <job> (отданный PDF в папке пользователя не затрагивается).
| Ответ | Что делать |
|---|---|
Не установлена библиотека pymupdf | Зависимости ставятся после ревью: перезапусти ревью, включи навык |
Модуль распознавания недоступен | rapidocr/onnxruntime не встали — сканы не прочитать, скажи; обычные страницы работают |
| OCR: «модели кириллицы нет» | Русские сканы не читаются без пакета модели кириллицы (cyrillic_model в ответе ocr) |
Сектор документа не выбран | facts_rules.py detect <job>, затем set <job> --sector <id> |
field_notes в ответе facts.py add | Факт принят; допиши status, party или focus, как подсказано |
| Резюме: «правило статуса / модальности / прецедента…» | Перепиши текст по правилу; не убирай fact_ids ради прохождения проверки |
Факт: «нет номера страницы» / fields_renamed | Страница — поле page (одно число), текст — claim |
skip: «страницы содержат текст» | Сдай факты; если там правда нечего брать — --reason и скажи пользователю |
Задание … не найдено | Сначала pdf.py open; список — pdf.py jobs |
PDF защищён паролем | Попроси версию без пароля |
| Факт отклонён: «чисел нет в тексте страницы N» | Перепиши число как в источнике; если fix называет другую страницу — укажи её в page; с графика — "from_image": true |
| Резюме: «чисел … нет на указанных страницах» | Поправь source_pages или убери число |
shorten_required | Сократи по shorten.rules и собери снова; естественность пока не трогай |
humanize_required | Один раз перепиши summary.json по humanize.instruction и собери снова — это финальная сборка |
| «вопрос с выбором «или»» / «вопрос «да или нет»» / «вопрос не открытый» | Переформулируй: «Как…», «Какие…», «Где…», «Сколько…», «На каких условиях…» — без вариантов на выбор |
| «вопросы повторяют друг друга» / «одна и та же опора» | Разведи вопросы по разным выводам и сторонам дела: деньги и риск, клиенты, технологии, рынок и страна |
| «вопрос написан без контекста» / «нет known» / «вопрос о компании без базы знаний» | sber_kb.py search, затем до 2 запросов в интернет; впиши scope, context_ids, known, players |
context.py: «запрос не о нашей стороне» | В запросе «Сбер»/«Сбербанк» или «Россия»/«РФ»/«российский» |
context.py: «Поиск в интернете не разрешён пользователем» | Спроси пользователя (п. 7а) и запиши ответ context.py consent; без согласия — только база знаний |
context.py: «Запрос раскрывает документ» | Убери числа, название и издателя документа; оставь тему отрасли и «Сбер»/«Россия» |
context.py: «лимит» | Пиши вопрос по уже найденному (context.py list --slot q1) |
factcheck_required | Сверь каждое утверждение из factcheck.claims с excerpts, отправь отчёт summary.py factcheck, впиши исправления и собери снова |
Отчёт сверки accepted: false | Цитаты — дословно со страницы, на языке документа; вердикт для каждого id; числа — в цитатах |
| «сверка нашла ошибку, а предложение не исправлено» | Замени предложение на correction из отчёта |
| «после N раундов сверки утверждение не подтверждено» | Обычное предложение — удали (или замени дословно на correction) и собери снова. Заголовок, преамбулу, тезис и вопрос удалить нельзя: для них есть ещё 2 раунда сверки — замени строку дословно на correction или на уже подтверждённое предложение |
DOCX после разбора слишком велик | Попроси PDF-версию документа |
trim_required | Редактура вывела текст за страницу: подрежь по shorten.rules и собери снова |
ready_as_is | Отдай PDF как есть, скажи пользователю число страниц |
| Преамбула «из N предложений» | Одно предложение: кто, когда и о чём |
context.py consent (без него
context.py add отказывает). Запросы общие: скрипт отклоняет запросы с числами (кроме года), с
названием, автором или издателем документа и длиннее 90 знаков. Риск остаётся: тема запроса
видна поисковику, поэтому для конфиденциальных документов навык советует поиск не делать.
Результаты поиска хранятся в context.json задания для проверки. В текст резюме из поиска ничего не
переносится; подвал резюме честно говорит, что учтено при вопросах (только отчёт, база знаний о
Сбере, поиск в интернете). База знаний — локальный файл data/sber_knowledge_base.json, только чтение.env). Читаются только OUROBOROS_SKILL_STATE_DIR, OUROBOROS_SKILL_NAME и (вне
Ouroboros) PDF_SKILL_STATE_DIR — путь к папке состояния; без неё скрипты завершаются с ошибкой.
Ключи и секреты не читаются (env_from_settings пуст). Устанавливается одна переменная —
ORT_DISABLE_TELEMETRY=1 до импорта onnxruntime (иначе он пишет и отправляет телеметрию).eval/exec и загрузки кода; все модули — в scripts/.
Необязательные импорты — только onnxruntime/rapidocr (из dependencies) и пакет модели
кириллицы pdf_rezume_ocr_cyrillic.fs). Вне папок навыка читается только PDF или DOCX по пути пользователя — после
проверки (обычный файл, ≤ 300 МБ, %PDF или ZIP с word/document.xml, без пароля) он копируется в
jobs/<job>/, оригинал не меняется. Запись — только в jobs/<job>/ папки состояния (<job>
проверяется regex и resolve()); в папку навыка ничего не пишется (sys.dont_write_bytecode), из
неё читаются только references/*.md, assets/summary_template.html и
data/sber_knowledge_base.json. --file — только .json/.txt ≤ 5 МБ из папки состояния или
рабочих папок задачи (/data/task_drives, /data/uploads, /data/user/Deliverables).zipfile и xml.etree с ограничениями: распаковка ≤ 600 МБ и
≤ 20 000 частей; диаграмм ≤ 200, рядов в диаграмме ≤ 40, точек в ряду ≤ 500 (индексы точек из файла
проверяются, недопустимые отбрасываются); объединение ячеек ≤ 63; промежуточный HTML ≤ 40 млн
знаков; PDF ≤ 3000 страниц. Макросы, внешние ссылки и встроенные объекты не исполняются и не
открываются. PDF из DOCX собирает PyMuPDF (scripts/_docx.py).from_image) и смысловые выводы модели скрипт подтвердить не может — резюме для правления
перед рассылкой должен прочитать человек.pdf.py purge <job> удаляет её целиком.pymupdf ≥ 1.24.2, rapidocr (модели PP-OCRv6 внутри пакета, ничего не скачивается),
onnxruntime. Модель кириллицы берётся только из пакета pdf_rezume_ocr_cyrillic или
<папка состояния>/models/ и только со встроенным словарём. Шрифты — встроенные в PyMuPDF.[a-zа-я], \bслово), в названиях компаний (ЮMoney, ЮKassa) и в именах
файлов (…_ЧЕРНОВИК.pdf). Невидимых символов, управляющих направлением текста, и символов-двойников
в коде нет: особые пробелы и дефисы записаны escape-последовательностями (\u00a0, \u2011).SKILL.md; scripts/ — pdf.py, facts_rules.py (отраслевые правила), facts.py, summary.py, guide.py,
context.py (реестр контекста для вопросов), sber_kb.py (база знаний о Сбере, данные — data/sber_knowledge_base.json),
модули _core.py, _ocr.py, _natural.py (естественность и ясность), _factcheck.py (сверка утверждений с документом), _docx.py (перевод DOCX в PDF); references/summary_canon.md,
references/translation_guide.md, references/humanize_guide.md (проверка на человечность), references/factcheck_guide.md (сверка фактов; печатаются через guide.py); assets/summary_template.html; data/sber_knowledge_base.json.