Skip to content

thangkh02/MultiFinRAG

Repository files navigation

📊 MultiFinRAG SEC Filing RAG

pipeline RAG multimodal cho các báo cáo SEC. Ý tưởng cốt lõi theo hướng MultiFinRAG:

  • Xem text, bảng (table), hình ảnh (image) là các object độc lập để truy xuất
  • Chuyển bảng và ảnh → semantic text (summary)
  • Embed tất cả bằng BGE
  • Lưu trữ và truy xuất bằng FAISS

Pipeline hiện tại:

  • SEC HTML filings
  • Convert sang PDF để xử lý text
  • Table và image lấy trực tiếp từ HTML để đảm bảo độ chính xác

🧠 Tổng quan Pipeline

PDF/HTML filings
|
+-- Text
|   +-- PyMuPDF extract text theo page
|   +-- tách câu (sentence split)
|   +-- sliding window + overlap
|   +-- embedding bằng BGE
|   +-- cosine distance giữa các câu
|   +-- breakpoint tại 95 percentile
|   +-- merge nếu similarity >= 0.85
|   +-- embed chunk cuối bằng BAAI/bge-base-en-v1.5
|
+-- Table
|   +-- parse HTML <table> bằng BeautifulSoup
|   +-- 1 bảng = 1 chunk
|   +-- giữ table_json từ HTML (source of truth)
|   +-- render bảng thành ảnh
|   +-- Gemma 3 27B Vision tạo semantic summary
|   +-- embed summary bằng BGE
|
+-- Image/chart
    +-- HTML <img>
    +-- tải ảnh gốc từ SEC
    +-- lọc ảnh meaningful
    +-- Gemma 3 27B Vision tạo summary
    +-- embed summary bằng BGE

FAISS
+-- text.faiss
+-- table.faiss
+-- image.faiss
+-- all.faiss (gộp tất cả)

📁 Cấu trúc Project

src/
  common/
    bge_embedder.py
  ingestion/
    html_to_pdf.py
  chunking/
    rebuild_text_chunks_bge.py
    build_pdfminer_image_chunks.py
    render_table_assets.py
  vlm/
    nvidia_vlm_client.py
    download_sec_image_assets.py
    enrich_image_chunks_vlm.py
    enrich_table_chunks_vlm.py
  indexing/
    build_bge_index.py
    combine_bge_indexes.py
  retrieval/
    retrieve_bge.py
  semantic_tagging/
    tag_pipeline.py
    semantic_tagger.py
  graph_extraction/
    extract_chunk_graph.py
    build_graph_nodes_edges.py
    build_graph_tensor.py
    llm_openie_model.py
    prompts.py
    base_openie_model.py
  evaluation/
    generate_eval_qa.py

data/
  raw_filings/
  pdfs/
  chunks/
  qa/
  index_bge/
  graph/

📦 Dữ liệu chính

Chunk files

data/chunks/text_chunks.jsonl
data/chunks/table_chunks.jsonl
data/chunks/image_chunks.jsonl
data/chunks/all_chunks.jsonl

Số lượng chunk

text: 1318
table: 1847
image: 369
total: 3534

Evaluation QA

eval: 150 câu
dev: 30 câu
test: 120 câu

Phân loại:

text: 75
table: 35
image: 25
multimodal: 15

Semantic Tagging

Semantic tagging currently follows only the paper schema from Multi-Document Financial Question Answering using LLMs.

The semantic_tags schema for chunks and queries is exactly:

{
  "named_entities": [],
  "dates": [],
  "industries": [],
  "domains": [],
  "sectors": [],
  "organizations": [],
  "partnerships": [],
  "partners": [],
  "dividends": [],
  "products": [],
  "locations": []
}

No extra semantic fields are added. The paper-schema output does not use chunk_role, evidence_type, section_tags, financial_metrics, business_topics, risk_topics, or retrieval_keywords.

Tagged Files

Chunk tags:

data/chunks/all_chunks_tagged_paper_schema.jsonl

Query tags for QA test split:

data/qa/test_qa_tagged.jsonl

Each tagged chunk keeps the original chunk fields and adds:

"semantic_tags": { "...": [] }

Each tagged QA item keeps the original QA fields and adds:

"query_semantic_tags": { "...": [] }

API Configuration

The taggers use an OpenAI-compatible chat API. For NVIDIA:

$env:OPENAI_API_KEY="your_nvidia_key"
$env:OPENAI_BASE_URL="https://integrate.api.nvidia.com/v1"
$env:OPENAI_MODEL="openai/gpt-oss-20b"

The local .env file can contain the same values:

OPENAI_API_KEY=...
OPENAI_BASE_URL=https://integrate.api.nvidia.com/v1
OPENAI_MODEL=openai/gpt-oss-20b

Tag All Chunks

Run from scratch:

python src/semantic_tagging/tag_pipeline.py --input data/chunks/all_chunks.jsonl --output data/chunks/all_chunks_tagged_paper_schema.jsonl --model openai/gpt-oss-20b --overwrite

Resume:

python src/semantic_tagging/tag_pipeline.py --input data/chunks/all_chunks.jsonl --output data/chunks/all_chunks_tagged_paper_schema.jsonl --model openai/gpt-oss-20b --resume

Dry run writes empty paper-schema tags without calling the LLM:

python src/semantic_tagging/tag_pipeline.py --input data/chunks/all_chunks.jsonl --output data/chunks/all_chunks_tagged_paper_schema.jsonl --dry-run --overwrite

Tag QA Queries

Tag all test QA queries:

python src/semantic_tagging/tag_query_pipeline.py --input data/qa/test_qa.jsonl --output data/qa/test_qa_tagged.jsonl --model openai/gpt-oss-20b --overwrite

Resume:

python src/semantic_tagging/tag_query_pipeline.py --input data/qa/test_qa.jsonl --output data/qa/test_qa_tagged.jsonl --model openai/gpt-oss-20b --resume

Tag one query for inspection:

python src/semantic_tagging/query_tagger.py --question "What risks does Apple mention about tariffs in 2025?" --model openai/gpt-oss-20b

Logs:

tagging_errors.log
query_tagging_errors.log

Knowledge Graph từ chunk (OpenIE + LLM)

Module src/graph_extraction trích thực thểtriple quan hệ từ nội dung chunk báo cáo tài chính (OpenIE hai bước: NER rồi trích triple), gọi API OpenAI-compatible giống semantic tagging (OPENAI_API_KEY, OPENAI_BASE_URL, OPENAI_MODEL trong .env hoặc biến môi trường).

