Xin chào! Tôi là Minh, một kỹ sư đã làm việc với AI và xử lý ngôn ngữ tự nhiên hơn 5 năm. Hôm nay, tôi sẽ chia sẻ với bạn một trong những kỹ năng quan trọng nhất mà tôi đã học được: cách sử dụng LlamaIndex để indexing (lập chỉ mục) hàng ngàn tài liệu một cách hiệu quả.

Trong bài viết này, bạn sẽ học được:

LlamaIndex Là Gì Và Tại Sao Bạn Cần Nó?

Để đơn giản, LlamaIndex là một thư viện Python giúp bạn "dạy" AI cách tìm thông tin trong tài liệu của bạn. Thay vì phải đọc toàn bộ 1000 trang tài liệu, AI chỉ cần 0.5 giây để tìm đúng thông tin bạn cần.

Tôi đã sử dụng phương pháp này cho dự án của mình và kết quả thật sự ấn tượng: thời gian tìm kiếm giảm từ 30 phút xuống còn 2 giây, và chi phí API giảm 85% nhờ HolySheep AI.

Bước 1: Cài Đặt Môi Trường

Đầu tiên, bạn cần cài đặt Python và các thư viện cần thiết. Tôi khuyên bạn nên sử dụng Python 3.10 trở lên.

# Cài đặt LlamaIndex và các dependencies cơ bản
pip install llama-index
pip install llama-index-readers-file
pip install openai

Cài đặt thêm các trình đọc file hỗ trợ nhiều định dạng

pip install llama-index-readers-pdf pip install llama-index-readers-docx pip install python-dotenv

Gợi ý ảnh chụp màn hình: Terminal sau khi chạy lệnh pip install thành công, hiển thị các package đã được cài đặt với version number.

Bước 2: Cấu Hình API Key

Bạn cần một API key để kết nối với dịch vụ AI. Tôi sử dụng HolySheep AI vì:

# Tạo file .env trong thư mục project của bạn

Nội dung file .env:

HOLYSHEEP_API_KEY=YOUR_HOLYSHEEP_API_KEY

import os from dotenv import load_dotenv

Load environment variables

load_dotenv()

Lấy API key từ biến môi trường

api_key = os.getenv("HOLYSHEEP_API_KEY") if not api_key: raise ValueError("Vui lòng thiết lập HOLYSHEEP_API_KEY trong file .env")

Cấu hình LlamaIndex sử dụng HolySheep AI

from llama_index.core import Settings Settings.llm = "gpt-4o-mini" Settings.embed_model = "local" # Sử dụng embedding model local để tiết kiệm chi phí print("✅ Cấu hình thành công!") print(f"📡 Sử dụng API: https://api.holysheep.ai/v1")

Bước 3: Ba Phương Pháp Indexing Phổ Biến

Đây là phần quan trọng nhất! Tôi sẽ giải thích ba phương pháp indexing và khi nào nên sử dụng từng cái.

3.1. Simple Directory Reader - Cho Người Mới Bắt Đầu

Đây là cách đơn giản nhất. Tất cả file trong một thư mục sẽ được đọc và indexing tự động.

from llama_index.core import VectorStoreIndex, SimpleDirectoryReader
from llama_index.core import Settings
import openai

Cấu hình OpenAI client sử dụng HolySheep AI

client = openai.OpenAI( api_key="YOUR_HOLYSHEEP_API_KEY", base_url="https://api.holysheep.ai/v1" )

Đọc tất cả file từ thư mục documents/

LlamaIndex hỗ trợ: .pdf, .docx, .txt, .pptx, .csv, .jpg, .png...

