SonFox2920 commited on
Commit
b208559
·
verified ·
1 Parent(s): 3514724

Upload 6 files

Browse files
Files changed (6) hide show
  1. API.csv +31 -0
  2. Mbert.py +64 -0
  3. Model/classifier.pt +3 -0
  4. app.py +604 -0
  5. config.py +70 -0
  6. predictor.py +73 -0
API.csv ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ STT,SUPPORTED,REFUTED,NEI
2
+ 1,AIzaSyBAIFOiKcFbwTXRazRAoakZhkF6R4W3j1I,AIzaSyBrECiTuLl45qxb-NUqL_6wuUbRqPXL3lo,AIzaSyAfdRKTphVa6PJ15G3L_i02JNEP2TaCq5w
3
+ 2,AIzaSyC-NtmmiZWojXAD4XsuRsTDzaUwMY_iiNQ,AIzaSyBSKVP3Y4Lx3H36YgsBrdUxKiAVBakVUFs,AIzaSyB_50Q2YUWABz8oDrbEcRgMlhryQvmWgEw
4
+ 3,AIzaSyALckbqi4da-_FQJIK8P3p5gcijMC9F5PY,AIzaSyCq1uLPWoDo1Kk-JAT8AQBuEHk6QG1z2IM,AIzaSyDObWlzu1zZP_zd0FW6FYrpiXxcGOhLi5Y
5
+ 4,AIzaSyBrvs8kMpDuz-kgJ3oIghDgF8s3xmT7570,AIzaSyBJEBMWtbpOYH-52pbQf2GyKx78c9_h9Kk,AIzaSyAA1EAklM-bq-5MfcI9Y2kt63M1Zebvx00
6
+ 5,AIzaSyAEqolxPN1NpItPfPLBxVLEBUzKWrc0xeA,AIzaSyDvQY1JJOAAXmsx8_WlPqrLgVqqvd3lud4,AIzaSyBRWS4IyakT5Gu8__SSZADvar5v6L-hy_k
7
+ 6,AIzaSyBndL2HtHxawrpI7QTiIq2EmFG-ukCYfag,AIzaSyDCRts0ztEdv6WWHhQ3ZQyDnxS6L2ILoQk,AIzaSyBMCSJjjK3rKODi1y9eJd2glusztqrDj4g
8
+ 7,AIzaSyAaPAwyHZls4oqh0uWYjXazrkAPIm1QzQY,AIzaSyB6v_mH_RD0mWusok6EhvvLYQqh-vDg5Js,AIzaSyDW0NIQJJqge-Qqtey9vgQb4jMqsu0IssQ
9
+ 8,AIzaSyAAbn0oXtQX-E3RSFiNFcwLZKF1Q00Ch6c,AIzaSyC5ebttT7Vhj-gXK4TPvATGCPV9AJfVF1E,AIzaSyAxwjSoGBmDY-l9DtDWTvD3xUDlWwWGOFY
10
+ 9,AIzaSyB6WjKVrItKY6rumH50fXF_n43fSNQnjJQ,AIzaSyDloEA_1DukyeLS79OfbL-uNDfqLdrqb7I,AIzaSyBXM7PGRU1Tp1XugljM-xwLcnO4OEsRgGY
11
+ 10,AIzaSyDvaj6DTpYoBDxoKZxB5_Z2XmjObnHqY_U,AIzaSyBi3rMG4kidCGOEugZ8nJf_j0zvhbNoHB0,AIzaSyALTPwGXKWUZcuPl5Wnug0_XHLJJJinn4Q
12
+ 11,AIzaSyCsYyLWelVKeCLBOyyMQz5f-3exvJDkoHM,AIzaSyAEkM4hqzO9Fgb-Dwy9mzdN4cP-G2yZ41c,AIzaSyCuti6ldTheLMFsO3qKjtUpen1tFQEzRIg
13
+ 12,AIzaSyBZAFsZ1hg1CVaGdZ-L4H0A3gj74_iwjRc,AIzaSyB_TjmCt_xX_IGL6Pl6gS1qxHlQGYQyNKo,AIzaSyD9NMHc6p1hJ-kjAokMnVLn-IRE8ZhW3Do
14
+ 13,AIzaSyAmpGtMQQgJnhqjvxlSSUiXEKAKwSQN8uE,AIzaSyBeXXs3rxxwjcYwCJmVJKewoiEmjMdZVx4,AIzaSyAdgYJF8ajpxjs8WylFjba6fZIKc-9VTLE
15
+ 14,AIzaSyBBA-oQZr4u1GQ-N21x04-StYbuX_z8jAg,AIzaSyCZ-HeRuZp1HO4sPqAFwR7O0VVawVyc3pk,AIzaSyAnkRp0H4MjxL1ntQikaQC-P1PAvIXcqzI
16
+ 15,AIzaSyAhuapkaBUdef7qnGyuKEwhCENonfiF1aw,AIzaSyA0Bm1XF0_2GPH7H4UkgZeYeSTAq4jc5WA,AIzaSyBGguLyCllMuPIXqLFApw-If8OGLrNdeQk
17
+ 16,AIzaSyDzo9LWKvQOC5Pej-kM2Kt8cywxLDpcNwQ,AIzaSyCMbsNFMeiSNi90hDrw7WKdHVi1Sh-es74,AIzaSyCseI95TfJJPJja8wXK5L1BPjY7lWQ_KvA
18
+ 17,AIzaSyDWgOjUbtN4dTSHpW3aAJngpQXU-U8-CJc,AIzaSyB0XCw1oTs_aSD-3_KcIBr3StUQyFGRGYI,AIzaSyAmKRn79iRVii-5GxdotpFqTgI9NQzI6P8
19
+ 18,AIzaSyAcx86oHI8h0NhsjNBNQveV8DpxnVtG7wU,AIzaSyB5olPLuqJvzuIjP10Ykm2wVYZk83lr9m4,AIzaSyAZ8dp5Ethg4aTBlkq6QwwYU_ac8rgbnEs
20
+ 19,AIzaSyAdiDGoVCrdGK4sZ_bgONbNDlvctEv0h_M,AIzaSyAAEQE6mb8pmnIl0jO-_f-1XkNwpg8Pvpc,AIzaSyDUXnxdRkdAr8fu3aVSIMtKmXrAVdGURz4
21
+ 20,AIzaSyBrDa7tSh5SfIshD0jZG-meFO-iCxEz70I,AIzaSyAA6esL9qhK14qGR6E7hWxqkUrouitQxEU,AIzaSyALD5rmLUvrEEzJkI6PrzdzhwuNjXP0CyY
22
+ 21,AIzaSyBi0r0Bk1oHSH0FZ7_TZKSE7rnMIzk8zGA,AIzaSyAk4-cIn5Vy6C5o6opXocBksLpQ3cjQybQ,AIzaSyDjadl0cgzzbDAEEr7RA38dqYKFYNyujeY
23
+ 22,AIzaSyD4-MWH63DYrZHaqKTQ5K689co1cBcArGw,AIzaSyDBTOkf5Dzf6MvACV9yAHLeUNAbB_SewKU,AIzaSyDg4FAu8OjYCa6u9NWhJBI4KgnJoB5QxhI
24
+ 23,AIzaSyBDVJ2NRX3D4T3jG3fxGrO7jqJrFbsg_gc,AIzaSyClqiFZ2ImNx8wQvo90wVnUUxmAlcZm58c,AIzaSyDku5uiYfILBEOoeE_A6QyI03yUL3JIWbw
25
+ 24,AIzaSyB9AES6QUUwpKDpEt3eln9R6sHUZBmUz6A,AIzaSyD6YkUFUrN9ntGtvDkMVRU0s4iojFiR7X8,AIzaSyDzK8C2QcrBPXRbMb38zVVCd2Qr25dCQrU
26
+ 25,AIzaSyBaL-9z24cmbTAHXAh0zbKbcx9FLaHfepg,AIzaSyCun__LfDDNQBfUdF5lZEpKLa83gyhsR0U,AIzaSyDzyt-8tuRAqQ0Ff28-Wi9Aw-BAAxEgJEc
27
+ 26,AIzaSyAyu4dbWSMeh-BSnEXSwCP505Zlbsu3oWg,AIzaSyBfZOqldIDNoEQAlUpU26xNgy_rCvdUbW0,AIzaSyCmS4AqIlxktL_VGdLNxA3f-2rzFgPU5W8
28
+ 27,AIzaSyBFylav_tGcQEVUZ7HUyHUAmEHq2JmnzWQ,AIzaSyA_Cz1RH-ru74co60LOqOnLMpG_Jo5Mq5A,AIzaSyCMSP--GpHzzsLv5CeAftTeA2pdDsXv1Fk
29
+ 28,AIzaSyAQRh5KhN_nn5Hzr5syMhShqLf301H0Ozg,AIzaSyDVjp8IzIGQ-hOnSiFnuPa02VcsoEwQSQs,AIzaSyAI48UGAr82YuiXU2mBIukdOms_gx-N0rU
30
+ 29,AIzaSyBf3Tz6jCToK7mckfTbuKylvOeum9u25RA,AIzaSyDOhVzfL-lEHdqmFJ2wkYedbSyaa1TV7hw,AIzaSyD40fHhbjg0iGcqitqp461Mj2mnzLCqVwc
31
+ 30,AIzaSyDYecw8ln5eNrIkLC7N2FxD9hXnrWSXaEI,AIzaSyAk8TMOgleWNS6UQqN4SSNV3orAreRPEeM,AIzaSyDBsGgdOvSyKPXU1QGlTA_ijCqNpAd2BP8
Mbert.py ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ from torch import nn
3
+ from torch.utils.data import Dataset
4
+
5
+ class SentencePairDataset(Dataset):
6
+ def __init__(self, sentence_pairs, labels, tokenizer, max_length):
7
+ self.sentence_pairs = sentence_pairs
8
+ self.labels = labels
9
+ self.tokenizer = tokenizer
10
+ self.max_length = max_length
11
+
12
+ def __len__(self):
13
+ return len(self.sentence_pairs)
14
+
15
+ def __getitem__(self, idx):
16
+ sentence, context = self.sentence_pairs[idx]
17
+ label = self.labels[idx]
18
+
19
+ # Calculate max lengths for each part
20
+ max_context_length = int(self.max_length * 0.8) # 80% for context
21
+ max_claim_length = int(self.max_length * 0.2) # 20% for claim
22
+
23
+ # Encode claim and context separately
24
+ encoding = self.tokenizer.encode_plus(
25
+ sentence,
26
+ text_pair=context,
27
+ add_special_tokens=True,
28
+ max_length=self.max_length,
29
+ padding="max_length",
30
+ return_attention_mask=True,
31
+ return_tensors="pt",
32
+ truncation=True,
33
+ truncation_strategy='longest_first' # Truncate the longer text first
34
+ )
35
+
36
+ return {
37
+ "input_ids": encoding["input_ids"].flatten(),
38
+ "attention_mask": encoding["attention_mask"].flatten(),
39
+ "label": torch.tensor(label, dtype=torch.long),
40
+ }
41
+
42
+ class MBERTClassifier(nn.Module):
43
+ def __init__(self, mbert, num_classes):
44
+ super(MBERTClassifier, self).__init__()
45
+ self.mbert = mbert
46
+ self.layer_norm = nn.LayerNorm(self.mbert.config.hidden_size)
47
+ self.dropout = nn.Dropout(0.2)
48
+ self.batch_norm = nn.BatchNorm1d(self.mbert.config.hidden_size)
49
+ self.linear = nn.LazyLinear(num_classes)
50
+ self.activation = nn.ELU()
51
+
52
+ def forward(self, input_ids, attention_mask):
53
+ _, pooled_output = self.mbert(input_ids=input_ids, attention_mask=attention_mask, return_dict=False)
54
+ norm_output = self.layer_norm(pooled_output)
55
+ batch_norm_output = self.batch_norm(norm_output)
56
+ logits = self.linear(batch_norm_output)
57
+ activated_output = self.activation(logits)
58
+ dropout_output = self.dropout(activated_output)
59
+ return dropout_output
60
+
61
+ def predict_proba(self, input_ids, attention_mask):
62
+ logits = self.forward(input_ids, attention_mask)
63
+ probabilities = torch.softmax(logits, dim=-1)
64
+ return probabilities
Model/classifier.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:72343f29aa14a07f9835f5d5e7567690b10df6783d625badf42d4c423be4454a
3
+ size 711526350
app.py ADDED
@@ -0,0 +1,604 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Import custom modules for prediction
2
+ from predictor import predict
3
+ import google.generativeai as genai
4
+ import streamlit as st
5
+ import pandas as pd
6
+ import wikipedia
7
+ import json
8
+ import regex as re
9
+ from typing import List, Dict, Any
10
+ import google.generativeai as genai
11
+ import warnings
12
+ import logging
13
+ import time
14
+
15
+ # Disable warnings and logging
16
+ warnings.filterwarnings('ignore')
17
+ logging.disable(logging.WARNING)
18
+ def split_sentences_vietnamese(text):
19
+ # Thay thế dấu ba chấm tạm thời
20
+ text = text.replace("...", " @@@ ")
21
+
22
+ # Chia câu bằng các dấu chấm, chấm hỏi, chấm than
23
+ sentences = re.split(r'(?<!\w\.\w.)(?<!\w\.\w)(?<!\w\.)[.!?]\s+', text)
24
+
25
+ # Khôi phục dấu ba chấm và làm sạch dữ liệu
26
+ sentences = [s.replace(" @@@ ", "...").strip() for s in sentences if s.strip()]
27
+
28
+ return sentences
29
+ # Set Wikipedia language to Vietnamese
30
+ wikipedia.set_lang("vi")
31
+
32
+ # Character to number mapping for Vietnamese alphabet
33
+ char_to_num = {
34
+ 'A': 1, 'Ă': 2, 'Â': 3, 'B': 4, 'C': 5, 'D': 6, 'Đ': 7, 'E': 8, 'Ê': 9, 'G': 10,
35
+ 'H': 11, 'I': 12, 'K': 13, 'L': 14, 'M': 15, 'N': 16, 'O': 17, 'Ô': 18, 'Ơ': 19,
36
+ 'P': 20, 'Q': 21, 'R': 22, 'S': 23, 'T': 24, 'U': 25, 'Ư': 26, 'V': 27, 'X': 28, 'Y': 29
37
+ }
38
+
39
+ class ClaimGenerator:
40
+ """Class to handle advanced claim generation with different APIs."""
41
+
42
+ def __init__(self, claim_type: str, api_keys_file: str = "API.csv"):
43
+ self.claim_type = claim_type
44
+ self.api_keys = self._load_api_keys(api_keys_file)
45
+ self.current_key_index = 0
46
+ self._configure_api()
47
+ API_KEYS = {
48
+ "SUPPORTED": "AIzaSyCWoLgqVB8WLM7JPQMz4u3_jIOsHVs_SkA",
49
+ "REFUTED": "AIzaSyBe4ycn90utUlwhbD-fiyHJCitsPqVUO20",
50
+ "NEI": "AIzaSyBqcQXJlF18yItimSQRtVcKCSpxguLa360"
51
+ }
52
+
53
+ self.SCHEMAS = {
54
+ "SUPPORTED": {
55
+ "type": "object",
56
+ "properties": {
57
+ "claims": {
58
+ "type": "array",
59
+ "items": {
60
+ "type": "string"
61
+ },
62
+ "description": """
63
+ Câu nhận định đúng với các thông tin và số liệu được trích xuất trực tiếp từ context,yêu cầu phức tạp và dễ bị nhầm lẫn thành nhãn REFUTED, kết hợp nhiều kỹ thuật biến đổi:
64
+ Yêu cầu:
65
+ - Thông tin phải chính xác 100% so với context
66
+ - Không được thêm thông tin ngoài context
67
+ - Có thể kết hợp nhiều thông tin từ các phần khác nhau của context
68
+ - Phải có thể verify được từ context
69
+ Gợi ý cách đặt câu:
70
+ - Thay thế các bằng các từ đồng nghĩa
71
+ - Thay thế các lượng từ có cùng ý nghĩa
72
+ - Chuyển từ chủ động thành bị động & ngược lại
73
+ - Dùng từ trái nghĩa + phủ định
74
+ - Lược bỏ những bổ ngữ "không cần thiết" (không làm thay đổi nội dung của câu)
75
+ - Chuyển đổi danh từ, tân ngữ thành 1 mệnh đề quan hệ
76
+ - Tạo câu tiền giả định
77
+ Ví dụ:
78
+ VD1:
79
+ Claim: Quân Hán của Hàn Tín đã hủy diệt quân Triệu ở trận Tình Hình.
80
+ Context: ^ Năm 204 TCN, Trận Tỉnh Hình (trận Bối Thủy - Hàn Tín phá Triệu), quân nước Hán do danh tướng Hàn Tín chỉ huy đập tan nát quân Triệu của tướng Trần Dư.
81
+ VD2:
82
+ Claim: Trong quá trình làm việc nếu có tương tác với những vật dụng dính virus thì đều có nguy cơ nhiễm bệnh.
83
+ Context: Nhân viên Y tế: Bất kỳ nhân viên Y tế nào (Bác sĩ, Nha sỹ, Y tá, Y công.) cũng có thể bị nhiễm Viêm gan siêu vi C do tiếp xúc với bệnh phẩm chứa siêu vi trong quá trình làm việc.
84
+ VD3:
85
+ Claim: Trần Bảo dẫn quân sang cứu viện phủ thành Đại La nhưng thất bại.
86
+ Context: Năm 931, Dương Đình Nghệ là tướng cũ của Khúc Hạo đem quân đánh phủ thành Đại La, lại đánh tan quân Nam Hán do Trần Bảo dẫn sang cứu viện, giết Trần Bảo và tự xưng là Tiết độ sứ.
87
+ VD4:
88
+ Claim: Gan bị xơ sẽ không dễ dàng khôi phục lại.
89
+ Context: Khi đã xơ, gan khó hồi phục lại, cho dù tình trạng viêm có thuyên giảm. Vì vậy, các thầy thuốc khuyên nên điều trị sớm nhằm ngăn ngừa hoặc làm chậm tiến triển sang giai đoạn xơ gan.
90
+ VD5:
91
+ Claim: Nền văn minh này đóng góp một trong những văn bản lâu đời nhất thế giới.
92
+ Context: Các văn bản lịch sử văn hóa đã góp phần vào sự tồn tại của nền văn minh này. Một trong những văn bản cổ nhất trên thế giới, có tên Sử thi Gilgamesh, có nguồn gốc từ nền văn minh này.
93
+ VD6:
94
+ Claim: Sau khi thua trận trước quân Hán, Hai Bà Trưng đã tuẫn tiết.
95
+ Context: Năm 43, nhà Hán sai Phục ba tướng quân Mã Viện đem quân sang tái chiếm và đàn áp, Hai Bà Trưng chống không nổi phải rút về giữ Cấm Khê rồi tự vẫn ở sông Hát. Dân địa phương lập đền thờ ở Hát Giang.
96
+ """
97
+ }
98
+ },
99
+ "required": ["claims"]
100
+ },
101
+ "REFUTED": {
102
+ "type": "object",
103
+ "properties": {
104
+ "claims": {
105
+ "type": "array",
106
+ "items": {
107
+ "type": "string"
108
+ },
109
+ "description": """
110
+ Câu nhận định sai, mâu thuẫn với thông tin trong context, tinh vi, khó phát hiện và dễ bị nhầm lẫn thành nhãn SUPPORTED:
111
+ Yêu cầu:
112
+ - Phải sử dụng cùng chủ đề và phạm vi với context
113
+ - Thông tin hoặc số liệu phải mâu thuẫn rõ ràng với context
114
+ - Có thể thay đổi số liệu, sự kiện, hoặc mối quan hệ
115
+ - Phải có thể verify được là sai dựa trên context
116
+ Gợi ý cách đặt câu:
117
+ - Xáo trộn các giải thích của các đối tượng với nhau
118
+ - Thay thế bằng các từ trái nghĩa
119
+ - Thay thế các từ ngữ trong cùng lĩnh vực
120
+ - Biến đổi các thông số, đơn vị của các đối tượng
121
+ Ví dụ:
122
+ VD1:
123
+ Claim: Các phụ âm của phương ngữ California của tiếng Anh Mỹ, và của chuẩn RP được mô tả qua bảng phía trên.
124
+ Context: Đa số phương ngữ tiếng Anh sở hữu cùng 24 phụ âm giống nhau. Bảng bên dưới thể hiện các phụ âm của phương ngữ California của tiếng Anh Mỹ, và của chuẩn RP.
125
+ VD2:
126
+ Claim: Mặc dù đã xảy ra sự kiện đắm tàu Amphitrite vào năm 1698 nhưng quần đảo vẫn không một ai biết đến và ngày càng bị lu mờ đi.
127
+ Context: Năm 1698: Quần đảo trở nên nổi tiếng trong các biên niên sử hàng hải với vụ đắm tàu Amphitrite dưới thời vua Louis XIV trong khi đi từ Pháp sang Trung Quốc.
128
+ VD3:
129
+ Claim: Lí do để quần đảo trở nên nổi tiếng và được nhiều người biết đến trong các biên niên sử của hàng hải là vụ đắm tàu Amphitrite vào năm 1700.
130
+ Context: Năm 1698: Quần đảo trở nên nổi tiếng trong các biên niên sử hàng hải với vụ đắm tàu Amphitrite dưới thời vua Louis XIV trong khi đi từ Pháp sang Trung Quốc.
131
+ VD4:
132
+ Claim: Trôi dạt lục địa đã đẩy toàn bộ bề mặt đất liền lại với nhau.
133
+ Context: Trôi dạt lục địa đã tái định hình thể cho các đại dương của Trái Đất, kết hợp và chia cắt các đại dương cổ để tạo ra các đại dương như hiện nay. Các đại dương cổ có:
134
+ VD5:
135
+ Claim: Các tài liệu ghi về thời kỳ bắc thuộc cuối cùng của Đại Việt đã biến mất hoàn toàn từ xưa cho tới nay.
136
+ Context: Annam Lưu trữ 2006-12-03 tại Wayback Machine, thu thập các đoạn tài liệu Minh thực lục (明實錄) của nhà Minh về Đại Việt, trong đó có phần về thời kỳ bắc thuộc lần cuối.
137
+ VD6
138
+ Claim: Hiện tượng mô não mất quyền kiểm soát trong cơ thể là vì bệnh thiếu máu cục bộ khiến máu tràn một lượng lớn vào não.
139
+ Context: Trong đột quỵ do thiếu máu cục bộ, lượng máu cung cấp cho một phần não bị giảm, dẫn đến rối loạn chức năng của mô não ở khu vực đó. Có bốn lý do tại sao điều này có thể xảy ra:
140
+ """
141
+ }
142
+ },
143
+ "required": ["claims"]
144
+ },
145
+ "NEI": {
146
+ "type": "object",
147
+ "properties": {
148
+ "claims": {
149
+ "type": "array",
150
+ "items": {
151
+ "type": "string"
152
+ },
153
+ "description": """
154
+ Câu có thông tin không thể xác minh tính chính xác chỉ dựa vào context, có khả năng gây nhầm lẫn với SUPPORTED hoặc REFUTED:
155
+
156
+ Yêu cầu cơ bản:
157
+ - Phải liên quan chặt chẽ đến chủ đề chính của context
158
+ - Có ít nhất 1 thông tin không được có trong context
159
+ - Không được mâu thuẫn trực tiếp với context
160
+ - Không thể xác định được đúng sai chỉ dựa vào context
161
+ - Phải tạo ra sự mơ hồ và không chắc chắn cao
162
+ Gợi ý cách đặt câu:
163
+ - Tạo câu một phần thông tin liên quan đến context, nhưng đã thêm vào những chi tiết, suy luận hoặc kết luận không được hỗ trợ trực tiếp bởi context.
164
+ Ví dụ:
165
+ VD1:
166
+ Claim: Thời kỳ bắc thuộc lần cuối không được biết đến cho tới khi Annam lưu trữ xuất hiện.
167
+ Context: Annam Lưu trữ 2006-12-03 tại Wayback Machine, thu thập các đoạn tài liệu Minh thực lục (明實錄) của nhà Minh về Đại Việt, trong đó có phần về thời kỳ bắc thuộc lần cuối.
168
+ VD2:
169
+ Claim: Phát triển du lịch là mục tiêu phấn đấu của tỉnh Nghệ An.
170
+ Context: Nghệ An còn lưu giữ được nhiều di tích văn hoá lịch sử, nhiều danh lam thắng cảnh, lễ hội văn hoá truyền thống - đó là những yếu tố thuận lợi giúp cho du lịch Nghệ Antriển.
171
+ VD3:
172
+ Claim: Quân đội Ba Tư đông hơn nhưng vẫn không địch lại người La Mã.
173
+ Context: ^ Năm 627, Trận Nineveh (trong cuộc Chiến tranh La Mã-Ba Tư), quân Đông La Mã do đích thân Hoàng đế Heraclius thống suất đánh thắng quân Ba Tư do Đại tướng Rhahzadh cầm đầu.
174
+ VD4:
175
+ Claim: Bệnh phẩm chứa siêu vi viêm gan C được đề xuất nên bị loại bỏ hoàn toàn.
176
+ Context: Nhân viên Y tế: Bất kỳ nhân viên Y tế nào (Bác sĩ, Nha sỹ, Y tá, Y công.) cũng có thể bị nhiễm Viêm gan siêu vi C do tiếp xúc với bệnh phẩm chứa siêu vi trong quá trình làm việc.
177
+ VD5:
178
+ Claim: Thập Nhị Chi là tính toán thời gian theo 12 con vật.
179
+ Context: Tương truyền ngày xưa có một người tên Đại Nhiêu đã lập ra Thập Can và Thập Nhị Chi để giúp người ta tính toán thời gian. Việc tính giờ cũng có liên quan đến tập tính của 12 loài vật:
180
+ VD5:
181
+ Claim: Nghệ An là một tỉnh nằm ở phía bắc sông Lam.
182
+ Context: Năm 1831, vua Minh Mệnh chia trấn Nghệ An thành 2 tỉnh: Nghệ An (phía Bắc sông Lam); Hà Tĩnh (phía nam sông Lam). Sau đó hai tỉnh Nghệ An và Hà Tĩnh sáp nhập lại, lấy tên là tỉnh An Tĩnh.
183
+ VD6:
184
+ Claim: Được mô phỏng giống như lễ hội đường phố tại các nước Châu Âu, Carneval Hội An đã được tổ chức tại Hội An vào Giao thừa 2009
185
+ Context: Carneval Hội An là lễ hội đường phố được tổ chức lần đầu tiên tại thành phố Hội An vào Giao thừa năm 2009 (dương lịch). Lễ hội mô phỏng theo các lễ hội Carneval đường phố vốn rất nổi tiếng tại các nước châu Âu và Mỹ Latin .
186
+ Lưu ý quan trọng:
187
+ - Ưu tiên sử dụng các từ ngữ gợi ý về quan hệ nhân quả, so sánh, hoặc khái quát hóa
188
+ - Tránh tạo ra các claim quá rõ ràng là không có trong context
189
+ - Nên tận dụng các thông tin ngữ cảnh để tạo ra các suy luận hợp lý nhưng không thể kiểm chứng
190
+ - Kết hợp nhiều kỹ thuật để tăng độ khó trong việc xác định nhãn
191
+ - Đảm bảo câu claim vẫn giữ được tính logic và khả năng xảy ra trong thực tế
192
+ """
193
+ }
194
+ },
195
+ "required": ["claims"]
196
+ }
197
+ }
198
+
199
+ def _load_api_keys(self, file_path: str ) -> List[str]:
200
+ """Load API keys from CSV file for the specific claim type."""
201
+ try:
202
+ df = pd.read_csv(file_path)
203
+ # Get all keys for the specific claim type, excluding NaN values
204
+ keys = df[self.claim_type].dropna().tolist()
205
+ if not keys:
206
+ raise ValueError(f"No API keys found for {self.claim_type}")
207
+ return keys
208
+ except Exception as e:
209
+ raise Exception(f"Error loading API keys: {str(e)}")
210
+
211
+ def _configure_api(self):
212
+ """Configure the API with the current key."""
213
+ genai.configure(api_key=self.api_keys[self.current_key_index])
214
+
215
+ def _rotate_api_key(self):
216
+ """Rotate to the next available API key."""
217
+ self.current_key_index = (self.current_key_index + 1) % len(self.api_keys)
218
+ self._configure_api()
219
+ print(f"Rotating to next API key for {self.claim_type}")
220
+
221
+
222
+ def generate_claims(self, context: str, max_retries: int = 10) -> List[str]:
223
+ """Generate claims with automatic API key rotation on errors."""
224
+ retries = 0
225
+ while retries < max_retries:
226
+ try:
227
+ model = genai.GenerativeModel(
228
+ 'models/gemini-1.5-flash-latest',
229
+ generation_config={
230
+ "response_mime_type": "application/json",
231
+ "response_schema": self.SCHEMAS[self.claim_type],
232
+ "temperature": 0.9,
233
+ "top_p": 0.95,
234
+ "top_k": 40,
235
+ "max_output_tokens": 1024
236
+ }
237
+ )
238
+
239
+ prompt = f"""
240
+ Fact checking là 1 trong lĩnh vực xử lý ngôn ngữ tự nhiên (NLP), là bài toán kiểm tra và xác minh tính chính xác của 1 nhận định được đưa ra trên các thông tin, tin tức từ mạng xã hội, báo chí. Mô hình NLP sẽ xác định câu nhận định đó là chính xác hay sai sự thật hoặc không được đề cập đến trong thông tin đã được cung cấp trước đó (context).
241
+ Trong bối cảnh của Adversarial, đây là bài toán tạo ra bộ dữ liệu đối kháng với mục đích đánh lừa gây và gây khó khăn cho các mô hình NLP để dự đoán tính xác thực của các câu nhận định đó. Mục đích của bài toán này là thử thách khả năng suy luận của các mô hình NLP, từ đó để tạo nên bộ dữ liệu mới chất lượng hơn, cải thiện “khả năng học” của mô hình học máy.
242
+ Context: là nguồn thông tin, nội dung được cung cấp hiện có trong dataset mà annotator sẽ dựa vào để tiến hành đặt câu và đánh dấu.
243
+ Câu Claim: là câu nhận định, tuyên bố viết về bất kỳ chủ đề gì, được xác định tính đúng sai hoặc không liên quan dựa trên thông tin từ context đưa ra mà không sử dụng bất kỳ kiến thức hoặc thông tin ngoài lề
244
+ + SUPPORTED là nhãn dành cho câu nhận định đúng, chính xác với các thông tin, số liệu trong câu được trích xuất từ đoạn văn gốc
245
+ + REFUTED là nhãn dành cho câu nhận định sai, với các thông tin, số liệu trong câu bị sai so với đoạn văn gốc
246
+ + NEI là nhãn dành cho câu có các thông tin, số liệu chưa được xác định là đúng hay sai dựa trên đoạn văn gốc
247
+ Context: "{context}"
248
+ Nhiệm vụ: Tạo một câu claim {self.claim_type} có liên quan đến context có độ khó cao, có thể gây khó khăn cho các mô hình NLP trong việc dự đoán nhãn chính xác.
249
+ Yêu cầu chi tiết:
250
+ 1. Tuân thủ chặt chẽ các yêu cầu và kỹ thuật được mô tả trong schema
251
+ 2. Tạo câu có cấu trúc phức tạp, kết hợp nhiều kỹ thuật biến đổi
252
+ 3. Đảm bảo câu vẫn hợp lý và có thể hiểu được
253
+ 4. Tránh:
254
+ - Copy nguyên văn từ context
255
+ - Sử dụng các biến đổi quá đơn giản
256
+ - Tạo câu không liên quan đến chủ đề
257
+ - Sử dụng thông tin ngoài context (trừ NEI có kiểm soát)
258
+ Trả về kết quả theo đúng format JSON với trường {self.claim_type}.
259
+ """
260
+
261
+ # Sử dụng regex để xóa các khoảng trắng thừa
262
+ prompt = re.sub(r'\s+', ' ', prompt).strip()
263
+ # Xóa toàn bộ ký tự xuống dòng
264
+ prompt = re.sub(r'\n', ' ', prompt).strip()
265
+ response = model.generate_content(prompt)
266
+ time.sleep(2) # Prevent rate limiting
267
+ return json.loads(response.text)["claims"]
268
+
269
+ except Exception as e:
270
+ error_msg = str(e)
271
+ if "429" in error_msg or "500" in error_msg:
272
+ print(f"API error: {error_msg}")
273
+ self._rotate_api_key()
274
+ retries += 1
275
+ else:
276
+ raise Exception(f"Unexpected error: {error_msg}")
277
+
278
+
279
+ def generate_hard_claims(self, context: str, predict_func, max_attempts: int = 10) -> Dict[str, Any]:
280
+ """Generate and validate claims with API key rotation support.
281
+ Tracks and returns the claim with lowest probability across all attempts."""
282
+ lowest_prob_claim = None
283
+ lowest_prob = float('inf') # Initialize with infinity to ensure first claim is captured
284
+ attempts = 0
285
+
286
+ while attempts < max_attempts:
287
+ try:
288
+ attempts += 1
289
+ claims = self.generate_claims(context)
290
+
291
+ for claim in claims:
292
+ prediction = predict_func(context, claim)
293
+ current_prob = prediction['probabilities'][self.claim_type]
294
+ other_labels = [label for label in ["SUPPORTED", "REFUTED", "NEI"]
295
+ if label != self.claim_type]
296
+ other_probs = [prediction['probabilities'][label] for label in other_labels]
297
+
298
+ claim_result = {
299
+ 'claim': claim,
300
+ 'predicted_label': prediction['verdict'],
301
+ f'{self.claim_type}_probability': current_prob,
302
+ 'other_probabilities': dict(zip(other_labels, other_probs)),
303
+ 'all_probabilities': prediction['probabilities']
304
+ }
305
+
306
+ # Update lowest probability claim if current is lower
307
+ if current_prob < lowest_prob:
308
+ lowest_prob = current_prob
309
+ lowest_prob_claim = claim_result
310
+
311
+ # Validation logic based on label type
312
+ if self.claim_type == "NEI":
313
+ max_other_prob = max(other_probs)
314
+ if current_prob < sum(other_probs) or (0.7 > current_prob > 0.5):
315
+ return {
316
+ 'success': True,
317
+ 'attempts': attempts,
318
+ 'results': [claim_result],
319
+ 'used_fallback': False
320
+ }
321
+ else:
322
+ if current_prob < sum(other_probs):
323
+ return {
324
+ 'success': True,
325
+ 'attempts': attempts,
326
+ 'results': [claim_result],
327
+ 'used_fallback': False
328
+ }
329
+
330
+ except Exception as e:
331
+ print(f"Error during claim generation: {str(e)}")
332
+ self._rotate_api_key()
333
+ continue
334
+
335
+ return {
336
+ 'success': True,
337
+ 'attempts': attempts,
338
+ 'results': [lowest_prob_claim] if lowest_prob_claim else [],
339
+ 'used_fallback': True
340
+ }
341
+
342
+ def generate_claims_for_context(
343
+ context: str,
344
+ claim_types: List[str],
345
+ predict_func,
346
+ progress_bar
347
+ ) -> List[Dict[str, Any]]:
348
+ """Generate claims for the context with progress tracking and fallback handling."""
349
+ claims_data = []
350
+ total_steps = len(claim_types)
351
+
352
+ for i, claim_type in enumerate(claim_types):
353
+ progress_bar.progress((i / total_steps), f"Generating {claim_type} claims...")
354
+
355
+ generator = ClaimGenerator(claim_type)
356
+ result = generator.generate_hard_claims(context, predict_func)
357
+
358
+ if result['success']:
359
+ for claim_result in result['results']:
360
+ claim_data = {
361
+ 'context': context,
362
+ 'claim': claim_result['claim'],
363
+ 'label': claim_type,
364
+ 'predicted_label': claim_result['predicted_label'],
365
+ f'{claim_type}_probability': claim_result[f'{claim_type}_probability'],
366
+ 'probabilities': claim_result['all_probabilities']
367
+ }
368
+ claims_data.append(claim_data)
369
+
370
+ if result.get('used_fallback'):
371
+ st.warning(f"Used fallback claims for {claim_type} after {result['attempts']} attempts")
372
+ else:
373
+ st.error(f"Failed to generate any {claim_type} claims after {result['attempts']} attempts")
374
+
375
+ return claims_data
376
+
377
+ def process_dataframe_with_claims(df: pd.DataFrame) -> pd.DataFrame:
378
+ """Process each summary in the DataFrame and generate claims with fallback handling."""
379
+ all_rows = []
380
+ progress_bar = st.progress(0)
381
+
382
+ for i, row in df.iterrows():
383
+ context = row['Summary']
384
+
385
+ for claim_type in ["SUPPORTED", "REFUTED", "NEI"]:
386
+ generator = ClaimGenerator(claim_type)
387
+ result = generator.generate_hard_claims(context, predict)
388
+
389
+ if result['success']:
390
+ for claim_result in result['results']:
391
+ new_row = row.copy()
392
+ new_row['claim'] = claim_result['claim']
393
+ new_row['label'] = claim_type
394
+ new_row['predicted_label'] = claim_result['predicted_label']
395
+ new_row['probability'] = claim_result[f'{claim_type}_probability']
396
+ new_row['all_probabilities'] = json.dumps(claim_result['all_probabilities'])
397
+ new_row['used_fallback'] = result.get('used_fallback', False)
398
+ all_rows.append(new_row)
399
+
400
+ if result.get('used_fallback'):
401
+ st.warning(f"Used fallback claims for article {row['ID']} {claim_type}")
402
+
403
+ progress_bar.progress((i + 1) / len(df))
404
+
405
+ new_df = pd.DataFrame(all_rows)
406
+ return new_df
407
+
408
+ def generate_claims_for_context(
409
+ context: str,
410
+ claim_types: List[str],
411
+ predict_func,
412
+ progress_bar
413
+ ) -> List[Dict[str, Any]]:
414
+ """Generate claims for the context with progress tracking."""
415
+ claims_data = []
416
+ total_steps = len(claim_types)
417
+
418
+ for i, claim_type in enumerate(claim_types):
419
+ progress_bar.progress((i / total_steps), f"Generating {claim_type} claims...")
420
+
421
+ generator = ClaimGenerator(claim_type)
422
+ result = generator.generate_hard_claims(context, predict_func)
423
+
424
+ if result['success']:
425
+ for claim_result in result['results']:
426
+ claim_data = {
427
+ 'context': context,
428
+ 'claim': claim_result['claim'],
429
+ 'label': claim_type,
430
+ 'predicted_label': claim_result['predicted_label'],
431
+ f'{claim_type}_probability': claim_result[f'{claim_type}_probability'],
432
+ 'probabilities': claim_result['all_probabilities']
433
+ }
434
+ claims_data.append(claim_data)
435
+ else:
436
+ st.error(f"Error generating {claim_type} claims after {result['attempts']} attempts")
437
+
438
+ return claims_data
439
+
440
+ # Wikipedia helper functions
441
+ def format_content(content):
442
+ cleaned_content = re.sub(r'==.*?==', '', content)
443
+ cleaned_text = re.sub(r'\n\s*\n', '\n', cleaned_content)
444
+ lines = cleaned_text.split("\n")
445
+ cleaned_lines = [line.strip() for line in lines]
446
+ return "\n\n".join(cleaned_lines)
447
+
448
+ def chars_to_nums(s):
449
+ return ''.join(str((char_to_num.get(char.upper(), 0) % 4) + 1) for char in s if char.upper() in char_to_num)
450
+
451
+ def create_id(topic, stt):
452
+ topic_abbr = ''.join([word[0] for word in topic.split() if word])
453
+ topic_num = chars_to_nums(topic_abbr)
454
+ return f'uit_{topic_num}_{stt}'
455
+
456
+ def wikipedia_scrape(title_input, stt, filename):
457
+ try:
458
+ page = wikipedia.page(title_input)
459
+ title = page.title
460
+ summary = wikipedia.summary(title_input, sentences=10)
461
+ url = page.url
462
+ topic = filename.split(".")[0]
463
+ base_article_id = create_id(topic, stt)
464
+
465
+ summary = format_content(summary)
466
+ # Chia câu dựa trên dấu chấm
467
+ sentences = split_sentences_vietnamese(summary)
468
+ total_sentences = len(sentences)
469
+
470
+ # Tính toán chia đoạn động
471
+ part_lengths = [5, total_sentences - 5]
472
+
473
+ results = []
474
+ start = 0
475
+ for i, length in enumerate(part_lengths, 1):
476
+ # Đảm bảo không vượt quá tổng số câu
477
+ end = min(start + length, total_sentences)
478
+ part = '. '.join(sentences[start:end]) + '.'
479
+
480
+ if len(part)>=5:
481
+ article_id = f"{base_article_id}_{i}"
482
+ results.append({
483
+ "ID": article_id,
484
+ "Title": title,
485
+ "Topic": topic,
486
+ "Summary": part,
487
+ "URL": url
488
+ })
489
+
490
+ start = end
491
+
492
+ return results
493
+ except (wikipedia.exceptions.DisambiguationError, wikipedia.exceptions.PageError) as e:
494
+ return None
495
+
496
+
497
+
498
+ @st.cache_data
499
+ def convert_df_to_csv(df):
500
+ return df.to_csv(index=False).encode("utf-8-sig")
501
+
502
+ def process_dataframe_with_claims(df: pd.DataFrame) -> pd.DataFrame:
503
+ """Process each summary in the DataFrame and generate claims."""
504
+
505
+ # Create lists to store the new data
506
+ all_rows = []
507
+ progress_bar = st.progress(0)
508
+ # Process each row in the original DataFrame
509
+ for i, row in df.iterrows():
510
+ context = row['Summary']
511
+
512
+ # Generate claims for each type
513
+ for claim_type in ["SUPPORTED", "REFUTED", "NEI"]:
514
+ generator = ClaimGenerator(claim_type)
515
+ result = generator.generate_hard_claims(context, predict)
516
+
517
+ if result['success']:
518
+ for claim_result in result['results']:
519
+ # Create a new row with all original columns plus new claim data
520
+ new_row = row.copy()
521
+ new_row['claim'] = claim_result['claim']
522
+ new_row['label'] = claim_type
523
+ new_row['predicted_label'] = claim_result['predicted_label']
524
+ new_row['probability'] = claim_result[f'{claim_type}_probability']
525
+ new_row['support_probability'] = claim_result['all_probabilities']["SUPPORTED"]
526
+ new_row['refuted_probability'] = claim_result['all_probabilities']["REFUTED"]
527
+ new_row['nei_probability'] = claim_result['all_probabilities']["NEI"]
528
+ all_rows.append(new_row)
529
+ progress_bar.progress((i + 1) / len(df))
530
+
531
+
532
+ # Create new DataFrame with all rows
533
+ new_df = pd.DataFrame(all_rows)
534
+ return new_df
535
+
536
+ def main():
537
+ st.title("Ứng dụng crawl data wiki tiếng việt và tạo claims")
538
+
539
+ uploaded_file = st.file_uploader("Tải lên tệp văn bản (txt)", type=["txt"])
540
+
541
+ if uploaded_file is not None:
542
+ file_progress = st.progress(0)
543
+ status_text = st.empty()
544
+
545
+ file_contents = uploaded_file.getvalue().decode("utf-8")
546
+ titles = file_contents.split("\n")
547
+
548
+ articles_info = []
549
+ for index, title in enumerate(titles):
550
+ title = title.strip()
551
+ if title:
552
+ status_text.text(f"Processing article {index + 1}/{len(titles)}: {title}")
553
+ article_infos = wikipedia_scrape(title, index + 1, uploaded_file.name)
554
+
555
+ # Safely append results, handling potential None values
556
+ if article_infos:
557
+ articles_info.extend(article_infos)
558
+ file_progress.progress((index + 1) / len(titles))
559
+ else:
560
+ st.warning(f"Dòng {index + 1}: Tiêu đề trống")
561
+
562
+ file_progress.empty()
563
+ status_text.empty()
564
+
565
+ if not articles_info:
566
+ st.error("Không có bài viết nào được thu thập từ Wikipedia.")
567
+ else:
568
+ df = pd.DataFrame(articles_info)
569
+
570
+ st.subheader("Danh sách bài viết từ Wikipedia:")
571
+ st.dataframe(df, use_container_width=True, hide_index=True)
572
+
573
+ # Add automatic claim generation for all summaries
574
+ if st.button("Tạo Claims cho tất cả bài viết"):
575
+ with st.spinner("Đang tạo claims cho tất cả bài viết..."):
576
+
577
+ # Process the DataFrame and generate claims
578
+ df_with_claims = process_dataframe_with_claims(df)
579
+
580
+ st.subheader("Bảng dữ liệu với Claims:")
581
+ st.dataframe(df_with_claims, use_container_width=True)
582
+
583
+ # Download options
584
+ csv = convert_df_to_csv(df_with_claims)
585
+ claims_filename = f"uit_{uploaded_file.name.split('.')[0]}_with_claims.csv"
586
+ st.download_button(
587
+ label="Download CSV với Claims",
588
+ data=csv,
589
+ file_name=claims_filename,
590
+ mime="text/csv",
591
+ )
592
+
593
+ # Original download option for basic DataFrame
594
+ csv = convert_df_to_csv(df)
595
+ csv_filename = "uit_" + uploaded_file.name.split(".")[0] + ".csv"
596
+ st.download_button(
597
+ label="Download CSV (không có claims)",
598
+ data=csv,
599
+ file_name=csv_filename,
600
+ mime="text/csv",
601
+ )
602
+
603
+ if __name__ == "__main__":
604
+ main()
config.py ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ hf_token = "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"
2
+
3
+ supported_schema = {
4
+ "type": "object",
5
+ "properties": {
6
+ "SUPPORTED": {
7
+ "type": "string",
8
+ "description": """
9
+ Câu khẳng định đúng, với các thông tin và số liệu được trích xuất trực tiếp từ context.
10
+ Yêu cầu:
11
+ - Thông tin phải chính xác 100% so với context
12
+ - Không được thêm thông tin ngoài context
13
+ - Có thể kết hợp nhiều thông tin từ các phần khác nhau của context
14
+ - Phải có thể verify được từ context
15
+ Gợi ý cách đặt câu:
16
+ - Thay thế các bằng các từ đồng nghĩa
17
+ - Thay thế các lượng từ có cùng ý nghĩa
18
+ - Chuyển từ chủ động thành bị động & ngược lại
19
+ - Dùng từ trái nghĩa + phủ định
20
+ - Lược bỏ những bổ ngữ “không cần thiết” (không làm thay đổi nội dung của câu)
21
+ - Chuyển đổi danh từ, tân ngữ thành 1 mệnh đề quan hệ
22
+ - Tạo câu tiền giả định
23
+ """
24
+ }
25
+ },
26
+ "required": ["SUPPORTED"]
27
+ }
28
+
29
+ refuted_schema = {
30
+ "type": "object",
31
+ "properties": {
32
+ "REFUTED": {
33
+ "type": "string",
34
+ "description": """
35
+ Câu khẳng định sai, mâu thuẫn với thông tin trong context.
36
+ Yêu cầu:
37
+ - Phải sử dụng cùng chủ đề và phạm vi với context
38
+ - Thông tin hoặc số liệu phải mâu thuẫn rõ ràng với context
39
+ - Có thể thay đổi số liệu, sự kiện, hoặc mối quan hệ
40
+ - Phải có thể verify được là sai dựa trên context
41
+ Gợi ý cách đặt câu:
42
+ - Xáo trộn các giải thích của các đối tượng với nhau
43
+ - Thay thế bằng các từ trái nghĩa
44
+ - Thay thế các từ ngữ trong cùng lĩnh vực
45
+ - Biến đổi các thông số, đơn vị của các đối tượng
46
+ """
47
+ },
48
+ },
49
+ "required": ["REFUTED"]
50
+ }
51
+ nei_schema = {
52
+ "type": "object",
53
+ "properties": {
54
+ "NEI": {
55
+ "type": "string",
56
+ "description": """
57
+ Câu có thông tin không thể xác minh từ context.
58
+ Yêu cầu:
59
+ - Phải liên quan đến chủ đề của context
60
+ - Thông tin không được có trong context
61
+ - Không được mâu thuẫn trực tiếp với context
62
+ - Không thể xác định đúng sai chỉ dựa vào
63
+ Gợi ý cách đặt câu:
64
+ - Viết lại câu với thông tin bị thu hẹp, mở rộng, suy diễn hoặc kết hợp với 1 thông tin khác chưa xác định
65
+ - Tạo câu giả định
66
+ """
67
+ }
68
+ },
69
+ "required": ["NEI"]
70
+ }
predictor.py ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ hf_token = "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"
2
+ import warnings
3
+ warnings.filterwarnings('ignore')
4
+ import logging
5
+ logging.disable(logging.WARNING)
6
+
7
+ import torch
8
+ import numpy as np
9
+ import random
10
+ from transformers import AutoModel, AutoTokenizer
11
+ from torch.utils.data import DataLoader
12
+ from Mbert import MBERTClassifier, SentencePairDataset
13
+ import pandas as pd
14
+
15
+ # Thiết lập seed cố định
16
+ def set_seed(seed):
17
+ random.seed(seed)
18
+ np.random.seed(seed)
19
+ torch.manual_seed(seed)
20
+ if torch.cuda.is_available():
21
+ torch.cuda.manual_seed(seed)
22
+ torch.cuda.manual_seed_all(seed)
23
+ torch.backends.cudnn.deterministic = True
24
+ torch.backends.cudnn.benchmark = False
25
+
26
+ # Gọi hàm set_seed với seed cố định, ví dụ: 42
27
+ set_seed(42)
28
+ device = torch.device("cpu")
29
+ modelname = "bert-base-multilingual-cased"
30
+ tokenizer = AutoTokenizer.from_pretrained(modelname, token=hf_token)
31
+ mbert = AutoModel.from_pretrained(modelname, token=hf_token).to(device)
32
+ model = MBERTClassifier(mbert, num_classes=3).to(device)
33
+ model.load_state_dict(torch.load('Model/classifier.pt', map_location=device))
34
+
35
+ def predict(context, claim):
36
+ data = pd.DataFrame([{'context': context, 'claim': claim}])
37
+ X1_pub_test = data['claim']
38
+ X2_pub_test = data['context']
39
+ X_pub_test = [(X1_pub_test, X2_pub_test) for (X1_pub_test, X2_pub_test) in zip(X1_pub_test, X2_pub_test)]
40
+ y_pub_test = [1]
41
+
42
+ test_dataset = SentencePairDataset(X_pub_test, y_pub_test, tokenizer, 256)
43
+ test_loader_pub = DataLoader(test_dataset, batch_size=1)
44
+
45
+ model.eval()
46
+ predictions = []
47
+ probabilities = []
48
+
49
+ for batch in test_loader_pub:
50
+ input_ids = batch["input_ids"].to(device)
51
+ attention_mask = batch["attention_mask"].to(device)
52
+ with torch.no_grad():
53
+ outputs = model(input_ids, attention_mask)
54
+ probs = torch.nn.functional.softmax(outputs, dim=1)
55
+ predicted = torch.argmax(outputs, dim=1)
56
+ predictions.extend(predicted.cpu().numpy().tolist())
57
+ probabilities.extend(probs.cpu().numpy().tolist())
58
+
59
+ data['verdict'] = predictions
60
+ data['verdict'] = data['verdict'].replace(0, "SUPPORTED")
61
+ data['verdict'] = data['verdict'].replace(1, "REFUTED")
62
+ data['verdict'] = data['verdict'].replace(2, "NEI")
63
+
64
+ result = {
65
+ 'verdict': data['verdict'][0],
66
+ 'probabilities': {
67
+ 'SUPPORTED': probabilities[0][0],
68
+ 'REFUTED': probabilities[0][1],
69
+ 'NEI': probabilities[0][2]
70
+ }
71
+ }
72
+
73
+ return result