Văn bản đưa vào LLM ưu tiên theo thứ tự: textsummaryembed_text. Một đoạn “focus” có thể được cắt quanh các từ mang tính biến động (vd. increased/decreased) khi passage quá dài; không bắt buộc chunk phải có quan hệ đó.

Schema trong chunk_graph.jsonl

Mỗi dòng là một chunk gốc kèm trường graph:

{
  "id": "...",
  "text": "...",
  "graph": {
    "entities": ["..."],
    "triples": [["subject", "relation_canonical", "object"]],
    "clean_triples": [["...", "...", "..."]],
    "noisy_triples": [{"triple": [...], "reason": "..."}]
  }
}
  • clean_triples: triple đã qua kiểm tra (grounding trong đoạn, chuẩn hóa relation, và ít nhất một đầu mút trùng NER).
  • noisy_triples: các triple bị loại kèm lý do để audit.
  • triples: trùng nội dung chính của clean_triples sau bước xử lý trong model.

Bước 1 — Trích graph (LLM)

Chạy từ đầu (ghi đè file output):

python src/graph_extraction/extract_chunk_graph.py --input data/chunks/all_chunks.jsonl --output data/graph/chunk_graph.jsonl --summary-out data/graph/graph_summary.json --overwrite

Tiếp tục sau khi dừng giữa chừng (giữ các dòng đã có graph, chỉ xử lý chunk thiếu):

python src/graph_extraction/extract_chunk_graph.py --input data/chunks/all_chunks.jsonl --output data/graph/chunk_graph.jsonl --summary-out data/graph/graph_summary.json --resume

Tham số hữu ích:

--model <ten_model>          # ghi đè OPENAI_MODEL
--max-chunks N               # thử nhanh trên N chunk đầu
--enable-delta-heuristic     # tùy chọn: chỉ khi LLM ra quá ít triple, fallback nhẹ cho câu có từ khóa tăng/giảm (mặc định tắt để không ép buộc)
--log-file graph_extraction_errors.log

Output:

data/graph/chunk_graph.jsonl
data/graph/graph_summary.json
graph_extraction_errors.log

Bước 2 — Gộp nodes / relations / edges (định dạng gần GFM-RAG)

Từ chunk_graph.jsonl sinh các file JSONL và CSV (cột CSV tương thích ý đồ nodes.csv, relations.csv, edges.csv của luồng bring-your-own-graph trong GFM-RAG: uid/name/type/attributes, source/relation/target/attributes, v.v.). Node loại chunk dùng chunk:<chunk_id>; node entity có id băm cố định từ tên đã normalize.

Khuyến nghị để có graph “đầy đủ” nhưng không lọc quá gắt (chỉ bỏ self-loop và object boolean yes/no và vài relation trạng thái nội bộ như filer_status / shell_company_status khi dùng --drop-low-value-edges; đã không loại triple chỉ vì object là số liệu):

python src/graph_extraction/build_graph_nodes_edges.py \
  --input data/graph/chunk_graph.jsonl \
  --nodes-out data/graph/nodes.jsonl \
  --edges-out data/graph/edges.jsonl \
  --relations-out data/graph/relations.jsonl \
  --nodes-csv-out data/graph/nodes.csv \
  --edges-csv-out data/graph/edges.csv \
  --relations-csv-out data/graph/relations.csv \
  --summary-out data/graph/graph_nodes_edges_summary.json \
  --add-equivalent-edges \
  --drop-low-value-edges \
  --use-default-relation-whitelist

Nếu muốn giữ mọi relation do LLM trích (không whitelist), bỏ --use-default-relation-whitelist và có thể bỏ --drop-low-value-edges.

Tham số khác:

--relation-whitelist rel1,rel2,...   # cộng thêm hoặc chỉ định (kết hợp được với default nếu cần logic riêng: chạy không flag default và chỉ dùng whitelist tùy bạn)

Một lệnh full pipeline + resume trích LLM

Sau khi đã có chunk_graph.jsonl một phần, chạy lệnh sau sẽ resume trích chunk thiếu rồi build lại toàn bộ nodes/relations/edges:

python src/graph_extraction/extract_chunk_graph.py --input data/chunks/all_chunks.jsonl --output data/graph/chunk_graph.jsonl --summary-out data/graph/graph_summary.json --resume && python src/graph_extraction/build_graph_nodes_edges.py --input data/graph/chunk_graph.jsonl --nodes-out data/graph/nodes.jsonl --edges-out data/graph/edges.jsonl --relations-out data/graph/relations.jsonl --nodes-csv-out data/graph/nodes.csv --edges-csv-out data/graph/edges.csv --relations-csv-out data/graph/relations.csv --summary-out data/graph/graph_nodes_edges_summary.json --add-equivalent-edges --drop-low-value-edges --use-default-relation-whitelist

Step 3 - Convert CSV graph to tensor graph for GFM/GNN

The CSV graph can be converted to a PyTorch Geometric Data object. This keeps the original directed edges as target_edge_index / target_edge_type, and also adds inverse edges to edge_index / edge_type for message passing.

python src/graph_extraction/build_graph_tensor.py \
  --graph-dir data/graph \
  --output-dir data/graph_tensor

Output:

data/graph_tensor/graph.pt
data/graph_tensor/node2id.json
data/graph_tensor/id2node.json
data/graph_tensor/rel2id.json
data/graph_tensor/tensor_summary.json

By default this creates structural tensors only (x=None, rel_attr=None, feat_dim=0). To add BGE node/relation features:

python src/graph_extraction/build_graph_tensor.py \
  --graph-dir data/graph \
  --output-dir data/graph_tensor_bge \
  --embed-features \
  --embedding-model BAAI/bge-base-en-v1.5

Step 4 - GFM-RAG Graph Retriever (KGC + Stage 2 SFT)

Pipeline GFM-RAG gom 2 giai doan: Stage 1 KGC fine-tune model hieu bieu do, Stage 2 SFT fine-tune model lay chunk lien quan den cau hoi.

Graph stats

nodes:     17,262  (13,728 entity + 3,534 chunk)
relations: 24 forward + 24 inverse = 48 total
edges:     79,592  (3,714 entity-entity + 75,878 entity-chunk via is_mentioned_in)

Stage 1 - KGC Fine-tuning

Fine-tune model tu checkpoint pretrain cua tac gia (model/model.pth) tren graph entity-entity.

