trustgraph/docs/tech-specs/extraction-time-provenance.ru.md
Alex Jenkins 8954fa3ad7 Feat: TrustGraph i18n & Documentation Translation Updates (#781)
Native CLI i18n: The TrustGraph CLI has built-in translation support
that dynamically loads language strings. You can test and use
different languages by simply passing the --lang flag (e.g., --lang
es for Spanish, --lang ru for Russian) or by configuring your
environment's LANG variable.

Automated Docs Translations: This PR introduces autonomously
translated Markdown documentation into several target languages,
including Spanish, Swahili, Portuguese, Turkish, Hindi, Hebrew,
Arabic, Simplified Chinese, and Russian.
2026-04-14 12:08:32 +01:00

770 lines
57 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
layout: default
title: "Происхождение данных во время извлечения: Исходный слой"
parent: "Russian (Beta)"
---
# Происхождение данных во время извлечения: Исходный слой
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
## Обзор
Этот документ содержит заметки о происхождении данных во время извлечения для будущих работ по спецификации. Происхождение данных во время извлечения фиксирует "исходный слой" - откуда данные были получены изначально, как они были извлечены и преобразованы.
Это отличается от происхождения данных во время запроса (см. `query-time-provenance.md`), которое фиксирует логику работы агента.
## Описание проблемы
### Текущая реализация
В настоящее время происхождение данных работает следующим образом:
Метаданные документа хранятся в виде RDF-триплетов в графе знаний.
Идентификатор документа связывает метаданные с документом, поэтому документ отображается как узел в графе.
Когда связи (отношения/факты) извлекаются из документов, связь `subjectOf` связывает извлеченную связь с исходным документом.
### Проблемы текущего подхода
1. **Повторная загрузка метаданных:** Метаданные документа группируются и загружаются повторно при каждой партии триплетов, извлеченных из этого документа. Это неэффективно и избыточно - одни и те же метаданные передаются как "груз" с каждым результатом извлечения.
2. **Поверхностное происхождение данных:** Текущая связь `subjectOf` связывает факты только с верхним уровнем документа. Нет информации о цепочке преобразований - с какой страницы был получен факт, из какого фрагмента, какой метод извлечения был использован.
### Желаемое состояние
1. **Загрузка метаданных один раз:** Метаданные документа должны быть загружены один раз и привязаны к узлу верхнего уровня документа, а не повторяться с каждой партией триплетов.
<<<<<<< HEAD
2. **Разветвленная структура данных о происхождении:** Захватите полную цепочку преобразований от исходного документа через все промежуточные артефакты до извлеченных фактов. Например, преобразование PDF-документа:
=======
2. **Разветвленная структура происхождения данных:** Захватите полную цепочку преобразований от исходного документа через все промежуточные артефакты до извлеченных фактов. Например, преобразование PDF-документа:
>>>>>>> 82edf2d (New md files from RunPod)
```
PDF file (source document with metadata)
→ Page 1 (decoded text)
→ Chunk 1
→ Extracted edge/fact (via subjectOf)
→ Extracted edge/fact
→ Chunk 2
→ Extracted edge/fact
→ Page 2
→ Chunk 3
→ ...
```
<<<<<<< HEAD
3. **Унифицированное хранилище:** Граф происхождения хранится в той же базе знаний, что и извлеченные знания. Это позволяет запрашивать происхождение так же, как и знания, прослеживая связи обратно по цепочке от любого факта к его точному источнику.
=======
3. **Унифицированное хранилище:** Граф происхождения хранится в той же базе знаний, что и извлеченные знания. Это позволяет запрашивать происхождение так же, как и знания, прослеживая связи вверх по цепочке от любого факта к его точному источнику.
>>>>>>> 82edf2d (New md files from RunPod)
4. **Стабильные идентификаторы:** Каждый промежуточный артефакт (страница, фрагмент) имеет стабильный идентификатор в виде узла в графе.
5. **Связь родитель-потомок:** Производные документы связаны с их родительскими документами до самого верхнего уровня, используя согласованные типы отношений.
6. **Точное определение источника факта:** Отношение `subjectOf` на извлеченных связях указывает на непосредственный родительский элемент (фрагмент), а не на верхний документ. Полное происхождение восстанавливается путем прохода по графу.
## Случаи использования
### UC1: Определение источника в ответах GraphRAG
**Сценарий:** Пользователь выполняет запрос GraphRAG и получает ответ от агента.
**Процесс:**
1. Пользователь отправляет запрос агенту GraphRAG.
2. Агент извлекает соответствующие факты из базы знаний для формирования ответа.
<<<<<<< HEAD
3. В соответствии со спецификацией происхождения во время запроса, агент сообщает, какие факты внесли вклад в ответ.
=======
3. В соответствии со спецификацией происхождения для запросов, агент сообщает, какие факты послужили основой для ответа.
>>>>>>> 82edf2d (New md files from RunPod)
4. Каждый факт связан с его исходным фрагментом через граф происхождения.
5. Фрагменты связаны со страницами, страницы связаны с исходными документами.
**Результат для пользователя:** Интерфейс отображает ответ LLM вместе с указанием источника. Пользователь может:
<<<<<<< HEAD
Увидеть, какие факты подтверждают ответ.
Переходить от фактов к фрагментам, страницам и документам.
Просматривать исходные документы для проверки утверждений.
Понимать, откуда в документе (на какой странице, в каком разделе) произошел факт.
=======
Увидеть, какие факты послужили основой для ответа.
Переходить от фактов к фрагментам, страницам и документам.
Просматривать исходные документы для проверки утверждений.
Понимать, откуда в документе (на какой странице, в каком разделе) произошел тот или иной факт.
>>>>>>> 82edf2d (New md files from RunPod)
**Преимущество:** Пользователи могут проверять ответы, сгенерированные ИИ, по сравнению с первичными источниками, что повышает доверие и позволяет проводить проверку фактов.
### UC2: Отладка качества извлечения
<<<<<<< HEAD
Факт кажется неверным. Проследите обратно через фрагмент, страницу и документ, чтобы увидеть исходный текст. Это была ошибка извлечения, или исходный документ был неверным?
### UC3: Инкрементное повторное извлечение
Исходный документ обновлен. Какие фрагменты/факты были получены из него? Отмените и перезапустите только эти, а не перерабатывайте все.
### UC4: Удаление данных / Право на забвение
Исходный документ должен быть удален (GDPR, юридические требования и т.д.). Найдите и удалите все производные факты, пройдя по графу.
### UC5: Разрешение конфликтов
Два факта противоречат друг другу. Проследите оба обратно к их источникам, чтобы понять, почему, и решить, кому доверять (более авторитетному источнику, более свежему и т.д.).
=======
Факт кажется неверным. Проследите по цепочке от фрагмента к странице и документу, чтобы увидеть исходный текст. Была ли это ошибка извлечения, или исходный текст был неверным?
### UC3: Инкрементное повторное извлечение
Исходный документ был обновлен. Какие фрагменты/факты были получены из него? Отмените и перегенерируйте только эти, а не перерабатывайте все.
### UC4: Удаление данных / Право на забвение
Исходный документ должен быть удален (GDPR, юридические требования и т.д.). Пройдите по графу, чтобы найти и удалить все производные факты.
### UC5: Разрешение конфликтов
Два факта противоречат друг другу. Проследите оба факта до их источников, чтобы понять причину и решить, кому доверять (более авторитетному источнику, более свежему и т.д.).
>>>>>>> 82edf2d (New md files from RunPod)
### UC6: Взвешивание авторитетности источника
Некоторые источники более авторитетны, чем другие. Факты могут быть взвешены или отфильтрованы на основе авторитетности/качества исходных документов.
### UC7: Сравнение конвейеров извлечения
Сравните результаты, полученные с использованием различных методов/версий извлечения. Какой экстрактор выдал лучшие факты из одного и того же источника?
## Точки интеграции
### Библиотекарь
Компонент "библиотекарь" уже предоставляет хранение документов с уникальными идентификаторами документов. Система отслеживания происхождения интегрируется с существующей инфраструктурой.
#### Существующие возможности (уже реализовано)
**Связывание документов "родитель-потомок":**
Поле `parent_id` в `DocumentMetadata` - связывает дочерний документ с родительским документом.
<<<<<<< HEAD
Поле `document_type` - значения: `"source"` (оригинальный) или `"extracted"` (производный).
=======
Поле `document_type` - значения: `"source"` (исходный) или `"extracted"` (производный).
>>>>>>> 82edf2d (New md files from RunPod)
API `add-child-document` - создает дочерний документ с автоматическим `document_type = "extracted"`.
API `list-children` - извлекает все дочерние документы родительского документа.
Каскадное удаление - удаление родительского документа автоматически удаляет все дочерние документы.
**Идентификация документов:**
Идентификаторы документов задаются клиентом (не генерируются автоматически).
Документы индексируются по составному ключу `(user, document_id)` в Cassandra.
Объектные идентификаторы (UUID) генерируются внутренне для хранения двоичных данных.
**Поддержка метаданных:**
Поле `metadata: list[Triple]` - тройки RDF для структурированных метаданных.
`title`, `comments`, `tags` - основные метаданные документа.
`time` - метка времени, `kind` - MIME-тип.
**Архитектура хранения:**
Метаданные хранятся в Cassandra (пространство ключей `librarian`, таблица `document`).
Содержимое хранится в хранилище двоичных данных MinIO/S3 (контейнер `library`).
Интеллектуальная доставка контента: документы размером менее 2 МБ встраиваются, более крупные документы передаются потоком.
#### Основные файлы
`trustgraph-flow/trustgraph/librarian/librarian.py` - Основные операции "библиотекаря".
`trustgraph-flow/trustgraph/librarian/service.py` - Сервисный процессор, загрузка документов.
`trustgraph-flow/trustgraph/tables/library.py` - Хранилище таблиц Cassandra.
`trustgraph-base/trustgraph/schema/services/library.py` - Определения схемы.
<<<<<<< HEAD
#### Необходимые улучшения
=======
#### Проблемы, требующие решения
>>>>>>> 82edf2d (New md files from RunPod)
"Библиотекарь" имеет необходимые компоненты, но в настоящее время:
1. Связывание "родитель-потомок" ограничено одним уровнем - отсутствуют вспомогательные функции для обхода многоуровневых графов.
2. Отсутствует стандартная терминология для типов отношений (например, `derivedFrom`, `extractedFrom`).
<<<<<<< HEAD
3. Метаданные происхождения (метод извлечения, уверенность, позиция фрагмента) не стандартизированы.
=======
3. Метаданные происхождения (метод извлечения, достоверность, позиция фрагмента) не стандартизированы.
>>>>>>> 82edf2d (New md files from RunPod)
4. Отсутствует API запросов для прослеживания полной цепочки происхождения от факта до исходного источника.
## Проектирование сквозного потока
Каждый процессор в конвейере следует последовательной схеме:
Получает идентификатор документа от предыдущего этапа.
Извлекает содержимое из "библиотекаря".
Создает дочерние артефакты.
Для каждого дочернего элемента: сохраняет в "библиотекаре", создает связь в графе и передает идентификатор на следующий этап.
### Потоки обработки
Существуют два потока в зависимости от типа документа:
#### Поток обработки документов PDF
```
┌─────────────────────────────────────────────────────────────────────────┐
│ Librarian (initiate processing) │
│ 1. Emit root document metadata to knowledge graph (once) │
│ 2. Send root document ID to PDF extractor │
└─────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────┐
│ PDF Extractor (per page) │
│ 1. Fetch PDF content from librarian using document ID │
│ 2. Extract pages as text │
│ 3. For each page: │
│ a. Save page as child document in librarian (parent = root doc) │
│ b. Emit parent-child edge to knowledge graph │
│ c. Send page document ID to chunker │
└─────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────┐
│ Chunker (per chunk) │
│ 1. Fetch page content from librarian using document ID │
│ 2. Split text into chunks │
│ 3. For each chunk: │
│ a. Save chunk as child document in librarian (parent = page) │
│ b. Emit parent-child edge to knowledge graph │
│ c. Send chunk document ID + chunk content to next processor │
└─────────────────────────────────────────────────────────────────────────┘
─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
Post-chunker optimization: messages carry both
chunk ID (for provenance) and content (to avoid
librarian round-trip). Chunks are small (2-4KB).
─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
┌─────────────────────────────────────────────────────────────────────────┐
│ Knowledge Extractor (per chunk) │
│ 1. Receive chunk ID + content directly (no librarian fetch needed) │
│ 2. Extract facts/triples and embeddings from chunk content │
│ 3. For each triple: │
│ a. Emit triple to knowledge graph │
│ b. Emit reified edge linking triple → chunk ID (edge pointing │
│ to edge - first use of reification support) │
│ 4. For each embedding: │
│ a. Emit embedding with its entity ID │
│ b. Link entity ID → chunk ID in knowledge graph │
└─────────────────────────────────────────────────────────────────────────┘
```
#### Поток текстовых документов
Текстовые документы пропускают этап извлечения из PDF и сразу поступают в компоновщик:
```
┌─────────────────────────────────────────────────────────────────────────┐
│ Librarian (initiate processing) │
│ 1. Emit root document metadata to knowledge graph (once) │
│ 2. Send root document ID directly to chunker (skip PDF extractor) │
└─────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────┐
│ Chunker (per chunk) │
│ 1. Fetch text content from librarian using document ID │
│ 2. Split text into chunks │
│ 3. For each chunk: │
│ a. Save chunk as child document in librarian (parent = root doc) │
│ b. Emit parent-child edge to knowledge graph │
│ c. Send chunk document ID + chunk content to next processor │
└─────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────┐
│ Knowledge Extractor │
│ (same as PDF flow) │
└─────────────────────────────────────────────────────────────────────────┘
```
Полученный ориентированный ациклический граф (DAG) имеет на один уровень меньше:
```
PDF: Document → Pages → Chunks → Triples/Embeddings
Text: Document → Chunks → Triples/Embeddings
```
Дизайн учитывает оба варианта, поскольку компонент, разделяющий текст на части, обрабатывает входные данные универсально - он использует любой идентификатор документа, который он получает, в качестве родительского, независимо от того, является ли это исходным документом или страницей.
### Схема метаданных (PROV-O)
Метаданные происхождения используют онтологию W3C PROV-O. Это обеспечивает стандартный словарь и позволяет в будущем осуществлять подпись/аутентификацию результатов извлечения.
#### Основные концепции PROV-O
| Тип PROV-O | Использование в TrustGraph |
|-------------|------------------|
| `prov:Entity` | Документ, страница, фрагмент, тройка, вложение |
| `prov:Activity` | Экземпляры операций извлечения |
| `prov:Agent` | Компоненты TG (извлечение PDF, компонент, разделяющий текст на части и т.д.) с версиями |
#### Отношения PROV-O
| Предикат | Значение | Пример |
|-----------|---------|---------|
| `prov:wasDerivedFrom` | Сущность, полученная из другой сущности | Страница была получена из документа |
| `prov:wasGeneratedBy` | Сущность, сгенерированная действием | Страница была сгенерирована действием извлечения PDF |
| `prov:used` | Действие, использующее сущность в качестве входных данных | Действие извлечения PDF использовало документ |
| `prov:wasAssociatedWith` | Действие, выполненное агентом | Действие извлечения PDF было связано с tg:PDFExtractor |
#### Метаданные на каждом уровне
**Исходный документ (генерируется Librarian):**
```
doc:123 a prov:Entity .
doc:123 dc:title "Research Paper" .
doc:123 dc:source <https://example.com/paper.pdf> .
doc:123 dc:date "2024-01-15" .
doc:123 dc:creator "Author Name" .
doc:123 tg:pageCount 42 .
doc:123 tg:mimeType "application/pdf" .
```
**Страница (сгенерирована извлечением из PDF):**
```
page:123-1 a prov:Entity .
page:123-1 prov:wasDerivedFrom doc:123 .
page:123-1 prov:wasGeneratedBy activity:pdf-extract-456 .
page:123-1 tg:pageNumber 1 .
activity:pdf-extract-456 a prov:Activity .
activity:pdf-extract-456 prov:used doc:123 .
activity:pdf-extract-456 prov:wasAssociatedWith tg:PDFExtractor .
activity:pdf-extract-456 tg:componentVersion "1.2.3" .
activity:pdf-extract-456 prov:startedAtTime "2024-01-15T10:30:00Z" .
```
<<<<<<< HEAD
**Раздел (выдан разделителем):**
=======
**Раздел (выдан Компоновщиком):**
>>>>>>> 82edf2d (New md files from RunPod)
```
chunk:123-1-1 a prov:Entity .
chunk:123-1-1 prov:wasDerivedFrom page:123-1 .
chunk:123-1-1 prov:wasGeneratedBy activity:chunk-789 .
chunk:123-1-1 tg:chunkIndex 1 .
chunk:123-1-1 tg:charOffset 0 .
chunk:123-1-1 tg:charLength 2048 .
activity:chunk-789 a prov:Activity .
activity:chunk-789 prov:used page:123-1 .
activity:chunk-789 prov:wasAssociatedWith tg:Chunker .
activity:chunk-789 tg:componentVersion "1.0.0" .
activity:chunk-789 tg:chunkSize 2048 .
activity:chunk-789 tg:chunkOverlap 200 .
```
<<<<<<< HEAD
**Жирный шрифт (вывод Knowledge Extractor):**
=======
**Жирный шрифт (выделен извлечением знаний):**
>>>>>>> 82edf2d (New md files from RunPod)
```
# The extracted triple (edge)
entity:JohnSmith rel:worksAt entity:AcmeCorp .
# Subgraph containing the extracted triples
subgraph:001 tg:contains <<entity:JohnSmith rel:worksAt entity:AcmeCorp>> .
subgraph:001 prov:wasDerivedFrom chunk:123-1-1 .
subgraph:001 prov:wasGeneratedBy activity:extract-999 .
activity:extract-999 a prov:Activity .
activity:extract-999 prov:used chunk:123-1-1 .
activity:extract-999 prov:wasAssociatedWith tg:KnowledgeExtractor .
activity:extract-999 tg:componentVersion "2.1.0" .
activity:extract-999 tg:llmModel "claude-3" .
activity:extract-999 tg:ontology <http://example.org/ontologies/business-v1> .
```
<<<<<<< HEAD
**Встраивание (хранится в векторной базе данных, а не в тройной базе данных):**
=======
**Встраивания (хранятся в векторной базе данных, а не в тройной базе данных):**
>>>>>>> 82edf2d (New md files from RunPod)
Встраивания хранятся в векторной базе данных вместе с метаданными, а не в виде RDF-троек. Каждая запись встраивания содержит:
| Поле | Описание | Пример |
|-------|-------------|---------|
| vector | Вектор встраивания | [0.123, -0.456, ...] |
| entity | URI узла, который представляет встраивание | `entity:JohnSmith` |
| chunk_id | Исходный фрагмент (происхождение) | `chunk:123-1-1` |
| model | Используемая модель встраивания | `text-embedding-ada-002` |
| component_version | Версия компонента TG | `1.0.0` |
<<<<<<< HEAD
Поле `entity` связывает встраивание с графом знаний (URI узла). Поле `chunk_id` предоставляет информацию о происхождении, указывающую на исходный фрагмент, что позволяет проследить путь до исходного документа.
=======
Поле `entity` связывает встраивание с графом знаний (URI узла). Поле `chunk_id` предоставляет информацию о происхождении, указывающую на исходный фрагмент, что позволяет проследить путь вверх по DAG к исходному документу.
>>>>>>> 82edf2d (New md files from RunPod)
#### Расширения пространства имен TrustGraph
Пользовательские предикаты в пространстве имен `tg:` для метаданных, специфичных для извлечения:
| Предикат | Область | Описание |
|-----------|--------|-------------|
| `tg:contains` | Подграф | Указывает на тройку, содержащуюся в этом подграфе извлечения |
| `tg:pageCount` | Документ | Общее количество страниц в исходном документе |
| `tg:mimeType` | Документ | MIME-тип исходного документа |
| `tg:pageNumber` | Страница | Номер страницы в исходном документе |
<<<<<<< HEAD
| `tg:chunkIndex` | Фрагмент | Индекс фрагмента внутри родительского фрагмента |
=======
| `tg:chunkIndex` | Фрагмент | Индекс фрагмента внутри родительского элемента |
>>>>>>> 82edf2d (New md files from RunPod)
| `tg:charOffset` | Фрагмент | Смещение символов в родительском тексте |
| `tg:charLength` | Фрагмент | Длина фрагмента в символах |
| `tg:chunkSize` | Действие | Настроенный размер фрагмента |
| `tg:chunkOverlap` | Действие | Настроенное перекрытие между фрагментами |
| `tg:componentVersion` | Действие | Версия компонента TG |
| `tg:llmModel` | Действие | LLM, используемый для извлечения |
| `tg:ontology` | Действие | URI онтологии, используемой для управления извлечением |
| `tg:embeddingModel` | Действие | Модель, используемая для встраиваний |
| `tg:sourceText` | Утверждение | Точный текст, из которого была извлечена тройка |
| `tg:sourceCharOffset` | Утверждение | Смещение символов внутри фрагмента, где начинается исходный текст |
| `tg:sourceCharLength` | Утверждение | Длина исходного текста в символах |
#### Начальная загрузка словаря (для каждой коллекции)
<<<<<<< HEAD
Граф знаний является онтологически нейтральным и изначально пуст. При первом добавлении данных о происхождении PROV-O в коллекцию словарь должен быть инициализирован с помощью RDF-меток для всех классов и предикатов. Это обеспечивает удобочитаемое отображение в запросах и пользовательском интерфейсе.
=======
Граф знаний является онтологически нейтральным и изначально пуст. При записи данных о происхождении PROV-O в коллекцию в первый раз словарь должен быть инициализирован с помощью меток RDF для всех классов и предикатов. Это обеспечивает удобочитаемое отображение в запросах и пользовательском интерфейсе.
>>>>>>> 82edf2d (New md files from RunPod)
**Классы PROV-O:**
```
prov:Entity rdfs:label "Entity" .
prov:Activity rdfs:label "Activity" .
prov:Agent rdfs:label "Agent" .
```
**Предикаты PROV-O:**
```
prov:wasDerivedFrom rdfs:label "was derived from" .
prov:wasGeneratedBy rdfs:label "was generated by" .
prov:used rdfs:label "used" .
prov:wasAssociatedWith rdfs:label "was associated with" .
prov:startedAtTime rdfs:label "started at" .
```
**Предикаты TrustGraph:**
```
tg:contains rdfs:label "contains" .
tg:pageCount rdfs:label "page count" .
tg:mimeType rdfs:label "MIME type" .
tg:pageNumber rdfs:label "page number" .
tg:chunkIndex rdfs:label "chunk index" .
tg:charOffset rdfs:label "character offset" .
tg:charLength rdfs:label "character length" .
tg:chunkSize rdfs:label "chunk size" .
tg:chunkOverlap rdfs:label "chunk overlap" .
tg:componentVersion rdfs:label "component version" .
tg:llmModel rdfs:label "LLM model" .
tg:ontology rdfs:label "ontology" .
tg:embeddingModel rdfs:label "embedding model" .
tg:sourceText rdfs:label "source text" .
tg:sourceCharOffset rdfs:label "source character offset" .
tg:sourceCharLength rdfs:label "source character length" .
```
<<<<<<< HEAD
**Примечания по реализации:** Этот механизм начальной загрузки словаря должен быть идемпотентным, то есть его можно безопасно запускать несколько раз без создания дубликатов. Его можно запускать при первой обработке документа в коллекции или как отдельный этап инициализации коллекции.
#### Происхождение подраздела (желательно)
Для более детальной информации о происхождении полезно записывать, из какой именно части фрагмента была извлечена тройка. Это позволяет:
=======
**Примечания по реализации:** Этот начальный набор словаря должен быть идемпотентным - его можно безопасно запускать несколько раз без создания дубликатов. Его можно запускать при первой обработке документа в коллекции или как отдельный этап инициализации коллекции.
#### Происхождение под-фрагментов (желательно)
Для более детальной информации о происхождении, было бы полезно записывать, из какой именно части фрагмента была извлечена тройка. Это позволяет:
>>>>>>> 82edf2d (New md files from RunPod)
Выделять точный исходный текст в пользовательском интерфейсе
Проверять точность извлечения по отношению к исходному тексту
Отлаживать качество извлечения на уровне предложений
**Пример с отслеживанием позиции:**
```
# The extracted triple
entity:JohnSmith rel:worksAt entity:AcmeCorp .
# Subgraph with sub-chunk provenance
subgraph:001 tg:contains <<entity:JohnSmith rel:worksAt entity:AcmeCorp>> .
subgraph:001 prov:wasDerivedFrom chunk:123-1-1 .
subgraph:001 tg:sourceText "John Smith has worked at Acme Corp since 2019" .
subgraph:001 tg:sourceCharOffset 1547 .
subgraph:001 tg:sourceCharLength 46 .
```
**Пример с выделением текста (альтернативный):**
```
subgraph:001 tg:contains <<entity:JohnSmith rel:worksAt entity:AcmeCorp>> .
subgraph:001 prov:wasDerivedFrom chunk:123-1-1 .
subgraph:001 tg:sourceRange "1547-1593" .
subgraph:001 tg:sourceText "John Smith has worked at Acme Corp since 2019" .
```
**Соображения по реализации:**
Извлечение на основе LLM может не всегда предоставлять информацию о позициях символов.
<<<<<<< HEAD
Можно запросить LLM, чтобы он возвращал исходное предложение/фразу вместе с извлеченными тройками.
=======
Можно запросить LLM, чтобы она возвращала исходное предложение/фразу вместе с извлеченными тройками.
>>>>>>> 82edf2d (New md files from RunPod)
Альтернативно, можно выполнить постобработку для сопоставления извлеченных сущностей с исходным текстом.
Компромисс между сложностью извлечения и детализацией происхождения.
Может быть проще реализовать с использованием структурированных методов извлечения, чем с использованием LLM для извлечения в свободной форме.
<<<<<<< HEAD
Это обозначено как перспективное направление - сначала следует реализовать базовое отслеживание происхождения на уровне фрагментов, а отслеживание подфрагментов следует рассматривать как улучшение в будущем, если это будет возможно.
### Двухуровневая модель хранения
Граф происхождения строится постепенно по мере прохождения документов через конвейер:
| Хранилище | Что хранится | Назначение |
|-------|---------------|---------|
| Библиотекарь | Содержимое документа + ссылки "родитель-потомок" | Извлечение содержимого, каскадное удаление |
| Граф знаний | Ребра "родитель-потомок" + метаданные | Запросы происхождения, атрибуция фактов |
Оба хранилища поддерживают одну и ту же структуру графа. Библиотекарь хранит содержимое, а граф хранит отношения и обеспечивает возможности запросов для обхода.
=======
Это обозначено как перспективное направление - сначала следует реализовать базовое отслеживание происхождения на уровне фрагментов, а отслеживание подфрагментов следует рассматривать как улучшение в будущем, если это возможно.
### Двухуровневая модель хранения
Граф происхождения строится постепенно по мере прохождения документов по конвейеру:
| Хранилище | Что хранится | Назначение |
|-------|---------------|---------|
| Библиотекарь | Содержимое документа + ссылки родитель-потомок | Извлечение содержимого, каскадное удаление |
| Граф знаний | Ребра родитель-потомок + метаданные | Запросы происхождения, атрибуция фактов |
Оба хранилища поддерживают одну и ту же структуру графа. Библиотекарь хранит содержимое, а граф хранит отношения и обеспечивает возможность выполнения запросов для обхода графа.
>>>>>>> 82edf2d (New md files from RunPod)
### Основные принципы проектирования
1. **Идентификатор документа как единица потока данных** - Процессоры передают идентификаторы, а не содержимое. Содержимое извлекается из библиотеки, когда это необходимо.
<<<<<<< HEAD
2. **Отправка данных только в исходной точке** - Метаданные записываются в граф только один раз при начале обработки, а не повторяются далее по цепочке.
=======
2. **Однократная отправка данных в источнике** - Метаданные записываются в граф один раз при начале обработки, а не повторяются далее по цепочке.
>>>>>>> 82edf2d (New md files from RunPod)
3. **Единый шаблон для процессоров** - Каждый процессор следует одному и тому же шаблону: прием/извлечение/создание/сохранение/отправка/передача.
4. **Постепенное построение графа** - Каждый процессор добавляет свой уровень в граф. Полная цепочка происхождения строится постепенно.
5. **Оптимизация после разбиения на фрагменты** - После разбиения на фрагменты сообщения содержат как идентификатор, так и содержимое. Фрагменты небольшие (2-4 КБ), поэтому включение содержимого позволяет избежать ненужных обращений к библиотеке, сохраняя при этом происхождение с помощью идентификатора.
## Задачи реализации
### Изменения в библиотеке
#### Текущее состояние
Инициирует обработку документа, отправляя идентификатор документа первому процессору.
Нет подключения к хранилищу тройных данных - метаданные добавляются к результатам извлечения.
<<<<<<< HEAD
`add-child-document` создает одноуровневые ссылки "родитель-потомок".
=======
`add-child-document` создает одноуровневые ссылки родитель-потомок.
>>>>>>> 82edf2d (New md files from RunPod)
`list-children` возвращает только непосредственные потомки.
#### Необходимые изменения
**1. Новый интерфейс: Подключение к хранилищу тройных данных**
Библиотекарь должен напрямую отправлять ребра метаданных документа в граф знаний при начале обработки.
Добавить клиент/публикатор хранилища тройных данных в сервис библиотеки.
При инициации обработки: отправлять метаданные корневого документа в виде ребер графа (один раз).
**2. Словарь типов документов**
<<<<<<< HEAD
Стандартизировать значения `document_type` для дочерних документов:
=======
Стандартизировать значения `document_type` для документов-потомков:
>>>>>>> 82edf2d (New md files from RunPod)
`source` - исходный загруженный документ.
`page` - страница, извлеченная из источника (PDF и т.д.).
`chunk` - текстовый фрагмент, полученный из страницы или источника.
#### Краткое описание изменений интерфейса
| Интерфейс | Изменение |
|-----------|--------|
| Хранилище тройных данных | Новый исходящий канал - отправка ребер метаданных документа |
| Инициация обработки | Отправка метаданных в граф перед передачей идентификатора документа |
<<<<<<< HEAD
### Изменения в извлечении данных из PDF
=======
### Изменения в извлечении PDF
>>>>>>> 82edf2d (New md files from RunPod)
#### Текущее состояние
Получает содержимое документа (или потоковую передачу больших документов).
Извлекает текст из страниц PDF.
Передает содержимое страницы в компоновщик.
Не взаимодействует с библиотекой или хранилищем тройных данных.
#### Необходимые изменения
**1. Новый интерфейс: Клиент библиотеки**
<<<<<<< HEAD
Извлечение данных из PDF должно сохранять каждую страницу как дочерний документ в библиотеке.
Добавить клиент библиотеки в сервис извлечения данных из PDF.
=======
Извлечение PDF должно сохранять каждую страницу как документ-потомок в библиотеке.
Добавить клиент библиотеки в сервис извлечения PDF.
>>>>>>> 82edf2d (New md files from RunPod)
Для каждой страницы: вызвать `add-child-document` с parent = идентификатор корневого документа.
**2. Новый интерфейс: Подключение к хранилищу тройных данных**
<<<<<<< HEAD
Извлечение данных из PDF должно отправлять ребра "родитель-потомок" в граф знаний.
=======
Извлечение PDF должно отправлять ребра родитель-потомок в граф знаний.
>>>>>>> 82edf2d (New md files from RunPod)
Добавить клиент/публикатор хранилища тройных данных.
Для каждой страницы: отправлять ребро, связывающее документ страницы с родительским документом.
**3. Изменить формат вывода**
Вместо прямой передачи содержимого страницы, передавайте идентификатор документа страницы.
Chunker будет извлекать содержимое из хранилища, используя идентификатор.
#### Краткое описание изменений интерфейса
| Интерфейс | Изменение |
|-----------|--------|
| Хранилище | Новый исходящий поток - сохранение дочерних документов |
| Тройной магазин | Новый исходящий поток - генерация связей родитель-потомок |
| Сообщение вывода | Изменение с содержимого на идентификатор документа |
<<<<<<< HEAD
### Изменения Chunker
=======
### Изменения в Chunker
>>>>>>> 82edf2d (New md files from RunPod)
#### Текущее состояние
Получает содержимое страницы/текста
Разбивает на фрагменты
Передает содержимое фрагмента обработчикам на последующих этапах
Не взаимодействует с хранилищем или тройным магазином
#### Необходимые изменения
**1. Изменение обработки входных данных**
Вместо содержимого получайте идентификатор документа, извлекайте из хранилища.
Добавьте клиент хранилища в сервис Chunker
Извлекайте содержимое страницы, используя идентификатор документа
**2. Новый интерфейс: Клиент хранилища (запись)**
Сохраняйте каждый фрагмент как дочерний документ в хранилище.
Для каждого фрагмента: вызывайте `add-child-document` с parent = идентификатор документа страницы
**3. Новый интерфейс: Подключение к тройному магазину**
Генерируйте связи родитель-потомок для графа знаний.
Добавьте клиент/публикатор тройного магазина
Для каждого фрагмента: генерируйте связь, связывающую документ фрагмента с документом страницы
**4. Изменение формата вывода**
Передавайте как идентификатор документа фрагмента, так и содержимое фрагмента (оптимизация после обработки фрагмента).
Обработчики на последующих этапах получают идентификатор для отслеживания происхождения + содержимое для работы
#### Краткое описание изменений интерфейса
| Интерфейс | Изменение |
|-----------|--------|
| Сообщение ввода | Изменение с содержимого на идентификатор документа |
| Хранилище | Новый исходящий поток (чтение + запись) - извлечение содержимого, сохранение дочерних документов |
| Тройной магазин | Новый исходящий поток - генерация связей родитель-потомок |
| Сообщение вывода | Изменение с содержимого только на идентификатор + содержимое |
<<<<<<< HEAD
### Изменения Knowledge Extractor
=======
### Изменения в Knowledge Extractor
>>>>>>> 82edf2d (New md files from RunPod)
#### Текущее состояние
Получает содержимое фрагмента
Извлекает тройки и вложения
<<<<<<< HEAD
Передает в тройной магазин и хранилище вложений
=======
Отправляет в тройной магазин и хранилище вложений
>>>>>>> 82edf2d (New md files from RunPod)
`subjectOf` отношение указывает на верхний уровень документа (а не на фрагмент)
#### Необходимые изменения
**1. Изменение обработки входных данных**
<<<<<<< HEAD
Получайте идентификатор фрагмента вместе с содержимым.
=======
Получайте идентификатор документа фрагмента вместе с содержимым.
>>>>>>> 82edf2d (New md files from RunPod)
Используйте идентификатор фрагмента для отслеживания происхождения (содержимое уже включено в соответствии с оптимизацией)
**2. Обновление отслеживания происхождения тройками**
Связывайте извлеченные тройки с фрагментом (а не с верхним уровнем документа).
Используйте реификацию для создания связи, указывающей на связь
`subjectOf` отношение: тройка → идентификатор документа фрагмента
Первое использование существующей поддержки реификации
**3. Обновление отслеживания происхождения вложениями**
Связывайте идентификаторы сущностей вложений с фрагментом.
Генерируйте связь: идентификатор сущности вложения → идентификатор документа фрагмента
#### Краткое описание изменений интерфейса
| Интерфейс | Изменение |
|-----------|--------|
| Сообщение ввода | Ожидается идентификатор фрагмента + содержимое (а не только содержимое) |
| Тройной магазин | Используйте реификацию для отслеживания происхождения тройки → фрагмент |
<<<<<<< HEAD
| Отслеживание происхождения вложениями | Свяжите идентификатор сущности → идентификатор фрагмента |
=======
| Отслеживание происхождения вложений | Свяжите идентификатор сущности → идентификатор фрагмента |
>>>>>>> 82edf2d (New md files from RunPod)
## Ссылки
Отслеживание происхождения во время запроса: `docs/tech-specs/query-time-provenance.md`
Стандарт PROV-O для моделирования происхождения
Существующие метаданные источника в графе знаний (требуется аудит)