Fix LlamaIndex IndexError: list index out of range từ phản hồi truy xuất rỗng

intermediate🧠 AI Tools2026-05-17| Python 3.9+, LlamaIndex (llama-index) 0.9.x – 0.10.x, mọi hệ điều hành

Error Message

IndexError: list index out of range
#llamaindex#retrieval#rag#empty-response

Lỗi Gặp Phải

Bạn đang chạy pipeline RAG với LlamaIndex và đột nhiên gặp lỗi này:

Traceback (most recent call last):
  File "query.py", line 14, in <module>
    response = query_engine.query("What is the refund policy?")
  File ".../llama_index/core/query_engine/retriever_query_engine.py", line 190, in query
    ...
  File ".../llama_index/core/response_synthesizers/base.py", line 102, in synthesize
    text_chunks = [node.get_content() for node in nodes]
IndexError: list index out of range

Retriever trả về không có node nào, và một thành phần phía sau cố gắng truy cập vào danh sách rỗng. Lỗi này xuất hiện liên tục trong các setup RAG với LlamaIndex — và hầu như luôn là một lỗi âm thầm, không có cảnh báo trước khi crash.

Nguyên Nhân

Mọi trường hợp đều bắt nguồn từ một điều: retriever không tìm thấy node nào khớp với truy vấn. Đây là các nguyên nhân thường gặp:

  • Index được xây dựng từ danh sách tài liệu rỗng, hoặc tài liệu chưa được chunk đúng cách
  • Ngưỡng similarity được đặt quá cao — không có chunk nào đạt điểm trên ngưỡng cắt (0.85+ thường quá nghiêm ngặt)
  • similarity_top_k được đặt là 0, hoặc index có ít node hơn số lượng yêu cầu
  • Embedding không khớp — index được xây dựng bằng một model, nhưng truy vấn bằng model khác
  • Sự cố kết nối vector store (Pinecone, Weaviate, Chroma) trả về kết quả rỗng mà không có lỗi
  • File index bị hỏng hoặc không được lưu trữ đúng cách trước khi tải

Cách Khắc Phục Từng Bước

Bước 1 — Kiểm tra xem retriever có thực sự trả về node không

Bắt đầu bằng cách cô lập retriever. Gọi trực tiếp, bỏ qua hoàn toàn query engine:

from llama_index.core import VectorStoreIndex, SimpleDirectoryReader

# Build hoặc load index của bạn
index = VectorStoreIndex.from_documents(documents)
retriever = index.as_retriever(similarity_top_k=5)

# Gọi retriever trực tiếp — bỏ qua query engine
nodes = retriever.retrieve("What is the refund policy?")
print(f"Retrieved {len(nodes)} nodes")
for node in nodes:
    print(node.score, node.get_content()[:100])

Nếu len(nodes) == 0, lỗi nằm ở cấu hình retriever hoặc dữ liệu index — không phải query engine. Điều này giúp thu hẹp phạm vi nhanh chóng.

Bước 2 — Kiểm tra xem index có thực sự chứa dữ liệu không

# Với VectorStoreIndex in-memory
print(f"Index has {len(index.docstore.docs)} documents")

# Với index đã được lưu trữ
from llama_index.core import StorageContext, load_index_from_storage

storage_context = StorageContext.from_defaults(persist_dir="./storage")
index = load_index_from_storage(storage_context)
print(f"Loaded index with {len(index.docstore.docs)} docs")

Số lượng bằng 0? Tài liệu của bạn chưa được index. Chạy lại pipeline ingestion và xác nhận tài liệu được tải đúng trước khi index.

Bước 3 — Giảm hoặc bỏ ngưỡng similarity

Một node postprocessor với ngưỡng similarity quá khắt khe có thể âm thầm lọc bỏ toàn bộ kết quả:

from llama_index.core.postprocessor import SimilarityPostprocessor

# Quá khắt khe — có thể loại bỏ tất cả kết quả
postprocessor = SimilarityPostprocessor(similarity_cutoff=0.85)

# Điểm khởi đầu hợp lý hơn
postprocessor = SimilarityPostprocessor(similarity_cutoff=0.5)

Tắt postprocessor trước. Xác nhận retrieval hoạt động. Sau đó thêm lại bộ lọc theo từng bước nhỏ — giảm ngưỡng xuống 0.1 mỗi lần cho đến khi tìm được giá trị không loại bỏ hết kết quả.

Bước 4 — Khắc phục lỗi không khớp embedding model