Model: QueryNBFNetinput_dim=512, hidden_dims=[512]*6, message_func=distmult

Config:

configs/graph_retriever/kgc_gfm_ee_finetune.yaml

Chay:

python src/graph_retriever/train_kgc.py \
  --config configs/graph_retriever/kgc_gfm_ee_finetune.yaml

Ket qua:

typed_mrr: 0.2666  (epoch 13)
checkpoint: outputs/graph_retriever/kgc_gfm_typed_after_patch_full/model_besteefinal.pth

Luu y: disable_custom_rspmm: true de dung PyG message-passing fallback, khong can compile rspmm C++ extension.


Stage 2 - Data Preparation

Chuan bi data train Stage 2 tu data/qa/test_qa.jsonl (120 mau).

Pipeline:

test_qa.jsonl
  -> NER (GPT-OSS-20B API) trich entity tu cau hoi
  -> Entity Linking (exact match + company fallback tu ticker)
  -> Chunk Mapping (loc theo source_pdf + Jaccard overlap voi evidence)
  -> Target Entity (entity lien ket voi chunk qua is_mentioned_in)
  -> test_qa_stage2.json

Config:

configs/graph_retriever/stage2_data_prep.yaml

Chay:

python src/graph_retriever/prepare_stage2_data.py \
  --config configs/graph_retriever/stage2_data_prep.yaml

Ket qua:

output: data/qa/test_qa_stage2.json
total:  120 samples
start_nodes.entity co data: 120/120 (100%)
target_nodes.chunk co data: 120/120 (100%)
target_nodes.entity co data: 99/120 (82.5%)

Yeu cau API (dat trong .env):

OPENAI_API_KEY=...
OPENAI_BASE_URL=https://integrate.api.nvidia.com/v1
OPENAI_MODEL=openai/gpt-oss-20b

Stage 2 - Sanity Test

Kiem tra pipeline truoc khi full train: overfit 20 mau, xac nhan chunk_mrr > 0.1 va tang.

python src/graph_retriever/sanity_stage2.py \
  --config configs/graph_retriever/stage2_sft.yaml \
  --sanity-steps 300

Ket qua sanity: chunk_mrr: 0.0014 -> 0.3359 (300 steps) — PASS.


Stage 2 - SFT Fine-tuning

Fine-tune GNNRetriever tu KGC checkpoint, hoc lay chunk lien quan den cau hoi.

Model: GNNRetriever = QueryNBFNet (entity scorer) + SimpleRanker (entity -> chunk mapping)

Config:

configs/graph_retriever/stage2_sft_distill_bge_m3.yaml

Chay (can GPU, khuyen nghi T4 tro len):

python src/graph_retriever/train_stage2.py \
  --config configs/graph_retriever/stage2_sft_distill_bge_m3.yaml

Luu y quan trong:

  • Phai dung dtype: float32torch.sparse.mm khong ho tro float16 tren CUDA
  • train_batch_size: 1 do forward pass qua toan bo graph
  • BGE encoder nen chay tren CPU (relation_embedding_device: cpu)

Ket qua training BGE-M3 distill (run 2026-05-04 03:28 UTC):

chunk_mrr:      0.1994
chunk_hits@1:   0.0952
chunk_hits@5:   0.3333
chunk_hits@10:  0.5238
entity_mrr:     0.1221
checkpoint: outputs/graph_retriever/kgc_stage2_sft_distill_bge_m3/model_best.pth

So sanh voi random baseline: chunk_mrr cao hon random ~705 lan (random ≈ 1/3534).


Stage 2 - Retrieval Evaluation

Da co script danh gia retrieval doc lap cho Stage 2:

python src/graph_retriever/eval_stage2.py \
  --config configs/graph_retriever/stage2_sft.yaml \
  --checkpoint outputs/graph_retriever/kgc_stage2_sft/model_best.pth \
  --data data/qa/test_qa_stage2.json \
  --output outputs/graph_retriever/kgc_stage2_sft/eval_results.json \
  --top-k 20

Bang so sanh ket qua retrieval (full test 120 samples)

Metric Stage2 Model (GNNRetriever) HippoRAG (baseline lite) LightRAG (dense baseline) HippoRAG full-style + LLM rerank
chunk_mrr 0.3897 0.0691 0.2579 0.1501
chunk_hits@1 0.2750 0.0500 0.1167 0.0667
chunk_hits@2 0.3583 0.0583 0.1833 0.1000
chunk_hits@5 0.5583 0.0667 0.4083 0.2167
chunk_hits@10 0.6667 0.1083 0.6750 0.3833
chunk_hits@20 0.6833 0.1333 0.8083 0.4833
chunk_recall@5 0.5583 0.0667 0.4083 0.2167
chunk_recall@10 0.6667 0.1083 0.6750 0.3833
chunk_recall@20 0.6833 0.1333 0.8083 0.4833
entity_mrr 0.4595 0.1046 0.0171 0.0366
entity_hits@1 0.3460 0.0452 0.0038 0.0093
entity_hits@2 0.4481 0.1053 0.0144 0.0469
entity_hits@5 0.5972 0.1498 0.0183 0.0637
entity_hits@10 0.6755 0.2125 0.0365 0.0798
entity_hits@20 0.7651 0.2745 0.0571 0.0910
entity_recall@5 0.3431 0.1259 0.0183 0.0616
entity_recall@10 0.5098 0.1890 0.0365 0.0780
entity_recall@20 0.6606 0.2598 0.0565 0.0893

Ngoai ra da co them script baseline retrieval:

python src/graph_retriever/eval_retrieval_baselines.py \
  --config configs/graph_retriever/stage2_sft.yaml \
  --data data/qa/test_qa_stage2.json \
  --output outputs/graph_retriever/baseline_eval_results.json \
  --methods hipporag,lightrag \
  --top-k 20

HippoRAG full-style (fact retrieval + aggregate) kem LLM rerank tren top-K fact bang NVIDIA NIM/chat/completions (request requests trong script, dong bo voi tagging; can .env OPENAI_API_KEY/NVIDIA_API_KEY, OPENAI_BASE_URL):

python src/graph_retriever/eval_retrieval_baselines.py \
  --config configs/graph_retriever/stage2_sft.yaml \
  --data data/qa/test_qa_stage2.json \
  --output outputs/graph_retriever/baseline_nvidia_hipporag_full_llm.json \
  --methods hipporag_full \
  --top-k 20 \
  --hipporag-full-llm-rerank

