htg2501 commited on
Commit
21b70be
·
verified ·
1 Parent(s): dff3652

Upload 12 files

Browse files
.gitattributes CHANGED
@@ -33,3 +33,5 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ c_25_0.3071.mdl filter=lfs diff=lfs merge=lfs -text
37
+ e_25_0.3071.mdl filter=lfs diff=lfs merge=lfs -text
Dockerfile CHANGED
@@ -1,20 +1,23 @@
1
- FROM python:3.13.5-slim
2
-
3
- WORKDIR /app
4
-
5
- RUN apt-get update && apt-get install -y \
6
- build-essential \
7
- curl \
8
- git \
9
- && rm -rf /var/lib/apt/lists/*
10
-
11
- COPY requirements.txt ./
12
- COPY src/ ./src/
13
-
14
- RUN pip3 install -r requirements.txt
15
-
16
- EXPOSE 8501
17
-
18
- HEALTHCHECK CMD curl --fail http://localhost:8501/_stcore/health
19
-
20
- ENTRYPOINT ["streamlit", "run", "src/streamlit_app.py", "--server.port=8501", "--server.address=0.0.0.0"]
 
 
 
 
1
+ FROM python:3.9-slim
2
+
3
+ WORKDIR /app
4
+
5
+ # Cài thư viện hệ thống cần thiết
6
+ RUN apt-get update && apt-get install -y \
7
+ build-essential \
8
+ git \
9
+ && rm -rf /var/lib/apt/lists/*
10
+
11
+ # Copy requirements trước để cache
12
+ COPY requirements.txt .
13
+
14
+ RUN pip install --no-cache-dir -r requirements.txt
15
+
16
+ # Copy toàn bộ source code + model
17
+ COPY . .
18
+
19
+ # Expose port cho HF
20
+ EXPOSE 7860
21
+
22
+ # Chạy Streamlit
23
+ CMD ["streamlit", "run", "app.py", "--server.port=7860", "--server.address=0.0.0.0"]
LDA_models.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:7fe550070538e5cf9f47f4f94dacb170662b607a69c1d294ef03c6c5400031d7
3
+ size 1983272
Logo_UET.png ADDED
README.md CHANGED
@@ -1,19 +1,84 @@
1
- ---
2
- title: AI
3
- emoji: 🚀
4
- colorFrom: red
5
- colorTo: red
6
- sdk: docker
7
- app_port: 8501
8
- tags:
9
- - streamlit
10
- pinned: false
11
- short_description: Streamlit template space
12
- ---
13
-
14
- # Welcome to Streamlit!
15
-
16
- Edit `/src/streamlit_app.py` to customize this app to your heart's desire. :heart:
17
-
18
- If you have any questions, checkout our [documentation](https://docs.streamlit.io) and [community
19
- forums](https://discuss.streamlit.io).
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # VNU Summarizer - Hệ thống tóm tắt đa văn bản tiếng Việt
2
+
3
+ ![Logo UET](./Logo_UET.png)
4
+
5
+ ## Giới thiệu
6
+
7
+ VNU Summarizer là một ứng dụng web được phát triển nhằm cung cấp giải pháp tóm tắt đa văn bản cho tiếng Việt. Hệ thống này được xây dựng trên nền tảng Streamlit, cung cấp giao diện trực quan và dễ sử dụng cho người dùng.
8
+
9
+ ## Mục tiêu
10
+
11
+ - Tạo các bản tóm tắt chất lượng cao từ nhiều tài liệu đầu vào
12
+ - Hỗ trợ cả hai phương pháp tóm tắt: trích lược (extractive) và trích rút (abstractive)
13
+ - Cung cấp công cụ đánh giá chất lượng tóm tắt dựa trên các chỉ số ROUGE
14
+ - Tạo giao diện người dùng thân thiện, dễ sử dụng
15
+
16
+ ## Chức năng chính
17
+
18
+ ### 1. Nhập liệu đa dạng
19
+ - **Nhập văn bản trực tiếp**: Người dùng có thể thêm nhiều vùng nhập văn bản
20
+ - **Tải lên tệp**: Hỗ trợ nhiều định dạng tệp phổ biến (txt, pdf, docx)
21
+
22
+ ### 2. Phương pháp tóm tắt
23
+ - **Tóm tắt trích lược (Extractive Summarization)**: Trích xuất các câu quan trọng từ văn bản gốc
24
+ - **Tóm tắt trích rút (Abstractive Summarization)**: Tạo ra bản tóm tắt mới với cách diễn đạt riêng
25
+
26
+ ### 3. Tùy chỉnh tham số
27
+ - **Tỷ lệ rút gọn**: Người dùng có thể chọn tỷ lệ rút gọn từ 0-50%
28
+ - **Số câu đầu ra**: Người dùng có thể chỉ định số câu cần xuất ra trong bản tóm tắt
29
+
30
+ ### 4. Đánh giá chất lượng
31
+ - **Chỉ số ROUGE**: Hệ thống cung cấp các chỉ số ROUGE-1, ROUGE-2, ROUGE-L để đánh giá chất lượng tóm tắt
32
+ - **Tóm tắt mẫu**: Người dùng có thể nhập tóm tắt mẫu để so sánh với kết quả tóm tắt của hệ thống
33
+
34
+ ## Cách sử dụng
35
+
36
+ 1. **Nhập văn bản**:
37
+ - Chọn phương thức nhập liệu (nhập trực tiếp hoặc tải tệp lên)
38
+ - Nếu nhập trực tiếp, sử dụng nút "Thêm vùng nhập văn bản" để thêm nhiều văn bản
39
+ - Nếu tải tệp, kéo thả các tệp vào vùng quy định
40
+
41
+ 2. **Nhập tóm tắt mẫu** (không bắt buộc):
42
+ - Nhập bản tóm tắt mẫu cho phương pháp trích lược
43
+ - Nhập bản tóm tắt mẫu cho phương pháp trích rút
44
+
45
+ 3. **Cấu hình tóm tắt**:
46
+ - Chọn phương thức rút gọn (tỷ lệ hoặc số câu)
47
+ - Điều chỉnh tỷ lệ rút gọn hoặc số câu đầu ra theo nhu cầu
48
+
49
+ 4. **Xem kết quả**:
50
+ - Nhấn nút "Tóm tắt" để xem kết quả
51
+ - Kết quả sẽ hiển thị cả hai phương pháp tóm tắt cùng các chỉ số đánh giá ROUGE
52
+
53
+ ## Cấu trúc mã nguồn
54
+
55
+ Ứng dụng được xây dựng dựa trên các thành phần chính sau:
56
+ - `streamlit`: Framework để xây dựng giao diện web
57
+ - `api.summarization.MultiDocSummarizationAPI`: API chính để xử lý tóm tắt đa văn bản
58
+ - `fitz`: Thư viện xử lý tệp PDF
59
+ - `docx`: Thư viện xử lý tệp Word
60
+
61
+ ## Yêu cầu hệ thống
62
+
63
+ - Python 3.11
64
+ - Streamlit
65
+ - PyMuPDF (fitz)
66
+ - python-docx
67
+ - Các thư viện phụ thuộc khác được liệt kê trong tệp requirements.txt
68
+
69
+ ## Cài đặt và chạy
70
+
71
+ ```bash
72
+ # Clone repository
73
+ git clone <repository-url>
74
+
75
+ # Di chuyển vào thư mục dự án
76
+ cd vnu-summarizer
77
+
78
+ # Cài đặt các thư viện phụ thuộc
79
+ pip install -r requirements.txt
80
+
81
+ # Chạy ứng dụng
82
+ streamlit run app.py
83
+
84
+ Tải thêm checkpoint-2200 trên notion
__init__.py ADDED
File without changes
app.py ADDED
@@ -0,0 +1,147 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+
3
+ st.set_page_config(page_title="VNU Summarizer", layout="wide")
4
+
5
+ # Chèn JavaScript để thay đổi tiêu đề ngay lập tức
6
+ st.markdown(
7
+ """
8
+ <script>
9
+ document.title = "VNU Summarizer";
10
+ </script>
11
+ """,
12
+ unsafe_allow_html=True
13
+ )
14
+ from summarization import MultiDocSummarizationAPI
15
+ import fitz
16
+ from docx import Document
17
+
18
+ # Cấu hình tiêu đề trang ngay từ đầu
19
+
20
+
21
+ # Ẩn footer "Made with Streamlit"
22
+ hide_streamlit_style = """
23
+ <style>
24
+ #MainMenu {visibility: hidden;}
25
+ footer {visibility: hidden;}
26
+ </style>
27
+ """
28
+ st.markdown(hide_streamlit_style, unsafe_allow_html=True)
29
+
30
+ st.image("./Logo_UET.png", width=150)
31
+
32
+ def extract_text_from_pdf(uploaded_file):
33
+ pdf_text = ""
34
+ try:
35
+ with fitz.open(stream=uploaded_file.read(), filetype="pdf") as doc:
36
+ for page in doc:
37
+ pdf_text += page.get_text("text") + "\n"
38
+ except Exception as e:
39
+ st.error(f"Lỗi khi xử lý PDF: {e}")
40
+ return pdf_text
41
+
42
+ def extract_text_from_docx(uploaded_file):
43
+ try:
44
+ doc = Document(uploaded_file)
45
+ return "\n".join([para.text for para in doc.paragraphs])
46
+ except Exception as e:
47
+ st.error(f"Lỗi khi xử lý DOCX: {e}")
48
+ return ""
49
+
50
+ def add_text_area():
51
+ st.session_state.additional_texts.append("")
52
+
53
+ def remove_text_area(index):
54
+ st.session_state.additional_texts.pop(index)
55
+
56
+ if "show_summary" not in st.session_state:
57
+ st.session_state.show_summary = False
58
+
59
+ if "additional_texts" not in st.session_state:
60
+ st.session_state.additional_texts = []
61
+
62
+ st.markdown("<h1>Hệ thống tóm tắt đa văn bản tiếng Việt</h1>", unsafe_allow_html=True)
63
+
64
+ col1, col2 = st.columns([3, 1])
65
+
66
+ with col1:
67
+ st.markdown("### ✍️ Nhập văn bản")
68
+ input_method = st.radio("Phương thức nhập liệu:", ["Nhập văn bản", "Kéo thả tệp"], horizontal=True)
69
+ texts = []
70
+
71
+ if input_method == "Nhập văn bản":
72
+ if st.button("➕ Thêm vùng nhập văn bản"):
73
+ add_text_area()
74
+ for i, text in enumerate(st.session_state.additional_texts):
75
+ with st.expander(f"📌 Văn bản {i + 1}", expanded=True):
76
+ col_expander = st.columns([13, 0.5])
77
+ with col_expander[0]:
78
+ updated_text = st.text_area("", text, height=200, key=f"text_{i}")
79
+ st.session_state.additional_texts[i] = updated_text
80
+ with col_expander[1]:
81
+ if st.button("🗑", key=f"delete_{i}", help="Xóa văn bản"):
82
+ remove_text_area(i)
83
+ st.experimental_rerun()
84
+ texts.append(st.session_state.additional_texts[i])
85
+
86
+ else:
87
+ uploaded_files = st.file_uploader(
88
+ "📂 Kéo thả tệp văn bản:",
89
+ type=["txt", "pdf", "docx"],
90
+ accept_multiple_files=True
91
+ )
92
+
93
+ if uploaded_files:
94
+ for uploaded_file in uploaded_files:
95
+ all_texts = ""
96
+ if uploaded_file.type == "text/plain":
97
+ all_texts = uploaded_file.getvalue().decode("utf-8")
98
+ elif uploaded_file.type == "application/pdf":
99
+ all_texts = extract_text_from_pdf(uploaded_file)
100
+ elif uploaded_file.type == "application/vnd.openxmlformats-officedocument.wordprocessingml.document":
101
+ all_texts = extract_text_from_docx(uploaded_file)
102
+
103
+ texts.append(all_texts)
104
+
105
+ # st.markdown("### 🎯 Nhập tóm tắt mẫu")
106
+ # golden_ext = st.text_area("📑 Tóm tắt tóm lược", height=100)
107
+ # golden_abs = st.text_area("📝 Tóm tắt trích rút", height=100)
108
+
109
+
110
+ with col2:
111
+ st.markdown("### ⚙️ Tuỳ chọn tóm tắt")
112
+ summary_method = st.selectbox("Chọn phương thức rút gọn:", ["Số câu", "Tỷ lệ"])
113
+
114
+ if summary_method == "Tỷ lệ":
115
+ compress_ratio = st.slider("🔽 Chọn tỷ lệ rút gọn:", 0, 50, 15, step=1, format="%d%%") / 100
116
+ else:
117
+ compress_ratio = st.number_input("🔢 Số câu đầu ra:", min_value=1, max_value=20, value=5, step=1)
118
+
119
+ if st.button("🚀 Tóm tắt") and any(texts):
120
+ summary_results = MultiDocSummarizationAPI(
121
+ texts, compress_ratio#, golden_ext=golden_ext or None, golden_abs=golden_abs or None
122
+ )
123
+ st.session_state.extractive_summary = summary_results.get("extractive_summ", "Không có kết quả")
124
+ st.session_state.abstractive_summary = summary_results.get("abstractive_summ", "Không có kết quả")
125
+ st.session_state.rouge_ext = summary_results.get("score_ext", ("None", "None", "None"))
126
+ st.session_state.rouge_abs = summary_results.get("score_abs", ("None", "None", "None"))
127
+ st.session_state.show_summary = True
128
+ st.experimental_rerun()
129
+
130
+ if st.session_state.get("show_summary", False):
131
+ col_summary = st.columns(2)
132
+ rouge_ext = st.session_state.rouge_ext if st.session_state.rouge_ext is not None else ("None", "None", "None")
133
+ rouge_abs = st.session_state.rouge_abs if st.session_state.rouge_abs is not None else ("None", "None", "None")
134
+
135
+ with col_summary[0]:
136
+ st.markdown("### 📑 Tóm tắt tóm lược")
137
+ # st.markdown(f"**🔹 ROUGE 1:** {rouge_ext[0]}")
138
+ # st.markdown(f"**🔹 ROUGE 2:** {rouge_ext[1]}")
139
+ # st.markdown(f"**🔹 ROUGE L:** {rouge_ext[2]}")
140
+ st.text_area("📑 Tóm tắt trích lược:", st.session_state.extractive_summary, height=250)
141
+
142
+ # with col_summary[1]:
143
+ # st.markdown("### 📝 Tóm tắt trích rút")
144
+ # st.markdown(f"**🔹 ROUGE 1:** {rouge_abs[0]}")
145
+ # st.markdown(f"**🔹 ROUGE 2:** {rouge_abs[1]}")
146
+ # st.markdown(f"**🔹 ROUGE L:** {rouge_abs[2]}")
147
+ # st.text_area("Văn bản tóm tắt trích rút:", st.session_state.abstractive_summary, height=250)
c_25_0.3071.mdl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:a3064b88582b598217f7c9a1f1dd307fc9b3838c5df5f00f97ffa15261d17e19
3
+ size 41996419
dict_map.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"\u00f2a": "o\u00e0", "\u00d2a": "O\u00e0", "\u00d2A": "O\u00c0", "\u00f3a": "o\u00e1", "\u00d3a": "O\u00e1", "\u00d3A": "O\u00c1", "\u1ecfa": "o\u1ea3", "\u1ecea": "O\u1ea3", "\u1eceA": "O\u1ea2", "\u00f5a": "o\u00e3", "\u00d5a": "O\u00e3", "\u00d5A": "O\u00c3", "\u1ecda": "o\u1ea1", "\u1ecca": "O\u1ea1", "\u1eccA": "O\u1ea0", "\u00f2e": "o\u00e8", "\u00d2e": "O\u00e8", "\u00d2E": "O\u00c8", "\u00f3e": "o\u00e9", "\u00d3e": "O\u00e9", "\u00d3E": "O\u00c9", "\u1ecfe": "o\u1ebb", "\u1ecee": "O\u1ebb", "\u1eceE": "O\u1eba", "\u00f5e": "o\u1ebd", "\u00d5e": "O\u1ebd", "\u00d5E": "O\u1ebc", "\u1ecde": "o\u1eb9", "\u1ecce": "O\u1eb9", "\u1eccE": "O\u1eb8", "\u00f9y": "u\u1ef3", "\u00d9y": "U\u1ef3", "\u00d9Y": "U\u1ef2", "\u00fay": "u\u00fd", "\u00day": "U\u00fd", "\u00daY": "U\u00dd", "\u1ee7y": "u\u1ef7", "\u1ee6y": "U\u1ef7", "\u1ee6Y": "U\u1ef6", "\u0169y": "u\u1ef9", "\u0168y": "U\u1ef9", "\u0168Y": "U\u1ef8", "\u1ee5y": "u\u1ef5", "\u1ee4y": "U\u1ef5", "\u1ee4Y": "U\u1ef4", "\u2026": "."}
e_25_0.3071.mdl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:3977998fae042e01c9b8d5c56303ace9cfa696cf016ea6fc924332f63cc85afc
3
+ size 42000261
requirements.txt CHANGED
@@ -1,3 +1,11 @@
1
- altair
2
- pandas
3
- streamlit
 
 
 
 
 
 
 
 
 
1
+ streamlit == 1.25.0
2
+ torch
3
+ torchvision
4
+ torchaudio
5
+ transformers
6
+ sentencepiece
7
+ numpy
8
+ rouge
9
+ underthesea
10
+ pymupdf
11
+ python-docx
summarization.py ADDED
@@ -0,0 +1,616 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ import torch.nn as nn
3
+ import torch.nn.functional as F
4
+ import pickle
5
+ import numpy as np
6
+ from rouge import Rouge
7
+ import string
8
+ import re
9
+ from transformers import AutoModel, AutoModelForSeq2SeqLM, AutoTokenizer
10
+ from underthesea import sent_tokenize, word_tokenize
11
+
12
+ device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
13
+ abstract_tokenizer_path = "vinai/bartpho-syllable-base"
14
+ abstract_model_path = "htg2501/checkpoint"
15
+ extractive_model_path = "./e_25_0.3071.mdl"
16
+ contrastive_model_path = "./c_25_0.3071.mdl"
17
+
18
+ stopword_path = "./vietnamese-stopwords-dash.txt"
19
+ LDA_model_path = "./LDA_models.pkl"
20
+
21
+ phobert = AutoModel.from_pretrained("vinai/phobert-base-v2").to(device)
22
+ phobert_tokenizer = AutoTokenizer.from_pretrained("vinai/phobert-base-v2")
23
+ model_summarization = AutoModelForSeq2SeqLM.from_pretrained(abstract_model_path).to(device)
24
+ tokenizer_summarization = AutoTokenizer.from_pretrained(abstract_tokenizer_path)
25
+
26
+ """# Extractive model"""
27
+
28
+
29
+ def getRouge2(ref, pred, kind):
30
+ try:
31
+ return round(Rouge().get_scores(pred.lower(), ref.lower())[0]['rouge-2'][kind], 4)
32
+ except ValueError:
33
+ return 0.0
34
+
35
+
36
+ class MLP(nn.Module):
37
+ def __init__(self, dims: list, layers=2, act=nn.LeakyReLU(), dropout_p=0.1, keep_last_layer=False):
38
+ super(MLP, self).__init__()
39
+ assert len(dims) == layers + 1
40
+ self.layers = layers
41
+ self.act = act
42
+ self.dropout = nn.Dropout(dropout_p)
43
+ self.keep_last = keep_last_layer
44
+
45
+ self.mlp_layers = nn.ModuleList([])
46
+ for i in range(self.layers):
47
+ self.mlp_layers.append(nn.Linear(dims[i], dims[i + 1]))
48
+
49
+ def forward(self, x):
50
+ for i in range(len(self.mlp_layers) - 1):
51
+ x = self.dropout(self.act(self.mlp_layers[i](x)))
52
+ if self.keep_last:
53
+ x = self.mlp_layers[-1](x)
54
+ else:
55
+ x = self.act(self.mlp_layers[-1](x))
56
+ return x
57
+
58
+
59
+ class GraphAttentionLayer(nn.Module):
60
+ def __init__(self, in_features: int, out_features: int, n_heads: int,
61
+ is_concat: bool = True,
62
+ dropout: float = 0.6,
63
+ leaky_relu_negative_slope: float = 0.2):
64
+ super().__init__()
65
+
66
+ self.is_concat = is_concat
67
+ self.n_heads = n_heads
68
+
69
+ # Calculate the number of dimensions per head
70
+ if is_concat:
71
+ assert out_features % n_heads == 0
72
+ self.n_hidden = out_features // n_heads
73
+ else:
74
+ self.n_hidden = out_features
75
+
76
+ self.linear = nn.Linear(in_features, self.n_hidden * n_heads, bias=False)
77
+ self.attn = nn.Linear(self.n_hidden * 2, 1, bias=False)
78
+ self.activation = nn.LeakyReLU(negative_slope=leaky_relu_negative_slope)
79
+ self.softmax = nn.Softmax(dim=1)
80
+ self.dropout = nn.Dropout(dropout)
81
+
82
+ def forward(self, h: torch.Tensor, adj_mat: torch.Tensor, docnum, secnum):
83
+ n_nodes = h.shape[0]
84
+ g = self.linear(h).view(n_nodes, self.n_heads, self.n_hidden)
85
+ g_repeat = g.repeat(n_nodes, 1, 1)
86
+ g_repeat_interleave = g.repeat_interleave(n_nodes, dim=0)
87
+ g_concat = torch.cat([g_repeat_interleave, g_repeat], dim=-1)
88
+ g_concat = g_concat.view(n_nodes, n_nodes, self.n_heads, 2 * self.n_hidden)
89
+ e = self.activation(self.attn(g_concat))
90
+
91
+ e = e.squeeze(-1)
92
+
93
+ # The adjacency matrix should have shape
94
+ # `[n_nodes, n_nodes, n_heads]` or`[n_nodes, n_nodes, 1]`
95
+ assert adj_mat.shape[0] == 1 or adj_mat.shape[0] == n_nodes
96
+ assert adj_mat.shape[1] == 1 or adj_mat.shape[1] == n_nodes
97
+ assert adj_mat.shape[2] == 1 or adj_mat.shape[2] == self.n_heads
98
+ # Mask $e_{ij}$ based on adjacency matrix.
99
+ # $e_{ij}$ is set to $- \infty$ if there is no edge from $i$ to $j$.
100
+ e = e.masked_fill(adj_mat == 0, float(-1e9))
101
+ a = self.softmax(e)
102
+ a = self.dropout(a)
103
+ attn_res = torch.einsum('ijh,jhf->ihf', a, g)
104
+
105
+ # Concatenate the heads
106
+ if self.is_concat:
107
+ return attn_res.reshape(n_nodes, self.n_heads * self.n_hidden)
108
+ # Take the mean of the heads
109
+ else:
110
+ return attn_res.mean(dim=1)
111
+
112
+
113
+ class GAT(nn.Module):
114
+ def __init__(self, in_features: int, n_hidden: int, n_classes: int, n_heads: int, dropout: float):
115
+ super().__init__()
116
+ self.layer1 = GraphAttentionLayer(in_features, n_hidden, n_heads, is_concat=True, dropout=dropout)
117
+ self.activation = nn.ELU()
118
+ self.output = GraphAttentionLayer(n_hidden, n_classes, 1, is_concat=False, dropout=dropout)
119
+ self.dropout = nn.Dropout(dropout)
120
+
121
+ def forward(self, x: torch.Tensor, adj_mat: torch.Tensor, docnum, secnum):
122
+ x = x.squeeze(0)
123
+ adj_mat = adj_mat.squeeze(0)
124
+ adj_x = adj_mat.clone().sum(dim=1, keepdim=True).repeat(1, x.shape[1]).bool()
125
+ adj_mat = adj_mat.unsqueeze(-1).bool()
126
+ x = self.dropout(x)
127
+ x = self.layer1(x, adj_mat, docnum, secnum)
128
+ x = self.activation(x)
129
+ x = self.dropout(x)
130
+ x = self.output(x, adj_mat, docnum, secnum).masked_fill(adj_x == 0, float(0))
131
+ return x.unsqueeze(0)
132
+
133
+
134
+ class StepWiseGraphConvLayer(nn.Module):
135
+ def __init__(self, in_dim, hid_dim, dropout_p=0.1, act=nn.LeakyReLU(), nheads=6, iter=1, final="att"):
136
+ super().__init__()
137
+ self.act = act
138
+ self.dropout = nn.Dropout(dropout_p)
139
+ self.iter = iter
140
+ self.in_dim = in_dim
141
+ self.gat = nn.ModuleList([GAT(in_features=in_dim, n_hidden=hid_dim, n_classes=in_dim,
142
+ dropout=dropout_p, n_heads=nheads) for _ in range(iter)])
143
+ self.gat2 = nn.ModuleList([GAT(in_features=in_dim, n_hidden=hid_dim, n_classes=in_dim,
144
+ dropout=dropout_p, n_heads=nheads) for _ in range(iter)])
145
+ self.gat3 = nn.ModuleList([GAT(in_features=in_dim, n_hidden=hid_dim, n_classes=in_dim,
146
+ dropout=dropout_p, n_heads=nheads) for _ in range(iter)])
147
+
148
+ self.out_ffn = MLP([in_dim * 3, hid_dim, hid_dim, in_dim], layers=3, dropout_p=dropout_p)
149
+
150
+ def forward(self, feature, adj, docnum, secnum):
151
+ sen_adj = adj.clone()
152
+ sen_adj[:, -docnum - secnum - 1:, :] = sen_adj[:, :, -docnum - secnum - 1:] = 0
153
+ sec_adj = adj.clone()
154
+ sec_adj[:, :-docnum - secnum - 1, :] = sec_adj[:, -docnum - 1:, :] = sec_adj[:, :, -docnum - 1:] = 0
155
+ doc_adj = adj.clone()
156
+ doc_adj[:, :-docnum - 1, :] = 0
157
+
158
+ feature_sen = feature.clone()
159
+ feature_resi = feature
160
+
161
+ feature_sen_re = feature_sen.clone()
162
+ for i in range(0, self.iter):
163
+ feature_sen = self.gat[i](feature_sen, sen_adj, docnum, secnum)
164
+ feature_sen = F.layer_norm(feature_sen + feature_sen_re, [self.in_dim])
165
+
166
+ feature_sec = feature_sen.clone()
167
+ feature_sec_re = feature_sec.clone()
168
+ for i in range(0, self.iter):
169
+ feature_sec = self.gat2[i](feature_sec, sec_adj, docnum, secnum)
170
+ feature_sec = F.layer_norm(feature_sec + feature_sec_re, [self.in_dim])
171
+
172
+ feature_doc = feature_sec.clone()
173
+ feature_doc_re = feature_doc.clone()
174
+ for i in range(0, self.iter):
175
+ feature_doc = self.gat3[i](feature_doc, doc_adj, docnum, secnum)
176
+ feature_doc = F.layer_norm(feature_doc + feature_doc_re, [self.in_dim])
177
+
178
+ feature_sec[:, :-docnum - secnum - 1, :] = adj[:, :-docnum - secnum - 1,
179
+ -docnum - secnum - 1:-docnum - 1] @ feature_sec[:,
180
+ -docnum - secnum - 1:-docnum - 1,
181
+ :]
182
+ feature_doc[:, -docnum - secnum - 1:-docnum - 1, :] = adj[:, -docnum - secnum - 1:-docnum - 1,
183
+ -docnum - 1:] @ feature_doc[:, -docnum - 1:, :]
184
+ feature_doc[:, :-docnum - secnum - 1, :] = adj[:, :-docnum - secnum - 1,
185
+ -docnum - secnum - 1:-docnum - 1] @ feature_doc[:,
186
+ -docnum - secnum - 1:-docnum - 1,
187
+ :]
188
+ feature = torch.concat([feature_doc, feature_sec, feature_sen], dim=-1)
189
+ feature = F.layer_norm(self.out_ffn(feature) + feature_resi, [self.in_dim])
190
+ return feature
191
+
192
+
193
+ class Contrast_Encoder(nn.Module):
194
+ def __init__(self, input_dim, hidden_dim, heads, act=nn.LeakyReLU(0.1), dropout_p=0.1):
195
+ super(Contrast_Encoder, self).__init__()
196
+ self.graph_encoder = StepWiseGraphConvLayer(in_dim=input_dim, hid_dim=hidden_dim,
197
+ dropout_p=dropout_p, act=act, nheads=heads, iter=1)
198
+ self.common_proj_mlp = MLP([input_dim, hidden_dim, input_dim], layers=2, dropout_p=dropout_p, act=act,
199
+ keep_last_layer=False)
200
+
201
+ def forward(self, p_gfeature, doc_lens, p_adj, docnum, secnum):
202
+ posVec = torch.cat(
203
+ [PositionVec[:l] for l in doc_lens] + [torch.zeros(secnum + docnum + 1, 768).float().to(device)], dim=0)
204
+ p_gfeature = p_gfeature + posVec.unsqueeze(0)
205
+ pg = self.graph_encoder(p_gfeature, p_adj, docnum, secnum)
206
+ pg = self.common_proj_mlp(pg)
207
+ return pg
208
+
209
+
210
+ class End2End_Encoder(nn.Module):
211
+ def __init__(self, input_dim, hidden_dim, heads, act=nn.LeakyReLU(0.1), dropout_p=0.3):
212
+ super(End2End_Encoder, self).__init__()
213
+ self.graph_encoder = StepWiseGraphConvLayer(in_dim=input_dim, hid_dim=hidden_dim,
214
+ dropout_p=dropout_p, act=act, nheads=heads, iter=1)
215
+ self.dropout = nn.Dropout(dropout_p)
216
+ self.out_proj_layer_mlp = MLP([input_dim, hidden_dim, input_dim], layers=2, dropout_p=dropout_p, act=act,
217
+ keep_last_layer=False)
218
+ self.linear = MLP([input_dim, 1], layers=1, dropout_p=dropout_p, act=act, keep_last_layer=True)
219
+
220
+ def forward(self, x, doc_lens, adj, docnum, secnum):
221
+ x = self.graph_encoder(x, adj, docnum, secnum)
222
+ x = self.out_proj_layer_mlp(x)
223
+ return self.linear(x)[:, :-docnum - secnum - 1, :]
224
+
225
+
226
+ def _similarity(h1: torch.Tensor, h2: torch.Tensor):
227
+ h1 = F.normalize(h1)
228
+ h2 = F.normalize(h2)
229
+ return h1 @ h2.t()
230
+
231
+
232
+ class InfoNCE(nn.Module):
233
+ def __init__(self, tau):
234
+ super(InfoNCE, self).__init__()
235
+ self.tau = tau
236
+
237
+ def forward(self, anchor, sample, pos_mask, *args, **kwargs):
238
+ sim = _similarity(anchor, sample) / self.tau
239
+ if len(anchor) > 1:
240
+ sim, _ = torch.max(sim, dim=0, keepdim=True)
241
+ exp_sim = torch.exp(sim)
242
+ loss = torch.log((exp_sim * pos_mask).sum(dim=1)) - torch.log(exp_sim.sum(dim=1))
243
+ return -loss.mean()
244
+
245
+
246
+ class Cluster:
247
+ def __init__(self, sent_texts, sent_vecs, doc_lens, doc_sec_mask, sec_sen_mask):
248
+ assert len(sent_vecs) == len(sent_texts)
249
+ self.docnum = len(doc_sec_mask)
250
+ self.secnum = len(sec_sen_mask)
251
+ self.feature = torch.cat(
252
+ (torch.stack(sent_vecs, dim=0), torch.zeros((self.secnum + self.docnum + 1, sent_vecs[0].shape[0]))),
253
+ dim=0).to(device)
254
+ self.adj = torch.from_numpy(self.mask_to_adj(doc_sec_mask, sec_sen_mask)).float().to(device)
255
+ self.sent_text = np.array(sent_texts)
256
+ self.doc_lens = doc_lens
257
+ self.init_node_vec()
258
+ self.feature = self.feature.float()
259
+
260
+ def init_node_vec(self):
261
+ docnum, secnum = self.docnum, self.secnum
262
+ for i in range(-secnum - docnum - 1, -docnum - 1):
263
+ mask = self.adj[i].clone()
264
+ mask[-secnum - docnum - 1:] = 0
265
+ self.feature[i] = torch.mean(self.feature[mask.bool()], dim=0)
266
+ for i in range(-docnum - 1, -1):
267
+ mask = self.adj[i].clone()
268
+ mask[-docnum - 1:] = 0
269
+ self.feature[i] = torch.mean(self.feature[mask.bool()], dim=0)
270
+ self.feature[-1] = torch.mean(self.feature[-docnum - 1:-1], dim=0)
271
+
272
+ def mask_to_adj(self, doc_sec_mask, sec_sen_mask):
273
+ sen_num = sec_sen_mask.shape[1]
274
+ sec_num = sec_sen_mask.shape[0]
275
+ doc_num = doc_sec_mask.shape[0]
276
+ adj = np.zeros((sen_num + sec_num + doc_num + 1, sen_num + sec_num + doc_num + 1))
277
+ # section connection
278
+ adj[-sec_num - doc_num - 1:-doc_num - 1, 0:-sec_num - doc_num - 1] = sec_sen_mask
279
+ adj[0:-sec_num - doc_num - 1, -sec_num - doc_num - 1:-doc_num - 1] = sec_sen_mask.T
280
+ for i in range(0, doc_num):
281
+ doc_mask = doc_sec_mask[i]
282
+ doc_mask = doc_mask.reshape((1, len(doc_mask)))
283
+ adj[sen_num:-doc_num - 1, sen_num:-doc_num - 1] += doc_mask * doc_mask.T
284
+ # doc connection
285
+ adj[-doc_num - 1:-1, -sec_num - doc_num - 1:-doc_num - 1] = doc_sec_mask
286
+ adj[-sec_num - doc_num - 1:-doc_num - 1, -doc_num - 1:-1] = doc_sec_mask.T
287
+ adj[-doc_num - 1:, -doc_num - 1:] = 1
288
+
289
+ #build sentence connection
290
+ for i in range(0, sec_num):
291
+ sec_mask = sec_sen_mask[i]
292
+ sec_mask = sec_mask.reshape((1, len(sec_mask)))
293
+ adj[:sen_num, :sen_num] += sec_mask * sec_mask.T
294
+ return adj
295
+
296
+
297
+ def meanTokenVecs(text):
298
+ sent = text.lower()
299
+ input_ids = torch.tensor([phobert_tokenizer.encode(sent)])
300
+ tokenized_text = phobert_tokenizer.tokenize(sent)
301
+ with torch.no_grad():
302
+ features = phobert(input_ids.to(device))
303
+ wordVecs, buffer, buffer_str = {}, [], ''
304
+ for token in zip(tokenized_text, features.last_hidden_state[0, 1:-1, :]):
305
+ if token[0][-2:] == '@@':
306
+ buffer.append(token[1])
307
+ buffer_str += token[0][:-2]
308
+ continue
309
+ if buffer:
310
+ buffer.append(token[1])
311
+ buffer_str += token[0]
312
+ wordVecs[buffer_str] = torch.mean(torch.stack(buffer), dim=0)
313
+ buffer, buffer_str = [], ''
314
+ else:
315
+ wordVecs[token[0]] = token[1]
316
+
317
+ return torch.mean(torch.stack([vec for w, vec in wordVecs.items() if w not in string.punctuation]), dim=0).to(
318
+ torch.device('cpu'))
319
+
320
+
321
+ def getPositionEncoding(pos, d=768, n=10000):
322
+ P = np.zeros(d)
323
+ for i in np.arange(int(d / 2)):
324
+ denominator = np.power(n, 2 * i / d)
325
+ P[2 * i] = np.sin(pos / denominator)
326
+ P[2 * i + 1] = np.cos(pos / denominator)
327
+ return P
328
+
329
+
330
+ def removeRedundant(text):
331
+ text = text.lower()
332
+ words = [w for w in text.split(' ') if w not in stop_w]
333
+ return ' '.join(words)
334
+
335
+
336
+ def divideSection(doc_text, category='Giáo dục'):
337
+ sent_para, para_sec, sent_sec = {}, {}, {}
338
+
339
+ paras = [para for para in doc_text.split('\n') if para != '']
340
+ all_sents = []
341
+ # prepare sent_Para
342
+ sentcnt = 0
343
+ for i, para in enumerate(paras):
344
+ sents = [word_tokenize(sent, format="text") for sent in sent_tokenize(para) if sent != '' and len(sent) > 4]
345
+ all_sents.extend(sents)
346
+ for ii, sent in enumerate(sents):
347
+ sent_para[sentcnt + ii] = i
348
+ sent = removeRedundant(sent)
349
+ sentcnt += len(sents)
350
+
351
+ # prepare para_sec
352
+ paras = [removeRedundant(para) for para in paras]
353
+ tf, lda_model = cate_models[category]
354
+ X = tf.transform(paras)
355
+ lda_top = lda_model.transform(X)
356
+ for i, para_top in enumerate(lda_top):
357
+ para_sec[i] = para_top.argmax()
358
+
359
+ # output sent_sec
360
+ for k, v in sent_para.items():
361
+ sent_sec[k] = para_sec[v]
362
+ return sent_sec, all_sents
363
+
364
+
365
+ def loadClusterData(docs_org, category='Giáo dục'): # docs_org: list of text for each document
366
+ seclist, docs = {}, []
367
+ for d, doc in enumerate(docs_org):
368
+ seclist[d], sentTexts = divideSection(doc, category)
369
+ docs.append(sentTexts)
370
+
371
+ secnum = 0
372
+ for k, val_dict in seclist.items():
373
+ vals = set(val_dict.values())
374
+ for ki, vi in val_dict.items():
375
+ for i, v in enumerate(vals):
376
+ if vi == v:
377
+ val_dict[ki] = i + secnum
378
+ break
379
+ seclist[k] = val_dict
380
+ secnum += len(vals)
381
+
382
+ sents, sentVecs, secIDs, doc_lens = [], [], [], []
383
+ sentnum = sum([len(doc.values()) for doc in seclist.values()])
384
+ doc_sec_mask = np.zeros((len(docs), secnum))
385
+ sec_sen_mask = np.zeros((secnum, sentnum))
386
+ cursec, cursent = 0, 0
387
+
388
+ for d, doc in enumerate(docs):
389
+ doc_lens.append(len(doc))
390
+ doc_endsec = max(seclist[d].values())
391
+ doc_sec_mask[d][cursec:doc_endsec + 1] = 1
392
+ cursec = doc_endsec + 1
393
+ for s, sent in enumerate(doc):
394
+ sents.append(sent)
395
+ sentVecs.append(meanTokenVecs(sent))
396
+ sec_sen_mask[seclist[d][s], cursent] = 1
397
+ cursent += 1
398
+
399
+ return Cluster(sents, sentVecs, doc_lens, doc_sec_mask, sec_sen_mask)
400
+
401
+
402
+ def val_e2e(data):
403
+ feature = data.feature.unsqueeze(0)
404
+ doc_lens = data.doc_lens
405
+ adj = data.adj.unsqueeze(0)
406
+ docnum = data.docnum
407
+ secnum = data.secnum
408
+
409
+ with torch.no_grad():
410
+ feature = c_model(feature, doc_lens, adj, docnum, secnum)
411
+ x = model(feature, doc_lens, adj, docnum, secnum)
412
+ scores = torch.sigmoid(x.squeeze(-1))
413
+
414
+ return scores, data.sent_text
415
+
416
+
417
+ def normalize_text(text):
418
+ text = str(text).replace('_', ' ')
419
+ text = re.sub(r'\s+', ' ', text)
420
+ text = re.sub(r'\s+([.,;:?)/!?”])', r'\1', text)
421
+ text = re.sub(r'([\(“])\s+', r'\1', text)
422
+ return text
423
+
424
+
425
+ def track_changes(old_words, new_words):
426
+ # Find the longest common subsequence (LCS) between the two word sequences
427
+ def get_lcs_matrix(words1, words2):
428
+ m, n = len(words1), len(words2)
429
+ dp = [[0] * (n + 1) for _ in range(m + 1)]
430
+
431
+ for i in range(1, m + 1):
432
+ for j in range(1, n + 1):
433
+ if words1[i - 1] == words2[j - 1]:
434
+ dp[i][j] = dp[i - 1][j - 1] + 1
435
+ else:
436
+ dp[i][j] = max(dp[i - 1][j], dp[i][j - 1])
437
+
438
+ return dp
439
+
440
+ def get_lcs(words1, words2, dp):
441
+ i, j = len(words1), len(words2)
442
+ lcs = []
443
+
444
+ while i > 0 and j > 0:
445
+ if words1[i - 1] == words2[j - 1]:
446
+ lcs.append((i - 1, j - 1))
447
+ i -= 1
448
+ j -= 1
449
+ elif dp[i - 1][j] > dp[i][j - 1]:
450
+ i -= 1
451
+ else:
452
+ j -= 1
453
+
454
+ return sorted(lcs)
455
+
456
+ # Find the changed segments at word level
457
+ dp_matrix = get_lcs_matrix(old_words, new_words)
458
+ lcs_positions = get_lcs(old_words, new_words, dp_matrix)
459
+
460
+ changes = []
461
+ old_pos = 0
462
+ new_pos = 0
463
+
464
+ # Process matching and non-matching segments
465
+ for old_idx, new_idx in lcs_positions:
466
+ # If there's a gap before this match, it's a change
467
+ if old_idx > old_pos or new_idx > new_pos:
468
+ changes.append((old_pos, old_idx, new_pos, new_idx))
469
+
470
+ # Move positions after the match
471
+ old_pos = old_idx + 1
472
+ new_pos = new_idx + 1
473
+
474
+ # Check if there's a change at the end
475
+ if old_pos < len(old_words) or new_pos < len(new_words):
476
+ changes.append((old_pos, len(old_words), new_pos, len(new_words)))
477
+
478
+ return changes
479
+
480
+
481
+ class Abstractive_Summarization:
482
+ @staticmethod
483
+ def generateSummaryBySent(texts, batch=32):
484
+ model_summarization.eval()
485
+ predictions = []
486
+ with torch.no_grad():
487
+ for i in range(0, len(texts), batch):
488
+ batch_texts = texts[i:i + batch]
489
+ inputs = tokenizer_summarization(batch_texts, padding=True, max_length=1024, truncation=True,
490
+ return_tensors='pt').to(device)
491
+ outputs = model_summarization.generate(**inputs, num_beams=5,
492
+ early_stopping=True, no_repeat_ngram_size=3)
493
+ prediction = tokenizer_summarization.batch_decode(outputs, skip_special_tokens=True)
494
+ predictions.extend(prediction)
495
+ return predictions
496
+
497
+
498
+ PositionVec = torch.stack([torch.from_numpy(getPositionEncoding(i, d=768)) for i in range(200)], dim=0).float().to(
499
+ device)
500
+ stop_w = ['...']
501
+ # with open(stopword_path, 'r', encoding='utf-8') as f:
502
+ # for w in f.readlines():
503
+ # stop_w.append(w.strip())
504
+ stop_w.extend([c for c in '!"#$%&\'()*+,./:;<=>?@[\\]^`{|}~…“”’‘'])
505
+
506
+ with open(LDA_model_path, mode='rb') as fp:
507
+ cate_models = pickle.load(fp)
508
+
509
+ c_model = Contrast_Encoder(768, 1024, 4).to(device)
510
+ model = End2End_Encoder(768, 1024, 4).to(device)
511
+ model.load_state_dict(torch.load(extractive_model_path, map_location=device), strict=False)
512
+ c_model.load_state_dict(torch.load(contrastive_model_path, map_location=device), strict=False)
513
+ model.eval()
514
+ c_model.eval()
515
+
516
+ def get_summary(scores, sents, max_sent=5):
517
+ ranked_score_idxs = torch.argsort(scores[0], dim=0, descending=True)
518
+ sents = [s.replace('_', ' ') for s in sents]
519
+ summSentIDList = []
520
+ for i in ranked_score_idxs:
521
+ if len(summSentIDList) >= max_sent: break
522
+ s = sents[i]
523
+
524
+ replicated, delIDs = False, []
525
+ for chosedID in summSentIDList:
526
+ if getRouge2(s, sents[chosedID], 'p') >= 0.45:
527
+ delIDs.append(chosedID)
528
+ if getRouge2(sents[chosedID], s, 'p') >= 0.45:
529
+ replicated = True
530
+ break
531
+ if replicated: continue
532
+
533
+ for delID in delIDs:
534
+ del summSentIDList[summSentIDList.index(delID)]
535
+ summSentIDList.append(i)
536
+ summSentIDList = sorted(summSentIDList)
537
+ return [s for i, s in enumerate(sents) if i in summSentIDList]
538
+
539
+ def MultiDocSummarizationAPI(texts, compress_ratio):
540
+ """
541
+ Summarizes a list of documents using both extractive and abstractive methods.
542
+
543
+ Parameters:
544
+ - texts (list of str): A list of document texts to be summarized.
545
+ - compress_ratio (float): A ratio or count determining the number of sentences in the summary.
546
+ If less than 1, it represents the fraction of the original sentences to include in the summary.
547
+ If 1 or greater, it represents the exact number of sentences to include in the summary.
548
+
549
+ Returns:
550
+ - dict: A dictionary containing:
551
+ - 'extractive_summ' (str): The extractive summary of the documents.
552
+ - 'abstractive_summ' (str): The abstractive summary of the documents.
553
+ """
554
+ assert compress_ratio > 0, "Compress ratio need to be greater than 0."
555
+ docs = [text.strip() for text in texts]
556
+ data_tree = loadClusterData(docs)
557
+ scores, sents = val_e2e(data_tree)
558
+
559
+ output_sent_cnt = int(len(sents) * compress_ratio) if compress_ratio < 1 else int(compress_ratio)
560
+ print('Expected sentence count:', output_sent_cnt)
561
+
562
+ extractive_summ_sents = [normalize_text(sent) for sent in get_summary(scores, sents, max_sent=output_sent_cnt)]
563
+ extractive_summ = ' '.join(extractive_summ_sents)
564
+
565
+ abstractive_summ_sents = Abstractive_Summarization.generateSummaryBySent(extractive_summ_sents)
566
+ abstractive_summ_sents = [normalize_text(s) for s in abstractive_summ_sents]
567
+ final_sents = []
568
+ for ii, (ext, abs) in enumerate(zip(extractive_summ_sents, abstractive_summ_sents)):
569
+ if ii == 0:
570
+ final_sents.append(ext)
571
+ continue
572
+ abs_splits, ext_splits = word_tokenize(abs), word_tokenize(ext)
573
+ abs_splits_cop, ext_splits_cop = abs_splits.copy(), ext_splits.copy()
574
+ if len(abs_splits_cop):
575
+ abs_splits_cop[-1] = abs_splits[-1][:-1] if len(abs_splits[-1]) and abs_splits[-1][-1] == '.' else abs_splits[-1]
576
+ if len(ext_splits_cop):
577
+ ext_splits_cop[-1] = ext_splits[-1][:-1] if len(ext_splits[-1]) and ext_splits[-1][-1] == '.' else ext_splits[-1]
578
+
579
+ changes, abs_parts = track_changes(ext_splits_cop, abs_splits_cop), [(0, len(abs_splits))]
580
+ for start_old, end_old, start_new, end_new in changes:
581
+ old_part = ' '.join(ext_splits[start_old:end_old])
582
+ # Revert change in the cases of spelling errors
583
+ revert, ignoreFirstSentWord = False, 1 if start_old == 0 else 0
584
+ old_names = {}
585
+ for w in ext_splits_cop[start_old + ignoreFirstSentWord:end_old]:
586
+ if len(w) == 0: continue
587
+ if 'A'<=w[0]<='Z' or w[0] in ['Ä‚', 'Ă‚', 'Đ', 'Ê', 'Ă”', 'Æ ', 'Ư']:
588
+ if w in old_names:
589
+ old_names[w] += 1
590
+ else:
591
+ old_names[w] = 1
592
+
593
+ for w in abs_splits_cop[start_new + ignoreFirstSentWord:end_new]:
594
+ if len(w) == 0: continue
595
+ if 'A'<=w[0]<='Z' or w[0] in ['Ä‚', 'Ă‚', 'Đ', 'Ê', 'Ă”', 'Æ ', 'Ư']:
596
+ if w in old_names:
597
+ old_names[w] -= 1
598
+ if old_names[w] < 0:
599
+ revert = True
600
+ break
601
+ else:
602
+ revert = True
603
+ break
604
+ if revert:
605
+ pop_part = abs_parts[-1]
606
+ abs_parts.pop()
607
+ abs_parts.extend([(pop_part[0], start_new), old_part, (end_new, pop_part[1])])
608
+ # print('\nOLD:', old_part, '\n', ' '.join(abs_splits[start_new:end_new]))
609
+ # print(ext, '\n', abs)
610
+
611
+ abs = ' '.join([part if isinstance(part, str) else ' '.join(abs_splits[part[0]:part[1]]) for part in abs_parts])
612
+ final_sents.append(normalize_text(abs))
613
+ abstract_summ = ' '.join(final_sents)
614
+
615
+ return {'extractive_summ': extractive_summ,
616
+ 'abstractive_summ': abstract_summ}
vietnamese-stopwords-dash.txt ADDED
@@ -0,0 +1,1942 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ a_lô
2
+ a_ha
3
+ ai
4
+ ai_ai
5
+ ai_nấy
6
+ ai_đó
7
+ alô
8
+ amen
9
+ anh
10
+ anh_ấy
11
+ ba
12
+ ba_ba
13
+ ba_bản
14
+ ba_cùng
15
+ ba_họ
16
+ ba_ngày
17
+ ba_ngôi
18
+ ba_tăng
19
+ bao_giờ
20
+ bao_lâu
21
+ bao_nhiêu
22
+ bao_nả
23
+ bay_biến
24
+ biết
25
+ biết_bao
26
+ biết_bao_nhiêu
27
+ biết_chắc
28
+ biết_chừng_nào
29
+ biết_mình
30
+ biết_mấy
31
+ biết_thế
32
+ biết_trước
33
+ biết_việc
34
+ biết_đâu
35
+ biết_đâu_chừng
36
+ biết_đâu_đấy
37
+ biết_được
38
+ buổi
39
+ buổi_làm
40
+ buổi_mới
41
+ buổi_ngày
42
+ buổi_sớm
43
+
44
+ bà_ấy
45
+ bài
46
+ bài_bác
47
+ bài_bỏ
48
+ bài_cái
49
+ bác
50
+ bán
51
+ bán_cấp
52
+ bán_dạ
53
+ bán_thế
54
+ bây_bẩy
55
+ bây_chừ
56
+ bây_giờ
57
+ bây_nhiêu
58
+ bèn
59
+ béng
60
+ bên
61
+ bên_bị
62
+ bên_có
63
+ bên_cạnh
64
+ bông
65
+ bước
66
+ bước_khỏi
67
+ bước_tới
68
+ bước_đi
69
+ bạn
70
+ bản
71
+ bản_bộ
72
+ bản_riêng
73
+ bản_thân
74
+ bản_ý
75
+ bất_chợt
76
+ bất_cứ
77
+ bất_giác
78
+ bất_kì
79
+ bất_kể
80
+ bất_kỳ
81
+ bất_luận
82
+ bất_ngờ
83
+ bất_nhược
84
+ bất_quá
85
+ bất_quá_chỉ
86
+ bất_thình_lình
87
+ bất_tử
88
+ bất_đồ
89
+ bấy
90
+ bấy_chầy
91
+ bấy_chừ
92
+ bấy_giờ
93
+ bấy_lâu
94
+ bấy_lâu_nay
95
+ bấy_nay
96
+ bấy_nhiêu
97
+ bập_bà_bập_bõm
98
+ bập_bõm
99
+ bắt_đầu
100
+ bắt_đầu_từ
101
+ bằng
102
+ bằng_cứ
103
+ bằng_không
104
+ bằng_người
105
+ bằng_nhau
106
+ bằng_như
107
+ bằng_nào
108
+ bằng_nấy
109
+ bằng_vào
110
+ bằng_được
111
+ bằng_ấy
112
+ bển
113
+ bệt
114
+ bị
115
+ bị_chú
116
+ bị_vì
117
+ bỏ
118
+ bỏ_bà
119
+ bỏ_cha
120
+ bỏ_cuộc
121
+ bỏ_không
122
+ bỏ_lại
123
+ bỏ_mình
124
+ bỏ_mất
125
+ bỏ_mẹ
126
+ bỏ_nhỏ
127
+ bỏ_quá
128
+ bỏ_ra
129
+ bỏ_riêng
130
+ bỏ_việc
131
+ bỏ_xa
132
+ bỗng
133
+ bỗng_chốc
134
+ bỗng_dưng
135
+ bỗng_không
136
+ bỗng_nhiên
137
+ bỗng_nhưng
138
+ bỗng_thấy
139
+ bỗng_đâu
140
+ bộ
141
+ bộ_thuộc
142
+ bộ_điều
143
+ bội_phần
144
+ bớ
145
+ bởi
146
+ bởi_ai
147
+ bởi_chưng
148
+ bởi_nhưng
149
+ bởi_sao
150
+ bởi_thế
151
+ bởi_thế_cho_nên
152
+ bởi_tại
153
+ bởi_vì
154
+ bởi_vậy
155
+ bởi_đâu
156
+ bức
157
+ cao
158
+ cao_lâu
159
+ cao_ráo
160
+ cao_răng
161
+ cao_sang
162
+ cao_số
163
+ cao_thấp
164
+ cao_thế
165
+ cao_xa
166
+ cha
167
+ cha_chả
168
+ chao_ôi
169
+ chia_sẻ
170
+ chiếc
171
+ cho
172
+ cho_biết
173
+ cho_chắc
174
+ cho_hay
175
+ cho_nhau
176
+ cho_nên
177
+ cho_rằng
178
+ cho_rồi
179
+ cho_thấy
180
+ cho_tin
181
+ cho_tới
182
+ cho_tới_khi
183
+ cho_về
184
+ cho_ăn
185
+ cho_đang
186
+ cho_được
187
+ cho_đến
188
+ cho_đến_khi
189
+ cho_đến_nỗi
190
+ choa
191
+ chu_cha
192
+ chui_cha
193
+ chung
194
+ chung_cho
195
+ chung_chung
196
+ chung_cuộc
197
+ chung_cục
198
+ chung_nhau
199
+ chung_qui
200
+ chung_quy
201
+ chung_quy_lại
202
+ chung_ái
203
+ chuyển
204
+ chuyển_tự
205
+ chuyển_đạt
206
+ chuyện
207
+ chuẩn_bị
208
+ chành_chạnh
209
+ chí_chết
210
+ chính
211
+ chính_bản
212
+ chính_giữa
213
+ chính_là
214
+ chính_thị
215
+ chính_điểm
216
+ chùn_chùn
217
+ chùn_chũn
218
+ chú
219
+ chú_dẫn
220
+ chú_khách
221
+ chú_mày
222
+ chú_mình
223
+ chúng
224
+ chúng_mình
225
+ chúng_ta
226
+ chúng_tôi
227
+ chúng_ông
228
+ chăn_chắn
229
+ chăng
230
+ chăng_chắc
231
+ chăng_nữa
232
+ chơi
233
+ chơi_họ
234
+ chưa
235
+ chưa_bao_giờ
236
+ chưa_chắc
237
+ chưa_có
238
+ chưa_cần
239
+ chưa_dùng
240
+ chưa_dễ
241
+ chưa_kể
242
+ chưa_tính
243
+ chưa_từng
244
+ chầm_chập
245
+ chậc
246
+ chắc
247
+ chắc_chắn
248
+ chắc_dạ
249
+ chắc_hẳn
250
+ chắc_lòng
251
+ chắc_người
252
+ chắc_vào
253
+ chắc_ăn
254
+ chẳng_lẽ
255
+ chẳng_những
256
+ chẳng_nữa
257
+ chẳng_phải
258
+ chết_nỗi
259
+ chết_thật
260
+ chết_tiệt
261
+ chỉ
262
+ chỉ_chính
263
+ chỉ_có
264
+ chỉ_là
265
+ chỉ_tên
266
+ chỉn
267
+ chị
268
+ chị_bộ
269
+ chị_ấy
270
+ chịu
271
+ chịu_chưa
272
+ chịu_lời
273
+ chịu_tốt
274
+ chịu_ăn
275
+ chọn
276
+ chọn_bên
277
+ chọn_ra
278
+ chốc_chốc
279
+ chớ
280
+ chớ_chi
281
+ chớ_gì
282
+ chớ_không
283
+ chớ_kể
284
+ chớ_như
285
+ chợt
286
+ chợt_nghe
287
+ chợt_nhìn
288
+ chủn
289
+ chứ
290
+ chứ_ai
291
+ chứ_còn
292
+ chứ_gì
293
+ chứ_không
294
+ chứ_không_phải
295
+ chứ_lại
296
+ chứ_lị
297
+ chứ_như
298
+ chứ_sao
299
+ coi_bộ
300
+ coi_mòi
301
+ con
302
+ con_con
303
+ con_dạ
304
+ con_nhà
305
+ con_tính
306
+ cu_cậu
307
+ cuối
308
+ cuối_cùng
309
+ cuối_điểm
310
+ cuốn
311
+ cuộc
312
+ càng
313
+ càng_càng
314
+ càng_hay
315
+ cá_nhân
316
+ các
317
+ các_cậu
318
+ cách
319
+ cách_bức
320
+ cách_không
321
+ cách_nhau
322
+ cách_đều
323
+ cái
324
+ cái_gì
325
+ cái_họ
326
+ cái_đã
327
+ cái_đó
328
+ cái_ấy
329
+ câu_hỏi
330
+ cây
331
+ cây_nước
332
+ còn
333
+ còn_như
334
+ còn_nữa
335
+ còn_thời_gian
336
+ còn_về
337
+
338
+ có_ai
339
+ có_chuyện
340
+ có_chăng
341
+ có_chăng_là
342
+ có_chứ
343
+ có_cơ
344
+ có_dễ
345
+ có_họ
346
+ có_khi
347
+ có_ngày
348
+ có_người
349
+ có_nhiều
350
+ có_nhà
351
+ có_phải
352
+ có_số
353
+ có_tháng
354
+ có_thế
355
+ có_thể
356
+ có_vẻ
357
+ có_ý
358
+ có_ăn
359
+ có_điều
360
+ có_điều_kiện
361
+ có_đáng
362
+ có_đâu
363
+ có_được
364
+ cóc_khô
365
+
366
+ cô_mình
367
+ cô_quả
368
+ cô_tăng
369
+ cô_ấy
370
+ công_nhiên
371
+ cùng
372
+ cùng_chung
373
+ cùng_cực
374
+ cùng_nhau
375
+ cùng_tuổi
376
+ cùng_tột
377
+ cùng_với
378
+ cùng_ăn
379
+ căn
380
+ căn_cái
381
+ căn_cắt
382
+ căn_tính
383
+ cũng
384
+ cũng_như
385
+ cũng_nên
386
+ cũng_thế
387
+ cũng_vậy
388
+ cũng_vậy_thôi
389
+ cũng_được
390
+
391
+ cơ_chỉ
392
+ cơ_chừng
393
+ cơ_cùng
394
+ cơ_dẫn
395
+ cơ_hồ
396
+ cơ_hội
397
+ cơ_mà
398
+ cơn
399
+ cả
400
+ cả_nghe
401
+ cả_nghĩ
402
+ cả_ngày
403
+ cả_người
404
+ cả_nhà
405
+ cả_năm
406
+ cả_thảy
407
+ cả_thể
408
+ cả_tin
409
+ cả_ăn
410
+ cả_đến
411
+ cảm_thấy
412
+ cảm_ơn
413
+ cấp
414
+ cấp_số
415
+ cấp_trực_tiếp
416
+ cần
417
+ cần_cấp
418
+ cần_gì
419
+ cần_số
420
+ cật_lực
421
+ cật_sức
422
+ cậu
423
+ cổ_lai
424
+ cụ_thể
425
+ cụ_thể_là
426
+ cụ_thể_như
427
+ của
428
+ của_ngọt
429
+ của_tin
430
+ cứ
431
+ cứ_như
432
+ cứ_việc
433
+ cứ_điểm
434
+ cực_lực
435
+ do
436
+ do_vì
437
+ do_vậy
438
+ do_đó
439
+ duy
440
+ duy_chỉ
441
+ duy_có
442
+ dài
443
+ dài_lời
444
+ dài_ra
445
+ dành
446
+ dành_dành
447
+ dào
448
+
449
+
450
+ dù_cho
451
+ dù_dì
452
+ dù_gì
453
+ dù_rằng
454
+ dù_sao
455
+ dùng
456
+ dùng_cho
457
+ dùng_hết
458
+ dùng_làm
459
+ dùng_đến
460
+ dưới
461
+ dưới_nước
462
+ dạ
463
+ dạ_bán
464
+ dạ_con
465
+ dạ_dài
466
+ dạ_dạ
467
+ dạ_khách
468
+ dần_dà
469
+ dần_dần
470
+ dầu_sao
471
+ dẫn
472
+ dẫu
473
+ dẫu_mà
474
+ dẫu_rằng
475
+ dẫu_sao
476
+ dễ
477
+ dễ_dùng
478
+ dễ_gì
479
+ dễ_khiến
480
+ dễ_nghe
481
+ dễ_ngươi
482
+ dễ_như_chơi
483
+ dễ_sợ
484
+ dễ_sử_dụng
485
+ dễ_thường
486
+ dễ_thấy
487
+ dễ_ăn
488
+ dễ_đâu
489
+ dở_chừng
490
+ dữ
491
+ dữ_cách
492
+ em
493
+ em_em
494
+ giá_trị
495
+ giá_trị_thực_tế
496
+ giảm
497
+ giảm_chính
498
+ giảm_thấp
499
+ giảm_thế
500
+ giống
501
+ giống_người
502
+ giống_nhau
503
+ giống_như
504
+ giờ
505
+ giờ_lâu
506
+ giờ_này
507
+ giờ_đi
508
+ giờ_đây
509
+ giờ_đến
510
+ giữ
511
+ giữ_lấy
512
+ giữ_ý
513
+ giữa
514
+ giữa_lúc
515
+ gây
516
+ gây_cho
517
+ gây_giống
518
+ gây_ra
519
+ gây_thêm
520
+
521
+ gì_gì
522
+ gì_đó
523
+ gần
524
+ gần_bên
525
+ gần_hết
526
+ gần_ngày
527
+ gần_như
528
+ gần_xa
529
+ gần_đây
530
+ gần_đến
531
+ gặp
532
+ gặp_khó_khăn
533
+ gặp_phải
534
+ gồm
535
+ hay
536
+ hay_biết
537
+ hay_hay
538
+ hay_không
539
+ hay_là
540
+ hay_làm
541
+ hay_nhỉ
542
+ hay_nói
543
+ hay_sao
544
+ hay_tin
545
+ hay_đâu
546
+ hiểu
547
+ hiện_nay
548
+ hiện_tại
549
+ hoàn_toàn
550
+ hoặc
551
+ hoặc_là
552
+ hãy
553
+ hãy_còn
554
+ hơn
555
+ hơn_cả
556
+ hơn_hết
557
+ hơn_là
558
+ hơn_nữa
559
+ hơn_trước
560
+ hầu_hết
561
+ hết
562
+ hết_chuyện
563
+ hết_cả
564
+ hết_của
565
+ hết_nói
566
+ hết_ráo
567
+ hết_rồi
568
+ hết_ý
569
+ họ
570
+ họ_gần
571
+ họ_xa
572
+ hỏi
573
+ hỏi_lại
574
+ hỏi_xem
575
+ hỏi_xin
576
+ hỗ_trợ
577
+ khi
578
+ khi_khác
579
+ khi_không
580
+ khi_nào
581
+ khi_nên
582
+ khi_trước
583
+ khiến
584
+ khoảng
585
+ khoảng_cách
586
+ khoảng_không
587
+ khá
588
+ khá_tốt
589
+ khác
590
+ khác_gì
591
+ khác_khác
592
+ khác_nhau
593
+ khác_nào
594
+ khác_thường
595
+ khác_xa
596
+ khách
597
+ khó
598
+ khó_biết
599
+ khó_chơi
600
+ khó_khăn
601
+ khó_làm
602
+ khó_mở
603
+ khó_nghe
604
+ khó_nghĩ
605
+ khó_nói
606
+ khó_thấy
607
+ khó_tránh
608
+ không
609
+ không_ai
610
+ không_bao_giờ
611
+ không_bao_lâu
612
+ không_biết
613
+ không_bán
614
+ không_chỉ
615
+ không_còn
616
+ không_có
617
+ không_có_gì
618
+ không_cùng
619
+ không_cần
620
+ không_cứ
621
+ không_dùng
622
+ không_gì
623
+ không_hay
624
+ không_khỏi
625
+ không_kể
626
+ không_ngoài
627
+ không_nhận
628
+ không_những
629
+ không_phải
630
+ không_phải_không
631
+ không_thể
632
+ không_tính
633
+ không_điều_kiện
634
+ không_được
635
+ không_đầy
636
+ không_để
637
+ khẳng_định
638
+ khỏi
639
+ khỏi_nói
640
+ kể
641
+ kể_cả
642
+ kể_như
643
+ kể_tới
644
+ kể_từ
645
+ liên_quan
646
+ loại
647
+ loại_từ
648
+ luôn
649
+ luôn_cả
650
+ luôn_luôn
651
+ luôn_tay
652
+
653
+ là_cùng
654
+ là_là
655
+ là_nhiều
656
+ là_phải
657
+ là_thế_nào
658
+ là_vì
659
+ là_ít
660
+ làm
661
+ làm_bằng
662
+ làm_cho
663
+ làm_dần_dần
664
+ làm_gì
665
+ làm_lòng
666
+ làm_lại
667
+ làm_lấy
668
+ làm_mất
669
+ làm_ngay
670
+ làm_như
671
+ làm_nên
672
+ làm_ra
673
+ làm_riêng
674
+ làm_sao
675
+ làm_theo
676
+ làm_thế_nào
677
+ làm_tin
678
+ làm_tôi
679
+ làm_tăng
680
+ làm_tại
681
+ làm_tắp_lự
682
+ làm_vì
683
+ làm_đúng
684
+ làm_được
685
+ lâu
686
+ lâu_các
687
+ lâu_lâu
688
+ lâu_nay
689
+ lâu_ngày
690
+ lên
691
+ lên_cao
692
+ lên_cơn
693
+ lên_mạnh
694
+ lên_ngôi
695
+ lên_nước
696
+ lên_số
697
+ lên_xuống
698
+ lên_đến
699
+ lòng
700
+ lòng_không
701
+ lúc
702
+ lúc_khác
703
+ lúc_lâu
704
+ lúc_nào
705
+ lúc_này
706
+ lúc_sáng
707
+ lúc_trước
708
+ lúc_đi
709
+ lúc_đó
710
+ lúc_đến
711
+ lúc_ấy
712
+ lý_do
713
+ lượng
714
+ lượng_cả
715
+ lượng_số
716
+ lượng_từ
717
+ lại
718
+ lại_bộ
719
+ lại_cái
720
+ lại_còn
721
+ lại_giống
722
+ lại_làm
723
+ lại_người
724
+ lại_nói
725
+ lại_nữa
726
+ lại_quả
727
+ lại_thôi
728
+ lại_ăn
729
+ lại_đây
730
+ lấy
731
+ lấy_có
732
+ lấy_cả
733
+ lấy_giống
734
+ lấy_làm
735
+ lấy_lý_do
736
+ lấy_lại
737
+ lấy_ra
738
+ lấy_ráo
739
+ lấy_sau
740
+ lấy_số
741
+ lấy_thêm
742
+ lấy_thế
743
+ lấy_vào
744
+ lấy_xuống
745
+ lấy_được
746
+ lấy_để
747
+ lần
748
+ lần_khác
749
+ lần_lần
750
+ lần_nào
751
+ lần_này
752
+ lần_sang
753
+ lần_sau
754
+ lần_theo
755
+ lần_trước
756
+ lần_tìm
757
+ lớn
758
+ lớn_lên
759
+ lớn_nhỏ
760
+ lời
761
+ lời_chú
762
+ lời_nói
763
+ mang
764
+ mang_lại
765
+ mang_mang
766
+ mang_nặng
767
+ mang_về
768
+ muốn
769
+
770
+ mà_cả
771
+ mà_không
772
+ mà_lại
773
+ mà_thôi
774
+ mà_vẫn
775
+ mình
776
+ mạnh
777
+ mất
778
+ mất_còn
779
+ mọi
780
+ mọi_giờ
781
+ mọi_khi
782
+ mọi_lúc
783
+ mọi_người
784
+ mọi_nơi
785
+ mọi_sự
786
+ mọi_thứ
787
+ mọi_việc
788
+ mối
789
+ mỗi
790
+ mỗi_lúc
791
+ mỗi_lần
792
+ mỗi_một
793
+ mỗi_ngày
794
+ mỗi_người
795
+ một
796
+ một_cách
797
+ một_cơn
798
+ một_khi
799
+ một_lúc
800
+ một_số
801
+ một_vài
802
+ một_ít
803
+ mới
804
+ mới_hay
805
+ mới_rồi
806
+ mới_đây
807
+ mở
808
+ mở_mang
809
+ mở_nước
810
+ mở_ra
811
+ mợ
812
+ mức
813
+ nay
814
+ ngay
815
+ ngay_bây_giờ
816
+ ngay_cả
817
+ ngay_khi
818
+ ngay_khi_đến
819
+ ngay_lúc
820
+ ngay_lúc_này
821
+ ngay_lập_tức
822
+ ngay_thật
823
+ ngay_tức_khắc
824
+ ngay_tức_thì
825
+ ngay_từ
826
+ nghe
827
+ nghe_chừng
828
+ nghe_hiểu
829
+ nghe_không
830
+ nghe_lại
831
+ nghe_nhìn
832
+ nghe_như
833
+ nghe_nói
834
+ nghe_ra
835
+ nghe_rõ
836
+ nghe_thấy
837
+ nghe_tin
838
+ nghe_trực_tiếp
839
+ nghe_đâu
840
+ nghe_đâu_như
841
+ nghe_được
842
+ nghen
843
+ nghiễm_nhiên
844
+ nghĩ
845
+ nghĩ_lại
846
+ nghĩ_ra
847
+ nghĩ_tới
848
+ nghĩ_xa
849
+ nghĩ_đến
850
+ nghỉm
851
+ ngoài
852
+ ngoài_này
853
+ ngoài_ra
854
+ ngoài_xa
855
+ ngoải
856
+ nguồn
857
+ ngày
858
+ ngày_càng
859
+ ngày_cấp
860
+ ngày_giờ
861
+ ngày_ngày
862
+ ngày_nào
863
+ ngày_này
864
+ ngày_nọ
865
+ ngày_qua
866
+ ngày_rày
867
+ ngày_tháng
868
+ ngày_xưa
869
+ ngày_xửa
870
+ ngày_đến
871
+ ngày_ấy
872
+ ngôi
873
+ ngôi_nhà
874
+ ngôi_thứ
875
+ ngõ_hầu
876
+ ngăn_ngắt
877
+ ngươi
878
+ người
879
+ người_hỏi
880
+ người_khác
881
+ người_khách
882
+ người_mình
883
+ người_nghe
884
+ người_người
885
+ người_nhận
886
+ ngọn
887
+ ngọn_nguồn
888
+ ngọt
889
+ ngồi
890
+ ngồi_bệt
891
+ ngồi_không
892
+ ngồi_sau
893
+ ngồi_trệt
894
+ ngộ_nhỡ
895
+ nhanh
896
+ nhanh_lên
897
+ nhanh_tay
898
+ nhau
899
+ nhiên_hậu
900
+ nhiều
901
+ nhiều_ít
902
+ nhiệt_liệt
903
+ nhung_nhăng
904
+ nhà
905
+ nhà_chung
906
+ nhà_khó
907
+ nhà_làm
908
+ nhà_ngoài
909
+ nhà_ngươi
910
+ nhà_tôi
911
+ nhà_việc
912
+ nhân_dịp
913
+ nhân_tiện
914
+ nhé
915
+ nhìn
916
+ nhìn_chung
917
+ nhìn_lại
918
+ nhìn_nhận
919
+ nhìn_theo
920
+ nhìn_thấy
921
+ nhìn_xuống
922
+ nhóm
923
+ nhón_nhén
924
+ như
925
+ như_ai
926
+ như_chơi
927
+ như_không
928
+ như_là
929
+ như_nhau
930
+ như_quả
931
+ như_sau
932
+ như_thường
933
+ như_thế
934
+ như_thế_nào
935
+ như_thể
936
+ như_trên
937
+ như_trước
938
+ như_tuồng
939
+ như_vậy
940
+ như_ý
941
+ nhưng
942
+ nhưng_mà
943
+ nhược_bằng
944
+ nhất
945
+ nhất_loạt
946
+ nhất_luật
947
+ nhất_là
948
+ nhất_mực
949
+ nhất_nhất
950
+ nhất_quyết
951
+ nhất_sinh
952
+ nhất_thiết
953
+ nhất_thì
954
+ nhất_tâm
955
+ nhất_tề
956
+ nhất_đán
957
+ nhất_định
958
+ nhận
959
+ nhận_biết
960
+ nhận_họ
961
+ nhận_làm
962
+ nhận_nhau
963
+ nhận_ra
964
+ nhận_thấy
965
+ nhận_việc
966
+ nhận_được
967
+ nhằm
968
+ nhằm_khi
969
+ nhằm_lúc
970
+ nhằm_vào
971
+ nhằm_để
972
+ nhỉ
973
+ nhỏ
974
+ nhỏ_người
975
+ nhớ
976
+ nhớ_bập_bõm
977
+ nhớ_lại
978
+ nhớ_lấy
979
+ nhớ_ra
980
+ nhờ
981
+ nhờ_chuyển
982
+ nhờ_có
983
+ nhờ_nhờ
984
+ nhờ_đó
985
+ nhỡ_ra
986
+ những
987
+ những_ai
988
+ những_khi
989
+ những_là
990
+ những_lúc
991
+ những_muốn
992
+ những_như
993
+ nào
994
+ nào_cũng
995
+ nào_hay
996
+ nào_là
997
+ nào_phải
998
+ nào_đâu
999
+ nào_đó
1000
+ này
1001
+ này_nọ
1002
+ nên
1003
+ nên_chi
1004
+ nên_chăng
1005
+ nên_làm
1006
+ nên_người
1007
+ nên_tránh
1008
+
1009
+ nóc
1010
+ nói
1011
+ nói_bông
1012
+ nói_chung
1013
+ nói_khó
1014
+ nói_là
1015
+ nói_lên
1016
+ nói_lại
1017
+ nói_nhỏ
1018
+ nói_phải
1019
+ nói_qua
1020
+ nói_ra
1021
+ nói_riêng
1022
+ nói_rõ
1023
+ nói_thêm
1024
+ nói_thật
1025
+ nói_toẹt
1026
+ nói_trước
1027
+ nói_tốt
1028
+ nói_với
1029
+ nói_xa
1030
+ nói_ý
1031
+ nói_đến
1032
+ nói_đủ
1033
+ năm
1034
+ năm_tháng
1035
+ nơi
1036
+ nơi_nơi
1037
+ nước
1038
+ nước_bài
1039
+ nước_cùng
1040
+ nước_lên
1041
+ nước_nặng
1042
+ nước_quả
1043
+ nước_xuống
1044
+ nước_ăn
1045
+ nước_đến
1046
+ nấy
1047
+ nặng
1048
+ nặng_căn
1049
+ nặng_mình
1050
+ nặng_về
1051
+ nếu
1052
+ nếu_có
1053
+ nếu_cần
1054
+ nếu_không
1055
+ nếu_mà
1056
+ nếu_như
1057
+ nếu_thế
1058
+ nếu_vậy
1059
+ nếu_được
1060
+ nền
1061
+ nọ
1062
+ nớ
1063
+ nức_nở
1064
+ nữa
1065
+ nữa_khi
1066
+ nữa_là
1067
+ nữa_rồi
1068
+ oai_oái
1069
+ oái
1070
+ pho
1071
+ phè
1072
+ phè_phè
1073
+ phía
1074
+ phía_bên
1075
+ phía_bạn
1076
+ phía_dưới
1077
+ phía_sau
1078
+ phía_trong
1079
+ phía_trên
1080
+ phía_trước
1081
+ phóc
1082
+ phót
1083
+ phù_hợp
1084
+ phăn_phắt
1085
+ phương_chi
1086
+ phải
1087
+ phải_biết
1088
+ phải_chi
1089
+ phải_chăng
1090
+ phải_cách
1091
+ phải_cái
1092
+ phải_giờ
1093
+ phải_khi
1094
+ phải_không
1095
+ phải_lại
1096
+ phải_lời
1097
+ phải_người
1098
+ phải_như
1099
+ phải_rồi
1100
+ phải_tay
1101
+ phần
1102
+ phần_lớn
1103
+ phần_nhiều
1104
+ phần_nào
1105
+ phần_sau
1106
+ phần_việc
1107
+ phắt
1108
+ phỉ_phui
1109
+ phỏng
1110
+ phỏng_như
1111
+ phỏng_nước
1112
+ phỏng_theo
1113
+ phỏng_tính
1114
+ phốc
1115
+ phụt
1116
+ phứt
1117
+ qua
1118
+ qua_chuyện
1119
+ qua_khỏi
1120
+ qua_lại
1121
+ qua_lần
1122
+ qua_ngày
1123
+ qua_tay
1124
+ qua_thì
1125
+ qua_đi
1126
+ quan_trọng
1127
+ quan_trọng_vấn_đề
1128
+ quan_tâm
1129
+ quay
1130
+ quay_bước
1131
+ quay_lại
1132
+ quay_số
1133
+ quay_đi
1134
+ quá
1135
+ quá_bán
1136
+ quá_bộ
1137
+ quá_giờ
1138
+ quá_lời
1139
+ quá_mức
1140
+ quá_nhiều
1141
+ quá_tay
1142
+ quá_thì
1143
+ quá_tin
1144
+ quá_trình
1145
+ quá_tuổi
1146
+ quá_đáng
1147
+ quá_ư
1148
+ quả
1149
+ quả_là
1150
+ quả_thật
1151
+ quả_thế
1152
+ quả_vậy
1153
+ quận
1154
+ ra
1155
+ ra_bài
1156
+ ra_bộ
1157
+ ra_chơi
1158
+ ra_gì
1159
+ ra_lại
1160
+ ra_lời
1161
+ ra_ngôi
1162
+ ra_người
1163
+ ra_sao
1164
+ ra_tay
1165
+ ra_vào
1166
+ ra_ý
1167
+ ra_điều
1168
+ ra_đây
1169
+ ren_rén
1170
+ riu_ríu
1171
+ riêng
1172
+ riêng_từng
1173
+ riệt
1174
+ rày
1175
+ ráo
1176
+ ráo_cả
1177
+ ráo_nước
1178
+ ráo_trọi
1179
+ rén
1180
+ rén_bước
1181
+ rích
1182
+ rón_rén
1183
+
1184
+ rõ_là
1185
+ rõ_thật
1186
+ rút_cục
1187
+ răng
1188
+ răng_răng
1189
+ rất
1190
+ rất_lâu
1191
+ rằng
1192
+ rằng_là
1193
+ rốt_cuộc
1194
+ rốt_cục
1195
+ rồi
1196
+ rồi_nữa
1197
+ rồi_ra
1198
+ rồi_sao
1199
+ rồi_sau
1200
+ rồi_tay
1201
+ rồi_thì
1202
+ rồi_xem
1203
+ rồi_đây
1204
+ rứa
1205
+ sa_sả
1206
+ sang
1207
+ sang_năm
1208
+ sang_sáng
1209
+ sang_tay
1210
+ sao
1211
+ sao_bản
1212
+ sao_bằng
1213
+ sao_cho
1214
+ sao_vậy
1215
+ sao_đang
1216
+ sau
1217
+ sau_chót
1218
+ sau_cuối
1219
+ sau_cùng
1220
+ sau_hết
1221
+ sau_này
1222
+ sau_nữa
1223
+ sau_sau
1224
+ sau_đây
1225
+ sau_đó
1226
+ so
1227
+ so_với
1228
+ song_le
1229
+ suýt
1230
+ suýt_nữa
1231
+ sáng
1232
+ sáng_ngày
1233
+ sáng_rõ
1234
+ sáng_thế
1235
+ sáng_ý
1236
+
1237
+ sì_sì
1238
+ sất
1239
+ sắp
1240
+ sắp_đặt
1241
+ sẽ
1242
+ sẽ_biết
1243
+ sẽ_hay
1244
+ số
1245
+ số_cho_biết
1246
+ số_cụ_thể
1247
+ số_loại
1248
+ số_là
1249
+ số_người
1250
+ số_phần
1251
+ số_thiếu
1252
+ sốt_sột
1253
+ sớm
1254
+ sớm_ngày
1255
+ sở_dĩ
1256
+ sử_dụng
1257
+ sự
1258
+ sự_thế
1259
+ sự_việc
1260
+ tanh
1261
+ tanh_tanh
1262
+ tay
1263
+ tay_quay
1264
+ tha_hồ
1265
+ tha_hồ_chơi
1266
+ tha_hồ_ăn
1267
+ than_ôi
1268
+ thanh
1269
+ thanh_ba
1270
+ thanh_chuyển
1271
+ thanh_không
1272
+ thanh_thanh
1273
+ thanh_tính
1274
+ thanh_điều_kiện
1275
+ thanh_điểm
1276
+ thay_đổi
1277
+ thay_đổi_tình_trạng
1278
+ theo
1279
+ theo_bước
1280
+ theo_như
1281
+ theo_tin
1282
+ thi_thoảng
1283
+ thiếu
1284
+ thiếu_gì
1285
+ thiếu_điểm
1286
+ thoạt
1287
+ thoạt_nghe
1288
+ thoạt_nhiên
1289
+ thoắt
1290
+ thuần
1291
+ thuần_ái
1292
+ thuộc
1293
+ thuộc_bài
1294
+ thuộc_cách
1295
+ thuộc_lại
1296
+ thuộc_từ
1297
+ thà
1298
+ thà_là
1299
+ thà_rằng
1300
+ thành_ra
1301
+ thành_thử
1302
+ thái_quá
1303
+ tháng
1304
+ tháng_ngày
1305
+ tháng_năm
1306
+ tháng_tháng
1307
+ thêm
1308
+ thêm_chuyện
1309
+ thêm_giờ
1310
+ thêm_vào
1311
+ thì
1312
+ thì_giờ
1313
+ thì_là
1314
+ thì_phải
1315
+ thì_ra
1316
+ thì_thôi
1317
+ thình_lình
1318
+ thích
1319
+ thích_cứ
1320
+ thích_thuộc
1321
+ thích_tự
1322
+ thích_ý
1323
+ thím
1324
+ thôi
1325
+ thôi_việc
1326
+ thúng_thắng
1327
+ thương_ôi
1328
+ thường
1329
+ thường_bị
1330
+ thường_hay
1331
+ thường_khi
1332
+ thường_số
1333
+ thường_sự
1334
+ thường_thôi
1335
+ thường_thường
1336
+ thường_tính
1337
+ thường_tại
1338
+ thường_xuất_hiện
1339
+ thường_đến
1340
+ thảo_hèn
1341
+ thảo_nào
1342
+ thấp
1343
+ thấp_cơ
1344
+ thấp_thỏm
1345
+ thấp_xuống
1346
+ thấy
1347
+ thấy_tháng
1348
+ thẩy
1349
+ thậm
1350
+ thậm_chí
1351
+ thậm_cấp
1352
+ thậm_từ
1353
+ thật
1354
+ thật_chắc
1355
+ thật_là
1356
+ thật_lực
1357
+ thật_quả
1358
+ thật_ra
1359
+ thật_sự
1360
+ thật_thà
1361
+ thật_tốt
1362
+ thật_vậy
1363
+ thế
1364
+ thế_chuẩn_bị
1365
+ thế_là
1366
+ thế_lại
1367
+ thế_mà
1368
+ thế_nào
1369
+ thế_nên
1370
+ thế_ra
1371
+ thế_sự
1372
+ thế_thì
1373
+ thế_thôi
1374
+ thế_thường
1375
+ thế_thế
1376
+ thế_à
1377
+ thế_đó
1378
+ thếch
1379
+ thỉnh_thoảng
1380
+ thỏm
1381
+ thốc
1382
+ thốc_tháo
1383
+ thốt
1384
+ thốt_nhiên
1385
+ thốt_nói
1386
+ thốt_thôi
1387
+ thộc
1388
+ thời_gian
1389
+ thời_gian_sử_dụng
1390
+ thời_gian_tính
1391
+ thời_điểm
1392
+ thục_mạng
1393
+ thứ
1394
+ thứ_bản
1395
+ thứ_đến
1396
+ thửa
1397
+ thực_hiện
1398
+ thực_hiện_đúng
1399
+ thực_ra
1400
+ thực_sự
1401
+ thực_tế
1402
+ thực_vậy
1403
+ tin
1404
+ tin_thêm
1405
+ tin_vào
1406
+ tiếp_theo
1407
+ tiếp_tục
1408
+ tiếp_đó
1409
+ tiện_thể
1410
+ toà
1411
+ toé_khói
1412
+ toẹt
1413
+ trong
1414
+ trong_khi
1415
+ trong_lúc
1416
+ trong_mình
1417
+ trong_ngoài
1418
+ trong_này
1419
+ trong_số
1420
+ trong_vùng
1421
+ trong_đó
1422
+ trong_ấy
1423
+ tránh
1424
+ tránh_khỏi
1425
+ tránh_ra
1426
+ tránh_tình_trạng
1427
+ tránh_xa
1428
+ trên
1429
+ trên_bộ
1430
+ trên_dưới
1431
+ trước
1432
+ trước_hết
1433
+ trước_khi
1434
+ trước_kia
1435
+ trước_nay
1436
+ trước_ngày
1437
+ trước_nhất
1438
+ trước_sau
1439
+ trước_tiên
1440
+ trước_tuổi
1441
+ trước_đây
1442
+ trước_đó
1443
+ trả
1444
+ trả_của
1445
+ trả_lại
1446
+ trả_ngay
1447
+ trả_trước
1448
+ trếu_tráo
1449
+ trển
1450
+ trệt
1451
+ trệu_trạo
1452
+ trỏng
1453
+ trời_đất_ơi
1454
+ trở_thành
1455
+ trừ_phi
1456
+ trực_tiếp
1457
+ trực_tiếp_làm
1458
+ tuy
1459
+ tuy_có
1460
+ tuy_là
1461
+ tuy_nhiên
1462
+ tuy_rằng
1463
+ tuy_thế
1464
+ tuy_vậy
1465
+ tuy_đã
1466
+ tuyệt_nhiên
1467
+ tuần_tự
1468
+ tuốt_luốt
1469
+ tuốt_tuồn_tuột
1470
+ tuốt_tuột
1471
+ tuổi
1472
+ tuổi_cả
1473
+ tuổi_tôi
1474
+ tà_tà
1475
+ tên
1476
+ tên_chính
1477
+ tên_cái
1478
+ tên_họ
1479
+ tên_tự
1480
+ tênh
1481
+ tênh_tênh
1482
+ tìm
1483
+ tìm_bạn
1484
+ tìm_cách
1485
+ tìm_hiểu
1486
+ tìm_ra
1487
+ tìm_việc
1488
+ tình_trạng
1489
+ tính
1490
+ tính_cách
1491
+ tính_căn
1492
+ tính_người
1493
+ tính_phỏng
1494
+ tính_từ
1495
+ tít_mù
1496
+ tò_te
1497
+ tôi
1498
+ tôi_con
1499
+ tông_tốc
1500
+ tù_tì
1501
+ tăm_tắp
1502
+ tăng
1503
+ tăng_chúng
1504
+ tăng_cấp
1505
+ tăng_giảm
1506
+ tăng_thêm
1507
+ tăng_thế
1508
+ tại
1509
+ tại_lòng
1510
+ tại_nơi
1511
+ tại_sao
1512
+ tại_tôi
1513
+ tại_vì
1514
+ tại_đâu
1515
+ tại_đây
1516
+ tại_đó
1517
+ tạo
1518
+ tạo_cơ_hội
1519
+ tạo_nên
1520
+ tạo_ra
1521
+ tạo_ý
1522
+ tạo_điều_kiện
1523
+ tấm
1524
+ tấm_bản
1525
+ tấm_các
1526
+ tấn
1527
+ tấn_tới
1528
+ tất_cả
1529
+ tất_cả_bao_nhiêu
1530
+ tất_thảy
1531
+ tất_tần_tật
1532
+ tất_tật
1533
+ tập_trung
1534
+ tắp
1535
+ tắp_lự
1536
+ tắp_tắp
1537
+ tọt
1538
+ tỏ_ra
1539
+ tỏ_vẻ
1540
+ tốc_tả
1541
+ tối_ư
1542
+ tốt
1543
+ tốt_bạn
1544
+ tốt_bộ
1545
+ tốt_hơn
1546
+ tốt_mối
1547
+ tốt_ngày
1548
+ tột
1549
+ tột_cùng
1550
+ tớ
1551
+ tới
1552
+ tới_gần
1553
+ tới_mức
1554
+ tới_nơi
1555
+ tới_thì
1556
+ tức_thì
1557
+ tức_tốc
1558
+ từ
1559
+ từ_căn
1560
+ từ_giờ
1561
+ từ_khi
1562
+ từ_loại
1563
+ từ_nay
1564
+ từ_thế
1565
+ từ_tính
1566
+ từ_tại
1567
+ từ_từ
1568
+ từ_ái
1569
+ từ_điều
1570
+ từ_đó
1571
+ từ_ấy
1572
+ từng
1573
+ từng_cái
1574
+ từng_giờ
1575
+ từng_nhà
1576
+ từng_phần
1577
+ từng_thời_gian
1578
+ từng_đơn_vị
1579
+ từng_ấy
1580
+ tự
1581
+ tự_cao
1582
+ tự_khi
1583
+ tự_lượng
1584
+ tự_tính
1585
+ tự_tạo
1586
+ tự_vì
1587
+ tự_ý
1588
+ tự_ăn
1589
+ tựu_trung
1590
+ veo
1591
+ veo_veo
1592
+ việc
1593
+ việc_gì
1594
+ vung_thiên_địa
1595
+ vung_tàn_tán
1596
+ vung_tán_tàn
1597
+
1598
+ vài
1599
+ vài_ba
1600
+ vài_người
1601
+ vài_nhà
1602
+ vài_nơi
1603
+ vài_tên
1604
+ vài_điều
1605
+ vào
1606
+ vào_gặp
1607
+ vào_khoảng
1608
+ vào_lúc
1609
+ vào_vùng
1610
+ vào_đến
1611
+ vâng
1612
+ vâng_chịu
1613
+ vâng_dạ
1614
+ vâng_vâng
1615
+ vâng_ý
1616
+ vèo
1617
+ vèo_vèo
1618
+
1619
+ vì_chưng
1620
+ vì_rằng
1621
+ vì_sao
1622
+ vì_thế
1623
+ vì_vậy
1624
+ ví_bằng
1625
+ ví_dù
1626
+ ví_phỏng
1627
+ ví_thử
1628
+ vô_hình_trung
1629
+ vô_kể
1630
+ vô_luận
1631
+ vô_vàn
1632
+ vùng
1633
+ vùng_lên
1634
+ vùng_nước
1635
+ văng_tê
1636
+ vượt
1637
+ vượt_khỏi
1638
+ vượt_quá
1639
+ vạn_nhất
1640
+ vả_chăng
1641
+ vả_lại
1642
+ vấn_đề
1643
+ vấn_đề_quan_trọng
1644
+ vẫn
1645
+ vẫn_thế
1646
+ vậy
1647
+ vậy_là
1648
+ vậy_mà
1649
+ vậy_nên
1650
+ vậy_ra
1651
+ vậy_thì
1652
+ vậy_ư
1653
+ về
1654
+ về_không
1655
+ về_nước
1656
+ về_phần
1657
+ về_sau
1658
+ về_tay
1659
+ vị_trí
1660
+ vị_tất
1661
+ vốn_dĩ
1662
+ với
1663
+ với_lại
1664
+ với_nhau
1665
+ vở
1666
+ vụt
1667
+ vừa
1668
+ vừa_khi
1669
+ vừa_lúc
1670
+ vừa_mới
1671
+ vừa_qua
1672
+ vừa_rồi
1673
+ vừa_vừa
1674
+ xa
1675
+ xa_cách
1676
+ xa_gần
1677
+ xa_nhà
1678
+ xa_tanh
1679
+ xa_tắp
1680
+ xa_xa
1681
+ xa_xả
1682
+ xem
1683
+ xem_lại
1684
+ xem_ra
1685
+ xem_số
1686
+ xin
1687
+ xin_gặp
1688
+ xin_vâng
1689
+ xiết_bao
1690
+ xon_xón
1691
+ xoành_xoạch
1692
+ xoét
1693
+ xoẳn
1694
+ xoẹt
1695
+ xuất_hiện
1696
+ xuất_kì_bất_ý
1697
+ xuất_kỳ_bất_ý
1698
+ xuể
1699
+ xuống
1700
+ xăm_xúi
1701
+ xăm_xăm
1702
+ xăm_xắm
1703
+ xảy_ra
1704
+ xềnh_xệch
1705
+ xệp
1706
+ xử_lý
1707
+ yêu_cầu
1708
+ à
1709
+ à_này
1710
+ à_ơi
1711
+ ào
1712
+ ào_vào
1713
+ ào_ào
1714
+ á
1715
+ á_à
1716
+ ái
1717
+ ái_chà
1718
+ ái_dà
1719
+ áng
1720
+ áng_như
1721
+ âu_là
1722
+ ít
1723
+ ít_biết
1724
+ ít_có
1725
+ ít_hơn
1726
+ ít_khi
1727
+ ít_lâu
1728
+ ít_nhiều
1729
+ ít_nhất
1730
+ ít_nữa
1731
+ ít_quá
1732
+ ít_ra
1733
+ ít_thôi
1734
+ ít_thấy
1735
+ ô_hay
1736
+ ô_hô
1737
+ ô_kê
1738
+ ô_kìa
1739
+ ôi_chao
1740
+ ôi_thôi
1741
+ ông
1742
+ ông_nhỏ
1743
+ ông_tạo
1744
+ ông_từ
1745
+ ông_ấy
1746
+ ông_ổng
1747
+ úi
1748
+ úi_chà
1749
+ úi_dào
1750
+ ý
1751
+ ý_chừng
1752
+ ý_da
1753
+ ý_hoặc
1754
+ ăn
1755
+ ăn_chung
1756
+ ăn_chắc
1757
+ ăn_chịu
1758
+ ăn_cuộc
1759
+ ăn_hết
1760
+ ăn_hỏi
1761
+ ăn_làm
1762
+ ăn_người
1763
+ ăn_ngồi
1764
+ ăn_quá
1765
+ ăn_riêng
1766
+ ăn_sáng
1767
+ ăn_tay
1768
+ ăn_trên
1769
+ ăn_về
1770
+ đang
1771
+ đang_tay
1772
+ đang_thì
1773
+ điều
1774
+ điều_gì
1775
+ điều_kiện
1776
+ điểm
1777
+ điểm_chính
1778
+ điểm_gặp
1779
+ điểm_đầu_tiên
1780
+ đành_đạch
1781
+ đáng
1782
+ đáng_kể
1783
+ đáng_lí
1784
+ đáng_lý
1785
+ đáng_lẽ
1786
+ đáng_số
1787
+ đánh_giá
1788
+ đánh_đùng
1789
+ đáo_để
1790
+ đâu
1791
+ đâu_có
1792
+ đâu_cũng
1793
+ đâu_như
1794
+ đâu_nào
1795
+ đâu_phải
1796
+ đâu_đâu
1797
+ đâu_đây
1798
+ đâu_đó
1799
+ đây
1800
+ đây_này
1801
+ đây_rồi
1802
+ đây_đó
1803
+ đã
1804
+ đã_hay
1805
+ đã_không
1806
+ đã_là
1807
+ đã_lâu
1808
+ đã_thế
1809
+ đã_vậy
1810
+ đã_đủ
1811
+ đó
1812
+ đó_đây
1813
+ đúng
1814
+ đúng_ngày
1815
+ đúng_ra
1816
+ đúng_tuổi
1817
+ đúng_với
1818
+ đơn_vị
1819
+ đưa
1820
+ đưa_cho
1821
+ đưa_chuyện
1822
+ đưa_em
1823
+ đưa_ra
1824
+ đưa_tay
1825
+ đưa_tin
1826
+ đưa_tới
1827
+ đưa_vào
1828
+ đưa_về
1829
+ đưa_xuống
1830
+ đưa_đến
1831
+ được
1832
+ được_cái
1833
+ được_lời
1834
+ được_nước
1835
+ được_tin
1836
+ đại_loại
1837
+ đại_nhân
1838
+ đại_phàm
1839
+ đại_để
1840
+ đạt
1841
+ đảm_bảo
1842
+ đầu_tiên
1843
+ đầy
1844
+ đầy_năm
1845
+ đầy_phè
1846
+ đầy_tuổi
1847
+ đặc_biệt
1848
+ đặt
1849
+ đặt_làm
1850
+ đặt_mình
1851
+ đặt_mức
1852
+ đặt_ra
1853
+ đặt_trước
1854
+ đặt_để
1855
+ đến
1856
+ đến_bao_giờ
1857
+ đến_cùng
1858
+ đến_cùng_cực
1859
+ đến_cả
1860
+ đến_giờ
1861
+ đến_gần
1862
+ đến_hay
1863
+ đến_khi
1864
+ đến_lúc
1865
+ đến_lời
1866
+ đến_nay
1867
+ đến_ngày
1868
+ đến_nơi
1869
+ đến_nỗi
1870
+ đến_thì
1871
+ đến_thế
1872
+ đến_tuổi
1873
+ đến_xem
1874
+ đến_điều
1875
+ đến_đâu
1876
+ đều
1877
+ đều_bước
1878
+ đều_nhau
1879
+ đều_đều
1880
+ để
1881
+ để_cho
1882
+ để_giống
1883
+ để_không
1884
+ để_lòng
1885
+ để_lại
1886
+ để_mà
1887
+ để_phần
1888
+ để_được
1889
+ để_đến_nỗi
1890
+ đối_với
1891
+ đồng_thời
1892
+ đủ
1893
+ đủ_dùng
1894
+ đủ_nơi
1895
+ đủ_số
1896
+ đủ_điều
1897
+ đủ_điểm
1898
+ ơ
1899
+ ơ_hay
1900
+ ơ_kìa
1901
+ ơi
1902
+ ơi_là
1903
+ ư
1904
+
1905
+ ạ_ơi
1906
+ ấy
1907
+ ấy_là
1908
+ ầu_ơ
1909
+ ắt
1910
+ ắt_hẳn
1911
+ ắt_là
1912
+ ắt_phải
1913
+ ắt_thật
1914
+ ối_dào
1915
+ ối_giời
1916
+ ối_giời_ơi
1917
+
1918
+ ồ_ồ
1919
+ ổng
1920
+
1921
+ ớ_này
1922
+
1923
+ ờ_ờ
1924
+
1925
+ ở_lại
1926
+ ở_như
1927
+ ở_nhờ
1928
+ ở_năm
1929
+ ở_trên
1930
+ ở_vào
1931
+ ở_đây
1932
+ ở_đó
1933
+ ở_được
1934
+ ủa
1935
+ ứ_hự
1936
+ ứ_ừ
1937
+
1938
+ ừ_nhé
1939
+ ừ_thì
1940
+ ừ_ào
1941
+ ừ_ừ
1942
+