documents = SimpleDirectoryReader( input_dir="./documents", recursive=True, # Đọc cả trong thư mục con exclude_hidden=True, # Bỏ qua file ẩn file_metadata=lambda file_path: { "file_name": file_path.split("/")[-1] } ).load_data() print(f"📄 Đã đọc {len(documents)} tài liệu")

Tạo Vector Index

index = VectorStoreIndex.from_documents(documents)

Lưu index để tái sử dụng (không cần indexing lại)

index.storage_context.persist(persist_dir="./index_storage") print("✅ Index đã được tạo và lưu!")

3.2. VectorStoreIndex - Cho Tài Liệu Lớn (1000+ files)

Khi bạn có hàng nghìn tài liệu, cách này giúp quản lý bộ nhớ tốt hơn và tăng tốc độ truy vấn.

from llama_index.core import VectorStoreIndex
from llama_index.core.node_parser import SentenceSplitter
from llama_index.core import Settings
import tiktoken

Cấu hình cách chia nhỏ tài liệu

Settings.node_parser = SentenceSplitter( chunk_size=1024, # Mỗi chunk 1024 tokens chunk_overlap=128, # Chồng lấn 128 tokens để không mất context separator="\n\n", # Tách theo đoạn văn )

Đọc tài liệu đã được xử lý trước đó

(Bạn có thể tái sử dụng documents từ ví dụ trên)

Tạo index với các tùy chọn nâng cao

index = VectorStoreIndex.from_documents( documents, show_progress=True, # Hiển thị thanh tiến trình )

Tạo query engine với các tham số tối ưu

query_engine = index.as_query_engine( similarity_top_k=5, # Lấy 5 kết quả gần nhất vector_similarity_cutoff=0.7, # Ngưỡng tương đồng response_mode="compact" # Compact để tiết kiệm token )

Thực hiện truy vấn

response = query_engine.query( "Tổng kết doanh thu quý 3 năm 2024 là bao nhiêu?" ) print(f"📝 Câu trả lời: {response}") print(f"📊 Nguồn tham khảo: {len(response.source_nodes)} nodes")

Cleanup để giải phóng bộ nhớ

del documents del index import gc gc.collect()

3.3. Summary Index - Cho Việc Tổng Hợp Nhanh

Khi bạn cần tóm tắt nhanh hoặc trả lời câu hỏi đơn giản, Summary Index là lựa chọn tốt nhất.

from llama_index.core import SummaryIndex
from llama_index.core import Document

Ví dụ: Tạo index từ một danh sách văn bản

texts = [ "LlamaIndex là một framework để xây dựng ứng dụng RAG.", "RAG viết tắt của Retrieval Augmented Generation.", "HolyShehe AI cung cấp API với chi phí thấp và độ trễ thấp." ]

Chuyển đổi thành Document objects

docs = [Document(text=t) for t in texts]

Tạo Summary Index

summary_index = SummaryIndex.from_documents(docs)

Tạo chat engine cho hội thoại liên tục

chat_engine = summary_index.as_chat_engine( chat_mode="condense_plus_context", memory_buffer_limit=10, # Lưu 10 tin nhắn gần nhất verbose=True )

Bắt đầu hội thoại

response = chat_engine.chat("LlamaIndex dùng để làm gì?") print(f"🤖 AI: {response}")

Tiếp tục hội thoại

response2 = chat_engine.chat("Còn HolySheep AI thì sao?") print(f"🤖 AI: {response2}")

Reset conversation nếu cần

chat_engine.reset()

Bước 4: Xử Lý Quy Mô Lớn - Chiến Lược Thực Chiến

Trong dự án thực tế của tôi, tôi đã xử lý 50,000+ tài liệu PDF với tổng dung lượng 200GB. Đây là chiến lược tôi đã áp dụng:

import os
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader
from concurrent.futures import ThreadPoolExecutor, as_completed
import time
from tqdm import tqdm

def process_batch(batch_files, batch_id):
    """
    Xử lý một batch tài liệu
    Trả về: list of documents đã được parse
    """
    batch_docs = []
    
    for file_path in batch_files:
        try:
            # Kiểm tra định dạng file
            ext = os.path.splitext(file_path)[1].lower()
            if ext not in ['.pdf', '.docx', '.txt', '.pptx']:
                continue
            
            # Đọc từng file
            reader = SimpleDirectoryReader(input_files=[file_path])
            docs = reader.load_data()
            
            # Thêm metadata để theo dõi
            for doc in docs:
                doc.metadata['batch_id'] = batch_id
                doc.metadata['source_file'] = os.path.basename(file_path)
            
            batch_docs.extend(docs)
            
        except Exception as e:
            print(f"⚠️ Lỗi xử lý {file_path}: {e}")
            continue
    
    return batch_docs

def large_scale_indexing(folder_path, output_path, batch_size=100):
    """
    Indexing quy mô lớn với xử lý batch và parallel processing
    """
    # 1. Thu thập danh sách tất cả file
    all_files = []
    for root, dirs, files in os.walk(folder_path):
        for file in files:
            all_files.append(os.path.join(root, file))
    
    total_files = len(all_files)
    print(f"📁 Tìm thấy {total_files} tài liệu")
    
    # 2. Chia thành các batch
    batches = [all_files[i:i+batch_size] 
               for i in range(0, len(all_files), batch_size)]
    
    print(f"📦 Chia thành {len(batches)} batches")
    
    # 3. Xử lý song song các batch
    all_documents = []
    
    start_time = time.time()
    
    with ThreadPoolExecutor(max_workers=4) as executor:
        futures = {
            executor.submit(process_batch, batch, i): i 
            for i, batch in enumerate(batches)
        }
        
        for future in tqdm(as_completed(futures), 
                          total=len(futures),
                          desc="Đang indexing"):
            batch_id = futures[future]
            try:
                batch_docs = future.result()
                all_documents.extend(batch_docs)
                
                # In tiến độ sau mỗi batch
                progress = (batch_id + 1) / len(batches) * 100
                elapsed = time.time() - start_time
                print(f"✅ Batch {batch_id+1}/{len(batches)} "
                      f"({progress:.1f}%) - "
                      f"{len(all_documents)} docs - "
                      f"{elapsed:.1f}s")
                      
            except Exception as e:
                print(f"❌ Batch {batch_id} thất bại: {e}")
    
    # 4. Tạo final index
    print("🔨 Đang tạo Vector Index cuối cùng...")
    final_index = VectorStoreIndex.from_documents(all_documents)
    
    # 5. Lưu index
    final_index.storage_context.persist(persist_dir=output_path)
    
    total_time = time.time() - start_time
    print(f"🎉 Hoàn thành!")
    print(f"   - Tổng tài liệu: {len(all_documents)}")
    print(f"   - Thời gian: {total_time:.2f} giây")
    print(f"   - Tốc độ: {len(all_documents)/total_time:.1f} docs/giây")
    
    return final_index

Sử dụng hàm:

index = large_scale_indexing(

folder_path="/path/to/your/documents",

output_path="./my_large_index",

batch_size=50 # Giảm nếu bị tràn bộ nhớ

)

Bảng So Sánh Chi Phí: HolySheep AI vs OpenAI

Đây là lý do tôi chọn HolySheep AI cho các dự án lớn:

ModelOpenAI ($/1M tokens)HolySheep AI ($/1M tokens)Tiết kiệm
GPT-4o$15.00$8.0047%
Claude Sonnet 3.5$3.00$1.5050%
Gemini 1.5 Flash$0.35$2.50CPU only
DeepSeek V3.2$0.55$0.4224%

Ví dụ thực tế: Với dự án indexing 50,000 tài liệu của tôi:

Mẹo Tối Ưu Hiệu Suất

Qua kinh nghiệm thực chiến, đây là những mẹo giúp tăng tốc độ và giảm chi phí:

# 1. Sử dụng embedding model local để tiết kiệm chi phí API
from llama_index.core import Settings
from llama_index.embeddings.huggingface import HuggingFaceEmbedding

Settings.embed_model = HuggingFaceEmbedding(
    model_name="BAAI/bge-small-en-v1.5"  # Nhẹ và nhanh
)

2. Bật cache để không phải tính toán lại

from llama_index.core import load_index_from_storage def get_cached_index(storage_path): """Load index đã lưu hoặc tạo mới nếu chưa có""" if os.path.exists(f"{storage_path}/default_vector_store"): print("📂 Đang load index từ cache...") storage_context = StorageContext.from_defaults( persist_dir=storage_path ) return load_index_from_storage(storage_context) else: print("🆕 Tạo index mới...") return None

3. Sử dụng batch processing cho truy vấn

query_engine = index.as_query_engine( streaming=True, # Streaming response để UX tốt hơn )

Xử lý nhiều câu hỏi cùng lúc

questions = [ "Doanh thu Q1 là bao nhiêu?", "Chi phí vận hành tháng 3?", "Số lượng nhân viên hiện tại?" ] for q in questions: start = time.time() response = query_engine.query(q) elapsed = time.time() - start print(f"Q: {q}") print(f"A: {response} ({elapsed*1000:.0f}ms)\n")

Lỗi Thường Gặp Và Cách Khắc Phục

Trong quá trình làm việc với LlamaIndex, tôi đã gặp nhiều lỗi khó chịu. Dưới đây là cách tôi đã giải quyết chúng:

1. Lỗi "ModuleNotFoundError: No module named 'llama_index'"

Nguyên nhân: Package chưa được cài đặt hoặc cài sai môi trường Python.

# Cách khắc phục:

1. Kiểm tra Python và pip version

python --version # Phải là 3.10 trở lên pip --version

2. Cài đặt với phiên bản cụ thể

pip install llama-index==0.10.38 pip install llama-index-core llama-index-readers-file

3. Nếu dùng conda, sử dụng:

conda create -n llamaindex python=3.11 conda activate llamaindex pip install llama-index

4. Kiểm tra đã cài đúng chưa

python -c "import llama_index; print(llama_index.__version__)"

2. Lỗi "RateLimitError: Exceeded quota" Hoặc "AuthenticationError"

Nguyên nhân: API key không hợp lệ hoặc đã hết quota.

# Cách khắc phục:

1. Kiểm tra API key trong file .env

HOLYSHEEP_API_KEY=sk-xxxxxx (không phải sk-OpenAI-xxxxx)

2. Test kết nối trực tiếp

import openai client = openai.OpenAI( api_key="YOUR_HOLYSHEEP_API_KEY", base_url="https://api.holysheep.ai/v1" )

Test API

try: response = client.chat.completions.create( model="gpt-4o-mini", messages=[{"role": "user", "content": "test"}], max_tokens=10 ) print("✅ Kết nối API thành công!") except Exception as e: print(f"❌ Lỗi: {e}")

3. Kiểm tra balance trên dashboard HolySheep AI

Truy cập: https://www.holysheep.ai/dashboard

3. Lỗi "MemoryError" Khi Indexing Nhiều File

Nguyên nhân: Bộ nhớ RAM không đủ khi xử lý quá nhiều tài liệu cùng lúc.

# Cách khắc phục:
import gc

def memory_safe_indexing(folder_path, batch_size=20):
    """
    Indexing an toàn cho bộ nhớ
    """
    all_files = get_all_files(folder_path)
    all_documents = []
    
    for i in range(0, len(all_files), batch_size):
        batch = all_files[i:i+batch_size]
        
        # Xử lý batch
        reader = SimpleDirectoryReader(input_files=batch)
        batch_docs = reader.load_data()
        all_documents.extend(batch_docs)
        
        # Tạo index tạm thời cho batch
        temp_index = VectorStoreIndex.from_documents(batch_docs)
        
        # Lưu từng batch riêng
        temp_index.storage_context.persist(
            persist_dir=f"./index_batch_{i//batch_size}"
        )
        
        # Cleanup bắt buộc!
        del batch_docs
        del temp_index
        gc.collect()
        
        print(f"✅ Hoàn thành batch {i//batch_size + 1}")
    
    return all_documents

Hoặc sử dụng setting giảm bộ nhớ

Settings.chunk_size = 512 # Giảm chunk size Settings.embed_batch_size = 10 # Giảm batch embedding

4. Lỗi "FileNotFoundError" Khi Đọc PDF

Nguyên nhân: Đường dẫn file không đúng hoặc file bị mã hóa.

# Cách khắc phục:
import os

def safe_load_document(file_path):
    """
    Load document với kiểm tra an toàn
    """
    # 1. Kiểm tra file có tồn tại không
    if not os.path.exists(file_path):
        print(f"❌ File không tồn tại: {file_path}")
        return None
    
    # 2. Kiểm tra quyền đọc
    if not os.access(file_path, os.R_OK):
        print(f"❌ Không có quyền đọc: {file_path}")
        # Linux/Mac: chmod +r file.pdf
        # Windows: Right-click > Properties > Security
        return None
    
    # 3. Kiểm tra kích thước file
    file_size = os.path.getsize(file_path)
    if file_size == 0:
        print(f"❌ File rỗng: {file_path}")
        return None
    if file_size > 100 * 1024 * 1024:  # > 100MB
        print(f"⚠️ File lớn ({file_size/1024/1024:.1f}MB), "
              f"cân nhắc chia nhỏ")
    
    # 4. Thử load với error handling
    try:
        reader = SimpleDirectoryReader(input_files=[file_path])
        docs = reader.load_data()
        print(f"✅ Đọc thành công: {file_path}")
        return docs
    except Exception as e:
        print(f"❌ Lỗi khi đọc {file_path}: {e}")
        return None

Sử dụng:

docs = safe_load_document("./documents/report_2024.pdf")

5. Lỗi "Embedding Dimension Mismatch"

Nguyên nhân: Embedding model sử dụng cho query không khớp với model đã dùng để index.

# Cách khắc phục:

Luôn sử dụng cùng một embedding model cho cả indexing và querying

from llama_index.core import Settings from llama_index.embeddings.huggingface import HuggingFaceEmbedding

Định nghĩa embedding model một lần duy nhất

EMBED_MODEL = HuggingFaceEmbedding( model_name="BAAi/bge-small-en-v1.5", embed_batch_size=32 )

Sử dụng cho cả Settings và khi load index

Settings.embed_model = EMBED_MODEL

Khi load index đã lưu:

storage_context = StorageContext.from_defaults( persist_dir="./my_index" )

KHÔNG cần chỉ định embed_model lại

LlamaIndex sẽ tự động sử dụng model từ Settings

index = load_index_from_storage(storage_context)

Hoặc nếu muốn chỉ định rõ:

index = load_index_from_storage( storage_context, embed_model=EMBED_MODEL # Đảm bảo cùng model )

Tổng Kết

Trong bài viết này, tôi đã chia sẻ với bạn:

LlamaIndex là một công cụ cực kỳ mạnh mẽ, nhưng điều quan trọng là bạn cần:

  1. Chọn đúng phương pháp indexing cho use case của mình
  2. Tối ưu chi phí bằng cách sử dụng API giá rẻ như HolySheep AI
  3. Quản lý bộ nhớ cẩn thận khi xử lý số lượng lớn
  4. Xử lý lỗi một cách có hệ thống

Nếu bạn có bất kỳ câu hỏi nào, để lại comment bên dưới. Tôi sẽ hỗ trợ bạn!


👉 Đăng ký HolySheep AI — nhận tín dụng miễn phí khi đăng ký

Tác giả: Minh - HolySheep AI Technical Writer | 5+ năm kinh nghiệm với AI và NLP