Ghi chu:

  • LightRAG entity la dense query->entity baseline, chua co graph propagation.
  • HippoRAG cot "baseline lite" la propagation entity->chunk sparse, khong LLM rerank fact.
  • Cot "full-style + LLM rerank": retrieve facts bang embedding edge, LM chon subset fact (top nhap ~80 fact, output ~20); chunk_mrr cao hon lite va cao nhieu so voi full-style khong LM, nhung van thua Stage2 va LightRAG chunk (dense + graph entity da train).

Files GFM-RAG Graph Retriever

src/graph_retriever/
  train_kgc.py              Stage 1 KGC training
  prepare_stage2_data.py    Chuan bi data Stage 2 (NER + EL + chunk mapping)
  stage2_dataset.py         Dataset loader cho SFTTrainer
  train_stage2.py           Stage 2 SFT training
  sanity_stage2.py          Sanity check pipeline
  eval_stage2.py            Danh gia retrieval full test set cho Stage 2 model
  eval_retrieval_baselines.py  Baseline HippoRAG/LightRAG retrieval evaluation
  graph_adapter.py          Load graph + build target_to_other_types
  rel_features.py           Encode relation embeddings (BGE)
  prepare_distill_teacher_features.py  Prepare teacher embeddings for distillation
  distill_features.py       DistillationFeatureLoader class

configs/graph_retriever/
  kgc_gfm_ee_finetune.yaml  Config KGC Stage 1
  stage2_data_prep.yaml     Config data prep Stage 2
  stage2_sft.yaml           Config training Stage 2 (with BGE-base teacher)
  stage2_sft_distill_bge_m3.yaml  Config training Stage 2 (with BGE-M3 teacher)

outputs/graph_retriever/
  kgc_gfm_typed_after_patch_full/model_besteefinal.pth  KGC checkpoint (typed_mrr=0.2666)
  kgc_stage2_sft/model_best.pth                         Stage 2 checkpoint (chunk_mrr=0.2149)
  kgc_stage2_sft_distill_bge_m3/model_best.pth          Stage 2 checkpoint với BGE-M3 distill (chunk_mrr=0.1994)

Ablation Studies: Hard Labels + Distillation

Để so sánh ảnh hưởng của các thành phần khác nhau, có thể chạy các ablation khác nhau mà không thay đổi graph tensor chính hoặc KGC checkpoint.

Cấu trúc Ablation

Config Teacher Graph Losses Mục đích
stage2_sft.yaml BGE-base-en-v1.5 chính (768) hard + distill Baseline với distillation
stage2_sft_distill_bge_m3.yaml BAAI/bge-m3 chính (768) hard + distill Teacher model tốt hơn, checkpoint hiện tại
Hard-only none chính (768) hard only Hard labels baseline

Ablation 1: Chuẩn bị teacher embeddings (tùy chọn)

Teacher embeddings được chuẩn bị riêng biệt, không thay đổi graph tensor chính. Bước này bắt buộc khi muốn test teacher models khác.

Chuẩn bị BGE-base teacher (nếu chưa có):

python src/graph_retriever/prepare_distill_teacher_features.py \
  --config configs/graph_retriever/stage2_sft.yaml \
  --teacher-model BAAI/bge-base-en-v1.5 \
  --output-dir data/distill_features/bge-base-en-v1.5 \
  --force

Chuẩn bị BGE-M3 teacher (model tốt hơn):

python src/graph_retriever/prepare_distill_teacher_features.py \
  --config configs/graph_retriever/stage2_sft.yaml \
  --teacher-model BAAI/bge-m3 \
  --output-dir data/distill_features/bge-m3 \
  --force

Output:

data/distill_features/bge-base-en-v1.5/
  ├── node_x.pt                    (node embeddings)
  ├── question_embeddings.pt       (question embeddings)
  ├── sample_q2idx.json            (mapping sample -> embedding index)
  └── meta.json                    (metadata)

data/distill_features/bge-m3/
  ├── node_x.pt                    (shape: [17262, 1024])
  ├── question_embeddings.pt       (shape: [120, 1024])
  ├── sample_q2idx.json
  └── meta.json

Ablation 2a: Hard Labels Only (Baseline)

Chạy Stage 2 mà không có distillation (disable trong config):

Cách 1: Tạo config tạm thời

# Copy config và disable distillation
cp configs/graph_retriever/stage2_sft.yaml /tmp/stage2_hard_only.yaml

# Sửa /tmp/stage2_hard_only.yaml:
# distillation:
#   enable: false   <-- Thay từ true

python src/graph_retriever/train_stage2.py \
  --config /tmp/stage2_hard_only.yaml \
  --run-sanity-first

Cách 2: Dùng script

# Tạo config ngay
cat > configs/graph_retriever/stage2_sft_hard_only.yaml << 'EOF'
# Identical to stage2_sft.yaml but with distillation disabled
gfmrag_path: null
disable_custom_rspmm: true
# ... (copy toàn bộ config)
distillation:
  enable: false  # ← Key change
# ... (phần còn lại giống)
EOF

python src/graph_retriever/train_stage2.py \
  --config configs/graph_retriever/stage2_sft_hard_only.yaml \
  --run-sanity-first

Expected output: outputs/graph_retriever/kgc_stage2_sft/

Metrics (hard only, ~20 epochs):

chunk_mrr: ~0.15-0.17 (thấp hơn hard+distill)
entity_mrr: ~0.08-0.10

Ablation 2b: Hard + Distillation (BGE-base, mặc định)

Chạy với config mặc định (BGE-base teacher distillation):

python src/graph_retriever/train_stage2.py \
  --config configs/graph_retriever/stage2_sft_distill_bge_m3.yaml \
  --run-sanity-first

Expected output: outputs/graph_retriever/kgc_stage2_sft/

Metrics (hard + BGE-base distill, ~35 epochs):

chunk_mrr: 0.1828
entity_mrr: 0.1073
chunk_hits@10: 0.4286

Ablation 2c: Hard + Distillation (BGE-M3, teacher tốt hơn)

Bước 1: Chuẩn bị teacher embeddings (nếu chưa có)

python src/graph_retriever/prepare_distill_teacher_features.py \
  --config configs/graph_retriever/stage2_sft.yaml \
  --teacher-model BAAI/bge-m3 \
  --output-dir data/distill_features/bge-m3 \
  --force

Bước 2: Chạy training với config BGE-M3

