TL;DR
Как обрабатывать JSON-ответы от API и инструментов — исследование показывает, что LLM лучше справляются, когда генерируют Python-код для парсинга вместо прямого ответа. Особенно для сложных задач: фильтрации и агрегации данных.
Главная находка: Даже топовые модели плохо обрабатывают структурированные данные напрямую. GPT-4o достигает максимум 77% точности. Когда вы просите модель "посмотри в этот JSON и ответь" — она путается в структуре, выбирает не те ключи, теряет данные при вложенности. Точность падает с ростом размера ответа: GPT-4o теряет 7%, Mistral-large — 91% при увеличении с 10K до 80K токенов. Позиция ответа тоже влияет: модели лучше видят последние данные (recency bias).
Суть метода: Вместо "прочитай JSON и ответь" → "напиши Python-функцию, которая распарсит JSON и вернёт ответ". Код выполняется, результат возвращается. Для усиления: добавь схему JSON в промпт (+12% точности) и дай пример структуры даже если полный ответ не влезает в контекст.
Схема метода
Исследование сравнивало два основных подхода:
ПОДХОД 1: Генерация ответа (answer generation)
Запрос → LLM читает JSON → Выдаёт ответ текстом
ПОДХОД 2: Генерация кода (code generation) ← работает лучше
Запрос → LLM пишет Python-функцию → Код выполняется → Возвращается результат
Варианты улучшения:
- Добавить схему JSON в промпт
- Дать сокращённую версию ответа, если полный не влезает
- Для сложных задач: добавить инструкции по рассуждению (CoT)
Все подходы работают в одном запросе к модели.
Пример применения
Задача: Вы скачали данные о московских квартирах из API Авито в JSON (50+ объектов, вложенная структура: район → ЖК → квартира → характеристики). Нужно найти все двушки в пределах 15 млн с балконом.
Промпт (базовый подход — работает плохо):
Вот JSON с квартирами. Найди все двушки до 15 млн с балконом, выведи адреса списком.
[JSON]
Промпт (улучшенный — генерация кода):
Вот JSON-ответ от API Авито с квартирами и схема этого JSON.
Напиши Python-функцию, которая:
1. Принимает весь JSON как словарь
2. Фильтрует квартиры: rooms == 2, price <= 15000000, has_balcony == true
3. Возвращает список адресов строкой через запятую
Требования к коду:
- Начинается с "def "
- Проверяет существование ключей перед обращением
- Сравнивает строки в lowercase
- Возвращает только результат (строка), без лишнего текста
Схема JSON:
{
"apartments": [
{
"address": "string",
"price": "number",
"rooms": "number",
"has_balcony": "boolean",
...
}
]
}
JSON:
[вставить данные]
Python-функция:
Результат:
Модель выдаст Python-код с функцией def filter_apartments(data):, которая корректно обрабатывает вложенность, проверяет условия и возвращает список адресов. Код можно запустить сразу (в локальном Python или через инструмент code execution в чате). Точность выше на 3-50% в зависимости от сложности.
Почему это работает
Слабость LLM: Модели теряются в структуре при прямой обработке JSON. Они путают похожие ключи (name, room_name, name_without_policy), берут значения из не тех объектов, сбиваются на вложенности. При длинных ответах (50K+ символов) точность падает катастрофически. Это как искать нужную строку в таблице Excel на 100 листов на глаз.
Сильная сторона LLM: Модели отлично знают структуру кода и умеют писать точные инструкции. Python для парсинга JSON — это их родная территория. Код однозначен: if item['price'] <= 15000000 не может быть понят двояко. Плюс код компактнее — функция на 20 строк вместо развёрнутого текстового ответа на 200 слов.
Как метод использует это: Вы переводите задачу из пространства "понимания структуры" в пространство "написания кода". Вместо "найди и скажи" → "напиши функцию, которая найдёт". Модель генерирует код, код выполняется — результат точный. Схема JSON работает как карта местности — модель видит типы данных, вложенность, связи. Пример структуры (даже сокращённый) показывает реальные значения — модель понимает формат ("USD 250" vs 250).
Рычаги управления:
- Длина JSON → если >50K символов, используй сокращённую версию (один пример каждого типа объекта)
- Тип задачи → для извлечения одного значения (
"What is form type?") иногда лучше прямой ответ, для фильтрации/агрегации — всегда код - Схема → добавляй всегда, если есть — даёт +12% точности
- Инструкции CoT → для агрегации (суммы, средние) добавь "Think step-by-step" перед генерацией кода
Шаблон промпта
Вот JSON-ответ от {источник} и его схема.
Напиши Python-функцию, которая:
1. Принимает весь JSON как словарь (параметр data)
2. {описание задачи: фильтрует/извлекает/считает}
3. Возвращает результат строкой
Требования к коду:
- Начинается с "def "
- Проверяет существование ключей и None-значений
- Сравнивает строки в lowercase
- Очищает числовые строки (убирает "$", пробелы) перед конвертацией
- Возвращает только результат, без лишнего текста
Схема JSON:
{схема}
JSON:
{данные}
Python-функция:
Пояснение плейсхолдеров:
{источник}— откуда данные (API Авито, экспорт из CRM, etc){описание задачи}— конкретная операция ("найди все X где Y", "посчитай среднее Z"){схема}— JSON-схема структуры (можно сгенерировать онлайн или попросить модель){данные}— сам JSON-ответ (полный или сокращённый)
🚀 Быстрый старт — вставь в чат:
Вот шаблон для обработки JSON через код. Адаптируй под мою задачу: [твоя задача].
Задавай вопросы, чтобы заполнить поля.
[вставить шаблон выше]
LLM спросит откуда JSON, что нужно извлечь, есть ли схема — потому что эти данные критичны для точного парсинга. Она возьмёт паттерн функции из шаблона и адаптирует под твою структуру данных.
Ограничения
⚠️ Тип задачи: Для простого извлечения одного значения (
"What is the price?") прямой ответ иногда точнее кода — 10 из 15 моделей показали это. Код оправдан для фильтрации и агрегации.
⚠️ Размер контекста: При JSON >80K токенов точность падает у всех моделей. Даже с кодом. Используй сокращение (один пример каждого типа объекта).
⚠️ Синтаксис кода: ~5-10% ошибок из-за несовместимого синтаксиса (неправильный тип данных, ошибка обхода). Топовые модели (GPT-4o, Claude-4-Sonnet) генерируют исполнимый код в 95%+ случаев.
⚠️ Семантическая двусмысленность: Если в JSON есть похожие ключи (
name,room_name,full_name), модель может выбрать не тот. Указывай точный путь в задаче или чисти JSON перед подачей.
Как исследовали
Команда собрала 1298 реальных вопросов-ответов по API-ответам от RapidAPI (отели, машины, авиарейсы, SEC-документы, товары). JSON были длинными — от 24K до 74K символов. Вопросы разделили на три типа: extractive (найди значение по ключу), filtering (верни все записи по условию), aggregation (посчитай сумму/среднее/минимум).
Протестировали 15 моделей (от Llama-3.1-8B до GPT-4o) с разными промптами: генерация ответа vs код, с схемой и без, с рассуждениями (CoT) и без. Измеряли точность по трём метрикам: exact match (строгое совпадение), contains (результат содержится в ответе), LLM as a judge (семантическое совпадение).
Результаты удивили: Даже GPT-4o достиг только 77% на лучшем подходе. Код побеждал ответ в 13 из 15 моделей. Схема давала +12% для кода, +7% для прямых ответов. При увеличении JSON с 10K до 80K токенов — точность падала на 7% (GPT-4o) до 91% (Mistral-large). Recency bias (позиция ответа в списке) влиял на 5-75% в зависимости от модели.
Критический инсайт: Когда упростили JSON до минимума (oracle projection — оставили только нужные поля), точность подскочила на 8-38 пунктов. Это значит, шум и сложность структуры — главный враг точности. Модели могут справиться, если дать им чистую, упрощённую версию.
Оригинал из исследования
Контекст: Исследователи использовали этот промпт для генерации кода с полной схемой и ответом.
You will be given a JSON object as data which is a response from a REST API containing information returned from the API call.
You will be given a JSON schema of the response from the REST API returned from the API call.
Your task is to extract and return information from the JSON object which follows the JSON schema and answers the user query: <<task_prefix>>
You need to write a Python function that:
- Starts the function with "def".
- Takes only the entire api response as input and doesn't have any other input.
- Identifies the structure of the input data, ensuring it checks for relevant keys and data types.
- When comparing strings, it should always convert both sides of the comparison to lowercase.
- Processes the provided data.
- Iterates through the data to extract relevant information.
- Cleans numeric strings by removing non-numeric characters before converting them to integers.
- Performs proper checks to ensure a key exists and is not None before querying its value.
- Returns only the requested data as a string and no other extra information or words.
- Do not add any extra keys or terms to the output.
Final Check:
- The function must be formatted in Python markdown for direct execution.
- No explanations, comments, or additional text should be included.
- Do not include any example usage data.
The JSON schema of the object given as data is as follows: <<json_schema>>
data = <<json_obj>>
Python Function:
Адаптации и экстраполяции
💡 Адаптация для таблиц в PDF:
Та же логика работает для извлечения данных из таблиц. Вместо JSON — HTML-таблица или Markdown-таблица из PDF.
Вот таблица из PDF-отчёта в Markdown-формате.
Напиши Python-функцию, которая:
1. Парсит таблицу (можешь использовать pandas)
2. Фильтрует строки где {условие}
3. Возвращает результат списком
Таблица:
{markdown_table}
Python-функция:
💡 Адаптация для вложенных словарей:
Если структура очень сложная (API возвращает 5 уровней вложенности), попроси модель сначала упростить, потом обработать:
Вот сложный JSON с 5 уровнями вложенности.
Шаг 1: Напиши функцию flatten_json(), которая упростит структуру до 2 уровней
Шаг 2: Напиши функцию extract_data(), которая найдёт {что нужно} в упрощённом JSON
JSON:
{данные}
🔧 Техника: Добавь debug-вывод → видишь логику
В шаблоне промпта добавь:
- Добавь print() на каждом шаге обработки для отладки
Получишь код с print(f"Найдено {len(items)} элементов") — видишь как модель рассуждает. Полезно для проверки логики.
🔧 Техника: Замени безликие переменные на говорящие → меньше ошибок
Вместо:
for item in data:
if item['key'] == value:
Попроси:
- Используй говорящие названия переменных (apartment вместо item, price вместо value)
Модель генерирует более читаемый код, меньше путается.
Ресурсы
How Good Are LLMs at Processing Tool Outputs? https://github.com/LongFuncEval/toolJSONprocessing
Kiran Kate, Yara Rizk, Poulami Ghosh, Ashu Gulati, Tathagata Chakraborti, Zidane Wright, Mayank Agarwal — IBM Research, USA; Persistent Systems; Grab
