Nhận diện giới tính
- Trạng thái: Đã phê duyệt (Accepted)
- Ngày: 19-06-2026
- Chủ sở hữu (Owner): Đội ngũ Voice Engine
1. Bối cảnh (Context)
Đối với một số chiến dịch, bot cần có lời chào hoặc phản hồi khác nhau tùy thuộc vào người bắt máy là nam hay nữ. Server Etron ASR có khả năng ước lượng điều này: khi cấu hình WebSocket mang tham số request_gender_prob, mỗi văn bản giải mã cuối cùng (final transcript) trả về sẽ kèm theo trường gender_prob có định dạng [female_ratio, male_ratio] (hoặc null nếu không thể xác định).
Điều này đặt ra ba bài toán độc lập cần phải được liên kết chặt chẽ với nhau nhưng không làm ràng buộc (coupling) sai lệch giữa các tầng kiến trúc:
- Nhận diện (Detection): Dịch vụ STT quản lý kết nối WebSocket và nhận các tỷ lệ giới tính này. Quá trình nhận diện diễn ra bất đồng bộ (asynchronous) ở giữa cuộc gọi, và chỉ bắt đầu sau khi người nghe thực sự lên tiếng.
- Kết quả (Outcome): Giới tính được quyết định phải vừa ghi nhận vào kết quả cuộc gọi được xuất bản (phục vụ phân tích dữ liệu), vừa ảnh hưởng trực tiếp đến việc node thoại
record(bản ghi) sẽ phát file âm thanh ghi âm sẵn nào. - Nội dung (Content): Cấu trúc dữ liệu cấu hình nội dung node (
ScenarioSpeakRecordContent) được bổ sung các thuộc tính phân tách giới tính giúp một node bản ghi duy nhất có thể chứa các tài nguyên đa phương tiện tương ứng cho từng giới tính.
Khó khăn: Điểm khó khăn nằm ở chỗ bên tạo dữ liệu (STT - một dịch vụ tầng thấp) và bên tiêu thụ dữ liệu (tầng kịch bản/scenario - nơi xử lý nội dung node) nằm ở các tầng khác nhau và được khởi tạo tại các thời điểm khác nhau trong quá trình chạy bot (run_bot).
2. Quyết định kiến trúc (Decision)
D1 — STT quản lý State Machine của quyết định giới tính
Hàm đánh giá giới tính chạy trên mỗi văn bản giải mã cuối cùng (final transcript):
- Nếu một lượt có tỷ lệ nam (hoặc nữ) vượt ngưỡng tin cậy, giới tính đó sẽ lập tức được khóa cố định (lock).
- Sau 3 lượt đánh giá kết quả cuối cùng mà không đạt đủ độ tin cậy vượt ngưỡng, hệ thống sẽ khóa giới tính là trung tính (
"neutral"). - Ngay sau khi khóa, hệ thống sẽ kích hoạt hàm gọi lại (
gender_decision_callback) duy nhất một lần, đồng thời gửi sự kiện lệnh yêu cầu server dừng trả về dữ liệu giới tính để tối ưu hóa tài nguyên (thay vì âm thầm bỏ qua giá trị).
Cấu hình về ngưỡng tin cậy và số lần thử tối đa được quản lý tập trung tại file cấu hình hệ thống. Tính năng nhận diện này hoạt động theo cơ chế opt-in (tùy chọn kích hoạt) cho từng kịch bản cụ thể.
D2 — Sử dụng bộ lưu trữ trung gian chia sẻ để kết nối STT $\rightarrow$ Flow
Một đối tượng lưu trữ trạng thái giới tính nhỏ gọn được tạo ra từ rất sớm trong quy trình chạy bot, trước khi dịch vụ STT và FlowManager được khởi tạo. Nhờ vậy, hàm gọi lại (callback) quyết định giới tính của STT có thể thay đổi dữ liệu bên trong bộ lưu trữ này thông qua một closure mà không cần tham chiếu trực tiếp đến bất kỳ đối tượng nào trước khi chúng được xây dựng.
FlowManager sẽ sở hữu instance này và cung cấp thuộc tính truy cập cũng như cập nhật trạng thái giới tính của người nghe. Cách tiếp cận này giúp loại bỏ các closure tham chiếu ngược (forward-reference) và giữ cho dịch vụ STT hoàn toàn độc lập với tầng luồng nghiệp vụ (flow layer).
D3 — Cấu trúc dữ liệu tự xử lý biến thể giới tính của chính nó
Cấu trúc dữ liệu cấu hình nội dung node bản ghi tự cung cấp các hàm phân tách dữ liệu theo giới tính.
- Quy tắc cốt lõi: ưu tiên sử dụng giá trị đặc thù theo giới tính nếu có biến thể; nếu không, sẽ tự động quay về sử dụng giá trị mặc định (fallback default).
- Logic này nằm trực tiếp trên cấu trúc dữ liệu chứ không nằm ở dịch vụ phát âm thanh.
D4 — Việc lựa chọn nội dung diễn ra tại thời điểm xây dựng cấu hình node
Hàm xây dựng cấu hình node phát thoại nhận thông tin giới tính người nghe (được truyền từ FlowManager qua ScenarioManager) và gọi hàm phân tách dữ liệu giới tính để lấy URL và nội dung phù hợp. URL/văn bản được chọn sẽ chuyển vào metadata của node và được dịch vụ LLM phát ngôn văn bản. Dịch vụ LLM luôn giữ tính chất tổng quát và không cần biết về khái niệm giới tính.
D5 — Ghi nhận giới tính vào kết quả cuộc gọi
Hàm gọi lại (callback) từ STT đồng thời chuyển tiếp thông tin đến bộ quan sát tóm tắt cuộc gọi (Call Summary Observer), đảm bảo kết quả cuộc gọi được xuất bản sẽ chứa đầy đủ thông tin về giới tính quyết định và xác suất nhận diện tương ứng.
D6 — Chuyển đổi trạng thái nhận diện động giữa luồng (Mid-stream)
Ngay khi quyết định giới tính được khóa, một sự kiện tắt nhận diện sẽ được gửi qua kết nối WebSocket hiện tại; server sẽ phản hồi xác nhận đã cập nhật. Đây là một bước tối ưu hóa hiệu năng — vì quyết định cục bộ đã được khóa, nên nếu việc gửi sự kiện này thất bại hoặc không có, hệ thống vẫn hoạt động bình thường bằng cách bỏ qua dữ liệu ở phía client.
3. Hệ quả (Consequences)
- Cửa sổ thời gian (Timing window): Việc lựa chọn nội dung xảy ra khi luồng chuyển trạng thái bước vào một node bản ghi, chứ không phải tại thời điểm phát (playback). Vì người nghe chỉ nói trong các node lắng nghe (
LISTEN), quyết định từ câu thoại trước đó đã được cập nhật vào bộ lưu trữ trước khi node bản ghi tiếp theo được xây dựng. Một node bản ghi chạy trước khi người nghe kịp nói (ví dụ: lời chào đầu cuộc gọi) sẽ sử dụng cấu hình mặc định một cách chính xác. - Trung tính / Chưa quyết định $\rightarrow$ Mặc định: Trạng thái trung tính (
"neutral") và chưa quyết định (None) được xử lý như nhau và sẽ chọn tài nguyên mặc định. Người biên soạn kịch bản phải luôn cung cấp URL/nội dung mặc định hợp lý; các biến thể giới tính đóng vai trò là cấu hình ghi đè (override). - Quyết định là cuối cùng (Final): State machine chỉ khóa một lần duy nhất; câu thoại nói rõ ràng hơn về sau cũng không thể thay đổi giới tính đã quyết định trước đó. Bộ quan sát tóm tắt cuộc gọi cũng lưu giữ quyết định đầu tiên này.
- Một kết nối duy nhất mỗi cuộc gọi: WebSocket của STT được duy trì liên tục trong suốt cuộc gọi (luồng âm thanh được stream qua đây). Sự kiện tắt nhận diện chỉ chuyển đổi việc tính toán ở phía server chứ không thực hiện kết nối lại (reconnect).