python src/graph_retriever/train_stage2.py \
  --config configs/graph_retriever/stage2_sft_distill_bge_m3.yaml \
  --run-sanity-first

Expected output: outputs/graph_retriever/kgc_stage2_sft_distill_bge_m3/

Metrics (hard + BGE-M3 distill, run 2026-05-04 03:28 UTC):

chunk_mrr:       0.1994
chunk_hits@1:    0.0952
chunk_hits@2:    0.1429
chunk_hits@5:    0.3333
chunk_hits@10:   0.5238
chunk_hits@20:   0.5714
chunk_recall@5:  0.3333
chunk_recall@10: 0.5238
chunk_recall@20: 0.5714

entity_mrr:       0.1221
entity_hits@1:    0.0553
entity_hits@2:    0.1347
entity_hits@5:    0.1984
entity_hits@10:   0.2287
entity_hits@20:   0.2810
entity_recall@5:  0.1436
entity_recall@10: 0.1988
entity_recall@20: 0.2591

So sánh Ablation

Ablation Teacher chunk_mrr entity_mrr Ghi chú
Hard only none 0.15-0.17 0.08-0.10 Baseline không distill
Hard+Distill (BGE-base) bge-base-en-v1.5 0.1828 0.1073 Config mặc định
Hard+Distill (BGE-M3) bge-m3 0.1994 0.1221 Checkpoint hiện tại

Lưu ý quan trọng

  1. Không thay graph chính: Cả ba ablation dùng graph tensor chính data/graph_tensor/graph.pt (768 chiều)
  2. Student model giống nhau: Checkpoint KGC và model architecture không đổi
  3. Teacher features riêng: Mỗi teacher model được load từ folder riêng (data/distill_features/...)
  4. Sanity gate: --run-sanity-first chạy 20 samples, 300 steps trước khi full train
  5. Memory: Mỗi ablation dùng ~12-14GB VRAM trên T4 (batch_size=1 + full graph forward)

Monitoring Ablation

Mở mỗi checkpoint logs để so sánh:

# Check training curves
tail -100 outputs/graph_retriever/kgc_stage2_sft/training_logs.json
tail -100 outputs/graph_retriever/kgc_stage2_sft_distill_bge_m3/training_logs.json

