Những con bot không còn nói giống hệt nhau
Mọi câu mà các gương mặt quen từng đăng đều là một trong sáu câu. Giờ có hàng trăm câu, mỗi nhân vật viết theo giọng riêng, và không gì lặp lại khi câu trước vẫn còn trên màn hình.

Nói đơn giản
Hai ngày sau khi các gương mặt quen xuất hiện trong sảnh, chỉ cần nhìn kỹ là thấy ngay vấn đề: họ nói y hệt nhau. Một người đăng "quick game anyone", "lets play", "quick game anyone", "need one more", "need one more" chỉ trong một buổi tối. Người khác nói "anyone up for a game" ba lần trong chín mươi phút.
Cơ sở dữ liệu nói thẳng: mọi câu bất kỳ ai trong số họ từng đăng đều là một trong sáu câu. Trong ván đấu cũng vậy — một biệt danh nói "had to have it" chín lần. Còn một dấu hiệu thứ ba chưa ai phản ánh: cả mười hai đều viết đúng một giọng — chữ thường, câu cụt, không dấu câu — trong khi người thật ở cùng phòng gõ "Hi guys!", "Someone wanne play?" và "Let’s goooooooooo!".
Giờ mỗi gương mặt quen có một giọng riêng, bắt nguồn từ chính họ chứ không phải bốc ngẫu nhiên mỗi lần. Trên toàn bộ dàn nhân vật, điều đó có nghĩa là:
- người viết chữ thường, người viết câu hoàn chỉnh — và họ giữ nguyên như vậy;
- người dùng dấu câu rất nhiều, người không bao giờ dùng;
- mỗi người có hai hoặc ba biểu tượng cảm xúc thật sự hay dùng, thay vì một kho dùng chung;
- người kéo dài chữ, người viết tắt, có người thỉnh thoảng gõ sai;
- và điều họ nói khớp với căn phòng: không ai đòi "thêm một người" khi vẫn còn bốn ghế trống.
Họ chỉ viết bằng tiếng Anh ở mọi nơi, đúng theo quyết định áp dụng cho toàn bộ hành vi bot trong trò chơi.
Cho người thích chi tiết kỹ thuật
Kho câu được tổ chức theo ý định — chào hỏi, tìm ván, cần thêm một người, vừa vào phòng, bình luận về chế độ, chờ đợi, trêu đùa, cổ vũ, rủ đấu lại — và hai trong số đó được điền từ căn phòng đang chạy, nên câu chữ không thể mâu thuẫn với những gì người chơi đang nhìn thấy.
Giọng của một nhân vật được suy ra từ biệt danh chứ không lưu trữ, nên không cần thêm trường mới nào và vẫn nguyên vẹn sau khi tiến trình khởi động lại:
// botChat.voice.ts — the voice is a pure function of the nickname
const rng = createRng(`voice:${persona.nickname}`);
return {
sentenceCase: rng.float() < 0.34,
punctuation: pick(rng, ['none', 'light', 'heavy']),
emoji: pickN(rng, EMOJI_POOL, rng.int(2, 3)), // habitual, not shared
elongation: rng.float() * 0.2,
typoRate: rng.float() * 0.06,
};Việc lặp câu được xử lý bằng một bộ nhớ nhỏ có phạm vi tính theo cả căn phòng lẫn nhân vật, nên cùng một câu không thể quay lại khi nó vẫn còn trên màn hình, và hai nhân vật trong một phòng không thể nhại lại nhau.
Lỗi thú vị nằm ở phép biến đổi tạo lỗi gõ. Tin nhắn của bot được ghi bằng vai dịch vụ, vốn đi thẳng qua bộ lọc từ ngữ tục mà tin nhắn của người thật phải đi qua — nên một lỗi gõ "thật" có thể tạo ra một từ bị chặn ("and" gõ nhầm thành "nad" nằm trong danh sách). Bài kiểm thử với 2.600 mẫu vượt qua êm xuôi; phải khoảng 68.000 lượt bốc thì vấn đề mới lộ. Giờ bài kiểm thử liệt kê vét cạn khoảng 260.000 chuỗi khả dĩ trong 1,4 giây, và gọi đúng những bộ sinh mà lớp trò chuyện dùng thay vì viết lại — bản đầu tiên viết lại và lệch khỏi bản thật ngay lập tức.
