Giới hạn thời gian: 60.0s / Giới hạn bộ nhớ: 64M

Điểm: 100

Potato — Semantic Word Guessing

1. Bối cảnh thực tế & Mục tiêu

Trong các hệ thống xử lý ngôn ngữ tự nhiên (Natural Language Processing – NLP), khả năng biểu diễn và so sánh ngữ nghĩa của từ là một bài toán quan trọng. Hai từ có thể khác nhau hoàn toàn về mặt ký tự nhưng lại có ý nghĩa gần nhau, chẳng hạn hammer và shovel đều liên quan đến công cụ.

Trong bài thi này, thí sinh sẽ xây dựng một hệ thống đoán từ dựa trên độ tương đồng ngữ nghĩa. Ban giám khảo sẽ chọn một từ bí mật từ một tập từ vựng cố định. Chương trình không được biết trước từ bí mật mà chỉ nhận được thông tin cho biết từ nào trong hai từ đang được so sánh có ý nghĩa gần với từ bí mật hơn.

Mục tiêu là tìm chính xác từ bí mật trong không quá 30 lượt đoán, với số lượt càng ít thì điểm càng cao.


2. Nhiệm vụ

Xây dựng một chương trình PublicEmbeddingPlayer có khả năng tương tác với Judge để tìm từ bí mật.

Mỗi game bắt đầu với cặp từ cố định:

lamp vs potato

Ở mỗi lượt, Judge sẽ cho biết từ nào trong cặp hiện tại gần với từ bí mật hơn. Sau đó, chương trình phải đề xuất một từ mới thuộc tập vocabulary.

Ví dụ:

Từ bí mật: shovel

← {"turn": 1, "winner_word": "potato", "verdict": "second",
   "word1": "lamp", "word2": "potato"}
→ {"new_word": "rock"}

← {"turn": 2, "winner_word": "rock", "verdict": "second",
   "word1": "potato", "word2": "rock"}
→ {"new_word": "hammer"}

← {"turn": 3, "winner_word": "hammer", "verdict": "second",
   "word1": "rock", "word2": "hammer"}
→ {"new_word": "shovel"}

← {"status": "win"}

Game kết thúc ngay khi từ được đề xuất trùng chính xác với từ bí mật (không phân biệt chữ hoa/chữ thường).

Mỗi từ mà chương trình đề xuất bắt buộc phải xuất hiện trong dataset/vocabulary.json.

Quy tắc tương tác

Mỗi lượt Judge gửi một JSON object có dạng:

{
  "turn": 1,
  "winner_word": "potato",
  "verdict": "second",
  "word1": "lamp",
  "word2": "potato"
}

Trong đó:

  • turn: số thứ tự lượt, từ 1 đến 30.
  • word1, word2: hai từ đang được so sánh.
  • verdict:

    • first: word1 gần từ bí mật hơn.
    • second: word2 gần từ bí mật hơn.
    • same: hai từ có độ gần như nhau.
  • winner_word: từ được giữ lại để so sánh với từ đề xuất ở lượt tiếp theo.
  • Nếu verdict = "same", word1 được giữ lại.

Sau mỗi lượt, chương trình trả về:

{
  "new_word": "rock"
}

3. Dữ liệu

Bộ dữ liệu cung cấp một tập từ vựng cố định gồm 1602 từ tiếng Anh, cùng với embedding công khai tương ứng cho từng từ.

Tải về cùng với baseline tại: đây

Cấu trúc thư mục:

dataset/
│
├── vocabulary.json
└── public_embeddings.npy
vocabulary.json

Chứa 1602 từ duy nhất, viết thường.

Từ bí mật trong game luôn thuộc tập từ này.

public_embeddings.npy

Ma trận embedding công khai có kích thước:

(1602, 2560)

với kiểu dữ liệu:

float32

Mỗi hàng tương ứng với một từ trong vocabulary.json.

Cụ thể:

vocabulary[i]  <->  public_embeddings[i]

Thí sinh chỉ được sử dụng các public embeddings được cung cấp trong dataset để xây dựng chiến thuật dự đoán.

⚠️ Lưu ý: Judge sử dụng một biểu diễn ngữ nghĩa riêng để quyết định từ nào gần từ bí mật hơn. Vì vậy, việc tối ưu chỉ dựa trên public embeddings là một bài toán quan trọng của cuộc thi.


4. Giới hạn môi trường

Chương trình được chạy trong môi trường giới hạn:

  • Thời gian: tối đa 5 phút cho toàn bộ quá trình khởi tạo, chuẩn bị dữ liệu và chơi toàn bộ game.
  • Internet: không có Internet.
  • Solution: file solution.ipynb có kích thước tối đa 1 MB.

Các thư viện được phép sử dụng:

numpy
torch
sentence-transformers

Tuy nhiên, trong bài thi này không sử dụng pretrained models. Thí sinh chỉ được sử dụng:

dataset/vocabulary.json
dataset/public_embeddings.npy

và các thư viện được phép để xây dựng thuật toán.


5. Đánh giá

Mỗi game có tối đa 30 lượt.

Điểm của một game được tính theo lượt tìm thấy từ bí mật:

$$ Score = 1.0 - 0.02 \times \max(0, t - 10) $$

trong đó t là số lượt cần để tìm ra từ bí mật.

Cụ thể:

Lượt tìm thấy Điểm
1–10 1.00
11 0.98
12 0.96
15 0.90
20 0.80
25 0.70
30 0.60
Không tìm thấy 0.00

Điểm cuối cùng là điểm trung bình trên toàn bộ các game, quy đổi sang thang điểm 100:

$$ FinalScore = Mean(GameScore) \times 100 $$

Do đó, hệ thống không chỉ cần tìm được đáp án mà còn phải tìm được càng sớm càng tốt.


6. Chiến lược tham khảo

Thí sinh có thể tự do thiết kế thuật toán dựa trên public embeddings.

Một số hướng tiếp cận có thể cân nhắc:

  • Nearest Neighbor: sử dụng khoảng cách hoặc cosine similarity giữa các embedding để tìm các từ có ngữ nghĩa gần nhau.
  • Candidate Search: duy trì tập ứng viên và thu hẹp dần không gian tìm kiếm sau mỗi verdict.
  • Adaptive Search: lựa chọn từ tiếp theo dựa trên lịch sử các lần so sánh.
  • Cluster-based Search: phân nhóm các từ trong không gian embedding để tìm kiếm theo từng vùng ngữ nghĩa.
  • Hybrid Strategy: kết hợp similarity, lịch sử winner và chiến lược khám phá các vùng embedding khác nhau.
  • ...

⚠️ Lưu ý: Không có tập train được gán nhãn. Thuật toán cần hoạt động dựa trên public embeddings và thông tin nhận được trực tiếp từ Judge trong quá trình chơi.


7. Submission Format

Thí sinh chỉ cần nộp một file duy nhất:

solution.ipynb

Notebook phải chứa phần cài đặt PublicEmbeddingPlayer và toàn bộ logic cần thiết để chương trình tương tác với Judge.

Không cần tạo file answer hoặc submission CSV.

Yêu cầu
  • Tên file phải chính xác là solution.ipynb.
  • Kích thước file không vượt quá 1 MB.
  • Chương trình phải đọc/ghi dữ liệu theo protocol JSON của Judge.
  • Mọi new_word được đề xuất phải thuộc dataset/vocabulary.json.
  • Chương trình phải xử lý tối đa 30 lượt cho mỗi game.
  • PublicEmbeddingPlayer được khởi tạo mới ở đầu mỗi game.
  • Toàn bộ các game được chạy trong cùng một lần thực thi chương trình.

8. Local Testing

Bộ dữ liệu có sẵn để thí sinh tự kiểm tra chương trình.

Có thể chạy:

python local_test.py solution.ipynb --limit 5

Local Judge sử dụng public embeddings, do đó điểm local chỉ mang tính chất tham khảo và không đảm bảo phản ánh chính xác điểm trên Judge thật.


9. Cách nộp bài

  1. Mở solution.ipynb và chỉnh sửa class PublicEmbeddingPlayer.

  2. Chạy toàn bộ notebook để kiểm tra chương trình.

  3. Có thể chạy local test để kiểm tra nhanh:

    python local_test.py solution.ipynb --limit 5
    
  4. Lưu file solution.ipynb.

  5. Nén file solution.ipynb thành một file .zip.

    Ví dụ:

    solution.ipynb
    ↓
    solution.zip
    
  6. Nộp file solution.zip lên hệ thống thi.

Lưu ý
  • Chỉ nộp một file .zip.
  • Bên trong file .zip phải chứa file solution.ipynb.
  • Không đổi tên file notebook: tên bắt buộc là solution.ipynb.
  • Đảm bảo file solution.ipynb có kích thước không vượt quá 1 MB trước khi nén.
  • Không cần tạo file answer hoặc submission CSV.

Chúc các bạn xây dựng được chiến thuật tìm từ thật nhanh và đạt điểm cao!


Giới hạn thời gian: 60.0s / Giới hạn bộ nhớ: 64M

Điểm: 100

Find the Order

Bài toán sử dụng audio và các pretrained model tương đối lớn. Nếu máy cá nhân không có GPU phù hợp, thí sinh được khuyến khích sử dụng Google Colab hoặc Kaggle để phát triển và thử nghiệm solution.

📦 Dataset & Baseline: Download Dataset & Baseline

1. Bối cảnh & Mục tiêu

Trong các hệ thống xử lý ngôn ngữ nói, một đoạn hội thoại thường được tạo thành từ nhiều lượt nói của các nhân vật khác nhau. Thứ tự của các lượt nói quyết định ý nghĩa và tính mạch lạc của toàn bộ cuộc hội thoại.

Trong bài toán này, bạn được cung cấp các đoạn hội thoại tiếng Anh giữa hai người tham gia, Speaker A và Speaker B. Mỗi lượt nói được lưu thành một file âm thanh .wav riêng biệt.

Tuy nhiên, các lượt nói đã bị xáo trộn ngẫu nhiên. Tên file chunk_{k}.wav chỉ biểu thị chỉ số của chunk trong tập dữ liệu đã xáo trộn, không cho biết vị trí thực sự của chunk trong cuộc hội thoại.

Nhiệm vụ của bạn là khôi phục lại thứ tự thời gian ban đầu của toàn bộ cuộc hội thoại.


2. Dataset

Mỗi dialogue gồm n file âm thanh:

chunk_0.wav
chunk_1.wav
...
chunk_{n-1}.wav

Mỗi chunk chứa đúng một lượt nói của một trong hai speaker. Các chunk đã được xáo trộn và có độ dài từ 7 đến 20 lượt.

Các file âm thanh có đặc điểm:

  • Mono
  • Tần số lấy mẫu 44.1 kHz
  • Có thể resample nếu cần thiết
Thông tin về điểm bắt đầu

File prefix.json cung cấp hai chunk đầu tiên theo đúng thứ tự của cuộc hội thoại.

Ví dụ:

{
  "11": [7, 12]
}

có nghĩa là với dialogue 11:

chunk_7.wav → chunk_12.wav → ...

là hai lượt đầu tiên của cuộc hội thoại.

Thông tin này xác định điểm bắt đầu và loại bỏ sự mơ hồ giữa việc đọc cuộc hội thoại theo chiều thuận hoặc chiều ngược.


3. Dataset Structure

Dataset được chia thành các tập phục vụ cho những mục đích khác nhau:

Thư mục answers.json Mục đích
dataset/train/ ✅ Training / fine-tuning
dataset/pretrain/ ✅ Pretraining / training bổ sung
dataset/pretest/ ✅ Validation / local testing
dataset/test_private/ ❌ Final inference và tạo submission
Cấu trúc thư mục
dataset/
├── train/
│   ├── answers.json
│   ├── prefix.json
│   └── <dialogue_id>/
│       ├── chunk_0.wav
│       ├── ...
│       └── chunk_{n-1}.wav
│
├── pretrain/
│   ├── answers.json
│   ├── prefix.json
│   └── <dialogue_id>/
│       ├── chunk_0.wav
│       ├── ...
│       └── chunk_{n-1}.wav
│
├── pretest/
│   ├── answers.json
│   ├── prefix.json
│   └── <dialogue_id>/
│       ├── chunk_0.wav
│       ├── ...
│       └── chunk_{n-1}.wav
│
└── test_private/
    ├── prefix.json
    └── <dialogue_id>/
        ├── chunk_0.wav
        ├── ...
        └── chunk_{n-1}.wav

Trong đó:

  • prefix.json chứa thông tin về hai chunk đầu tiên của mỗi dialogue.
  • answers.json chứa thứ tự đúng của các chunk.
  • answers.json không được cung cấp trong test_private.

4. Nhiệm vụ

Với mỗi dialogue, hãy xác định vị trí theo thứ tự thời gian của từng chunk.

Kết quả của một dialogue phải là một permutation P của:

{0, 1, ..., n-1}

trong đó:

P[i]

là vị trí theo thứ tự thời gian của chunk_i.wav.

Quy ước:

  • 0: chunk đầu tiên
  • 1: chunk thứ hai
  • ...
  • n-1: chunk cuối cùng
Ví dụ

Một dialogue có 3 chunk:

Chunk Nội dung Vị trí đúng
chunk_0.wav "No worries — I'll send you the notes afterwards." 2
chunk_1.wav "Hey, are you coming to the three o'clock meeting?" 0
chunk_2.wav "I can't — I've got a dentist appointment then." 1

Thứ tự đúng là:

chunk_1 → chunk_2 → chunk_0

Do đó:

[2, 0, 1]

là đáp án cho dialogue này.

prefix.json tương ứng sẽ chứa:

[1, 2]

5. Output

Bạn cần tạo một file JSON chứa dự đoán cho toàn bộ dialogue trong:

dataset/test_private/

Ví dụ:

{
  "17": [2, 0, 1],
  "42": [0, 1],
  "108": [3, 1, 0, 4, 2, 5]
}

Trong đó:

  • Key là dialogue_id.
  • Value là permutation dự đoán cho dialogue tương ứng.

6. Submission Format

Bạn phải nộp một file .zip** duy nhất.

Ví dụ:

submission.zip

Bên trong ZIP bắt buộc phải có cả source code và prediction:

submission.zip
├── solution.ipynb
└── submission.json
solution.ipynb

solution.ipynb là source code của bạn và phải chứa toàn bộ logic cần thiết để tạo prediction.

Ban tổ chức sẽ kiểm tra sự tồn tại của file solution.ipynb** trong submission.

Notebook nên có khả năng chạy độc lập trong môi trường thi, sử dụng dataset được cung cấp và các model được phép.

submission.json

submission.json chứa prediction cho toàn bộ dialogue trong dataset/test_private/.

Ví dụ:

{
  "17": [2, 0, 1],
  "42": [0, 1],
  "108": [3, 1, 0, 4, 2, 5]
}

Tên của file JSON được yêu cầu là submission.json.

Cấu trúc bắt buộc

Submission hợp lệ phải có ít nhất:

submission.zip
├── solution.ipynb
└── submission.json

⚠️ Không nộp notebook hoặc JSON riêng lẻ. Hãy đóng gói cả hai file vào submission.zip.

⚠️ solution.ipynb được yêu cầu để đảm bảo submission có source code và có thể được kiểm tra/reproduce.


7. Quy tắc của Prediction

P phải là một permutation hợp lệ:

  • Độ dài đúng bằng n.
  • Mỗi giá trị xuất hiện đúng một lần.
  • Các giá trị nằm trong [0, n-1].
  • Sử dụng chỉ số 0-based.
  • Không được bỏ sót dialogue nào.

Nếu permutation không hợp lệ, dialogue đó được 0 điểm.

Dialogue bị thiếu khỏi submission.json, file JSON không hợp lệ hoặc dữ liệu output bị malformed cũng được tính 0 điểm cho dialogue tương ứng.


8. Scoring

Bài toán được chấm bằng pairwise ordering accuracy.

Với mỗi cặp chunk, hệ thống kiểm tra xem hai chunk đó có được đặt theo đúng thứ tự thời gian hay không.

Một dialogue có n chunk sẽ có:

$$ M = \frac{n(n-1)}{2} $$

cặp chunk.

Gọi I là số cặp bị đảo thứ tự so với đáp án đúng. Điểm của dialogue là:

$$ \text{score} = 1 - \frac{I}{M} $$

Do đó:

0 ≤ score ≤ 1
Điểm cuối cùng

Điểm cuối cùng là trung bình điểm của tất cả dialogue:

$$ \frac{1}{N} \sum_{d=1}^{N}\text{score}_d $$

Trong đó N là số dialogue được chấm.


9. Các mô hình được phép sử dụng

Bạn chỉ được sử dụng các pretrained model sau trong cả quá trình huấn luyện và inference:

Speech representation

wav2vec 2.0

Có thể sử dụng embedding của wav2vec 2.0 để biểu diễn nội dung âm thanh.

Automatic Speech Recognition

OpenAI Whisper, với bất kỳ kích thước model nào đã được cung cấp trong môi trường.

Whisper có thể được sử dụng để chuyển speech thành text và khai thác thông tin từ nội dung hội thoại.

Language model

Qwen2.5-0.5B

Có thể sử dụng:

  • zero-shot; hoặc
  • fine-tune trên các tập dữ liệu được cung cấp.

Các model được phép sử dụng đã được tải sẵn trong môi trường.

⚠️ Không được sử dụng bất kỳ pretrained model nào khác ngoài danh sách trên.

⚠️ Tổng thời gian 10 phút bao gồm cả thời gian train/fine-tune và inference.


10. Giới hạn môi trường

Toàn bộ chương trình phải chạy trong:

  • Thời gian: tối đa 10 phút.
  • GPU: 1 GPU, khoảng 16 GB VRAM.
  • Internet: không có Internet.
  • Storage: 5 GB.
  • Kích thước submission: không vượt quá 1 MB.

Thời gian giới hạn bao gồm toàn bộ quá trình cần thiết để tạo kết quả cuối cùng, bao gồm:

  1. Khởi tạo model.
  2. Load dữ liệu.
  3. Train/fine-tune nếu có.
  4. Trích xuất feature.
  5. Inference.
  6. Tạo submission.json.

11. Local Testing

Các tập train, pretrain và pretest đều có answers.json, cho phép bạn sử dụng chúng cho quá trình phát triển và kiểm tra.

Một workflow có thể là:

dataset/train/
dataset/pretrain/
        ↓
   training / fine-tuning
        ↓
dataset/pretest/
        ↓
   local evaluation
        ↓
dataset/test_private/
        ↓
   final inference
        ↓
submission.json
        ↓
submission.zip

Tập test_private *không có * answers.json và được sử dụng cho inference cuối cùng.


12. Cách nộp bài

  1. Phát triển solution bằng dataset/train/, dataset/pretrain/ và dataset/pretest/.
  2. Kiểm tra solution và đảm bảo solution.ipynb có thể chạy đúng.
  3. Chạy inference trên dataset/test_private/.
  4. Tạo:
submission.json
  1. Đặt source code và prediction vào cùng một thư mục:
submission/
├── solution.ipynb
└── submission.json
  1. Nén thành:
submission.zip
  1. Kiểm tra submission:
submission.zip
├── solution.ipynb   ← bắt buộc
└── submission.json  ← bắt buộc
  1. Đảm bảo file ZIP không vượt quá 1 MB.
  2. Upload submission.zip lên hệ thống chấm.

Quan trọng: Submission không chỉ chứa prediction. Cả solution.ipynb và submission.json đều bắt buộc phải có trong file ZIP.