trustgraph/docs/tech-specs/jsonl-prompt-output.ru.md

114 lines
11 KiB
Markdown
Raw Normal View History

# Спецификация технической реализации JSONL для выходных данных запросов
## Обзор
Эта спецификация описывает реализацию формата выходных данных JSONL (JSON Lines) для ответов на запросы в TrustGraph. JSONL позволяет надежно извлекать структурированные данные из ответов LLM, решая критические проблемы, связанные с повреждением выходных JSON-массивов при достижении LLM лимитов токенов.
Эта реализация поддерживает следующие сценарии использования:
1. **Надежное извлечение при обрезании**: Извлечение действительных частичных результатов даже при обрезании ответа LLM в середине запроса
2. **Масштабируемое извлечение**: Обработка извлечения множества элементов без риска полного сбоя из-за ограничений токенов
3. **Извлечение нескольких типов**: Поддержка извлечения нескольких типов сущностей (определения, взаимосвязи, сущности, атрибуты) в одном запросе
4. **Вывод, совместимый со стримингом**: Обеспечение возможности последующего стриминга/инкрементной обработки результатов извлечения
## Цели
- **Совместимость с предыдущими версиями**: Существующие запросы, использующие `response-type: "text"` и `response-type: "json"`, продолжают работать без изменений
- **Надежное извлечение при обрезании**: Частичные ответы LLM дают частичные валидные результаты вместо полного сбоя
- **Валидация схемы**: Поддержка валидации JSON Schema для отдельных объектов
- **Гибкость**: Поддержка различных сценариев извлечения, включая извлечение нескольких типов сущностей и использование стриминга
## Реализация
* **Обработка JSONL**: Метод `parse_jsonl` парсит входные данные JSONL построчно, обрабатывая ошибки при обнаружении невалидного JSON. Он возвращает список словарей, где каждый словарь представляет собой успешно обработанный объект.
* **Обработка JSON**: Метод `parse_json` парсит входные данные JSON, используя стандартную библиотеку `json`. Он возвращает объект Python, соответствующий структуре JSON.
* **Валидация схемы**: Функция `validate` проверяет, соответствует ли объект заданным требованиям JSON Schema.
* **Формат вывода**: Метод `PromptManager.invoke` возвращает список словарей Python, где каждый словарь представляет собой успешно обработанный объект.
* **Обработка ошибок**:
* Если входные данные JSONL не валидны или результат обрезания, метод возвращает пустой список (`[]`).
* Если при валидации схемы произошла ошибка, метод возвращает пустой список (`[]`) и выводит предупреждающие сообщения в лог.
* Если произошла ошибка парсинга JSON, метод выводит ошибку и выбрасывает исключение.
* **Совместимость**:
* Клиентский код, ожидающий список в качестве результата извлечения, не требует изменений при переходе на JSONL.
* Формат вывода для `response-type: "json"` (массив) и `response-type: "jsonl"` (список) одинаковый: Python `list`
* **API изменения**:
* **Клиентская перспектива**: Разбор JSONL выполняется на стороне сервера в сервисе запросов, и результат возвращается через стандартное поле `PromptResponse.object` в виде сериализованного JSON-массива.
* **Формат возвращаемого значения**: Для `response-type: "jsonl"`, метод `PromptManager.invoke()` возвращает `list[dict]`, содержащий все успешно обработанные объекты. Этот список сериализуется в JSON для поля `PromptResponse.object`.
* **Обработка ошибок**:
* Пустой результат: возвращает пустой список `[]` с сообщением в логе
* Частичная ошибка парсинга: возвращает список успешно обработанных объектов с сообщениями об ошибках
* Полная ошибка парсинга: возвращает пустой список `[]` с сообщениями об ошибках
* **Пример конфигурации**:
```json
{
"prompt": "Извлеките все сущности и их определения из следующего текста. Выведите один JSON объект на строку.\n\nТекст:\n{{text}}\n\nФормат вывода на строку:\n{\"entity\": \"<name>\", \"definition\": \"<definition>\"}",
"response-type": "jsonl",
"schema": {
"type": "object",
"properties": {
"entity": {
"type": "string",
"description": "Имя сущности"
},
"definition": {
"type": "string",
"description": "Четкое определение сущности"
}
},
"required": ["entity", "definition"]
}
}
```
* **Изменения в запросах**:
| ID запроса | Описание | Поле типа |
|---|---|---|
| `extract-definitions` | Извлечение всех сущностей и их определений из следующего текста. Выведите один JSON объект на строку. | Нет (один тип) |
| `extract-relationships` | Извлечение взаимосвязей | Нет (один тип) |
| `extract-topics` | Извлечение темы и определений | Нет (один тип) |
| `extract-rows` | Извлечение структурированных строк | Нет (один тип) |
| `agent-kg-extract` | Совместное извлечение определения и взаимосвязи | Да: `"definition"`, `"relationship"` |
| `extract-with-ontologies` / `ontology-extract` | Извлечение на основе онтологий | Да: `"entity"`, `"relationship"`, `"attribute"` |
## Безопасность
* **Валидация входных данных**: Используется стандартная библиотека `json.loads()` для парсинга, что безопасно от возможных атак внедрением.
* **Валидация схемы**: Используется `jsonschema.validate()` для проверки соответствия схемы.
* **Отсутствие новых уязвимостей**: Разбор JSONL безопаснее, чем разбор JSON-массивов, из-за построчной обработки.
## Производительность
* **Память**: Построчный разбор требует меньше памяти, чем загрузка всего JSON-массива.
* **Задержка**: Производительность парсинга сопоставима с разбором JSON-массивов.
* **Валидация**: Валидация объекта происходит для каждого объекта, что может привести к накладным расходам, но обеспечивает частичную валидацию при ошибках.
## Стратегия тестирования
* **Юнит-тесты**:
* Разбор JSONL с валидными данными
* Разбор JSONL с пустыми строками
* Разбор JSONL с маркерами markdown
* Разбор JSONL с обрезаными последними строками
* Разбор JSONL с невалидным JSON
* Валидация схемы с использованием `oneOf`
* Совместимость: существующие запросы `"text"` и `"json"` не изменяются
* **Интеграционные тесты**:
* Извлечение с JSONL-запросами
* Симулированное обрезание ответа LLM (искусственно ограниченный ответ)
* Извлечение нескольких типов сущностей с использованием поля типа
* Извлечение на основе онтологий
* **Тесты качества извлечения**:
* Сравнение результатов извлечения: JSONL vs JSON
* Проверка на надежное извлечение при обрезании: JSONL дает частичные результаты, где JSON не работает
## Вопросы
В настоящее время вопросов нет.
## Ссылки
* Реализация: `trustgraph-flow/trustgraph/template/prompt_manager.py`
* Спецификация JSON Lines: https://jsonlines.org/
* Спецификация JSON Schema `oneOf`: https://json-schema.org/understanding-json-schema/reference/combining.html#oneof
* Связанная спецификация: Streaming LLM Responses (`docs/tech-specs/streaming-llm-responses.md`)