Обновить

Эволюция личных ИИ‑агентов: от суммаризации до автономной организации

Уровень сложностиПростой
Время на прочтение10 мин
Охват и читатели7.4K
Всего голосов 3: ↑2 и ↓1+4
Комментарии6

Комментарии 6

Приветствую на Хабре! Расскажите по возможности в следующей статье как реализовывали агентов, с какими сложностями столкнулись. Было бы интересно почитать.

Приветствую! В принципе основной подход, который я для себя выработал, я обозначил: выстраивание пайплайна агентов ничем не отличается от выстраивания процесса с людьми. Разбиваете процесс на шаги, каждый из который максимально детерминирован и завершается четким и понятным артефактом. Когда строите процесс с людьми, бывает, что человек обладает несколькими квалификациями, и вы ему поручаете несколько последовательных шагов. С агентами лучше этого не делать. Чем "атомарнее" агент, тем проще определить для него инструменты (скиллы, MCP), встроить guardrails, определить формат выходного артефакта. Например, на этапе реализации кода на основе качественной спецификации, я пришел к тому, чтобы разделить процесс на трех агентов: непосредственно разработчик (в которого встроены требования и к стеку, и к критериям качества, и набор обязательных и неизменяемых процедур, которые агент обязан использовать в шаблоне программного кода), агент-ревьювер кода (задача которого выявить лишние расчеты, от которых можно отказаться без влияния на результаты алгоритмов), и агент-тестировщик, который проверяет повторно код после итерации "разработка - ревью - доработка предложений". А сама реализация агентов в opencode, в отличие от визуальных фреймворков типа n8n, делается просто промптом: описываешь словами структуру пайплайана, последовательность агентов, ответственность и требования к каждому. Потом можно проверить их md-файлы для контроля, можно попросить вывести последовательность вызовов в конкретном проекте opencode.

Добрый вечер! "навык распознавания PDF с кириллицей и таблицами;" поясните технические детали

Когда первый раз подсунул PDF и попросил распознать, агент реально в несколько итераций пытался, выдавая кривые символы. Я несколько раз указывал на ошибки и заставлял переделать. А когда ему удалось (он нашел в интернете подходящие библиотеки), я тут же попросил оформить это в виде навыка. Сейчас у меня в корне агента opencode (доступный навык для всех проектов) навык pdf-reader:

name: pdf-reader description: Extracts Russian/Cyrillic text from PDF files, handles encoding issues (cp1251, raw_unicode_escape), and processes tabular data. Use when working with medical PDFs, scanned documents, or any PDF with Cyrillic text that needs machine-readable conversion.

PDF Reader for Cyrillic and Tables

Extracts machine-readable text from PDF files that contain Russian text, tables, and mixed formatting. This skill handles the quirks of pdfminer in older Python environments (3.5.x) where f-strings are not available.

Environment Notes

  • Python: 3.5.4 (no f-strings — use .format())

  • PDF library: pdfminer (via from pdfminer.high_level import extract_text)

  • Environment path: Use C:/.../.venv/Scripts/python.exe explicitly

  • yfinance stub: Not related to PDF reading

Quick Start

from pdfminer.high_level import extract_text
text = extract_text('path/to/file.pdf')
for line in text.split('\n'):
    s = line.strip()
    if s:
        print(s)

Instructions

1. Basic extraction

For simple PDFs with embedded text:

from pdfminer.high_level import extract_text
text = extract_text('file.pdf')
for line in text.split('\n'):
    s = line.strip()
    if s:
        print(s)

2. Handle Cyrillic (cp1251) encoding

Most Russian medical PDFs encode text as cp1251. The raw text comes out as mojibake. Fix it:

from pdfminer.high_level import extract_text

text = extract_text('file.pdf')
decoded = text.encode('latin1', errors='replace').decode('cp1251', errors='replace')
for line in decoded.split('\n'):
    s = line.strip()
    if len(s) > 5:
        print(s)

If that fails, try the raw_unicode_escape approach:

from pdfminer.high_level import extract_text

text = extract_text('file.pdf')
try:
    decoded = text.encode('raw_unicode_escape').decode('cp1251', errors='replace')
except:
    # fallback to direct output
    decoded = text
for line in decoded.split('\n'):
    s = line.strip()
    if s:
        print(s)

3. Detect image-based (scanned) PDFs

