vì dụ như 1 file có cấu trúc như sau """ <Đề 1> <...

Created on: June 17, 2025

Answered using O3 by Chat01

Question

vì dụ như 1 file có cấu trúc như sau

"""
<Đề 1>
<Đề 2>
<Đề 3>

<Đáp án đề 1>
"""

Cũng có thể là
"""
<Đề 1>
<Đề 2>
<Đề 3>

<Đáp án 5 câu khó đề 3>
<Đáp án 10 câu đầu đề 2>
"""

Tôi có thể truy cập vào nội dung các câu của phần đề hoặc đáp án
nhưng tôi ko biết câu đó là đề hoặc đáp án và nó là đề đáp án đề nào

làm sao phát triển 1 thuật toán ( bạn có thể dùng 1 chút nlp, ml )

để ghép nối các đề thi và đáp án

Thought

Considering algorithm for linking questions and answers

The user is asking about developing an algorithm to match questions with their corresponding answers in files with an unclear structure. The challenge is that the content of the file is mixed, and it’s not clear whether a line contains a question or answer, or which set it belongs to.

Hmm, using NLP and machine learning could help here to identify patterns in the question sets and answers, potentially using content markers or section headings to detect and label them.

Designing question-answer mapping algorithm

The user is asking for an algorithm to match answers with questions in mixed file formats. I'd start by segmenting the file into components based on question sets, using headers, regex to detect answers, and line classification. After preprocessing (tokenization), I'd classify lines as question or answer using rule-based features like the word "Đáp án" or patterns like "(A)". Then, I could cluster answers by questions using semantic similarity or reference to question numbers. I'll need to create a high-level algorithm, potentially showing pseudocode or Python examples.

Thought for 15 seconds

Answer

Dưới đây là một lộ trình “từ dễ → khó” để tự động tách & ghép nối các khối đềđáp án trong một tệp văn bản lẫn lộn, chỉ dùng Python + một chút NLP/ML. Bạn có thể dừng ở bước 2 (hoàn toàn rule-based) hoặc đi xa hơn tới bước 4 nếu tệp của bạn quá “lệch chuẩn”.


1. Tiền xử lý chung

text
Đọc file ➜ chuẩn hóa dòng (strip, loại BOM) ➜ tách khối dựa trên dòng trống liên tiếp
python
blocks = re.split(r'\n\s*\n', raw_text.strip(), flags=re.MULTILINE)

Mỗi block bây giờ là một đoạn: tiêu đề, nhóm câu hỏi, hay nhóm đáp án.


2. Nhận diện khối bằng rule-based (70 % trường hợp đủ dùng)

Loại khốiRegex gợi ýGiải thích
Tiêu đề đề<\s*Đ[ềe]\s*(\d+)\s*> hoặc Đề\s+(\d+)Trích id đề
Đáp ánĐáp\s*án coˊhockho^ngcoˊ“đe^ˋ\d+có hoặc không có “đề \d+”Bắt đầu khối đáp án
Câu hỏi^\s*Câu\s+\d+ hoặc ^\d+\.Số thứ tự câu, dấu chấm

Thuật toán dòng-chạy:

text
current_exam = None exam_dict = {} # {exam_id: {"qs": [], "ans": []}} for block in blocks: if re_title.match(block): current_exam = exam_id exam_dict.setdefault(current_exam, {"qs": [], "ans": []}) elif re_answer_header.match(block): target_exam = extract_exam_id(block) or current_exam # nếu header nêu rõ "đề 3" exam_dict.setdefault(target_exam, {"qs": [], "ans": []}) exam_dict[target_exam]["ans"].append(block) else: # Mặc định: khối câu hỏi if current_exam: exam_dict[current_exam]["qs"].append(block)

Xử lý đáp án “một phần”

Giả sử bạn đọc được tiêu đề “Đáp án 5 câu khó đề 3” ⇒ dùng regex:

python
target = re.search(r'đề\s*(\d+)', header, re.I).group(1)

Nếu header KHÔNG nêu rõ đề đích, quy về current_exam (đề cuối vừa đọc).


3. Thêm ML nhẹ để phân loại dòng (khi rule-based chưa đủ)

3.1. Bài toán

  • Input: mỗi dòng/đoạn
  • Label: TITLE | QUESTION | ANSWER

3.2. Đặc trưng gọn

FeatureCách lấy
Từ khoá“đáp án”, “đề”, “câu”
Ký hiệutỉ lệ ký tự : ; . ( )
Pattern^\d+[\).] (đầu dòng số/chấm)
Context1 dòng trước / sau (bi-gram của nhãn)

3.3. Mô hình

  • Logistic Regression hoặc SVM với Bag-of-Words + features trên.
  • Dữ liệu gán nhãn: ~200–300 dòng là đủ.

Sau khi có mô-hình, chạy qua toàn file để nhận nhãn thay vì regex cứng.


4. Gán đáp án ↔ câu hỏi chính xác (nâng cao)

Nếu đáp án ghi “Câu 7: C” mà KHÔNG ghi “đề x”, ta cần đoán:

  1. Ghép theo số câu

    • Lấy tổng số câu của mỗi đề (n).
    • Nếu 7 ≤ n của đề hiện tại, coi đó là đáp án của đề hiện tại.
  2. Ghép bằng ngữ nghĩa

    • Sentence embeddings (Sentence-BERT, vi-sbert):
    python
    from sentence_transformers import SentenceTransformer, util model = SentenceTransformer("keepitreal/vietnamese-sbert") sim = util.cos_sim(model.encode(answer), model.encode(question))
    • Với mỗi đáp án, chọn câu hỏi có max(sim) > threshold (ví dụ 0.45) rồi gán.
  3. Hồi quy nhiều nhãn

    • Với tệp lớn hơn, đặt bài toán multi-class classification: câu đáp án thuộc đề nào.
    • Đặc trưng: TF-IDF của đáp án + id câu (1-st order), train gboost/random forest.

5. Kiến trúc mã nguồn gợi ý

python
class ExamParser: def __init__(self): self.title_re = re.compile(r'<\s*Đ[ềe]\s*(\d+)\s*>', re.I) self.ans_header = re.compile(r'Đáp\s*án', re.I) def parse(self, raw_text): blocks = re.split(r'\n\s*\n', raw_text.strip()) exams = {} cur = None for blk in blocks: if m := self.title_re.search(blk): cur = m.group(1) exams.setdefault(cur, {"qs": [], "ans": []}) elif self.ans_header.search(blk): target = self._extract_exam_in_header(blk) or cur exams.setdefault(target, {"qs": [], "ans": []}) exams[target]["ans"].append(blk) else: if cur: exams[cur]["qs"].append(blk) return exams def _extract_exam_in_header(self, header): m = re.search(r'đề\s*(\d+)', header, re.I) return m.group(1) if m else None

6. Tips triển khai & kiểm thử

  1. Bắt đầu đơn giản: chạy rule-based, in ra thống kê: đề nào thiếu câu, thiếu đáp án.
  2. Viết unit-test với một vài file ground-truth nhỏ.
  3. Log chất lượng:
    • Precision ghép: |answers_correct| / |answers_total|
    • Recall ghép: |answers_correct| / |ground_truth_answers|.
  4. Khi rule-based < 85 % precision ⇒ bắt đầu bật bước ML (Section 3-4).

Kết luận

  • Rule-based FSM 🡒 nhanh, dễ debug, đủ nếu file tuân chuẩn.
  • ML + embeddings 🡒 linh hoạt với định dạng “lệch chuẩn”, ít phải viết regex.
  • Kết hợp cả hai cho pipeline bền vững: rule lọc trước, ML xử lý ngoại lệ.

Nếu bạn muốn sample code đầy đủ hơn hoặc demo trên dữ liệu cụ thể, cứ gửi một file ví dụ, mình sẽ hỗ trợ chi tiết!

Share this Q&A