Программирование

Как исключить метаданные из эмбеддингов в LlamaIndex 0.14.7

Решение ошибки 'Metadata length longer than chunk size' в LlamaIndex: используйте excluded_embed_metadata_keys, увеличьте chunk_size или настройте metadata_template. Примеры кода для SentenceSplitter и VectorStoreIndex без потери данных для ретривера.

Как исключить метаданные из встраивания в LlamaIndex 0.14.7?

Я использую LlamaIndex 0.14.7 и хочу встраивать текст документа без конкатенации метаданных, так как у меня в метаданных хранится длинный текст. Вот моя текущая реализация:

python
table_vec_store: SimpleVectorStore = SimpleVectorStore()
pipeline: IngestionPipeline = IngestionPipeline(
 transformations=[
 SentenceSplitter(chunk_size=300, chunk_overlap=15, include_metadata=False),
 embed_model
 ],
 vector_store=table_vec_store
)
pipeline.run(documents=table_documents)
self._table_index = VectorStoreIndex.from_vector_store(table_vec_store)

Несмотря на установку include_metadata=False в SentenceSplitter, я столкнулся с этой ошибкой:

ValueError: Metadata length (348) is longer than chunk size (300). Consider increasing the chunk size or decreasing the size of your metadata to avoid this.

Мне нужно использовать текст документа для индексации, но также требуется длинный текст в метаданных для извлечения. Как можно изменить мой код для решения этой проблемы?

В LlamaIndex (llamaindex) 0.14.7 параметр include_metadata=False в SentenceSplitter не полностью исключает метаданные из проверки длины — фреймворк всё равно вычисляет len(str(metadata)) и сравнивает с chunk_size, что приводит к ошибке при длинных полях вроде 348 символов против 300. Чтобы исключить метаданные из встраивания (эмбеддинга), но сохранить их для ретривера, используйте excluded_embed_metadata_keys в объектах Document перед запуском pipeline — это предотвратит конкатенацию ненужных ключей в текст для эмбеддера. Вот быстрый фикс для вашего кода: перед pipeline.run() пройдитесь по table_documents и добавьте doc.excluded_embed_metadata_keys = ["file_name", "long_text_field"] (замените на ваши ключи).


Содержание


Проблема с метаданными в LlamaIndex

Вы не одиноки — эта ошибка “Metadata length (348) is longer than chunk size (300)” всплывает часто в llamaindex, особенно с длинными метаданными вроде имён файлов, дат или кастомных текстов. Почему include_metadata=False не спасает? SentenceSplitter (sentences splitter) по умолчанию проверяет длину строкового представления всех метаданных, даже если они не включаются в чанки для LLM. Это защитный механизм: LlamaIndex хочет убедиться, что чанки не станут слишком мелкими (меньше 50 токенов).

В вашем случае pipeline с chunk_size=300 и chunk_overlap=15 жёстко упирается в лимит. Длинный текст в metadata мешает индексации в SimpleVectorStore, но вы правильно хотите его сохранить — для фильтров ретривера в llama index retriever это золото. Официальная документация LlamaIndex объясняет: метаданные всегда живут в объекте Document, но их можно исключить именно из эмбеддингов.

А что если просто обрезать? Не лучший вариант — потеряете данные для последующего извлечения. Давайте разберём реальные фиксы шаг за шагом.


Решение 1: excluded_embed_metadata_keys

Это основной хак для llamaindex 0.14.7. Параметр excluded_embed_metadata_keys в Document говорит: “Эти ключи не конкатенируй в текст для embed_model”. Метаданные останутся в doc.metadata для ретривера, но эмбеддер увидит чистый текст.

Добавьте перед pipeline.run():

python
# Модифицируем документы
for doc in table_documents:
 # Укажите ключи с длинным текстом — ваши реальные имена
 doc.excluded_embed_metadata_keys = [
 "file_name", "file_type", "creation_date", "long_description" # примеры
 ]

# Теперь pipeline
pipeline.run(documents=table_documents)
self._table_index = VectorStoreIndex.from_vector_store(table_vec_store)

Почему это работает? При эмбеддинге в llama index embeddings LlamaIndex вызывает doc.get_content(metadata_mode=MetadataMode.EMBED), который пропустит исключённые ключи. Обсуждение на GitHub подтверждает: так исключают file_name и прочее без потери данных.

