--- library_name: sentence-transformers pipeline_tag: sentence-similarity tags: - sentence-transformers - sentence-similarity - feature-extraction license: mit datasets: - airesearch/WangchanX-Legal-ThaiCCL-RAG - VISAI-AI/nitibench language: - th base_model: - BAAI/bge-m3 --- # Auto-Finetuned BGE-M3 CCL **[[📄 Technical Report](https://arxiv.org/pdf/2502.10868)]** This is a finetuned [`BAAI/bge-m3`](https://huggingface.co/BAAI/bge-m3) model on [`airesearch/WangchanX-Legal-ThaiCCL-RAG`](https://huggingface.co/datasets/airesearch/WangchanX-Legal-ThaiCCL-RAG) queries. However, we didn't use the same positives as shown in the dataset card, the positives was collected without any human supervision. ## Finetuning Details Apart from the original [`airesearch/WangchanX-Legal-ThaiCCL-RAG`](https://huggingface.co/datasets/airesearch/WangchanX-Legal-ThaiCCL-RAG) which requires human to rerank and remove irrelevant documents, the model was finetuned on a completely automated environment. Specifically, given the query in the WangchanX-Legal-ThaiCCL-RAG dataset and a set of law sections to be retrieved, we follow the following procedure: 1. Use [`BAAI/bge-m3`](https://huggingface.co/BAAI/bge-m3) to retrieve N positive law sections based on thresholding score of 0.8 2. Among those N documents, we use [`BAAI/bge-reranker-v2-m3`](https://huggingface.co/BAAI/bge-reranker-v2-m3) to rerank documents and filtered any document that reranker scores less than 0.8 - achieving final positive law sections 3. Using positives from (2), we finetuned BGE-M3 model ## Model Performance | **Dataset** | **Top-K** | **HR@k** | **Multi HR@k** | **Recall@k** | **MRR@k** | **Multi MRR@k** | |:----------------:|:---------:|:-------:|:-------------:|:-----------:|:--------:|:---------------:| | **NitiBench-CCL** | 1 | 0.731 | – | 0.731 | 0.731 | – | | **NitiBench-CCL** | 5 | 0.900 | – | 0.900 | 0.800 | – | | **NitiBench-CCL** | 10 | 0.934 | – | 0.934 | 0.804 | – | | **NitiBench-Tax**| 1 | 0.520 | 0.160 | 0.281 | 0.520 | 0.281 | | **NitiBench-Tax**| 5 | 0.700 | 0.200 | 0.382 | 0.587 | 0.329 | | **NitiBench-Tax**| 10 | 0.780 | 0.260 | 0.483 | 0.600 | 0.345 | ## Usage Install: ``` git clone https://github.com/FlagOpen/FlagEmbedding.git cd FlagEmbedding pip install -e . ``` or: ``` pip install -U FlagEmbedding ``` ### Generate Embedding for text - Dense Embedding ```python from FlagEmbedding import BGEM3FlagModel model = BGEM3FlagModel('VISAI-AI/nitibench-ccl-auto-finetuned-bge-m3', use_fp16=True) # Setting use_fp16 to True speeds up computation with a slight performance degradation sentences_1 = ["What is BGE M3?", "Defination of BM25"] sentences_2 = ["BGE M3 is an embedding model supporting dense retrieval, lexical matching and multi-vector interaction.", "BM25 is a bag-of-words retrieval function that ranks a set of documents based on the query terms appearing in each document"] embeddings_1 = model.encode(sentences_1, batch_size=12, max_length=8192, # If you don't need such a long length, you can set a smaller value to speed up the encoding process. )['dense_vecs'] embeddings_2 = model.encode(sentences_2)['dense_vecs'] similarity = embeddings_1 @ embeddings_2.T print(similarity) # [[0.6265, 0.3477], [0.3499, 0.678 ]] ``` You also can use sentence-transformers and huggingface transformers to generate dense embeddings. Refer to [baai_general_embedding](https://github.com/FlagOpen/FlagEmbedding/tree/master/FlagEmbedding/baai_general_embedding#usage) for details. - Sparse Embedding (Lexical Weight) ```python from FlagEmbedding import BGEM3FlagModel model = BGEM3FlagModel('VISAI-AI/nitibench-ccl-auto-finetuned-bge-m3', use_fp16=True) # Setting use_fp16 to True speeds up computation with a slight performance degradation sentences_1 = ["āļŠāļ–āļēāļšāļąāļ™āļ—āļēāļ‡āļāļēāļĢāđ€āļ‡āļīāļ™āļŠāļēāļĄāļēāļĢāļ–āļĨāļ‡āļ—āļļāļ™āđƒāļ™āļŦāļĨāļąāļāļ—āļĢāļąāļžāļĒāđŒ āđ€āļ›āđ‡āļ™āļ­āļąāļ•āļĢāļēāļŠāđˆāļ§āļ™āļĢāđ‰āļ­āļĒāļĨāļ°āļŠāļīāļšāļ‚āļ­āļ‡āđ€āļ‡āļīāļ™āļāļ­āļ‡āļ—āļļāļ™āļ—āļąāđ‰āļ‡āļŦāļĄāļ”āļ‚āļ­āļ‡āļŠāļ–āļēāļšāļąāļ™āļāļēāļĢāđ€āļ‡āļīāļ™āļ™āļąāđ‰āļ™ āļŠāļģāļŦāļĢāļąāļšāļāļēāļĢāļ–āļ·āļ­āļŦāļĢāļ·āļ­āļĄāļĩāļŦāļļāđ‰āļ™āđƒāļ™āļ—āļļāļāļšāļĢāļīāļĐāļąāļ—āļĢāļ§āļĄāļāļąāļ™āđ„āļ”āđ‰āļŦāļĢāļ·āļ­āđ„āļĄāđˆ?", "āđƒāļ™āļāļĢāļ“āļĩāļ—āļĩāđˆāļ˜āļ™āļēāļ„āļēāļĢāđāļŦāđˆāļ‡āļ›āļĢāļ°āđ€āļ—āļĻāđ„āļ—āļĒāļĄāļĩāļ„āļģāļŠāļąāđˆāļ‡āļ›āļīāļ”āļāļīāļˆāļāļēāļĢāļ‚āļ­āļ‡āļŠāļ–āļēāļšāļąāļ™āļāļēāļĢāđ€āļ‡āļīāļ™ āđ€āļ™āļ·āđˆāļ­āļ‡āļŠāļ–āļēāļšāļąāļ™āļāļēāļĢāđ€āļ‡āļīāļ™āļ”āļģāļĢāļ‡āđ€āļ‡āļīāļ™āļāļ­āļ‡āļ—āļļāļ™āļ•āđˆāļģāļāļ§āđˆāļēāļĢāđ‰āļ­āļĒāļĨāļ°āļŠāļēāļĄāļŠāļīāļšāļŦāđ‰āļēāļ‚āļ­āļ‡āļ­āļąāļ•āļĢāļēāļ•āļēāļĄāļ—āļĩāđˆāļāļģāļŦāļ™āļ” āļˆāļ°āļ•āđ‰āļ­āļ‡āļ™āļģāđ€āļŠāļ™āļ­āļ•āđˆāļ­āļšāļļāļ„āļ„āļĨāđƒāļ”āļŦāļĢāļ·āļ­āļŦāļ™āđˆāļ§āļĒāļ‡āļēāļ™āđƒāļ”āđ€āļžāļ·āđˆāļ­āđ€āļžāļīāļāļ–āļ­āļ™āđƒāļšāļ­āļ™āļļāļāļēāļ•āļ‚āļ­āļ‡āļŠāļ–āļēāļšāļąāļ™āļāļēāļĢāđ€āļ‡āļīāļ™āļ™āļąāđ‰āļ™"] sentences_2 = ["āļžāļĢāļ°āļĢāļēāļŠāļšāļąāļāļāļąāļ•āļīāļ˜āļļāļĢāļāļīāļˆāļŠāļ–āļēāļšāļąāļ™āļāļēāļĢāđ€āļ‡āļīāļ™ āļž.āļĻ. 2551 āļĄāļēāļ•āļĢāļē 33 āļ āļēāļĒāđƒāļ•āđ‰āļšāļąāļ‡āļ„āļąāļšāļĄāļēāļ•āļĢāļē 34 āđāļĨāļ°āļĄāļēāļ•āļĢāļē 35 āđƒāļŦāđ‰āļŠāļ–āļēāļšāļąāļ™āļāļēāļĢāđ€āļ‡āļīāļ™āļĨāļ‡āļ—āļļāļ™āđƒāļ™āļŦāļĨāļąāļāļ—āļĢāļąāļžāļĒāđŒāđ€āļžāļ·āđˆāļ­āđ€āļ›āđ‡āļ™āļāļĢāļĢāļĄāļŠāļīāļ—āļ˜āļīāđŒāļ‚āļ­āļ‡āļ•āļ™āđ„āļ”āđ‰ āļ•āļēāļĄāļŦāļĨāļąāļāđ€āļāļ“āļ‘āđŒāļ—āļĩāđˆāļ˜āļ™āļēāļ„āļēāļĢāđāļŦāđˆāļ‡āļ›āļĢāļ°āđ€āļ—āļĻāđ„āļ—āļĒāļ›āļĢāļ°āļāļēāļĻāļāļģāļŦāļ™āļ”", "āļžāļĢāļ°āļĢāļēāļŠāļšāļąāļāļāļąāļ•āļīāļ˜āļļāļĢāļāļīāļˆāļŠāļ–āļēāļšāļąāļ™āļāļēāļĢāđ€āļ‡āļīāļ™ āļž.āļĻ. 2551 āļĄāļēāļ•āļĢāļē 97 āđƒāļ™āļāļĢāļ“āļĩāļ—āļĩāđˆāļŠāļ–āļēāļšāļąāļ™āļāļēāļĢāđ€āļ‡āļīāļ™āļ”āļģāļĢāļ‡āđ€āļ‡āļīāļ™āļāļ­āļ‡āļ—āļļāļ™āļ•āđˆāļģāļāļ§āđˆāļēāļĢāđ‰āļ­āļĒāļĨāļ°āļŠāļēāļĄāļŠāļīāļšāļŦāđ‰āļēāļ‚āļ­āļ‡āļ­āļąāļ•āļĢāļēāļ•āļēāļĄāļ—āļĩāđˆāļāļģāļŦāļ™āļ”āđƒāļ™āļĄāļēāļ•āļĢāļē 30 āđƒāļŦāđ‰āļ˜āļ™āļēāļ„āļēāļĢāđāļŦāđˆāļ‡āļ›āļĢāļ°āđ€āļ—āļĻāđ„āļ—āļĒāļĄāļĩāļ„āļģāļŠāļąāđˆāļ‡āļ›āļīāļ”āļāļīāļˆāļāļēāļĢāļ‚āļ­āļ‡āļŠāļ–āļēāļšāļąāļ™āļāļēāļĢāđ€āļ‡āļīāļ™āļ™āļąāđ‰āļ™ āđ€āļ§āđ‰āļ™āđāļ•āđˆāđƒāļ™āļāļĢāļ“āļĩāļ—āļĩāđˆāļ˜āļ™āļēāļ„āļēāļĢāđāļŦāđˆāļ‡āļ›āļĢāļ°āđ€āļ—āļĻāđ„āļ—āļĒāđ€āļŦāđ‡āļ™āļ§āđˆāļēāļāļēāļĢāļĄāļĩāļ„āļģāļŠāļąāđˆāļ‡āļ›āļīāļ”āļāļīāļˆāļāļēāļĢāļˆāļ°āļāđˆāļ­āđƒāļŦāđ‰āđ€āļāļīāļ”āļœāļĨāļāļĢāļ°āļ—āļš āļŦāļĢāļ·āļ­āļ„āļ§āļēāļĄāđ€āļŠāļĩāļĒāļŦāļēāļĒāļ•āđˆāļ­āļĢāļ°āļšāļšāđ€āļĻāļĢāļĐāļāļāļīāļˆāđ‚āļ”āļĒāļĢāļ§āļĄāļ­āļĒāđˆāļēāļ‡āļĢāļļāļ™āđāļĢāļ‡ āļ˜āļ™āļēāļ„āļēāļĢāđāļŦāđˆāļ‡āļ›āļĢāļ°āđ€āļ—āļĻāđ„āļ—āļĒāļ­āļēāļˆāļĒāļąāļ‡āđ„āļĄāđˆāļŠāļąāđˆāļ‡āļ›āļīāļ”āļāļīāļˆāļāļēāļĢāļ‚āļ­āļ‡āļŠāļ–āļēāļšāļąāļ™āļāļēāļĢāđ€āļ‡āļīāļ™āļāđ‡āđ„āļ”āđ‰\nāđ€āļĄāļ·āđˆāļ­āļ˜āļ™āļēāļ„āļēāļĢāđāļŦāđˆāļ‡āļ›āļĢāļ°āđ€āļ—āļĻāđ„āļ—āļĒāļĄāļĩāļ„āļģāļŠāļąāđˆāļ‡āļ›āļīāļ”āļāļīāļˆāļāļēāļĢāļ•āļēāļĄāļ§āļĢāļĢāļ„āļŦāļ™āļķāđˆāļ‡āđāļĨāđ‰āļ§ āđƒāļŦāđ‰āđ€āļŠāļ™āļ­āļĢāļąāļāļĄāļ™āļ•āļĢāļĩāđ€āļžāļīāļāļ–āļ­āļ™āđƒāļšāļ­āļ™āļļāļāļēāļ•āļ‚āļ­āļ‡āļŠāļ–āļēāļšāļąāļ™āļāļēāļĢāđ€āļ‡āļīāļ™āļ™āļąāđ‰āļ™"] output_1 = model.encode(sentences_1, return_dense=True, return_sparse=True, return_colbert_vecs=False) output_2 = model.encode(sentences_2, return_dense=True, return_sparse=True, return_colbert_vecs=False) # you can see the weight for each token: print(model.convert_id_to_token(output_1['lexical_weights'])) # [{'āļŠāļ–āļēāļšāļąāļ™': 0.126, 'āļāļēāļĢāđ€āļ‡āļīāļ™': 0.10956, 'āļŠāļēāļĄāļēāļĢāļ–': 0.07, 'āļĨāļ‡āļ—āļļāļ™': 0.1417, 'āđƒāļ™': 0.01715, 'āļŦāļĨāļąāļ': 0.0758, 'āļ—āļĢāļąāļžāļĒāđŒ': 0.1702, 'āļ­āļąāļ•āļĢāļē': 0.04926, 'āļŠāđˆāļ§āļ™': 0.06107, 'āļĢāđ‰āļ­āļĒāļĨāļ°': 0.09, 'āļŠāļīāļš': 0.14, 'āđ€āļ‡āļīāļ™': 0.05026, 'āļāļ­āļ‡āļ—āļļāļ™': 0.1205, 'āļ—āļąāđ‰āļ‡āļŦāļĄāļ”': 0.03644, 'āļ–āļ·āļ­': 0.0987, 'āļŦāļļāđ‰āļ™': 0.0928, 'āđƒāļ™āļ—āļļāļ': 0.04883, 'āļšāļĢāļīāļĐāļąāļ—': 0.0999, 'āļĢāļ§āļĄ': 0.0835, 'āļāļąāļ™āđ„āļ”āđ‰': 0.09814, 'āļŦāļĢāļ·āļ­āđ„āļĄāđˆ': 0.0398}, # {'āļāļĢāļ“āļĩ': 0.0323, 'āļ˜āļ™āļēāļ„āļēāļĢ': 0.08136, 'āđāļŦāđˆāļ‡āļ›āļĢāļ°āđ€āļ—āļĻāđ„āļ—āļĒ': 0.151, 'āļ„āđāļēāļŠāļąāđˆāļ‡': 0.161, 'āļ›āļīāļ”': 0.1583, 'āļāļīāļˆāļāļēāļĢ': 0.1199, 'āļŠāļ–āļēāļšāļąāļ™': 0.08545, 'āļāļēāļĢāđ€āļ‡āļīāļ™': 0.1334, 'āđ€āļ™āļ·āđˆāļ­āļ‡': 0.006992, 'āļ”āđāļēāļĢāļ‡': 0.1523, 'āđ€āļ‡āļīāļ™': 0.12146, 'āļāļ­āļ‡āļ—āļļāļ™': 0.1776, 'āļ•āđˆāđāļēāļāļ§āđˆāļē': 0.1335, 'āļĢāđ‰āļ­āļĒāļĨāļ°': 0.10126, 'āļŠāļēāļĄ': 0.02498, 'āļŦāđ‰āļē': 0.1158, 'āļ­āļąāļ•āļĢāļē': 0.12256, 'āļāđāļēāļŦāļ™āļ”': 0.0572, 'āļˆāļ°āļ•āđ‰āļ­āļ‡': 0.07074, 'āļ™āđāļēāđ€āļŠāļ™āļ­': 0.1752, 'āļ•āđˆāļ­': 0.0696, 'āļšāļļāļ„āļ„āļĨ': 0.0817, 'āđƒāļ”': 0.0577, 'āļŦāļĢāļ·āļ­': 0.0248, 'āļŦāļ™āđˆāļ§āļĒāļ‡āļēāļ™': 0.076, 'āđ€āļž': 0.02034, 'āļīāļ': 0.0921, 'āļ–āļ­āļ™': 0.1582, 'āđƒāļš': 0.04617, 'āļ­āļ™āļļāļāļēāļ•': 0.179}] # compute the scores via lexical mathcing lexical_scores = model.compute_lexical_matching_score(output_1['lexical_weights'][0], output_2['lexical_weights'][0]) print(lexical_scores) # 0.10838508605957031 print(model.compute_lexical_matching_score(output_1['lexical_weights'][0], output_1['lexical_weights'][1])) # 0.06803131103515625 ``` - Multi-Vector (ColBERT) ```python from FlagEmbedding import BGEM3FlagModel model = BGEM3FlagModel('VISAI-AI/nitibench-ccl-auto-finetuned-bge-m3', use_fp16=True) sentences_1 = ["āļŠāļ–āļēāļšāļąāļ™āļ—āļēāļ‡āļāļēāļĢāđ€āļ‡āļīāļ™āļŠāļēāļĄāļēāļĢāļ–āļĨāļ‡āļ—āļļāļ™āđƒāļ™āļŦāļĨāļąāļāļ—āļĢāļąāļžāļĒāđŒ āđ€āļ›āđ‡āļ™āļ­āļąāļ•āļĢāļēāļŠāđˆāļ§āļ™āļĢāđ‰āļ­āļĒāļĨāļ°āļŠāļīāļšāļ‚āļ­āļ‡āđ€āļ‡āļīāļ™āļāļ­āļ‡āļ—āļļāļ™āļ—āļąāđ‰āļ‡āļŦāļĄāļ”āļ‚āļ­āļ‡āļŠāļ–āļēāļšāļąāļ™āļāļēāļĢāđ€āļ‡āļīāļ™āļ™āļąāđ‰āļ™ āļŠāļģāļŦāļĢāļąāļšāļāļēāļĢāļ–āļ·āļ­āļŦāļĢāļ·āļ­āļĄāļĩāļŦāļļāđ‰āļ™āđƒāļ™āļ—āļļāļāļšāļĢāļīāļĐāļąāļ—āļĢāļ§āļĄāļāļąāļ™āđ„āļ”āđ‰āļŦāļĢāļ·āļ­āđ„āļĄāđˆ?", "āđƒāļ™āļāļĢāļ“āļĩāļ—āļĩāđˆāļ˜āļ™āļēāļ„āļēāļĢāđāļŦāđˆāļ‡āļ›āļĢāļ°āđ€āļ—āļĻāđ„āļ—āļĒāļĄāļĩāļ„āļģāļŠāļąāđˆāļ‡āļ›āļīāļ”āļāļīāļˆāļāļēāļĢāļ‚āļ­āļ‡āļŠāļ–āļēāļšāļąāļ™āļāļēāļĢāđ€āļ‡āļīāļ™ āđ€āļ™āļ·āđˆāļ­āļ‡āļŠāļ–āļēāļšāļąāļ™āļāļēāļĢāđ€āļ‡āļīāļ™āļ”āļģāļĢāļ‡āđ€āļ‡āļīāļ™āļāļ­āļ‡āļ—āļļāļ™āļ•āđˆāļģāļāļ§āđˆāļēāļĢāđ‰āļ­āļĒāļĨāļ°āļŠāļēāļĄāļŠāļīāļšāļŦāđ‰āļēāļ‚āļ­āļ‡āļ­āļąāļ•āļĢāļēāļ•āļēāļĄāļ—āļĩāđˆāļāļģāļŦāļ™āļ” āļˆāļ°āļ•āđ‰āļ­āļ‡āļ™āļģāđ€āļŠāļ™āļ­āļ•āđˆāļ­āļšāļļāļ„āļ„āļĨāđƒāļ”āļŦāļĢāļ·āļ­āļŦāļ™āđˆāļ§āļĒāļ‡āļēāļ™āđƒāļ”āđ€āļžāļ·āđˆāļ­āđ€āļžāļīāļāļ–āļ­āļ™āđƒāļšāļ­āļ™āļļāļāļēāļ•āļ‚āļ­āļ‡āļŠāļ–āļēāļšāļąāļ™āļāļēāļĢāđ€āļ‡āļīāļ™āļ™āļąāđ‰āļ™"] sentences_2 = ["āļžāļĢāļ°āļĢāļēāļŠāļšāļąāļāļāļąāļ•āļīāļ˜āļļāļĢāļāļīāļˆāļŠāļ–āļēāļšāļąāļ™āļāļēāļĢāđ€āļ‡āļīāļ™ āļž.āļĻ. 2551 āļĄāļēāļ•āļĢāļē 33 āļ āļēāļĒāđƒāļ•āđ‰āļšāļąāļ‡āļ„āļąāļšāļĄāļēāļ•āļĢāļē 34 āđāļĨāļ°āļĄāļēāļ•āļĢāļē 35 āđƒāļŦāđ‰āļŠāļ–āļēāļšāļąāļ™āļāļēāļĢāđ€āļ‡āļīāļ™āļĨāļ‡āļ—āļļāļ™āđƒāļ™āļŦāļĨāļąāļāļ—āļĢāļąāļžāļĒāđŒāđ€āļžāļ·āđˆāļ­āđ€āļ›āđ‡āļ™āļāļĢāļĢāļĄāļŠāļīāļ—āļ˜āļīāđŒāļ‚āļ­āļ‡āļ•āļ™āđ„āļ”āđ‰ āļ•āļēāļĄāļŦāļĨāļąāļāđ€āļāļ“āļ‘āđŒāļ—āļĩāđˆāļ˜āļ™āļēāļ„āļēāļĢāđāļŦāđˆāļ‡āļ›āļĢāļ°āđ€āļ—āļĻāđ„āļ—āļĒāļ›āļĢāļ°āļāļēāļĻāļāļģāļŦāļ™āļ”", "āļžāļĢāļ°āļĢāļēāļŠāļšāļąāļāļāļąāļ•āļīāļ˜āļļāļĢāļāļīāļˆāļŠāļ–āļēāļšāļąāļ™āļāļēāļĢāđ€āļ‡āļīāļ™ āļž.āļĻ. 2551 āļĄāļēāļ•āļĢāļē 97 āđƒāļ™āļāļĢāļ“āļĩāļ—āļĩāđˆāļŠāļ–āļēāļšāļąāļ™āļāļēāļĢāđ€āļ‡āļīāļ™āļ”āļģāļĢāļ‡āđ€āļ‡āļīāļ™āļāļ­āļ‡āļ—āļļāļ™āļ•āđˆāļģāļāļ§āđˆāļēāļĢāđ‰āļ­āļĒāļĨāļ°āļŠāļēāļĄāļŠāļīāļšāļŦāđ‰āļēāļ‚āļ­āļ‡āļ­āļąāļ•āļĢāļēāļ•āļēāļĄāļ—āļĩāđˆāļāļģāļŦāļ™āļ”āđƒāļ™āļĄāļēāļ•āļĢāļē 30 āđƒāļŦāđ‰āļ˜āļ™āļēāļ„āļēāļĢāđāļŦāđˆāļ‡āļ›āļĢāļ°āđ€āļ—āļĻāđ„āļ—āļĒāļĄāļĩāļ„āļģāļŠāļąāđˆāļ‡āļ›āļīāļ”āļāļīāļˆāļāļēāļĢāļ‚āļ­āļ‡āļŠāļ–āļēāļšāļąāļ™āļāļēāļĢāđ€āļ‡āļīāļ™āļ™āļąāđ‰āļ™ āđ€āļ§āđ‰āļ™āđāļ•āđˆāđƒāļ™āļāļĢāļ“āļĩāļ—āļĩāđˆāļ˜āļ™āļēāļ„āļēāļĢāđāļŦāđˆāļ‡āļ›āļĢāļ°āđ€āļ—āļĻāđ„āļ—āļĒāđ€āļŦāđ‡āļ™āļ§āđˆāļēāļāļēāļĢāļĄāļĩāļ„āļģāļŠāļąāđˆāļ‡āļ›āļīāļ”āļāļīāļˆāļāļēāļĢāļˆāļ°āļāđˆāļ­āđƒāļŦāđ‰āđ€āļāļīāļ”āļœāļĨāļāļĢāļ°āļ—āļš āļŦāļĢāļ·āļ­āļ„āļ§āļēāļĄāđ€āļŠāļĩāļĒāļŦāļēāļĒāļ•āđˆāļ­āļĢāļ°āļšāļšāđ€āļĻāļĢāļĐāļāļāļīāļˆāđ‚āļ”āļĒāļĢāļ§āļĄāļ­āļĒāđˆāļēāļ‡āļĢāļļāļ™āđāļĢāļ‡ āļ˜āļ™āļēāļ„āļēāļĢāđāļŦāđˆāļ‡āļ›āļĢāļ°āđ€āļ—āļĻāđ„āļ—āļĒāļ­āļēāļˆāļĒāļąāļ‡āđ„āļĄāđˆāļŠāļąāđˆāļ‡āļ›āļīāļ”āļāļīāļˆāļāļēāļĢāļ‚āļ­āļ‡āļŠāļ–āļēāļšāļąāļ™āļāļēāļĢāđ€āļ‡āļīāļ™āļāđ‡āđ„āļ”āđ‰\nāđ€āļĄāļ·āđˆāļ­āļ˜āļ™āļēāļ„āļēāļĢāđāļŦāđˆāļ‡āļ›āļĢāļ°āđ€āļ—āļĻāđ„āļ—āļĒāļĄāļĩāļ„āļģāļŠāļąāđˆāļ‡āļ›āļīāļ”āļāļīāļˆāļāļēāļĢāļ•āļēāļĄāļ§āļĢāļĢāļ„āļŦāļ™āļķāđˆāļ‡āđāļĨāđ‰āļ§ āđƒāļŦāđ‰āđ€āļŠāļ™āļ­āļĢāļąāļāļĄāļ™āļ•āļĢāļĩāđ€āļžāļīāļāļ–āļ­āļ™āđƒāļšāļ­āļ™āļļāļāļēāļ•āļ‚āļ­āļ‡āļŠāļ–āļēāļšāļąāļ™āļāļēāļĢāđ€āļ‡āļīāļ™āļ™āļąāđ‰āļ™"] output_1 = model.encode(sentences_1, return_dense=True, return_sparse=True, return_colbert_vecs=True) output_2 = model.encode(sentences_2, return_dense=True, return_sparse=True, return_colbert_vecs=True) print(model.colbert_score(output_1['colbert_vecs'][0], output_2['colbert_vecs'][0])) print(model.colbert_score(output_1['colbert_vecs'][0], output_2['colbert_vecs'][1])) # tensor(0.5813) # tensor(0.5718) ``` ### Compute score for text pairs Input a list of text pairs, you can get the scores computed by different methods. ```python from FlagEmbedding import BGEM3FlagModel model = BGEM3FlagModel('VISAI-AI/nitibench-ccl-auto-finetuned-bge-m3', use_fp16=True) sentences_1 = ["āļŠāļ–āļēāļšāļąāļ™āļ—āļēāļ‡āļāļēāļĢāđ€āļ‡āļīāļ™āļŠāļēāļĄāļēāļĢāļ–āļĨāļ‡āļ—āļļāļ™āđƒāļ™āļŦāļĨāļąāļāļ—āļĢāļąāļžāļĒāđŒ āđ€āļ›āđ‡āļ™āļ­āļąāļ•āļĢāļēāļŠāđˆāļ§āļ™āļĢāđ‰āļ­āļĒāļĨāļ°āļŠāļīāļšāļ‚āļ­āļ‡āđ€āļ‡āļīāļ™āļāļ­āļ‡āļ—āļļāļ™āļ—āļąāđ‰āļ‡āļŦāļĄāļ”āļ‚āļ­āļ‡āļŠāļ–āļēāļšāļąāļ™āļāļēāļĢāđ€āļ‡āļīāļ™āļ™āļąāđ‰āļ™ āļŠāļģāļŦāļĢāļąāļšāļāļēāļĢāļ–āļ·āļ­āļŦāļĢāļ·āļ­āļĄāļĩāļŦāļļāđ‰āļ™āđƒāļ™āļ—āļļāļāļšāļĢāļīāļĐāļąāļ—āļĢāļ§āļĄāļāļąāļ™āđ„āļ”āđ‰āļŦāļĢāļ·āļ­āđ„āļĄāđˆ?", "āđƒāļ™āļāļĢāļ“āļĩāļ—āļĩāđˆāļ˜āļ™āļēāļ„āļēāļĢāđāļŦāđˆāļ‡āļ›āļĢāļ°āđ€āļ—āļĻāđ„āļ—āļĒāļĄāļĩāļ„āļģāļŠāļąāđˆāļ‡āļ›āļīāļ”āļāļīāļˆāļāļēāļĢāļ‚āļ­āļ‡āļŠāļ–āļēāļšāļąāļ™āļāļēāļĢāđ€āļ‡āļīāļ™ āđ€āļ™āļ·āđˆāļ­āļ‡āļŠāļ–āļēāļšāļąāļ™āļāļēāļĢāđ€āļ‡āļīāļ™āļ”āļģāļĢāļ‡āđ€āļ‡āļīāļ™āļāļ­āļ‡āļ—āļļāļ™āļ•āđˆāļģāļāļ§āđˆāļēāļĢāđ‰āļ­āļĒāļĨāļ°āļŠāļēāļĄāļŠāļīāļšāļŦāđ‰āļēāļ‚āļ­āļ‡āļ­āļąāļ•āļĢāļēāļ•āļēāļĄāļ—āļĩāđˆāļāļģāļŦāļ™āļ” āļˆāļ°āļ•āđ‰āļ­āļ‡āļ™āļģāđ€āļŠāļ™āļ­āļ•āđˆāļ­āļšāļļāļ„āļ„āļĨāđƒāļ”āļŦāļĢāļ·āļ­āļŦāļ™āđˆāļ§āļĒāļ‡āļēāļ™āđƒāļ”āđ€āļžāļ·āđˆāļ­āđ€āļžāļīāļāļ–āļ­āļ™āđƒāļšāļ­āļ™āļļāļāļēāļ•āļ‚āļ­āļ‡āļŠāļ–āļēāļšāļąāļ™āļāļēāļĢāđ€āļ‡āļīāļ™āļ™āļąāđ‰āļ™"] sentences_2 = ["āļžāļĢāļ°āļĢāļēāļŠāļšāļąāļāļāļąāļ•āļīāļ˜āļļāļĢāļāļīāļˆāļŠāļ–āļēāļšāļąāļ™āļāļēāļĢāđ€āļ‡āļīāļ™ āļž.āļĻ. 2551 āļĄāļēāļ•āļĢāļē 33 āļ āļēāļĒāđƒāļ•āđ‰āļšāļąāļ‡āļ„āļąāļšāļĄāļēāļ•āļĢāļē 34 āđāļĨāļ°āļĄāļēāļ•āļĢāļē 35 āđƒāļŦāđ‰āļŠāļ–āļēāļšāļąāļ™āļāļēāļĢāđ€āļ‡āļīāļ™āļĨāļ‡āļ—āļļāļ™āđƒāļ™āļŦāļĨāļąāļāļ—āļĢāļąāļžāļĒāđŒāđ€āļžāļ·āđˆāļ­āđ€āļ›āđ‡āļ™āļāļĢāļĢāļĄāļŠāļīāļ—āļ˜āļīāđŒāļ‚āļ­āļ‡āļ•āļ™āđ„āļ”āđ‰ āļ•āļēāļĄāļŦāļĨāļąāļāđ€āļāļ“āļ‘āđŒāļ—āļĩāđˆāļ˜āļ™āļēāļ„āļēāļĢāđāļŦāđˆāļ‡āļ›āļĢāļ°āđ€āļ—āļĻāđ„āļ—āļĒāļ›āļĢāļ°āļāļēāļĻāļāļģāļŦāļ™āļ”", "āļžāļĢāļ°āļĢāļēāļŠāļšāļąāļāļāļąāļ•āļīāļ˜āļļāļĢāļāļīāļˆāļŠāļ–āļēāļšāļąāļ™āļāļēāļĢāđ€āļ‡āļīāļ™ āļž.āļĻ. 2551 āļĄāļēāļ•āļĢāļē 97 āđƒāļ™āļāļĢāļ“āļĩāļ—āļĩāđˆāļŠāļ–āļēāļšāļąāļ™āļāļēāļĢāđ€āļ‡āļīāļ™āļ”āļģāļĢāļ‡āđ€āļ‡āļīāļ™āļāļ­āļ‡āļ—āļļāļ™āļ•āđˆāļģāļāļ§āđˆāļēāļĢāđ‰āļ­āļĒāļĨāļ°āļŠāļēāļĄāļŠāļīāļšāļŦāđ‰āļēāļ‚āļ­āļ‡āļ­āļąāļ•āļĢāļēāļ•āļēāļĄāļ—āļĩāđˆāļāļģāļŦāļ™āļ”āđƒāļ™āļĄāļēāļ•āļĢāļē 30 āđƒāļŦāđ‰āļ˜āļ™āļēāļ„āļēāļĢāđāļŦāđˆāļ‡āļ›āļĢāļ°āđ€āļ—āļĻāđ„āļ—āļĒāļĄāļĩāļ„āļģāļŠāļąāđˆāļ‡āļ›āļīāļ”āļāļīāļˆāļāļēāļĢāļ‚āļ­āļ‡āļŠāļ–āļēāļšāļąāļ™āļāļēāļĢāđ€āļ‡āļīāļ™āļ™āļąāđ‰āļ™ āđ€āļ§āđ‰āļ™āđāļ•āđˆāđƒāļ™āļāļĢāļ“āļĩāļ—āļĩāđˆāļ˜āļ™āļēāļ„āļēāļĢāđāļŦāđˆāļ‡āļ›āļĢāļ°āđ€āļ—āļĻāđ„āļ—āļĒāđ€āļŦāđ‡āļ™āļ§āđˆāļēāļāļēāļĢāļĄāļĩāļ„āļģāļŠāļąāđˆāļ‡āļ›āļīāļ”āļāļīāļˆāļāļēāļĢāļˆāļ°āļāđˆāļ­āđƒāļŦāđ‰āđ€āļāļīāļ”āļœāļĨāļāļĢāļ°āļ—āļš āļŦāļĢāļ·āļ­āļ„āļ§āļēāļĄāđ€āļŠāļĩāļĒāļŦāļēāļĒāļ•āđˆāļ­āļĢāļ°āļšāļšāđ€āļĻāļĢāļĐāļāļāļīāļˆāđ‚āļ”āļĒāļĢāļ§āļĄāļ­āļĒāđˆāļēāļ‡āļĢāļļāļ™āđāļĢāļ‡ āļ˜āļ™āļēāļ„āļēāļĢāđāļŦāđˆāļ‡āļ›āļĢāļ°āđ€āļ—āļĻāđ„āļ—āļĒāļ­āļēāļˆāļĒāļąāļ‡āđ„āļĄāđˆāļŠāļąāđˆāļ‡āļ›āļīāļ”āļāļīāļˆāļāļēāļĢāļ‚āļ­āļ‡āļŠāļ–āļēāļšāļąāļ™āļāļēāļĢāđ€āļ‡āļīāļ™āļāđ‡āđ„āļ”āđ‰\nāđ€āļĄāļ·āđˆāļ­āļ˜āļ™āļēāļ„āļēāļĢāđāļŦāđˆāļ‡āļ›āļĢāļ°āđ€āļ—āļĻāđ„āļ—āļĒāļĄāļĩāļ„āļģāļŠāļąāđˆāļ‡āļ›āļīāļ”āļāļīāļˆāļāļēāļĢāļ•āļēāļĄāļ§āļĢāļĢāļ„āļŦāļ™āļķāđˆāļ‡āđāļĨāđ‰āļ§ āđƒāļŦāđ‰āđ€āļŠāļ™āļ­āļĢāļąāļāļĄāļ™āļ•āļĢāļĩāđ€āļžāļīāļāļ–āļ­āļ™āđƒāļšāļ­āļ™āļļāļāļēāļ•āļ‚āļ­āļ‡āļŠāļ–āļēāļšāļąāļ™āļāļēāļĢāđ€āļ‡āļīāļ™āļ™āļąāđ‰āļ™"] sentence_pairs = [[i,j] for i in sentences_1 for j in sentences_2] print(model.compute_score(sentence_pairs, max_passage_length=128, # a smaller max length leads to a lower latency weights_for_different_modes=[0.4, 0.2, 0.4])) # weights_for_different_modes(w) is used to do weighted sum: w[0]*dense_score + w[1]*sparse_score + w[2]*colbert_score # { # 'colbert': [0.5812647342681885, 0.5717734098434448, 0.6460118889808655, 0.8784525990486145], # 'sparse': [0.1083984375, 0.07684326171875, 0.07061767578125, 0.314208984375], # 'dense': [0.61865234375, 0.58935546875, 0.666015625, 0.8916015625], # 'sparse+dense': [0.4485676884651184, 0.41851806640625, 0.4675496518611908, 0.6991373896598816], # 'colbert+sparse+dense': [0.5016465187072754, 0.47982022166252136, 0.538934588432312, 0.7708634734153748] # } ``` ## Acknowledgement Thanks to Pirat Pothavorn for evaluating the model performance on NitiBench, Supavish Punchun for finetuning the model and preparing positives for finetuning. Additionally, we thank you all authors of this open-sourced project. ## Citation ### BibTeX ``` @misc{akarajaradwong2025nitibenchcomprehensivestudiesllm, title={NitiBench: A Comprehensive Studies of LLM Frameworks Capabilities for Thai Legal Question Answering}, author={Pawitsapak Akarajaradwong and Pirat Pothavorn and Chompakorn Chaksangchaichot and Panuthep Tasawong and Thitiwat Nopparatbundit and Sarana Nutanong}, year={2025}, eprint={2502.10868}, archivePrefix={arXiv}, primaryClass={cs.CL}, url={https://arxiv.org/abs/2502.10868}, } ```