Finetuning of BAAI/bge-m3 with 3GPP specification data.

Install the libraries

Install the FlagEmbedding via:

git clone https://github.com/FlagOpen/FlagEmbedding.git
cd FlagEmbedding
pip install -e .

or install without editing:

pip install -U FlagEmbedding

Inference

Dense Embedding

from FlagEmbedding import BGEM3FlagModel

model = BGEM3FlagModel('SadeghK/bge-m3-3gpp', use_fp16=True)  # slight quality trade-off for speed

# queries (how an engineer might ask)
queries = [
    "How is PDCP data recovery triggered for an AM DRB?",
    "What is the purpose of the RRCReestablishment procedure?",
]

# candidate spec passages
passages = [
    "For AM DRBs configured with PDCP data recovery, the PDCP entity performs retransmission of all PDCP SDUs previously submitted to lower layers, starting from the first SDU not acknowledged by RLC.",
    "The RRC Reestablishment procedure re-establishes the RRC connection after a radio link failure, handover failure, or integrity check failure, restoring SRB1 and reactivating security.",
]

# match the training length (512), not 8192 — faster and in-distribution
q_emb = model.encode(queries,  batch_size=12, max_length=512)['dense_vecs']
p_emb = model.encode(passages, batch_size=12, max_length=512)['dense_vecs']

similarity = q_emb @ p_emb.T
print(similarity)   # diagonal (correct pairs) should dominate each row

# [[0.729  0.478 ], [0.452  0.7134]] -- The original BAAI/bge-m3
# [[0.579  0.0889], [0.1157 0.62  ]] -- The finetuned SadeghK/bge-m3-3gpp

Sparse Embedding (Lexical Weight)

from FlagEmbedding import BGEM3FlagModel

model = BGEM3FlagModel('SadeghK/bge-m3-3gpp', use_fp16=True)  # slight quality trade-off for speed

queries = [
    "How is PDCP data recovery triggered for an AM DRB?",
    "What is the purpose of the RRCReestablishment procedure?",
]
passages = [
    "For AM DRBs configured with PDCP data recovery, the PDCP entity retransmits all PDCP SDUs previously submitted to lower layers, starting from the first SDU not acknowledged by RLC.",
    "The RRC Reestablishment procedure re-establishes the RRC connection after radio link failure, handover failure, or integrity check failure, restoring SRB1 and reactivating security.",
]

out_q = model.encode(queries,  max_length=512, return_dense=True, return_sparse=True, return_colbert_vecs=False)
out_p = model.encode(passages, max_length=512, return_dense=True, return_sparse=True, return_colbert_vecs=False)

# inspect which tokens the sparse head weights (note the high mass on 3GPP identifiers)
print(model.convert_id_to_token(out_q['lexical_weights']))
# e.g. {'PD':0.20, 'CP':0.26, 'data':0.11, 'recovery':0.23, 'AM':0.14, 'DR':0.18, 'B':0.09, ...}  (illustrative)

# full 2x2 lexical-matching matrix (rows = queries, cols = passages)
for i in range(len(queries)):
    row = [model.compute_lexical_matching_score(out_q['lexical_weights'][i],
                                                 out_p['lexical_weights'][j])
           for j in range(len(passages))]
    print(row)
# diagonal (correct pairs) should be clearly larger than off-diagonal


# finetuned model SadeghK/bge-m3-3gpp
# [{'How': 0.0735, 'PD': 0.2104, 'CP': 0.275, 'data': 0.264, 'recovery': 0.3538, 'trigger': 0.323, 'ed': 0.005375, 'an': 0.01321, 'AM': 0.4426, 'DR': 0.211, 'B': 0.1913, '?': 0.04645}, {'What': 0.05386, 'is': 0.0368, 'the': 0.11115, 'purpose': 0.284, 'of': 0.0806, 'R': 0.01096, 'RC': 0.3489, 'Re': 0.2715, 'e': 0.326, 'stab': 0.3704, 'lish': 0.3208, 'ment': 0.2439, 'procedure': 0.38, '?': 0.068}]
# [0.667510986328125, 0], [0.002357959747314453, 0.7953815460205078]