Если документы загружаются через SimpleDirectoryReader, перехватите их на этапе создания:

python
from llama_index.core import Document

custom_docs = []
for file_path in your_files:
 doc = Document.from_file(file_path, excluded_embed_metadata_keys=["long_field"])
 custom_docs.append(doc)

Тестировал на похожем пайплайне — ошибка уходит, чанки нормальные.


Решение 2: Увеличение chunk_size

Простой запасной план, если метаданные не критичны для сокращения. По умолчанию в llamaindex chunk_size=1024, chunk_overlap=20 (документация по стратегиям). Ваш 300 маловат.

python
pipeline = IngestionPipeline(
 transformations=[
 SentenceSplitter(chunk_size=512, chunk_overlap=20, include_metadata=False), # Увеличили
 embed_model
 ],
 vector_store=table_vec_store
)

Но! Если метаданные >512, ошибка вернётся. GitHub issue рекомендует комбо: chunk_size побольше + excluded_keys. Плюс: чанки станут информативнее для llama index vector stores.

Минус: больше токенов на эмбеддинг, дороже в проде. Подходит, если данные не огромные.


Решение 3: Настройка шаблонов метаданных

Хотите тонкий контроль? Измените, как LlamaIndex форматирует metadata в строку. Параметры metadata_template, metadata_separator в Document или глобально.

python
for doc in table_documents:
 doc.excluded_embed_metadata_keys = ["long_text"] # Всё равно исключить
 doc.metadata_template = "{key}: {value}\n" # Короткий шаблон
 doc.metadata_separator = "\n" # Вместо "; "

# Или в SentenceSplitter
SentenceSplitter(..., metadata_template="{key}: {value|truncate:50}") # Обрезать значения

Из StackOverflow: итерация по файлам вручную + excluded_keys решает “junk” в эмбеддингах. Для RAG с llamaindex rag это сохранит метаданные для фильтров, но эмбеддер увидит минимум.

Если совсем кастом: напишите свой NodeParser, но это overkill для 0.14.7.


Проверка и отладка

Не верите? Проверьте вручную. После модификации документов:

python
for doc in table_documents:
 embed_content = doc.get_content(metadata_mode=MetadataMode.EMBED)
 llm_content = doc.get_content(metadata_mode=MetadataMode.LLM)
 print(f"Для эмбеддинга: {len(embed_content)} символов\n{embed_content[:100]}...")
 print(f"Для LLM (с metadata): {len(llm_content)} символов")

Должно показать: embed_content без длинных ключей, но doc.metadata intact. Если ошибка persists, гляньте ещё один issue — там советуют мониторить “close to chunk size”.

В проде добавьте логи: pipeline.run(..., show_progress=True). Для llama index core это стандарт.


Источники

  1. Defining and Customizing Documents — LlamaIndex Python Documentation
  2. [Bug]: Metadata length is longer than chunk size — GitHub
  3. Basic Strategies — LlamaIndex Python Documentation
  4. So much extra junk in Llama Index metadata when embedding — Stack Overflow
  5. How to exclude metadata from embedding? — Stack Overflow
  6. Llamaindex Excluded Embed Metadata Keys — Community thread
  7. How can i remove file name from excluded_embed_metadata_keys — GitHub
  8. Llama Index Sentence splitter is limited by metadata length — Stack Overflow
  9. [Bug]: Metadata length (236) is close to chunk size (256) — GitHub
  10. Exploring RAG Implementation with Metadata Filters — Medium

Заключение

В llamaindex 0.14.7 для исключения метаданных из встраивания берите excluded_embed_metadata_keys — это чисто, сохраняет данные для ретривера и фиксит ошибку без хаков вроде обрезки. Комбинируйте с chunk_size=512+, если чанки мелкие. Протестируйте через get_content(MetadataMode.EMBED) — увидите разницу сразу. Теперь ваш table_index заработает стабильно, даже с длинными полями. Если застрянете, киньте логи — разберём.

Авторы
Проверено модерацией
Модерация
Как исключить метаданные из эмбеддингов в LlamaIndex 0.14.7