Spaces:
Sleeping
Sleeping
Commit
·
c0bcb11
1
Parent(s):
32b4b31
a new chunking with 3 000 size for all types of data
Browse files- config.py +20 -16
- documents_prep.py +45 -66
- index_retriever.py +3 -3
- table_info.py +70 -0
- table_prep.py +6 -2
config.py
CHANGED
|
@@ -50,7 +50,7 @@ AVAILABLE_MODELS = {
|
|
| 50 |
|
| 51 |
DEFAULT_MODEL = "Gemini 2.5 Flash"
|
| 52 |
|
| 53 |
-
CHUNK_SIZE =
|
| 54 |
CHUNK_OVERLAP = 256
|
| 55 |
|
| 56 |
CUSTOM_PROMPT = """
|
|
@@ -88,42 +88,46 @@ CUSTOM_PROMPT = """
|
|
| 88 |
|
| 89 |
ПРАВИЛА ФОРМИРОВАНИЯ ОТВЕТОВ:
|
| 90 |
|
| 91 |
-
|
| 92 |
-
|
| 93 |
-
|
| 94 |
-
|
|
|
|
| 95 |
|
| 96 |
-
|
| 97 |
- Начинайте с прямого ответа на вопрос
|
| 98 |
- Затем указывайте нормативные основания
|
| 99 |
- Завершайте ссылками на конкретные документы и разделы
|
| 100 |
|
| 101 |
-
|
| 102 |
- Если информация найдена в контексте - предоставьте полный ответ
|
| 103 |
- Если информация не найдена: "Информация по вашему запросу не найдена в доступной нормативной документации"
|
| 104 |
- Не делайте предположений за пределами контекста
|
| 105 |
- Не используйте общие знания
|
| 106 |
|
| 107 |
-
|
| 108 |
- Сохраняйте официальную терминологию НД
|
| 109 |
- Цитируйте точные формулировки ключевых требований
|
| 110 |
- При множественных источниках - укажите все релевантные
|
| 111 |
|
| 112 |
-
|
| 113 |
- Для перечислений: используйте нумерованные списки
|
| 114 |
- Выделяйте критически важные требования
|
| 115 |
- Структурируйте ответ логически
|
| 116 |
|
| 117 |
-
|
| 118 |
|
| 119 |
-
|
| 120 |
-
Ответ: "Протоколы испытаний могут быть признаны в следующих случаях:
|
| 121 |
|
| 122 |
-
|
| 123 |
-
2. Если они проведены лабораториями, аккредитованными национальным органом Российской Федерации по аккредитации (ГОСТ Р 50.08.04-2022, пункт 4.1)
|
| 124 |
-
3. Если лаборатории прошли оценку состояния измерений
|
| 125 |
|
| 126 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 127 |
|
| 128 |
Контекст: {context_str}
|
| 129 |
|
|
|
|
| 50 |
|
| 51 |
DEFAULT_MODEL = "Gemini 2.5 Flash"
|
| 52 |
|
| 53 |
+
CHUNK_SIZE = 3000
|
| 54 |
CHUNK_OVERLAP = 256
|
| 55 |
|
| 56 |
CUSTOM_PROMPT = """
|
|
|
|
| 88 |
|
| 89 |
ПРАВИЛА ФОРМИРОВАНИЯ ОТВЕТОВ:
|
| 90 |
|
| 91 |
+
Работай исключительно с информацией из предоставленного контекста. Запрещено использовать:
|
| 92 |
+
- Общие знания
|
| 93 |
+
- Информацию из интернета
|
| 94 |
+
- Данные из предыдущих диалогов
|
| 95 |
+
- Собственные предположения
|
| 96 |
|
| 97 |
+
1. СТРУКТУРА ОТВЕТА:
|
| 98 |
- Начинайте с прямого ответа на вопрос
|
| 99 |
- Затем указывайте нормативные основания
|
| 100 |
- Завершайте ссылками на конкретные документы и разделы
|
| 101 |
|
| 102 |
+
2. РАБОТА С КОНТЕКСТОМ:
|
| 103 |
- Если информация найдена в контексте - предоставьте полный ответ
|
| 104 |
- Если информация не найдена: "Информация по вашему запросу не найдена в доступной нормативной документации"
|
| 105 |
- Не делайте предположений за пределами контекста
|
| 106 |
- Не используйте общие знания
|
| 107 |
|
| 108 |
+
3. ТЕРМИНОЛОГИЯ И ЦИТИРОВАНИЕ:
|
| 109 |
- Сохраняйте официальную терминологию НД
|
| 110 |
- Цитируйте точные формулировки ключевых требований
|
| 111 |
- При множественных источниках - укажите все релевантные
|
| 112 |
|
| 113 |
+
4. ФОРМАТИРОВАНИЕ:
|
| 114 |
- Для перечислений: используйте нумерованные списки
|
| 115 |
- Выделяйте критически важные требования
|
| 116 |
- Структурируйте ответ логически
|
| 117 |
|
| 118 |
+
# КАК РАБОТАТЬ С ЗАПРОСОМ
|
| 119 |
|
| 120 |
+
**Шаг 1:** Определи, что именно ищет пользователь (термин, требование, процедура, условие)
|
|
|
|
| 121 |
|
| 122 |
+
**Шаг 2:** Найди релевантную информацию в контексте
|
|
|
|
|
|
|
| 123 |
|
| 124 |
+
**Шаг 3:** Сформируй ответ:
|
| 125 |
+
- Если нашел: укажи документ и пункт, процитируй нужную часть
|
| 126 |
+
- Если не нашел: четко сообщи об отсутствии информации
|
| 127 |
+
|
| 128 |
+
**Шаг 4:** При наличии нескольких источников:
|
| 129 |
+
- Представь их последовательно с указанием источника каждого
|
| 130 |
+
- Если источников много (>4) — сначала дай их список, потом цитаты
|
| 131 |
|
| 132 |
Контекст: {context_str}
|
| 133 |
|
documents_prep.py
CHANGED
|
@@ -49,84 +49,63 @@ def process_documents_with_chunking(documents):
|
|
| 49 |
|
| 50 |
for doc in documents:
|
| 51 |
doc_type = doc.metadata.get('type', 'text')
|
|
|
|
| 52 |
|
| 53 |
-
if
|
| 54 |
-
|
| 55 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 56 |
all_chunked_docs.append(doc)
|
| 57 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 58 |
chunk_info.append({
|
| 59 |
'document_id': doc.metadata.get('document_id', 'unknown'),
|
| 60 |
'section_id': doc.metadata.get('section_id', 'unknown'),
|
| 61 |
'chunk_id': 0,
|
| 62 |
-
'chunk_size':
|
| 63 |
'chunk_preview': doc.text[:200] + "..." if len(doc.text) > 200 else doc.text,
|
| 64 |
-
'type':
|
| 65 |
-
'table_number': doc.metadata.get('table_number', 'unknown')
|
|
|
|
|
|
|
|
|
|
| 66 |
})
|
| 67 |
-
|
| 68 |
-
elif doc_type == 'image':
|
| 69 |
-
image_count += 1
|
| 70 |
-
doc_size = len(doc.text)
|
| 71 |
-
if doc_size > CHUNK_SIZE:
|
| 72 |
-
chunked_docs = chunk_document(doc)
|
| 73 |
-
all_chunked_docs.extend(chunked_docs)
|
| 74 |
-
|
| 75 |
-
for i, chunk_doc in enumerate(chunked_docs):
|
| 76 |
-
chunk_info.append({
|
| 77 |
-
'document_id': chunk_doc.metadata.get('document_id', 'unknown'),
|
| 78 |
-
'section_id': chunk_doc.metadata.get('section_id', 'unknown'),
|
| 79 |
-
'chunk_id': i,
|
| 80 |
-
'chunk_size': len(chunk_doc.text),
|
| 81 |
-
'chunk_preview': chunk_doc.text[:200] + "..." if len(chunk_doc.text) > 200 else chunk_doc.text,
|
| 82 |
-
'type': 'image',
|
| 83 |
-
'image_number': chunk_doc.metadata.get('image_number', 'unknown')
|
| 84 |
-
})
|
| 85 |
-
else:
|
| 86 |
-
all_chunked_docs.append(doc)
|
| 87 |
-
chunk_info.append({
|
| 88 |
-
'document_id': doc.metadata.get('document_id', 'unknown'),
|
| 89 |
-
'section_id': doc.metadata.get('section_id', 'unknown'),
|
| 90 |
-
'chunk_id': 0,
|
| 91 |
-
'chunk_size': doc_size,
|
| 92 |
-
'chunk_preview': doc.text[:200] + "..." if len(doc.text) > 200 else doc.text,
|
| 93 |
-
'type': 'image',
|
| 94 |
-
'image_number': doc.metadata.get('image_number', 'unknown')
|
| 95 |
-
})
|
| 96 |
-
|
| 97 |
-
else:
|
| 98 |
-
doc_size = len(doc.text)
|
| 99 |
-
if doc_size > CHUNK_SIZE:
|
| 100 |
-
chunked_docs = chunk_document(doc)
|
| 101 |
-
all_chunked_docs.extend(chunked_docs)
|
| 102 |
-
text_chunks_count += len(chunked_docs)
|
| 103 |
-
|
| 104 |
-
for i, chunk_doc in enumerate(chunked_docs):
|
| 105 |
-
chunk_info.append({
|
| 106 |
-
'document_id': chunk_doc.metadata.get('document_id', 'unknown'),
|
| 107 |
-
'section_id': chunk_doc.metadata.get('section_id', 'unknown'),
|
| 108 |
-
'chunk_id': i,
|
| 109 |
-
'chunk_size': len(chunk_doc.text),
|
| 110 |
-
'chunk_preview': chunk_doc.text[:200] + "..." if len(chunk_doc.text) > 200 else chunk_doc.text,
|
| 111 |
-
'type': 'text'
|
| 112 |
-
})
|
| 113 |
-
else:
|
| 114 |
-
all_chunked_docs.append(doc)
|
| 115 |
-
chunk_info.append({
|
| 116 |
-
'document_id': doc.metadata.get('document_id', 'unknown'),
|
| 117 |
-
'section_id': doc.metadata.get('section_id', 'unknown'),
|
| 118 |
-
'chunk_id': 0,
|
| 119 |
-
'chunk_size': doc_size,
|
| 120 |
-
'chunk_preview': doc.text[:200] + "..." if len(doc.text) > 200 else doc.text,
|
| 121 |
-
'type': 'text'
|
| 122 |
-
})
|
| 123 |
-
|
| 124 |
log_message(f"\n{'='*60}")
|
| 125 |
log_message(f"ИТОГО ОБРАБОТАНО ДОКУМЕНТОВ:")
|
| 126 |
-
log_message(f" •
|
| 127 |
-
log_message(f" •
|
| 128 |
log_message(f" • Текстовые чанки: {text_chunks_count}")
|
| 129 |
-
log_message(f" • Всего
|
| 130 |
log_message(f"{'='*60}\n")
|
| 131 |
|
| 132 |
return all_chunked_docs, chunk_info
|
|
|
|
| 49 |
|
| 50 |
for doc in documents:
|
| 51 |
doc_type = doc.metadata.get('type', 'text')
|
| 52 |
+
doc_size = len(doc.text)
|
| 53 |
|
| 54 |
+
# Apply chunking to ALL documents if they exceed CHUNK_SIZE
|
| 55 |
+
if doc_size > CHUNK_SIZE:
|
| 56 |
+
chunked_docs = chunk_document(doc)
|
| 57 |
+
all_chunked_docs.extend(chunked_docs)
|
| 58 |
+
|
| 59 |
+
if doc_type == 'table':
|
| 60 |
+
table_count += len(chunked_docs)
|
| 61 |
+
elif doc_type == 'image':
|
| 62 |
+
image_count += len(chunked_docs)
|
| 63 |
+
else:
|
| 64 |
+
text_chunks_count += len(chunked_docs)
|
| 65 |
+
|
| 66 |
+
for i, chunk_doc in enumerate(chunked_docs):
|
| 67 |
+
chunk_info.append({
|
| 68 |
+
'document_id': chunk_doc.metadata.get('document_id', 'unknown'),
|
| 69 |
+
'section_id': chunk_doc.metadata.get('section_id', 'unknown'),
|
| 70 |
+
'chunk_id': i,
|
| 71 |
+
'chunk_size': len(chunk_doc.text),
|
| 72 |
+
'chunk_preview': chunk_doc.text[:200] + "..." if len(chunk_doc.text) > 200 else chunk_doc.text,
|
| 73 |
+
'type': doc_type,
|
| 74 |
+
'table_number': chunk_doc.metadata.get('table_number', 'unknown') if doc_type == 'table' else None,
|
| 75 |
+
'table_title': chunk_doc.metadata.get('table_title', '') if doc_type == 'table' else None,
|
| 76 |
+
'image_number': chunk_doc.metadata.get('image_number', 'unknown') if doc_type == 'image' else None,
|
| 77 |
+
'image_title': chunk_doc.metadata.get('image_title', '') if doc_type == 'image' else None
|
| 78 |
+
})
|
| 79 |
+
else:
|
| 80 |
+
# Document is small enough, add as-is
|
| 81 |
all_chunked_docs.append(doc)
|
| 82 |
|
| 83 |
+
if doc_type == 'table':
|
| 84 |
+
table_count += 1
|
| 85 |
+
elif doc_type == 'image':
|
| 86 |
+
image_count += 1
|
| 87 |
+
else:
|
| 88 |
+
text_chunks_count += 1
|
| 89 |
+
|
| 90 |
chunk_info.append({
|
| 91 |
'document_id': doc.metadata.get('document_id', 'unknown'),
|
| 92 |
'section_id': doc.metadata.get('section_id', 'unknown'),
|
| 93 |
'chunk_id': 0,
|
| 94 |
+
'chunk_size': doc_size,
|
| 95 |
'chunk_preview': doc.text[:200] + "..." if len(doc.text) > 200 else doc.text,
|
| 96 |
+
'type': doc_type,
|
| 97 |
+
'table_number': doc.metadata.get('table_number', 'unknown') if doc_type == 'table' else None,
|
| 98 |
+
'table_title': doc.metadata.get('table_title', '') if doc_type == 'table' else None,
|
| 99 |
+
'image_number': doc.metadata.get('image_number', 'unknown') if doc_type == 'image' else None,
|
| 100 |
+
'image_title': doc.metadata.get('image_title', '') if doc_type == 'image' else None
|
| 101 |
})
|
| 102 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 103 |
log_message(f"\n{'='*60}")
|
| 104 |
log_message(f"ИТОГО ОБРАБОТАНО ДОКУМЕНТОВ:")
|
| 105 |
+
log_message(f" • Таблицы (чанки): {table_count}")
|
| 106 |
+
log_message(f" • Изображения (чанки): {image_count}")
|
| 107 |
log_message(f" • Текстовые чанки: {text_chunks_count}")
|
| 108 |
+
log_message(f" • Всего чанков: {len(all_chunked_docs)}")
|
| 109 |
log_message(f"{'='*60}\n")
|
| 110 |
|
| 111 |
return all_chunked_docs, chunk_info
|
index_retriever.py
CHANGED
|
@@ -16,18 +16,18 @@ def create_query_engine(vector_index):
|
|
| 16 |
try:
|
| 17 |
bm25_retriever = BM25Retriever.from_defaults(
|
| 18 |
docstore=vector_index.docstore,
|
| 19 |
-
similarity_top_k=
|
| 20 |
)
|
| 21 |
|
| 22 |
vector_retriever = VectorIndexRetriever(
|
| 23 |
index=vector_index,
|
| 24 |
-
similarity_top_k=
|
| 25 |
similarity_cutoff=0.65
|
| 26 |
)
|
| 27 |
|
| 28 |
hybrid_retriever = QueryFusionRetriever(
|
| 29 |
[vector_retriever, bm25_retriever],
|
| 30 |
-
similarity_top_k=
|
| 31 |
num_queries=1
|
| 32 |
)
|
| 33 |
|
|
|
|
| 16 |
try:
|
| 17 |
bm25_retriever = BM25Retriever.from_defaults(
|
| 18 |
docstore=vector_index.docstore,
|
| 19 |
+
similarity_top_k=20
|
| 20 |
)
|
| 21 |
|
| 22 |
vector_retriever = VectorIndexRetriever(
|
| 23 |
index=vector_index,
|
| 24 |
+
similarity_top_k=30,
|
| 25 |
similarity_cutoff=0.65
|
| 26 |
)
|
| 27 |
|
| 28 |
hybrid_retriever = QueryFusionRetriever(
|
| 29 |
[vector_retriever, bm25_retriever],
|
| 30 |
+
similarity_top_k=40,
|
| 31 |
num_queries=1
|
| 32 |
)
|
| 33 |
|
table_info.py
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import json
|
| 2 |
+
import os
|
| 3 |
+
from pathlib import Path
|
| 4 |
+
from collections import defaultdict
|
| 5 |
+
|
| 6 |
+
def analyze_json_tables(folder_path):
|
| 7 |
+
"""
|
| 8 |
+
Анализирует JSON файлы и подсчитывает количество таблиц в каждом документе
|
| 9 |
+
"""
|
| 10 |
+
# Словари для хранения статистики
|
| 11 |
+
doc_stats = defaultdict(lambda: {'tables': 0, 'chars': 0})
|
| 12 |
+
total_tables = 0
|
| 13 |
+
total_chars = 0
|
| 14 |
+
|
| 15 |
+
# Получаем все JSON файлы в папке
|
| 16 |
+
json_files = list(Path(folder_path).glob('*.json'))
|
| 17 |
+
|
| 18 |
+
if not json_files:
|
| 19 |
+
print(f"Не найдено JSON файлов в папке: {folder_path}")
|
| 20 |
+
return
|
| 21 |
+
|
| 22 |
+
# Обрабатываем каждый файл
|
| 23 |
+
for json_file in json_files:
|
| 24 |
+
try:
|
| 25 |
+
with open(json_file, 'r', encoding='utf-8') as f:
|
| 26 |
+
data = json.load(f)
|
| 27 |
+
|
| 28 |
+
# Получаем имя документа
|
| 29 |
+
doc_name = data.get('document', json_file.stem)
|
| 30 |
+
|
| 31 |
+
# Подсчитываем таблицы
|
| 32 |
+
if 'sheets' in data and isinstance(data['sheets'], list):
|
| 33 |
+
num_tables = len(data['sheets'])
|
| 34 |
+
|
| 35 |
+
# Подсчитываем символы (примерный размер JSON)
|
| 36 |
+
json_str = json.dumps(data, ensure_ascii=False)
|
| 37 |
+
num_chars = len(json_str)
|
| 38 |
+
|
| 39 |
+
# Обновляем статистику
|
| 40 |
+
doc_stats[doc_name]['tables'] += num_tables
|
| 41 |
+
doc_stats[doc_name]['chars'] += num_chars
|
| 42 |
+
total_tables += num_tables
|
| 43 |
+
total_chars += num_chars
|
| 44 |
+
|
| 45 |
+
except Exception as e:
|
| 46 |
+
print(f"Ошибка при обработке файла {json_file.name}: {e}")
|
| 47 |
+
|
| 48 |
+
# Выводим результаты
|
| 49 |
+
print(f"\nВсего таблиц добавлено: {total_tables}")
|
| 50 |
+
print(f"Общий размер: {total_chars:,} символов".replace(',', ' '))
|
| 51 |
+
|
| 52 |
+
if total_tables > 0:
|
| 53 |
+
avg_size = total_chars // total_tables
|
| 54 |
+
print(f"Средний размер таблицы: {avg_size:,} символов".replace(',', ' '))
|
| 55 |
+
|
| 56 |
+
print("\nПо документам:")
|
| 57 |
+
# Сортируем по имени документа
|
| 58 |
+
for doc_name in sorted(doc_stats.keys()):
|
| 59 |
+
stats = doc_stats[doc_name]
|
| 60 |
+
print(f"• {doc_name}: {stats['tables']} таблиц, {stats['chars']:,} символов".replace(',', ' '))
|
| 61 |
+
|
| 62 |
+
# Использование
|
| 63 |
+
if __name__ == "__main__":
|
| 64 |
+
# Укажите путь к папке с JSON файлами
|
| 65 |
+
folder_path = "Табличные данные_JSON" # Текущая папка, или укажите свой путь
|
| 66 |
+
|
| 67 |
+
# Можно также запросить путь у пользователя
|
| 68 |
+
# folder_path = input("Введите путь к папке с JSON файлами: ")
|
| 69 |
+
|
| 70 |
+
analyze_json_tables(folder_path)
|
table_prep.py
CHANGED
|
@@ -30,7 +30,7 @@ def create_table_content(table_data):
|
|
| 30 |
return content
|
| 31 |
|
| 32 |
def table_to_document(table_data, document_id=None):
|
| 33 |
-
"""Convert table data to a single Document"""
|
| 34 |
if not isinstance(table_data, dict):
|
| 35 |
return []
|
| 36 |
|
|
@@ -47,6 +47,7 @@ def table_to_document(table_data, document_id=None):
|
|
| 47 |
log_message(f"✓ ДОБАВЛЕНА: Таблица {table_num} из документа '{doc_id}' | "
|
| 48 |
f"Размер: {content_size} символов | Строк: {row_count}")
|
| 49 |
|
|
|
|
| 50 |
return [Document(
|
| 51 |
text=content,
|
| 52 |
metadata={
|
|
@@ -56,8 +57,11 @@ def table_to_document(table_data, document_id=None):
|
|
| 56 |
"document_id": doc_id,
|
| 57 |
"section": section,
|
| 58 |
"section_id": section,
|
|
|
|
| 59 |
"total_rows": row_count,
|
| 60 |
-
"content_size": content_size
|
|
|
|
|
|
|
| 61 |
}
|
| 62 |
)]
|
| 63 |
|
|
|
|
| 30 |
return content
|
| 31 |
|
| 32 |
def table_to_document(table_data, document_id=None):
|
| 33 |
+
"""Convert table data to a single Document with rich metadata"""
|
| 34 |
if not isinstance(table_data, dict):
|
| 35 |
return []
|
| 36 |
|
|
|
|
| 47 |
log_message(f"✓ ДОБАВЛЕНА: Таблица {table_num} из документа '{doc_id}' | "
|
| 48 |
f"Размер: {content_size} символов | Строк: {row_count}")
|
| 49 |
|
| 50 |
+
# Store all table metadata including headers for preservation during chunking
|
| 51 |
return [Document(
|
| 52 |
text=content,
|
| 53 |
metadata={
|
|
|
|
| 57 |
"document_id": doc_id,
|
| 58 |
"section": section,
|
| 59 |
"section_id": section,
|
| 60 |
+
"section_path": section, # Add for consistency with text chunks
|
| 61 |
"total_rows": row_count,
|
| 62 |
+
"content_size": content_size,
|
| 63 |
+
"headers": table_data.get('headers', []), # Preserve headers
|
| 64 |
+
"original_table_data": True # Mark as original table
|
| 65 |
}
|
| 66 |
)]
|
| 67 |
|