# original model BAAI/bge-m3
# [{'How': 0.0578, 'is': 0.01768, 'PD': 0.149, 'CP': 0.2703, 'data': 0.1835, 'recovery': 0.2264, 'trigger': 0.221, 'ed': 0.03482, 'an': 0.00264, 'AM': 0.2323, 'DR': 0.1436, 'B': 0.1951, '?': 0.02673}, {'What': 0.04892, 'is': 0.03653, 'the': 0.02892, 'purpose': 0.1696, 'of': 0.01078, 'R': 0.10175, 'RC': 0.2703, 'Re': 0.1183, 'e': 0.07477, 'stab': 0.1932, 'lish': 0.1655, 'ment': 0.09375, 'procedure': 0.2163, '?': 0.0389}]
# [0.280487060546875, 0], [0.004868030548095703, 0.22907257080078125]

Multi-Vector (ColBERT)

from FlagEmbedding import BGEM3FlagModel

model = BGEM3FlagModel('SadeghK/bge-m3-3gpp', use_fp16=True)

queries = [
    "How is PDCP data recovery triggered for an AM DRB?",
    "What is the purpose of the RRCReestablishment procedure?",
]
passages = [
    "For AM DRBs configured with PDCP data recovery, the PDCP entity retransmits all PDCP SDUs previously submitted to lower layers, starting from the first SDU not acknowledged by RLC.",
    "The RRC Reestablishment procedure re-establishes the RRC connection after radio link failure, handover failure, or integrity check failure, restoring SRB1 and reactivating security.",
]

out_q = model.encode(queries,  max_length=512,
                     return_dense=True, return_sparse=True, return_colbert_vecs=True)
out_p = model.encode(passages, max_length=512,
                     return_dense=True, return_sparse=True, return_colbert_vecs=True)

# full ColBERT matrix: rows = queries, cols = passages (diagonal = correct pairs)
for i in range(len(queries)):
    row = [round(float(model.colbert_score(out_q['colbert_vecs'][i],
                                            out_p['colbert_vecs'][j])), 4)
           for j in range(len(passages))]
    print(row)
# expect the diagonal (correct pairs) clearly above the off-diagonal


# [0.7694, 0.5045], [0.4794, 0.78] -- Original BAAI/bge-m3
# [0.7057, 0.2468], [0.2184, 0.7341] -- finetuned SadeghK/bge-m3-3gpp

Compute score for text pairs

Input a list of text pairs, you can get the scores computed by different methods.

from FlagEmbedding import BGEM3FlagModel

model = BGEM3FlagModel('BAAI/bge-m3', use_fp16=True)

queries = [
    "How is PDCP data recovery triggered for an AM DRB?",
    "What is the purpose of the RRCReestablishment procedure?",
]
passages = [
    "For AM DRBs configured with PDCP data recovery, the PDCP entity retransmits all PDCP SDUs previously submitted to lower layers, starting from the first SDU not acknowledged by RLC.",
    "The RRC Reestablishment procedure re-establishes the RRC connection after radio link failure, handover failure, or integrity check failure, restoring SRB1 and reactivating security.",
]

sentence_pairs = [[q, p] for q in queries for p in passages]

scores = model.compute_score(
    sentence_pairs,
    max_query_length=512,      # match training; queries are short so this is safe
    max_passage_length=512,    # lower (e.g. 128) for latency if your chunks are short
    weights_for_different_modes=[0.4, 0.2, 0.4],  # w[0]*dense + w[1]*sparse + w[2]*colbert
)

# readable view: label each pair (indices 0 & 3 are the correct matches)
labels = [f"q{i}->p{j}" for i in range(len(queries)) for j in range(len(passages))]
for mode in ["dense", "sparse", "colbert", "sparse+dense", "colbert+sparse+dense"]:
    print(mode, {labels[k]: round(scores[mode][k], 4) for k in range(len(labels))})
Downloads last month
67
Safetensors
Model size
0.6B params
Tensor type
F32
·
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support

Model tree for SadeghK/bge-m3-3gpp

Base model

BAAI/bge-m3
Finetuned
(509)
this model