mirror of
https://github.com/trustgraph-ai/trustgraph.git
synced 2026-07-10 13:52:11 +02:00
114 lines
No EOL
11 KiB
Markdown
114 lines
No EOL
11 KiB
Markdown
# Спецификация технической реализации 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`) |