# Compare best metrics
grep "best_metric" outputs/graph_retriever/*/model_best.pth  # (requires reading .pth metadata)

# Or use tensorboard nếu có logs
# tensorboard --logdir outputs/graph_retriever/

Custom Ablation

Để thêm ablation mới (ví dụ: test teacher model khác), làm theo các bước:

  1. Chuẩn bị teacher embeddings:
python src/graph_retriever/prepare_distill_teacher_features.py \
  --config configs/graph_retriever/stage2_sft.yaml \
  --teacher-model <NEW_MODEL> \
  --output-dir data/distill_features/<NEW_MODEL> \
  --force
  1. Tạo config phụ:
# configs/graph_retriever/stage2_sft_distill_<name>.yaml
# Copy từ stage2_sft.yaml và thay:
distillation:
  teacher_model: <NEW_MODEL>
  teacher_feature_dir: data/distill_features/<NEW_MODEL>
  1. Chạy training:
python src/graph_retriever/train_stage2.py \
  --config configs/graph_retriever/stage2_sft_distill_<name>.yaml \
  --run-sanity-first

Rebuild Pipeline

1. Convert HTML → PDF

python src/ingestion/html_to_pdf.py

2. Text Chunking

python src/chunking/rebuild_text_chunks_bge.py

3. Image Chunking

Download ảnh:

python src/vlm/download_sec_image_assets.py

Summary bằng VLM:

python src/vlm/enrich_image_chunks_vlm.py --replace-current

4. Table Chunking

Render bảng:

python src/chunking/render_table_assets.py

Summary:

python src/vlm/enrich_table_chunks_vlm.py --replace-current
  • Số liệu bảng lấy từ HTML (không dùng VLM)
  • VLM chỉ dùng để tạo semantic summary

5. Build FAISS Index

python src/indexing/build_bge_index.py --index all --batch-size 64

Hoặc build riêng:

python src/indexing/build_bge_index.py --index table --batch-size 64
python src/indexing/combine_bge_indexes.py

6. Retrieval

python src/retrieval/retrieve_bge.py "restricted cash" --index table --top-k 3

python src/retrieval/retrieve_bge.py "Daily 95% One-Day Total Management VaR" --index image --top-k 3

python src/retrieval/retrieve_bge.py "net revenue increased" --index all --top-k 5

7. FinanceBench Retrieval Evaluation

FinanceBench khong co ground-truth chunk_id. File benchmark chi co question, answer, evidence_text, evidence_page_num, evidence_doc_name/doc_name va PDF goc. Vi vay evaluation script se tu map evidence vao chunk do pipeline cua minh tao ra:

  1. exact match evidence_text trong chunk.text
  2. fuzzy/token-overlap match neu exact match khong duoc
  3. fallback theo page neu van khong match duoc

Chay sau khi da chunk va build FAISS index cho PDF FinanceBench:

python src/evaluation/financebench_retrieval_eval.py ^
  --benchmark benchmark/financebench/data/financebench_open_source.jsonl ^
  --chunks data/chunks/all_chunks.jsonl ^
  --index data/index_bge/all.faiss ^
  --ids data/index_bge/all_chunk_ids.json ^
  --k-values 1,3,5,10 ^
  --out-dir data/eval/financebench_retrieval

Output:

data/eval/financebench_retrieval/qrels.jsonl
data/eval/financebench_retrieval/qrel_misses.jsonl
data/eval/financebench_retrieval/runs.jsonl
data/eval/financebench_retrieval/per_question_metrics.jsonl
data/eval/financebench_retrieval/aggregate_metrics.csv
data/eval/financebench_retrieval/report.md

Metrics gom Precision@k, Recall@k, Hit@k, MRR@k, Page Recall@k, va Evidence Recall@k.


7.1 Retrieval Benchmark cho RAG_SEM (tagged vs untagged)

Muc nay danh gia retrieval-only cho pipeline RAG_SEM trong project:

  • So sanh query khong tagged (data/qa/test_qa.jsonl) va query co tagged (data/qa/test_qa_tagged.jsonl)
  • So sanh cac method: BM25, Dense BGE, tag-aware variants, va Hybrid RRF(BM25 + Dense)
  • Co them buoc rerank top-N sau fusion (hien tai thu nghiem top-20)

Luu y quan trong:

  • Khong retag lai chunks
  • Khong retag lai queries
  • Khong re-embed chunks
  • Chi retrieve va tinh metric retrieval

Du lieu dau vao

data/chunks/all_chunks.jsonl
data/chunks/all_chunks_tagged_paper_schema.jsonl
data/index_bge/all.faiss
data/index_bge/all_chunk_ids.json
data/index_tagged_chunks/chunks.faiss
data/index_tagged_chunks/chunk_ids.json
data/qa/test_qa.jsonl
data/qa/test_qa_tagged.jsonl

Lenh chay benchmark (query khong tagged)

python -m src.evaluation.evaluate_rag_sem_retrieval `
  --queries data/qa/test_qa.jsonl `
  --tagged-index-dir data/index_tagged_chunks `
  --baseline-index data/index_bge/all.faiss `
  --baseline-ids data/index_bge/all_chunk_ids.json `
  --baseline-chunks data/chunks/all_chunks.jsonl `
  --out-dir outputs/retrieval_benchmark_report_untagged_queries_hybrid_rrf_top20 `
  --k-values 5 10 `
  --candidate-k 50 `
  --include-bm25 `
  --include-tag-aware `
  --include-hybrid-rrf `
  --rrf-k 60 `
  --hybrid-rerank-top-n 20 `
  --hybrid-rerank-weight 1.0 `
  --hybrid-rerank-batch-size 32

Lenh chay benchmark (query co tagged)

python -m src.evaluation.evaluate_rag_sem_retrieval `
  --queries data/qa/test_qa_tagged.jsonl `
  --tagged-index-dir data/index_tagged_chunks `
  --baseline-index data/index_bge/all.faiss `
  --baseline-ids data/index_bge/all_chunk_ids.json `
  --baseline-chunks data/chunks/all_chunks.jsonl `
  --out-dir outputs/retrieval_benchmark_report_tagged_queries_hybrid_rrf_top20 `
  --k-values 5 10 `
  --candidate-k 50 `
  --include-bm25 `
  --include-tag-aware `
  --include-hybrid-rrf `
  --rrf-k 60 `
  --hybrid-rerank-top-n 20 `
  --hybrid-rerank-weight 1.0 `
  --hybrid-rerank-batch-size 32

File output chinh

outputs/retrieval_benchmark_report_untagged_queries_hybrid_rrf_top20/metrics_summary.json
outputs/retrieval_benchmark_report_untagged_queries_hybrid_rrf_top20/metrics_by_question.jsonl
outputs/retrieval_benchmark_report_untagged_queries_hybrid_rrf_top20/retrieval_results_all_modes.jsonl
outputs/retrieval_benchmark_report_tagged_queries_hybrid_rrf_top20/metrics_summary.json
outputs/retrieval_benchmark_report_tagged_queries_hybrid_rrf_top20/metrics_by_question.jsonl
outputs/retrieval_benchmark_report_tagged_queries_hybrid_rrf_top20/retrieval_results_all_modes.jsonl
outputs/retrieval_benchmark_report_summary.md

Cach doc ket qua nhanh

  • Dung metrics_summary.json de so method theo Hit@k, Recall@k, MRR@k, NDCG@k
  • Dung metrics_by_question.jsonl de xem query nao huong loi/bi giam khi bat tag-aware hoac hybrid
  • Dung retrieval_results_all_modes.jsonl de debug chi tiet top chunks theo tung method
  • tag_boost va tag_filter la bien the implementation-specific cua project (paper khong cho cong thuc scoring/filtering cu the)

8. FinanceBench Semantic BGE Retrieval Result

Da tao benchmark retrieval tu FinanceBench open-source bang semantic text chunking BGE.

Input:

benchmark/financebench/data/financebench_open_source.jsonl
benchmark/financebench/pdfs/

Chunking:

PDF -> sentence split -> BGE sentence embedding -> semantic breakpoints -> text chunks

Do may hien tai khong co CUDA, da chay CPU voi:

BAAI/bge-small-en-v1.5

Output chunks:

outputs/financebench_eval_bge/chunks.jsonl

Chay semantic chunking:

python -m rag_eval.src.build_financebench_bge_chunks `
  --financebench benchmark/financebench/data/financebench_open_source.jsonl `
  --pdf-dir benchmark/financebench/pdfs `
  --output outputs/financebench_eval_bge/chunks.jsonl `
  --model BAAI/bge-small-en-v1.5 `
  --batch-size 32

Tao retrieval benchmark tu chunks:

python -m rag_eval.src.create_qrels `
  --financebench benchmark/financebench/data/financebench_open_source.jsonl `
  --chunks outputs/financebench_eval_bge/chunks.jsonl `
  --out-dir outputs/financebench_eval_bge/qrels

File danh gia duoc tao:

outputs/financebench_eval_bge/qrels/queries.jsonl
outputs/financebench_eval_bge/qrels/qrels.jsonl
outputs/financebench_eval_bge/qrels/unmatched_evidence.jsonl
outputs/financebench_eval_bge/qrels/mapping_report.json

Thong ke chunks/qrels:

semantic chunks:      9927
docs_with_chunks:     84
questions:            150
evidence_rows:        189
qrels raw:            258
qrels active:         248
unmatched_evidence:   0
match_method_counts:  fuzzy_text=182, exact_text=66

Da audit va loc bot qrels dang ngo:

Tieu chi loc: fuzzy_text co token_recall < 0.60
So qrels bi loai: 10
So query bi anh huong: 7
So query con lai trong benchmark: 150/150
remaining low-token fuzzy qrels: 0

Khong loai tat ca page_match=False, vi semantic chunk co the gom nhieu page hoac page index cua parser PDF lech voi FinanceBench. Neu token_recall van du cao thi qrel duoc giu lai.

File qrels:

outputs/financebench_eval_bge/qrels/qrels.jsonl                  # active, da loc
outputs/financebench_eval_bge/qrels/qrels_unfiltered.jsonl       # backup ban raw
outputs/financebench_eval_bge/qrels/removed_qrels_suspicious.jsonl
outputs/financebench_eval_bge/qrels/mapping_report.json

Phan bo query -> relevant chunks:

1 chunk relevant : 103 queries
2 chunks relevant: 30 queries
3 chunks relevant: 11 queries
4 chunks relevant: 5 queries
5 chunks relevant: 1 query

Evaluation output:

outputs/financebench_eval_bge/retrieval_eval/

Chay retrieval evaluation trong notebook:

notebooks/financebench_current_retrieval_hybrid_eval.ipynb
notebooks/financebench_fast_hybrid_retrieval_eval.ipynb

Audit qua trinh tao benchmark:

notebooks/financebench_retrieval_benchmark_audit.ipynb

File ket qua evaluation:

outputs/financebench_eval_bge/retrieval_eval_filtered/bm25_retrieval_results.jsonl
outputs/financebench_eval_bge/retrieval_eval_filtered/bge_dense_retrieval_results.jsonl
outputs/financebench_eval_bge/retrieval_eval_filtered/hybrid_retrieval_results.jsonl
outputs/financebench_eval_bge/retrieval_eval_filtered/metadata_aware_retrieval_results.jsonl
outputs/financebench_eval_bge/retrieval_eval_filtered/retrieval_results.jsonl
outputs/financebench_eval_bge/retrieval_eval_filtered/metrics_summary.json
outputs/financebench_eval_bge/retrieval_eval_filtered/metrics_by_question.jsonl
outputs/financebench_eval_bge/retrieval_eval_filtered/retrieval_eval_report.md

Chay lai evaluation filtered:

python -m rag_eval.src.run_financebench_filtered_retrieval_eval `
  --base-dir outputs/financebench_eval_bge `
  --out-dir outputs/financebench_eval_bge/retrieval_eval_filtered `
  --top-k 10 `
  --candidate-k 50 `
  --hybrid-alpha 0.60 `
  --reranker-model cross-encoder/ms-marco-MiniLM-L-6-v2 `
  --reranker-batch-size 8

Ket qua retrieval:

Method Hit@1 Recall@1 MRR@1 Hit@10 Recall@10 MRR@10 Precision@10
bge_dense 0.1067 0.0650 0.1067 0.3400 0.2694 0.1695 0.0387
bm25 0.0600 0.0500 0.0600 0.1733 0.1539 0.0947 0.0213
bm25_bge_hybrid_alpha_0.60 0.1000 0.0706 0.1000 0.3267 0.2639 0.1563 0.0387
bm25_bge_hybrid_alpha_0.60_reranker_cross_encoder_ms_marco_minilm_l_6_v2 0.1067 0.0722 0.1067 0.3133 0.2522 0.1605 0.0373
metadata_doc_filter_bm25_bge_hybrid_alpha_0.60 0.2067 0.1617 0.2067 0.5333 0.4596 0.3018 0.0680

Nhan xet:

bge_dense dang tot nhat trong open-corpus retrieval theo Hit@10/Recall@10.
BM25 thuan thap hon dense.
Hybrid alpha=0.60 gan bang dense nhung chua vuot dense.
Reranker nhe cross-encoder cai thien Recall@1 so voi dense/hybrid, nhung giam Hit@10/Recall@10 vi rerank lai top-50.
metadata_doc_filter la cau hinh oracle biet truoc doc_name, khong so sanh truc tiep voi open-corpus retrieval.
FinanceBench BGE chunks hien tai chi la text chunks, nen chua co table-aware retrieval rieng.

File metric chinh:

outputs/financebench_eval_bge/retrieval_eval_filtered/metrics_summary.json

🎯 Stage 2 Fine-tuning Results

Hybrid Training (Hard Labels + Distillation)

Pipeline Stage 2 sử dụng kết hợp Hard Labels (nhãn cứng từ ground truth) và Knowledge Distillation (chuyển giao kiến thức từ teacher model) để cải thiện hiệu suất ranking chunk.

Khái niệm và Cách tiếp cận

Hard Labels: Từ test_qa_stage2.json, mỗi câu hỏi có:

  • start_nodes: entity được trích rút từ câu hỏi (được NER API gán)
  • target_nodes.chunk: chunk ground truth (được mapping từ evidence)
  • target_nodes.entity: entity liên kết tới chunk đó qua is_mentioned_in

Hard label được coi là "cứng" vì nó là ground truth có sẵn, không soft/fuzzy.

Knowledge Distillation: Student model (GNNRetriever hiện tại) học từ teacher model (KGC checkpoint từ Stage 1):

  • Teacher model đã được huấn luyện trên entity-entity relation (có typed_mrr=0.2666)
  • Student học cả ranking loss + mse_distill_chunk để mềm hóa các prediction

Cấu hình Training

Training configuration mới nhất: configs/graph_retriever/stage2_sft_distill_bge_m3.yaml

Teacher distillation: BAAI/bge-m3

Loss Functions:

Loss Weight Mô tả
bce_chunk 0.3 Binary cross-entropy trên hard chunk labels. Giúp model học phân biệt chunk positive/negative
listce_chunk 0.7 ListCE (list-wise cross-entropy) / ranking loss. Cải thiện ranking giữa nhiều candidates
mse_distill_chunk 0.1 MSE distillation từ teacher model. Khuyến khích student học tương tự teacher logits

Cộng lại: $0.3 + 0.7 + 0.1 = 1.1$ (normalize trong code)

Tham số quan trọng:

  • train_batch_size: 1 — Do forward pass trên toàn bộ graph, cần batch nhỏ
  • num_epochs: 20
  • learning_rate: 1e-4
  • warmup_steps: 100
  • optimizer: AdamW
  • dtype: float32torch.sparse.mm không hỗ trợ float16 trên CUDA

Dữ liệu Training

Train: 100 samples (từ 120 test split)
Val:   20 samples
Test:  120 samples (full test set)

Distribution:
- start_nodes.entity 100% có data
- target_nodes.chunk 100% có data  
- target_nodes.entity 82.5% có data (41/50 missing do entity linking không match)

Nếu target_entity không có, loss mse_distill_chunk được skip cho sample đó.

Evaluation Metrics (BGE-M3 Distillation - run 2026-05-04 03:28 UTC)

Chunk Retrieval:

Metric Score
chunk_mrr 0.1994
chunk_hits@1 0.0952
chunk_hits@2 0.1429
chunk_hits@5 0.3333
chunk_hits@10 0.5238
chunk_hits@20 0.5714
chunk_recall@5 0.3333
chunk_recall@10 0.5238
chunk_recall@20 0.5714

Entity Retrieval:

Metric Score
entity_mrr 0.1221
entity_hits@1 0.0553
entity_hits@2 0.1347
entity_hits@5 0.1984
entity_hits@10 0.2287
entity_hits@20 0.2810
entity_recall@5 0.1436
entity_recall@10 0.1988
entity_recall@20 0.2591

So sánh với Baseline

Method chunk_mrr entity_mrr
Random (baseline) ~0.00028 ~0.00028
Stage 2 SFT (Hard+Distill, BGE-base) 0.1828 0.1073
Stage 2 SFT (Hard+Distill, BGE-M3) 0.1994 0.1221
Cải thiện BGE-M3 vs random ~712x ~436x

Training Command

Chạy từ đầu:

python src/graph_retriever/train_stage2.py \
  --config configs/graph_retriever/stage2_sft_distill_bge_m3.yaml

Chạy sanity test (overfit 20 samples, 300 steps) trước:

python src/graph_retriever/train_stage2.py \
  --config configs/graph_retriever/stage2_sft_distill_bge_m3.yaml \
  --run-sanity-first

Resume từ checkpoint:

python src/graph_retriever/train_stage2.py \
  --config configs/graph_retriever/stage2_sft_distill_bge_m3.yaml \
  --resume \
  --resume-from outputs/graph_retriever/kgc_stage2_sft_distill_bge_m3/model_checkpoint.pth

Output

outputs/graph_retriever/kgc_stage2_sft_distill_bge_m3/
  model_best.pth                    # Best checkpoint (chunk_mrr=0.1994)
  model_last.pth                    # Last checkpoint
  training_logs.json                # Training/val metrics per epoch
  training_args.bin                 # Huggingface Trainer config

Lưu ý khi Fine-tuning

  1. Memory: Vì batch_size=1 và forward pass trên toàn bộ graph, cần GPU có đủ memory (T4 16GB là chuẩn)
  2. Float32: Bắt buộc dtype: float32 do PyTorch sparse matrix không hỗ trợ float16 trên CUDA
  3. Distillation weight: Nếu distillation loss quá cao (0.1), model có thể quá khít theo teacher; nếu quá thấp (0.01), distillation không có tác dụng
  4. Hard label quality: Kết quả phụ thuộc vào chất lượng NER + entity linking ở Stage 2 data prep
  5. Teacher checkpoint: Phải là KGC checkpoint đã fine-tune đúng (không phải random pretrain)

Thay đổi Embedding Model Teacher

Hiện tại sử dụng BAAI/bge-base-en-v1.5 (768 chiều). Có thể upgrade lên mô hình tốt hơn cho T4:

Các lựa chọn khuyến nghị

Model Chiều Params Memory Tốc độ T4 Chất lượng Khuyến nghị
bge-base-en-v1.5 768 109M ~1.1GB baseline baseline Hiện tại
bge-m3 384 84M ~400MB +40% +2% Tốt nhất cho T4
bge-small-en-v1.5 384 33M ~150MB +60% -10% Chi tiết tức thì
bge-large-en-v1.5 1024 335M ~2.5GB -30% +5% Nếu VRAM đủ

Cách chuyển đổi (tự động - khuyến nghị)

Cách dễ nhất — dùng script tiện ích:

# Liệt kê các model khả dụng
python src/graph_retriever/switch_embedding_model.py --list-models

# Chuyển sang bge-m3 (auto rebuild graph tensor)
python src/graph_retriever/switch_embedding_model.py --model bge-m3 --auto-rebuild

# Hoặc chuyển sang model khác
python src/graph_retriever/switch_embedding_model.py --model bge-small --auto-rebuild
python src/graph_retriever/switch_embedding_model.py --model BAAI/bge-large-en-v1.5 --auto-rebuild

Script sẽ tự động:

  1. ✅ Cập nhật config YAML
  2. ✅ Xóa cache embedding cũ
  3. ✅ Rebuild graph tensor (đốn ~5 phút)

Sau đó chạy training:

python src/graph_retriever/train_stage2.py \
  --config configs/graph_retriever/stage2_sft.yaml

Cách chuyển đổi (thủ công)

Nếu muốn kiểm soát từng bước:

Bước 1: Cập nhật config

# configs/graph_retriever/stage2_sft.yaml
graph:
  relation_embedding_model: BAAI/bge-m3         # thay từ bge-base-en-v1.5
  relation_embedding_device: cpu
data:
  text_emb_model: BAAI/bge-m3                   # thay từ bge-base-en-v1.5

Bước 2: Xóa cache embedding cũ (vì chiều thay đổi từ 768 → 384)

rm -f data/qa/test_question_embeddings.pt
rm -rf data/graph_tensor/                       # rebuild relation embeddings

Bước 3: Rebuild graph tensor với embedding mới

python src/graph_extraction/build_graph_tensor.py \
  --graph-dir data/graph \
  --output-dir data/graph_tensor \
  --embed-features \
  --embedding-model BAAI/bge-m3

Bước 4: Chạy training Stage 2 (sẽ tự rebuild question embeddings)

python src/graph_retriever/train_stage2.py \
  --config configs/graph_retriever/stage2_sft.yaml

Kết quả dự kiến

Khi chuyển từ bge-base sang bge-m3:

Memory usage:       1.1GB → ~400MB  (-64%)
Relation embedding: ~45s → ~27s per batch
Training time:      ~2h → ~1.5h (tổng 35 epochs)
chunk_mrr:          0.1828 → 0.185-0.190 (tăng nhẹ ~1%)
Entity linking:     Tương tự (không phụ thuộc embedding dim)

Lưu ý quan trọng

⚠️ Khi thay đổi embedding model:

  1. Phải rebuild toàn bộ graph_tensor (chiều thay đổi)
  2. Phải xóa cache question embeddings (chiều khác)
  3. MSE distillation loss sẽ thay đổi vì node features khác
  4. Có thể cần retune mse_distill_chunk weight (mặc định 0.1)
  5. Performance ổn định sau ~10 epochs, không cần retrain từ đầu

So sánh chi tiết các model

bge-m3 (khuyến nghị):

  • ✅ Đủ tốt cho financial domain (multilingual, specialized)
  • ✅ Nhanh hơn 40% trên T4
  • ✅ Distillation loss ổn định (fewer dimensions = easier MSE fit)

bge-small (tiết kiệm tối đa):

  • ✅ Nhanh nhất, memory tối thiểu
  • ⚠️ Chất lượng giảm ~10% (có thể ảnh hưởng ranking)

bge-large (nếu upgrade):

  • ✅ Chất lượng tốt nhất
  • ⚠️ Cần VRAM nhiều, chạy CPU embedding_device bắt buộc
  • ⚠️ Chậm hơn base ~30% trên T4

About

MultiFinRAG SEC Filing RAG

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages