Tổng quan về FPT Speech Synthesis – Dịch vụ tổng hợp giọng nói tiếng Việt xây dựng dựa trên AWS

278

Hiện tại các hãng công nghệ lớn như IBM và Amazon đều có dịch vụ Text-to-Speech (TTS) chất lượng tốt, có API để dùng trong production, nhưng không hỗ trợ tiếng Việt. Google có TTS tiếng Việt trong Google Translate nhưng không có API. Ở Việt Nam cũng có một số trường đại học, nhóm nghiên cứu đưa ra dịch vụ TTS như VAIS (https://app.vais.vn/), AILAB (http://ailab.hcmus.edu.vn/vosdemo) có chất lượng đọc khá tốt, tuy nhiên mới chỉ dừng ở mức độ demo, khả năng dùng trong production chưa được chứng minh.

Trong bối cảnh đó, có thể coi FPT Speech Systhesis (FSS) là dịch vụ tổng hợp giọng nói tiếng Việt tốt nhất hiện nay với nhiều tính năng, nhiều giọng đọc, liên tục được cải tiến và có API mở cho cộng đồng. Được xây dựng trên nền tảng AWS của Amazon nên FSS sẵn sàng đáp ứng mọi nhu cầu dùng trong production.

Demo

Google TTS: 

FPT Speech Synthesis: 

Vấn đề

Lượng tải của FSS không trải đều cả ngày mà thường mang tính thời điểm, nên việc áp dụng một cơ chế auto scale hiệu quả là rất cần thiết để tối ưu chi phí. Hiện tại FSS đang dùng custom script để auto scale EC2 instances dựa trên lượng request. Chúng tôi đang thử nghiệm chuyển sang kiến trúc serverless (AWS Lambda) để tăng khả năng phục vụ hơn nữa và giảm bớt công sức quản lý. Nội dung chính của bài này sẽ bàn về hai cơ chế auto scale này.

EC2 Auto Scaling

Khả năng scale hệ thống theo nhu cầu sử dụng là một trong những thế mạnh mà chỉ điện toán đám mây mới cung cấp được. Trước đây chúng ta phải dự đoán tải của hệ thống để chuẩn bị resources cho phù hợp, thường thì cuối cùng sẽ bị thừa hoặc thiếu. Ngày nay với điện toán đám mây, chúng ta có thể tăng hoặc giảm số lượng resource theo đúng nhu cầu, với thời gian chỉ vài phút.

Xa hơn nữa, với chức năng auto scaling, resources của hệ thống sẽ tự động được tăng hoặc giảm tùy theo các tiêu chí được xác định trước mà không cần can thiệp của người quản trị.

Scaling policies dựa trên tình trạng của SQS

Để có thể handle số lượng request lớn, hệ thống FSS xử lý bất đồng bộ (asynchronously) bằng cách đẩy nội dung text cần tổng hợp vào SQS rồi trả về ngay url của file audio trên S3 (lúc này file chưa thực sự tồn tại), các worker (là các EC2 instances) sẽ lấy nội dung từ SQS, tổng hợp thành file âm thanh rồi upload lên S3 với url như trên. Tùy theo độ dài của text mà có thể mất từ 1-10s để tổng hợp, cộng với thời gian request nằm chờ trong queue.

Lúc đầu hệ thống sử dụng số message chờ trong queue (ApproximateNumberOfMessagesVisible) làm tiêu chí cho CloudWatch Alarm để thực thi scale up/down hệ thống, tuy nhiên sau một thời gian sử dụng thực tế gặp phải một số vấn đề:

  • SQS gửi thông tin lên CloudWatch 5 phút 1 lần, có nghĩa trong trường hợp xấu nhất thì phải mất 5 phút thì hệ thống mới nhận được thông tin để scale up, lúc này thường thì số lượng request ở trong queue đã rất lớn. Đây là con số quá lâu cho một ứng dụng TTS, hệ thống FSS mong muốn con số gần với thời gian thực, hoặc tối đa là dưới 1 phút.
  • Do EC2 tính tiền làm tròn theo giờ, ví dụ 1 instance bật trong 10 phút, tắt đi rồi start lại thì vẫn bị tính là 2 giờ, nên cần tối ưu cơ chế scale down, sao cho EC2 instance chạy được số giờ chẵn nhất có thể, cơ chế scale down sẵn có chưa hỗ trợ yêu cầu này.

Custom scaling script

May mắn là AWS cung cấp cả SDK và CLI tool để thực hiện việc scale up/down bằng custom code khá dễ dàng, ví dụ thay đổi số instance bằng CLI tool:

Để có thể phản ứng nhanh nhất với sự thay đổi của tải, chúng tôi đã tạo 1 custom script query vào ElasticSearch để lấy ra lưu lượng request trong khoảng thời gian 1 phút làm tiêu chí để scale up/down.

Script cũng tối đa hóa thời gian chạy của instance sao cho chẵn giờ nhất có thể, ví dụ chỉ scale down khi số giờ lẻ (partial hour) là 50 phút.

Do sử dụng custom script nên có thể thêm bất cứ chức năng nào, ví dụ khi bắt đầu auto scale up thì sẽ báo lên Slack channel:

AWS Lambda

Mặc dù với cấu hình auto scaling EC2 như hiện tại thì hệ thống đang hoạt động tốt, đáp ứng nhanh chóng với thay đổi của lượng tải, chúng tôi vẫn phải quản lý auto scale group (ví dụ khi update code thì sẽ phải tạo lại AMI image và update lại auto scale group).

Gần đây chúng tôi có thử nghiệm dùng kiến trúc serverless bằng AWS Lambda để đơn giản hóa việc quản lý này, đồng thời không cần quan tâm đến việc auto scale nữa.

Giới thiệu

AWS Lambda (ra đời năm 2014) là dịch vụ điện toán serverless khá mới mẻ của Amazon, còn được gọi là Function-as-a-Service (FaaS), với mô hình chạy dựa trên event (event-driven).

Khác với các service như EC2 hoặc Elastic Beanstalk cho phép người dùng chạy các app lớn nhỏ tùy ý, với thời gian tùy ý (thường là các service chạy liên tục), Lambda chỉ cho phép chạy theo các “function” trong 1 khoảng thời gian tương đối ngắn (tối đa 5 phút). Các Lambda function là stateless, được invoke qua events (ví dụ từ S3, SNS, API Gateway, CloudWatch Events,…) hoặc invoke trực tiếp qua SDK và CLI tool.

Lambda tự động handle việc thực thi đồng thời (concurrent executions) nếu có nhiều request đến cùng lúc, giới hạn mặc định là 1000.

Áp dụng

Hiện tại Lambda chỉ support 4 ngôn ngữ: Python, Java, .NET và JavaScript (Node.js), tuy nhiên về bản chất thì môi trường chạy Lambda là một sandbox container dùng Amazon Linux, nên chúng ta có thể chạy bất cứ app nào tương thích với môi trường này. Trong trường hợp của FSS thì phần engine được viết bằng C++ và biên dịch ra file shared library (.so), phần app được viết bằng Go và biên dịch ra file binary thực thi. Cuối cùng phần Lambda function được viết bằng Node.js để khởi tạo và thực thi Go binary.

Mặc dù mô hình chạy của Lambda function là stateless, nhưng Amazon có cơ chế re-use container để tăng performance. Tận dụng đặc tính này, chúng ta có thể thiết kế để trong trường hợp container được re-use thì không cần chạy lại các phần code khởi tạo, etc,… nữa.

Ví dụ với FSS, start một background service khi container được khởi tạo, mỗi khi Lambda function được gọi thì sẽ chỉ gọi đến background service này:

Có một điểm cần lưu ý là Lambda có khá nhiều giới hạn, ngoài thời gian chạy tối đa 5 phút như đã nói ở trên, Lambda chỉ cho phép upload tối đa 50MB code + thư viện đã zip và 250MB sau khi unzip, nên cần kiểm tra kích thước của code trước khi quyết định có dùng Lambda hay không.

So sánh với EC2 về chi phí

Nếu như EC2 tính tiền dựa trên thời gian chạy của instance tính chẵn giờ, thì Lambda tính tiền trên thời gian chạy của function, tính chẵn đến 100ms. Dù Amazon không đề cập đến trong tài liệu về giá, nhưng khi thử nghiệm kết quả cho thấy nếu tăng bộ nhớ của Lambda lên thì năng lực của CPU cũng tăng tương ứng, ví dụ khi cấu hình Lambda chạy với bộ nhớ 1024MB thì tốc độ tổng hợp speech tăng gấp đôi so với dùng bộ nhớ 512MB, và gấp 4 so với khi dùng bộ nhớ 256MB.

Loại bộ nhớ (MB)Thời gian xử lý 300 kí tự (s)Đơn giá/100ms (USD)Tổng (USD)
25610.9520.0000004170.0000457
5125.5080.0000008340.0000459
10242.7870.0000016670.0000465
15361.840.0000025010.0000460

Do đó, trong trường hợp của FSS thì chi phí tính toán đối các loại bộ nhớ khác nhau là gần như tương đương nhau, nhưng nếu dùng bộ nhớ lớn thì sẽ có response time tốt hơn rất nhiều.

So sánh với EC2, kết quả cho thấy năng lực xử lý của Lambda cấu hình 1024MB RAM tương đương với 1 core của EC2 t2.medium (2 core, 0.06$/h tại region Singapore). Như vậy để có năng lực xử lý như t2.medium trong 1 giờ thì nếu dùng Lambda sẽ mất:

Ở đây chưa tính đến yếu tố lãng phí của EC2 do tính chẵn giờ, cũng như giá của EC2 sẽ rẻ hơn nếu dùng reserved instance. Nhìn chung giá của Lambda sẽ đắt hơn EC2 từ 1.5 đến 2 lần.

Kết luận

AWS cung cấp nhiều công cụ linh hoạt, giúp đáp ứng linh hoạt nhu cầu về resource của ứng dụng, với chi phí tối ưu. Auto scaling EC2 vẫn là công cụ rất mạnh để thực hiện việc đó vì cho phép người dùng custom theo đúng business.

Lambda là công cụ mới và đáng quan tâm cho các ứng dụng stateless và có thời gian thực thi nhanh. Cần tính toán và so sánh với EC2 để tối ưu chi phí.

Hồ Minh Hiệp – Kiến trúc sư giải pháp FPT.AI

BÌNH LUẬN

Please enter your comment!
Please enter your name here