Xây dựng index bằng một model nhưng truy vấn bằng model khác? Điểm cosine similarity sẽ vô nghĩa — không có gì khớp cả. Hãy luôn chỉ định rõ ràng embedding model:

from llama_index.core import Settings
from llama_index.embeddings.openai import OpenAIEmbedding

# Đặt toàn cục — áp dụng cho cả indexing và querying
Settings.embed_model = OpenAIEmbedding(model="text-embedding-3-small")

# Xây dựng index
index = VectorStoreIndex.from_documents(documents)

# Và truy vấn — cùng embedding model được dùng tự động
query_engine = index.as_query_engine()

Đã thay đổi embedding model sau khi index được xây dựng? Bạn phải xây dựng lại từ đầu. Không có đường tắt nào ở đây.

Bước 5 — Bảo vệ code khỏi trường hợp kết quả rỗng

Dù sao đi nữa, ứng dụng của bạn không nên bị crash khi retrieval trả về rỗng. Thêm đoạn kiểm tra bảo vệ:

from llama_index.core import VectorStoreIndex
from llama_index.core.query_engine import RetrieverQueryEngine
from llama_index.core.response_synthesizers import get_response_synthesizer

retriever = index.as_retriever(similarity_top_k=5)

# Cách A: kiểm tra nodes trước khi synthesize
nodes = retriever.retrieve(query)
if not nodes:
    print("No relevant documents found for this query.")
else:
    synth = get_response_synthesizer()
    response = synth.synthesize(query, nodes=nodes)
    print(response)

# Cách B: bọc lời gọi query engine
try:
    response = query_engine.query(query)
    if not str(response).strip():
        print("Empty response — no matching content found.")
except IndexError:
    print("Retriever returned no results for this query.")

Bước 6 — Với vector store bên ngoài (Pinecone, Chroma, Weaviate)

Các store bên ngoài có thể trả về kết quả rỗng mà không có lỗi nào cả. Kiểm tra số lượng trong collection trước:

# Ví dụ với Chroma
import chromadb

client = chromadb.PersistentClient(path="./chroma_db")
collection = client.get_collection("my_collection")
print(f"Chroma collection has {collection.count()} entries")

# Nếu bằng 0, chạy lại script ingestion của bạn
from llama_index.vector_stores.chroma import ChromaVectorStore
from llama_index.core import StorageContext, VectorStoreIndex

vector_store = ChromaVectorStore(chroma_collection=collection)
storage_context = StorageContext.from_defaults(vector_store=vector_store)
index = VectorStoreIndex.from_documents(documents, storage_context=storage_context)

Số lượng bằng 0 có nghĩa là quá trình ingestion chưa bao giờ chạy, hoặc đã ghi vào một collection khác. Kiểm tra lại xem collection_name có khớp giữa script ingestion và script truy vấn của bạn không.

Xác Nhận Đã Khắc Phục

Chạy bài kiểm tra tổng quát này sau khi áp dụng bất kỳ cách sửa nào:

import logging
logging.basicConfig(level=logging.DEBUG)

retriever = index.as_retriever(similarity_top_k=3)
nodes = retriever.retrieve("test query matching your documents")

assert len(nodes) > 0, "Still returning empty — check index and embeddings"
print(f"OK: retrieved {len(nodes)} nodes")
print("Top result score:", nodes[0].score)
print("Top result preview:", nodes[0].get_content()[:200])

Bạn sẽ thấy ít nhất một node với điểm số khác 0. Điểm trả về là None? Vector store của bạn không trả về điểm similarity — hãy kiểm tra cấu hình của store, không phải retriever.

Mẹo Nhanh

  • Luôn xây dựng lại index sau khi thay đổi chunk size hoặc embedding model — các vector cũ gây ra lỗi retrieval khó phát hiện
  • Dùng similarity_top_k=10 khi debug — thu hẹp lại sau khi xác nhận retrieval thực sự hoạt động
  • Bật LlamaIndex debug events để theo dõi chính xác những gì retriever đang làm: from llama_index.core import set_global_handler; set_global_handler("simple")
  • Tài liệu rất ngắn (dưới 100 token) thường tạo ra các node có điểm quá thấp để vượt qua bất kỳ ngưỡng nào — tăng Settings.chunk_size lên ít nhất 256 và index lại
  • Trong môi trường production, luôn xử lý rõ ràng trường hợp nodes rỗng. Đừng để query engine quyết định sẽ raise lỗi gì.

Related Error Notes