If text extraction yields mostly garbage or very few readable strings, the PDF may be image-based (scanned document). Use the Read tool to view it directly:

  • Call read(file_path) — the tool returns base64-encoded PDF data

  • If text is not extractable, ask the user to provide values manually

Signs of a scanned PDF:

  • Very few text fragments extracted

  • Extracted text is mostly header/footer garbage

  • PDF size is large (150K+ for a single page)

4. Extract tables

For tabular data, extract line by line and reconstruct the table structure manually. Columns are usually separated by multiple spaces or pipe characters:

from pdfminer.high_level import extract_text

text = extract_text('file.pdf')
decoded = text.encode('raw_unicode_escape').decode('cp1251', errors='replace')

for line in decoded.split('\n'):
    s = line.strip()
    if '|' in s:
        # table row
        cells = [c.strip() for c in s.split('|')]
        print(cells)
    elif s and not s.startswith('-'):
        # label row
        print(s)

5. Handle mixed success/failure

If extract_text succeeds but the output is still garbled:

# Try multiple encodings
for enc in ['cp1251', 'cp866', 'koi8_r']:
    try:
        decoded = text.encode('latin1').decode(enc)
        print('Worked with: ' + enc)
        break
    except:
        continue

Known Issues

  1. pdfminer on Python 3.5: Works but emits deprecation warnings — suppress with 2>/dev/null

  2. No f-strings in Python 3.5 — use '{}'.format(var) style

  3. Large PDF paths with spaces: Quote them in bash commands

Example Workflow

1. Read PDF with pdfminer -> raw text with mojibake
2. Decode with latin1 -> cp1251 -> readable Cyrillic
3. If still garbled -> try raw_unicode_escape path
4. If minimal text extracted -> PDF is scanned -> use Read tool or ask user
5. Reconstruct tables manually from line-by-line output

Requirements

pip install pdfminer.six

Спасибо за подробную информацию. Из текста следует, что Вы работаете с markdown: "я же выбрал доступный open‑source навык LLMWiki на простых markdown‑файлах ". Рdfminer вроде напрямую markdown не выдает?

LLMWiki в другом проекте, где нет чтения PDF файлов, только сохранение выдачи питоновских ноутбуков в PDF, и выкладывание их на Google Drive.

А в том проекте, где используется распознавание PDF, оформлен вот такой markdown SKILL.md в папке workflow проекта:

name: medcarta-workflow description: Workflow для проекта medcarta — медицинская карта с анализом PDF. Использовать при добавлении нового анализа/исследования в resume.md. Запоминает последовательность: извлечь данные -> добавить в файл -> обновить динамику -> обновить общую клиническую картину и рекомендации.

MedCarta Workflow

Проект: C:\Users\Mikl\medcarta
Файл: resume.md
Окружение: Python 3.5.4 (C:/.../.venv/Scripts/python.exe)
Библиотека: pdfminer (pip install pdfminer)
Кодировка: raw_unicode_escape → cp1251 для кириллицы

Принцип работы с PDF

  1. PDF-файлы находятся в C:\Users\...\medcarta\

  2. Файлы могут быть в форматах .pdf — как текстовые, так и отсканированные (изображения)

  3. Для текстовых PDF: извлечение через pdfminer с декодированием

  4. Для image-based PDF: сообщить пользователю, что данные не извлекаются, и попросить внести их вручную

План действий (обязательный порядок)

При поступлении запроса «добавь новый анализ» или при появлении нового файла PDF:

Шаг 1: Анализ PDF и извлечение данных

  • Прочитать PDF-файл

  • Если не удаётся извлечь текст (image-based PDF) — попросить пользователя ввести данные вручную

  • Извлечённые данные оформить в структурированном виде (таблицы, показатели, нормы)

Шаг 2: Добавление в resume.md

  • Определить, в какой раздел относится исследование (УЗИ, кровь и т.д.)

  • Вставить новый подраздел ## ГГГГ.ММ с данными в правильное хронологическое место

  • Оформить в markdown-таблицы, указать нормы и статус

Шаг 3: Обновление раздела “Динамика”

  • Обновить или создать подраздел ## Динамика (X → Y) после самого позднего анализа по дате

  • Сравнить последний и предпоследний анализы в этом разделе

  • Указать изменения по каждому параметру

...

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации