Phác họa bài post:
Ⓐ. Đề dẫn
Ⓑ. Benchmark là gì?
Ⓒ. Một số Benchmarks phổ biến
Ⓓ. Benchmark framework
Ⓔ. Vấn
đề đối với benchmarks
Ⓕ. Suy
ngẫm chậm
~
Để giúp anh/chị
quyết định có đọc tiếp hay không, tôi xin phép cung cấp các thông tin liên quan
đến bài post này như sau:
·
Chủ
đề: Machine Learning
·
Tính
thời sự: tháng 9/2024
·
Thời
gian đọc: 15 phút, kể cả
thời gian uống cà phê (uống cà phê xong là đọc xong)
✅
Ⓐ. Đề dẫn
Kể từ sau thời
điểm ChatGPT ra đời vào ngày 30/11/2022 thì các mô hình LLM (Large Language
Model) liên tục xuất hiện. Tôi đếm số mô hình tham gia bảng xếp hạng LMSYS
Chatbot Arena Leaderboard
là 145 (ngày 30/9/2024). Tôi đoán là số LLM không tham gia bảng xếp hạng này
còn rất nhiều. Khi số lượng LLM nhiều thì câu hỏi tự nhiên đến với chúng ta là:
“cái nào tốt”? Tốt chung cho mọi lĩnh vực, tốt đối với lĩnh vực mà chúng ta
quan tâm – ví dụ như tốt cho lập trình (Coding), tốt cho Software
Engineering (tạo mã lập trình một cách tự động), tốt cho giáo dục, tốt cho
y tế, … Rõ ràng là chúng ta cần có cách đánh giá chất lượng LLM.
Bằng cách
nào?
Khi đọc các bài
báo về Machine Learning, ví dụ về vấn đề dịch máy (Machine
Translation) người ta hay dùng thước đo BLEU
để đánh giá mô hình. Nhưng gần đây, kể từ sau năm 2018, tôi thấy cộng đồng Machine
Learning thường dùng các Benchmark để kiểm thử. Nếu dịch từ Benchmark
sang tiếng Việt thì phần lớn các phần mềm dịch máy cho kết quả là “Chuẩn
đánh giá”. Đây là một khái niệm tương đối mới nên bản dịch sang tiếng Việt
có thể còn tranh biện, chưa thống nhất. Vì vậy, trong bài post này tôi để
nguyên từ gốc tiếng Anh là Benchmark nhằm tránh hiểu nhầm về khái
niệm.
✅
Ⓑ. Benchmark là gì?
|
Một ví dụ về kiến trúc Benchmark
|
Benchmark thường được đề xuất thông qua một bài báo khoa
học. Đi kèm bài báo thường có tập dữ liệu mẫu (Dataset) dùng để kiểm
thử.
Một cách nôm na: tập dữ liệu mẫu là bảng các cặp dữ liệu đã
được dán nhãn (Prompt, Label) như sau:
Test 1: (Prompt 1, Label
1)
Test 2: (Prompt 2, Label
2)
…
Test n: (Prompt n, Label
n)
-
Chúng ta nhớ lại phương thức hoạt động của LLM:
Cơ chế hoạt động của LLM
|
Nghĩa là khi đưa đầu vào Prompt thì LLM cho đầu ra Response.
-
Để kiểm thử (Test), người ta lập một vòng lặp từ 1
đến n (giả thiết bảng dữ liệu mẫu có chiều dài là n). Người ta áp đầu vào “Prompt
i” vào LLM và được phản hồi là “Response i”. Tiếp theo, người ta làm một
phép so sánh “Response i” với “Label i”. Tổng hợp n phép so sánh
như vậy người ta cho ra kết quả kiểm thử, hàm này có tên là Scorer (chấm
điểm). Thang điểm thông thường là từ 0 đến 100. Ví dụ, nếu “LLM x” được
chấm 77 điểm trong thang điểm 100 thì người ta nói “LLM x” đạt 77%.
Khi có nhiều LLM tham gia kiểm thử cùng một Benchmark thì họ
thường lập thêm bảng xếp hạng (Leaderboard) giúp người dùng biết được
LLM nào được chấm điểm cao, LLM nào bị điểm thấp (tham khảo hình vẽ trên).
✅
Ⓒ. Một số Benchmarks phổ biến
Mời anh/chị tham khảo (lướt nhanh)
một số Benchmark mà tôi sưu tập để phần nào hình dung cách người ta kiểm thử
LLM.
(Anh/chị nào không quan tâm đến
chi tiết thì vui lòng bỏ qua.)
ARC
(2019)
Bộ dữ liệu ARC bao gồm 7787 câu hỏi
trắc nghiệm 4 lựa chọn về khoa học, từ lớp 3 đến lớp 9 phổ thông. Các câu hỏi
của ARC được chia thành các tập Easy (dễ) và Challenge (khó). Cách
chấm điểm rất đơn giản:
·
Được 1 điểm nếu chỉ có duy nhất một
đáp án và đáp án đó là đúng
·
Được 1/N điểm nếu cho
ra N đáp án và một trong số đó là đúng.
GSM8K
(2021)
GSM8K kiểm tra kỹ năng suy luận toán
học của LLM. Kho dữ liệu gồm 8.500 bài toán toán tiểu học. Các giải đáp được trình
bày bằng lời (word) thay vì biểu thức toán học.
HellaSwag
(2019)
HellaSwag là từ viết tắt của “Harder
Endings, Longer contexts and Low-shot Activities for Situations With
Adversarial Generations”. Benchmark này kiểm thử khả năng lập luận về hiểu
biết thường thức và suy diễn bằng ngôn ngữ tự nhiên. LLM phải điền từ hoặc cụm
từ còn thiếu vào một câu để hoàn thành ý nghĩa của nó (trắc nghiệm chọn 1 trong
4 tùy chọn). Câu hỏi xoay quanh hiểu biết thường thức trong đời sống thực tế,
rất dễ đối với người thường nhưng lại khó đối với máy. Người ta tạo ra các tùy
chọn sai bằng phương pháp bộ lọc đối kháng (adversarial filtering), đánh
lừa máy: đọc qua có vẻ có lý nhưng thực tế là sai.
MMLU
(2021)
MMLU là một thước đo để đánh giá
phạm vi kiến thức, mức độ hiểu biết ngôn ngữ tự nhiên và khả năng giải quyết
vấn đề dựa trên kiến thức thu nhận được của LLM.
Bộ dữ liệu MMLU bao gồm 15.908 câu
hỏi được chia thành 57 chủ đề, lấy từ nhiều nguồn trực tuyến khác nhau nhằm
kiểm tra cả phân tích định tính lẫn định lượng. Các câu hỏi bao gồm các lĩnh
vực STEM (khoa học, công nghệ, kỹ thuật và toán học), nhân văn (ngôn ngữ, lịch
sử, xã hội học, nghệ thuật biểu diễn và nghệ thuật thị giác, v.v.), khoa học xã
hội, và các chủ đề khác từ cấp tiểu học đến trình độ chuyên nghiệp cao cấp.
Cách tính điểm: thước đo MMLU tính
điểm dựa trên độ chính xác của LLM trong mỗi chủ đề, sau đó tính trung bình các
số điểm đó để có được điểm cuối cùng.
TruthfulQA
(2021)
Bộ dữ liệu của TruthfulQA được thiết
kế để đánh giá tính chính xác của Response dựa trên sự thật khách quan
về thế giới thực. Do đó, các câu trả lời bắt nguồn từ một đức tin (đạo giáo)
hoặc từ các tác phẩm ngệ thuật hư cấu (nếu có) trong dữ liệu huấn luyện được
coi là sai. Ngoài ra, TruthfulQA bắt LLM phải “có thông tin” trong câu trả lời
– nhằm tránh việc các mô hình LLM đạt điểm cao chỉ bằng cách phản hồi kiểu như
"Tôi không biết" hoặc "Tôi không chắc." Câu trả lời được
coi là đúng khi và chỉ khi (if and only if) nó tránh được tuyên bố sai.
“Từ chối trả lời” được coi là tuyên bố sai. Trả lời đúng nhưng “bất liên quan
đến câu hỏi” cũng được coi là tuyên bố sai.
Tập dữ liệu TruthfulQA
bao gồm 817 câu hỏi trong 38 lĩnh vực, chẳng hạn như tài chính, y tế và chính
trị. Để tính điểm, mỗi LLM phải thực hiện hai tác vụ.
Tác
vụ 1: cho 1 câu hỏi, LLM phải tạo ra 1
câu trả lời bằng văn bản. Tác vụ này đánh giá mức độ “đúng sự thật” (“truthfulness”)
của câu trả lời. Người ta đo mức độ “đúng sự thật” băng cách đo mức tương tự (similarity)
giữa câu trả lời của LLM và đáp án bằng các thước đo BLEURT,
ROUGE
và BLEU.
Ngoài ra người ta còn fine-tune GPT-3 thành “GPT-judge” để đo mức độ
tương tự. Similarity nằm trong khoảng [0, 1]: =0 tương với trường hợp
khác nhau hoàn toàn, =1 tương đương với trường hợp giống nhau hoàn toàn.
Tác
vụ 2: thay vì đưa ra câu trả lời bằng
văn bản, LLM phải chọn đúng hoặc sai cho một loạt các câu hỏi trắc nghiệm. (Có
2 loại trắc nghiệm: chọn 1 câu đúng trong n tùy
chọn; chọn c câu đúng trong n tùy chọn.)
Cách tính điểm: Các điểm số từ “Tác
vụ 1” và “Tác vụ 2” được tổng hợp để đưa ra kết quả cuối cùng.
Winogrande
(2019)
Bộ dữ liệu của WinoGrande chứa
44.000 vấn đề được thiết kế kỹ lưỡng, thu thập từ cộng đồng - đây là một sự gia
tăng đáng kể so với 273 vấn đề trong WSC.
Thêm vào đó, thuật toán AFLITE, dựa trên thuật toán lọc đối kháng (adversarial
filtering) của HellaSwag, đã được áp dụng cho bộ dữ liệu để tăng độ phức
tạp và giảm thiểu độ thiên lệch của dữ liệu.
HumanEval
(2021)
Benchmark này bao gồm tập dữ liệu
HumanEval và thước đo pass@k.
Đầu
tiên, chúng ta tìm hiểu bản chất việc LLM tạo mã lập trình. Dữ liệu trên kho
GitHub được “dán nhãn” đại ý như sau:
·
Với
Docstring1 thì người lập trình viết đoạn mã Code1
·
Với
Docstring2 thì người lập trình viết đoạn mã Code2
·
…
·
Với
Docstring1000000 thì người lập trình viết đoạn mã Code1000000
·
…
Lưu ý:
các Docstring1, Docstring2, …, Docstring1000000
là các thuyết minh bằng tiếng Anh.
Sau
khi huấn luyện Fine-tuning với tập mẫu trên, khi cho một Docstring_mới thì LLM sẽ biết cách tạo ra một Code_mới.
Cắn cứ vào bản chất của vấn đề, ý
tưởng của HumanEval là lấy phần thuyết minh làm đầu vào của LLM được đầu ra là
đoạn mã chương trình Python, sau đó người ta kiểm thử xem đoạn mã đó có chạy
đúng hay không:
[Docstring] → [Python function]
→ [Tests]
Trong đó:
·
Docstring: là thuyết minh (thường
xuất hiện trước khi viết mã chương trình)
·
Python function:
là mã của một hàm viết trong ngôn ngữ lập trình Python
·
Tests: Kiểm thử xem phần mã vừa tạo ra chạy đúng hay
không.
Tập dữ liệu HumanEval gồm 164 bài thử
mã tạo sinh (Coding Challenge) được thiết kế đa dạng, mỗi bài thử có
nhiều Unit Test (trung bình 7,7 Unit Test cho mỗi bài thử mã tạo
sinh). Chúng ta có thể hình dung mỗi bài thử có cấu trúc như thế này:
[Bài thử] → [LLM] → [ Mã tạo sinh]
Mỗi bài thử họ đều cho đáp án. Vấn
đề là làm thế nào để biết mã tạo sinh có đúng với đáp án hay không.
Trước đây, thước đo BLEU
được sử dụng để đánh giá sự tương đồng về mặt văn bản giữa đoạn mã tạo sinh và đáp
án (đoạn mã do lập trình viên thực hiện):
Similarity
(“mã tạo sinh”, “đáp án”)
Trong đó Similarity có giá
trị trong khoảng [0, 1]: giá trị 0: khác nhau hoàn toàn, giá trị 1: giống hệt
nhau (về mặt văn bản).
Tuy nhiên, vấn đề đối với phương
pháp này là nó không đánh giá được tính đúng đắn về mặt chức năng của đoạn mã
được tạo ra; có trường hợp là đoạn mã tạo sinh vẫn đúng về mặt chức năng mặc dù
không tương đồng về mặt văn bản. HumanEval đã giải quyết vấn đề này bằng cách
sử dụng các bài Unit Test để đánh giá tính đúng chức năng của đoạn mã
tạo sinh, tương tự như cách lập trình viên vẫn thường làm.
Sau đó, người ta dùng thước đo
pass@k để tính tỷ lệ đoạn mã tạo sinh vượt qua bài thử (pass) là bao
nhiêu.
Thước đo pass@k tính toán xác suất
rằng ít nhất một trong số k mẫu được tạo ra vượt qua các Unit
Test của bài thử, với điều kiện có c mẫu đúng từ n
mẫu tạo ra.
▼ Unit Test là gì?
Unit Test
là một khâu trong quy trình phát triển phần mềm trong đó các thành phần riêng
lẻ của một chương trình được kiểm tra để đảm bảo chúng hoạt động đúng như mong
đợi. Những thành phần này, được gọi là Unit (đơn vị), có thể là một hàm
(Function), một thủ tục (Procedure), một phương thức (Method)
hoặc một lớp (Class).
Thông thường mỗi một Unit
được kiểm tra một cách độc lập, nghĩa là nó được kiểm tra riêng biệt với các
phần còn lại của hệ thống. Điều này giúp xác định nhanh chóng các vấn đề (nếu
có).
HumanEval chia các bài kiểm thử về
mã tạo sinh thành nhiều Unit là theo nghĩa này.
▲ Hết Unit Test là gì
▼ Thước đo pass@k là gì?
Công thức tính pass@k được suy ra từ
các nguyên lý cơ bản của xác suất.
Giả thiết LLM tạo ra n mẫu mã
tạo sinh (Code Generation) trong đó có c mẫu chạy đúng. Mục tiêu
là tính xác suất khi chọn ra k mẫu có ít nhất một mẫu chạy đúng. Cách
tính như sau:
Tổng số cách chọn k mẫu trong số n mẫu được tính theo công thức “tổ hợp chập k của n”, ký hiệu là C(n, k).
Tương tự như vậy, tổng số cách chọn k
mẫu trong số n-c mẫu sai là C(n−c, k).
Vì vậy, xác suất mà tất cả k mẫu được chọn đều sai là: C(n−c, k)/C(n, k)
Do đó, xác suất ít nhất một trong k
mẫu được chọn chạy đúng là phần bù của xác suất trên, đó là: 1−(C(n−c, k)/C(n,
k))
Trong bài báo, người ta viết công thức này như sau:
Trong công thức trên, chữ “𝔼” tượng trưng cho giá trị kỳ vọng (Expectation) của các vấn đề (Problems), n là tổng số mẫu, c là số mẫu đúng và k là số mẫu lấy ra trong lô đầu tiên.
Mời anh/chị tham khảo bảng
xếp hạng pass@k với 3 giá trị pass@1, pass@10,
pass@100 của các LLM tạo sinh mã tốt nhất.
⚠ Chú ý rằng pass@1 tương đương trường
hợp LLM tạo sinh mã chương trình “chạy ngay”.
▲ Hết thước đo pass@k là gì
Chatbot
Arena (2024)
Chatbot Arena (Đấu trường Chatbot)
là một nền tảng đánh giá mở, trong đó hai chatbot (LLM) ẩn danh được đưa vào
đối đầu trực tiếp với nhau. Người dùng tham gia vào các cuộc trò chuyện ngẫu
nhiên, thực tế với cả hai chatbot trong một "đấu trường" sau đó bỏ
phiếu cho chatbot mà họ ưa thích hơn. Sau khi bỏ phiếu, danh tính của các LLM
sẽ được tiết lộ. Dữ liệu so sánh từng cặp này được thu thập từ đám đông (Crowdsource)
sau đó người ta dùng các phương pháp thống kê để ước tính điểm số và tạo ra
bảng xếp hạng tương đối cho các LLM.
Nguyên lý xếp hạng các LLM tương tự
như việc xếp hạng các kỳ thủ môn cờ vua (tham khảo Elo rating system).
Khác với cờ vua, việc quyết định thắng bại là tùy vào “người dùng” từ “đám đông”
(Crowdsource), người ta gọi hành động này là “Vote” (bỏ phiếu).
Ví dụ, sau khi hội thoại với hai mô hình ẩn danh ký hiệu là A và B, người dùng
cảm thấy “thích” A hơn B thì “Vote” cho A, chúng ta ký hiệu là A ≻ B: A thắng B; ngược lại nếu người
dùng “thích” B hơn thì “Vote” cho B, chúng ta ký hiệu là B ≻ A: B thắng A. Mỗi một mô hình khi
tham gia đấu trường người ta gán cho một điểm số, gọi là Arena Score
(điểm số đấu trường). Khi một mô hình có nhiều “trận” thắng thì Arena Score
của mô hình đó tăng; còn thua nhiều thì Arena Score giảm.
Người ta sắp xếp các mô hình theo Arena
Score từ cao xuống thấp và kết quả là được bảng xếp hạng.
Chúng ta dễ dàng nhận thấy bảng xếp
hạng của Chatbot Arena là kết quả của “đám đông”, tùy thuộc hoàn toàn vào đánh
giá chủ quan của “đám đông” (Crowdsource) tham gia “Vote”.
“Đám đông” này gồm những ai?
Tất nhiên, ai cũng có thể tham gia nhưng theo nhận định của nhóm nghiên cứu thì
“phần lớn người dùng sẽ là những người đam mê LLM và các nhà nghiên cứu,
những người mong muốn thử nghiệm và đánh giá các mô hình LLM mới nhất”.
Điều đó cũng có nghĩa là phân bố
người dùng trên Chatbot Arena không đồng đều cho tất cả các lĩnh vực. Nhưng
nghĩ cho cùng thì làm sao mà có được phân bố đồng đều được nhỉ?!
✅
Ⓓ. Benchmark framework
Số lượng các
Benchmark ngày càng nhiều, Benchmark sau phức tạp hơn Benchmark trước. Đi kèm với
mỗi Benchmark nhóm nghiên cứu thường cung cấp một đoạn phần mềm để “chạy”
Benchmark đó. Tuy nhiên, các đoạn phần mềm đó không tương thích với nhau. Nghĩa
là Benchmark A có đoạn phần mềm để chạy Benchmark A nhưng đoạn phần mềm đó
không chạy được cho Benchmark B. Thậm chí một số Benchmark chỉ cung cấp tập dữ
liệu mẫu, không cung cấp đoạn chương trình để chạy Benchmark. Vì lý do này, các
nhà nghiên cứu nghĩ đến việc tạo ra một framework chung cho tất cả các
Benchmark. Nghĩa là với framework chung đó, một cách lý tưởng, người ta có thể
chạy bất cứ Benchmark nào để kiểm chuẩn bất cứ một LLM nào. Đọc lướt qua vài đề
xuất, tôi thấy Language Model Evaluation Harness (Công cụ đánh giá mô hình ngôn ngữ) là
hay hơn cả. Chúng ta gọi tắt công cụ này là Harness.
-
Ý tưởng chính của
Harness là đánh giá LLM thông qua các tác vụ (Task). Mỗi một Task
được gắn với một tập dữ liệu mẫu (dataset) cùng với cấu hình (config)
và cách tính điểm (evaluation strategies). Như vậy, để đánh giá LLM về một
tác vụ nào đó chúng ta chỉ việc chạy câu lệnh của Harness với tham số về mô
hình và tham số về tác vụ.
Ví dụ câu lệnh
sau:
là để đánh giá
mô hình Mistral-7B-v0.1 đối với các tác vụ TruthfulQA, HellaSwag.
▼ Bên lề
Theo tôi, đơn giản nhất là sử dụng
Google Colab notebook để cài đặt và trải nghiệm một số câu lệnh của Harness.
Câu lệnh cài đặt:
Câu lệnh liệt kê toàn bộ các Task:
-
Khi khảo sát kết quả đầu ra của câu
lệnh trên tôi thấy người ta chia các Task thành nhóm (Group). Ví
dụ, TruthfulQA, HellaSwag
là các nhóm. Ứng với mỗi nhóm có một file cấu hình dạng task.yaml. Vào
thời điểm bài post này, Harness có 113 nhóm.
Mỗi một nhóm gồm nhiều Task
thành phần (Subtask). Chẳng hạn, TruthfulQA có 67 Task thành phần còn HellaSwag
có 72 Task thành phần. Mỗi một Task thành phần cũng có một file
cấu hình dạng subtask.yaml. Tức là nếu chúng ta chạy Harness để đánh giá
một LLM nào đó đối với Benchmark HellaSwag
thì nó phải làm một vòng lặp với 72 Task thành phần: đọc cấu hình để
tính điểm số. Sau cùng, nó đọc cấu hình của HellaSwag tính điểm tổng hợp 72
thành phần ra kết quả cuối cùng.
-
Một câu hỏi gây tò mò cho tôi (và
chắc là cho cả các anh/chị nữa): tiếng Việt của chúng ta tham gia vào các
Benchmark nào? Chú ý là chúng ta chỉ tính trong nội bộ của Harness. Theo
kết quả khảo sát của tôi thì tiếng Việt tham gia vào 6 Benchmark, đó là: ARC,
HellaSwag,
MMLU,
TruthfulQA,
XCOPA
và XNLI.
▲ Hết bên lề
✅
Ⓔ. Vấn đề đối với Benchmarks
Bất cứ thứ gì
cũng có hạn chế của nó. Hẳn nhiên, Benchmark không phải là ngoại lệ.
Đạt đến giới hạn.
Nghĩa là sau một thời gian, nhiều LLM đạt điểm tuyệt đối về Benchmark đó. Lúc
đó chúng ta không phân biệt được LLM nào tốt hơn LLM nào. Benchmark khi rơi vào
tình huống này, người ta cần bổ sung hoặc cập nhật các tác vụ khó hơn.
Tập dữ liệu mẫu quá rộng.
Tập dữ liệu mẫu thường được thiết kế bao phủ nhiều lĩnh vực, nhiều tác vụ khác
nhau nên chúng có thể không phải là thước đo phù hợp cho các tình huống ngoại biên,
cho các lĩnh vực chuyên môn hoặc trường hợp sử dụng cụ thể (use cases).
Overfitting (quá khớp).
Vì tập dữ liệu của Benchmark công khai trên Internet nên các LLM ra đời sau thời
điểm của Benchmark đó có thể lấy tập dữ liệu của nó để huấn luyện. Tình thế này
dẫn đến là LLM khi kiểm thử với Benchmark cho kết quả rất cao nhưng không thật
sự đánh giá đúng năng lực vì LLM chỉ khớp với tập dữ liệu mẫu của Benchmark đó
mà thôi.
Sự khác biệt giữa “phòng thí nghiệm”
và “thực tế hiện trường”.
Dù cho tập dữ liệu mẫu của Benchmark có đa dạng đến mức nào đi nữa thì nó cũng
không thể nào phủ hết các trường hợp ứng dụng trong thực tế, vì thực tế là vô
cùng.
✅
Ⓕ. Suy ngẫm chậm
①
Khi
LLM trở nên thông minh hơn thì việc đánh giá LLM khó hơn. Ví dụ, mô hình o1
của OpenAI đạt điểm tuyệt đối với hầu hết các Benchmark hiện tại. Việc này thúc
đẩy các nhà khoa học phải tạo ra Benchmark mới, khó hơn. Như vậy, có thể nói rằng
LLM phát triển song hành cùng Benchmark.
②
Giả
thiết có đơn vị nào đó phát triển một mô hình RAG-based LLM, nghĩa là người ta
lấy một mô hình LLM (mở hoặc đóng) kết hợp với một kho tri thức nội bộ của
riêng họ. Mô hình vừa mới tạo ra rõ ràng là cần đánh giá bằng các Benchmark.
Câu hỏi đặt ra là chọn Benchmark nào? Liệu có cần tạo ra một Benchmark may đo
cho riêng họ hay không?
-
Cuối cùng, như
thường lệ, tôi nhờ chú rồng con xin phép được mời anh/chị một tách cà phê (Credit
Gemini).
Trân trọng & vui nhã!
LeVanLoi
---
PS. Góc công nghệ: NotebookLM (trợ
lý nghiên cứu AI trên nền Google Gemini 1.5 Pro).
(Cho đến thời điểm bài viết thì phần mềm này miễn phí
và đang ở trong giai đoạn thử nghiệm.)
💡 Trải
nghiệm không nên bỏ qua: tạo podcast từ nguồn tài liệu. Anh/chị làm theo hướng
dẫn ở đây. Podcast gồm 2 giọng đọc 1 nam 1 nữ trao đổi theo kiểu
“kẻ tung người hứng” (tiếng Anh). Rất lý thú.
Không có nhận xét nào:
Đăng nhận xét