Không cần phải lựa chọn giữa sự tiện lợi của AI có thể dùng ngay và tính linh hoạt của mô hình tuỳ chỉnh, bạn có thể triển khai cả hai trong một ứng dụng cực kỳ tinh gọn mà không cần thêm hàng megabyte tệp nhị phân thừa.
Trong phiên này, chúng tôi sẽ minh hoạ cách xây dựng chính xác cấu trúc ngăn xếp kép này trong một ứng dụng Android. Bạn sẽ thấy cách tận dụng Bộ công cụ học máy cho các tác vụ học máy cổ điển có sẵn (như quét tài liệu) cùng với LiteRT độc lập trong Dịch vụ Play cho khối lượng công việc âm thanh hoặc thị giác máy tính tuỳ chỉnh. Chúng tôi sẽ đi sâu vào cách cả hai phương thức triển khai kết hợp với nhau để sử dụng thời gian chạy LiteRT hiện đại, mang lại cho ứng dụng của bạn hiệu suất liền mạch, được tăng tốc phần cứng trên CPU và GPU với dung lượng tải xuống gần như bằng 0 byte.
Những điểm chính dành cho nhà phát triển:
– Hiệu suất vượt trội: Cả mô hình có sẵn và mô hình tuỳ chỉnh đều được tăng tốc phần cứng tự động bằng API CompiledModel hợp nhất.
– Micro-APK: Giảm đáng kể kích thước tải xuống của ứng dụng bằng cách giảm tải cả thời gian chạy Bộ công cụ học máy và LiteRT cho Dịch vụ Play.
– Tích hợp kết hợp: Thành thạo việc chạy nhiều quy trình công việc ML song song trong môi trường thực tế mà không xảy ra xung đột tài nguyên.
play-services-litert, gọi LiteRt.initialize để lấy môi trường và truyền môi trường đó đến CompiledModel.create.Bản chép lời
Chào mọi người.
Chúng ta sắp bắt đầu buổi trò chuyện.
Vì vậy, khi nói đến "AI trên thiết bị" ngày nay, mọi người thường nghĩ đến LLM.
Và trước đó, bạn đã xem một số bài nói về Gemini Nano được đề cập trong Bộ công cụ học máy, Firebase và nhiều sản phẩm khác của Google.
Buổi này sẽ nói về nửa còn lại: công nghệ học máy cổ điển và mô hình mà bạn tự mang đến.
Có thể bạn đã dùng AI vài lần trong hôm nay mà không hề hay biết.
Hãy nghĩ đến việc sử dụng bất kỳ ứng dụng nào mà bạn đã làm mờ nền hoặc sử dụng trình quét mã vạch hoặc sử dụng một số loại chỉnh sửa hình ảnh.
Phần lớn trong số đó là về công nghệ học máy cổ điển và thường chạy trên thiết bị.
Và nếu đã từng thêm bất kỳ tính năng nào trong số này vào ứng dụng hoặc tệp APK của riêng mình, thì bạn thường phải đánh đổi: về cơ bản, tôi có nên sử dụng API chìa khoá trao tay hay nên mang theo mô hình của riêng mình?
Điều này sẽ ảnh hưởng như thế nào đến kích thước ứng dụng?
Hôm nay, bạn sẽ thấy rằng mình không cần phải chọn giữa giải pháp chìa khoá trao tay hoặc tự xây dựng mô hình.
Bạn thực sự có thể làm cả hai việc này bằng một thời gian chạy tinh gọn.
Tôi là Chintan Parikh.
Tôi là nhà quản lý sản phẩm cho LiteRT, và cùng với tôi là Fergus, trưởng nhóm kỹ thuật cho các dịch vụ học máy trên Android.
Xin chào.
Và cuối cùng, bạn sẽ biết cách tạo một ứng dụng chạy hai mô hình trên mỗi khung hình của máy ảnh với tốc độ khoảng 30 khung hình/giây.
Bài nói chuyện này có 4 phần.
Phần một là chúng ta sẽ nói về các giải pháp AI trên thiết bị của Google, tập trung vào công nghệ học máy cổ điển, tức là Bộ công cụ học máy và LiteRT.
Thứ hai, chúng ta cũng sẽ tìm hiểu những điểm mới trong LiteRT và Dịch vụ Play.
Video này cũng sẽ đề cập đến API CompiledModel mới của LiteRT và các thiết bị mà chúng tôi hỗ trợ.
Ba, chúng tôi sẽ hướng dẫn bạn cách tạo một ứng dụng mới.
Fergus sẽ hướng dẫn cách tạo một ứng dụng bằng Bộ công cụ học máy và một mô hình tuỳ chỉnh, tất cả trong một tệp APK.
Cuối cùng, chúng tôi sẽ hướng dẫn bạn cách nâng cấp một ứng dụng hiện có bằng Chế độ tác nhân.
Ngoài ra, bạn thậm chí có thể tạo một ứng dụng mới bằng tính năng hỗ trợ của tác nhân này.
Được rồi.
Trước tiên, hãy bắt đầu với câu hỏi: LiteRT là gì?
LiteRT là môi trường thời gian chạy suy luận trên thiết bị của Google cho các mô hình của riêng bạn.
Thư viện này sử dụng cùng một định dạng tệp .tflite mà bạn đã dùng trước đây với TensorFlow Lite.
Thư viện này được thiết kế lại để tăng hiệu suất và cũng hỗ trợ nhiều khung.
Điều này có nghĩa là bạn có thể đưa các mô hình từ PyTorch, TensorFlow và thậm chí cả JAX vào để giảm xuống định dạng vùng đệm phẳng cho LiteRT.
Giờ đây, kể từ năm 2022, TensorFlow Lite trong Dịch vụ Google Play là thời gian chạy chính thức trên thiết bị của Android cho các mô hình tuỳ chỉnh.
Hôm nay, chúng tôi sẽ nâng cấp đáng kể cho chương trình này và đây cũng là nội dung chính của buổi trò chuyện hôm nay.
Bản nâng cấp này sẽ mang đến API LiteRT CompiledModel mới nhất, bao gồm cả tính năng suy luận GPU mới được cải tiến, nhanh hơn 1,4 lần và giúp bạn xây dựng các ứng dụng nhỏ hơn với kích thước APK gọn hơn nhiều.
Vậy tại sao lại cung cấp thông qua Dịch vụ Play?
Có một số lợi thế và đây chắc chắn là một điểm khó khăn lớn mà tôi nhận thấy trong nhiều cuộc thảo luận mà tôi được nghe, trong đó kích thước ứng dụng và tình trạng phình to của tệp APK đang trở thành một thách thức thực sự, phải không?
Vì vậy, bạn sẽ có một thời gian chạy nhỏ.
Thời gian chạy không có trong tệp APK, vì vậy, bạn phải dựa vào một ứng dụng phụ và điều đó giúp tệp APK của bạn nhỏ hơn khoảng 8 MB.
Lợi ích thứ hai là hiệu quả.
Bạn có một bản sao của thời gian chạy, vì vậy, thời gian chạy LiteRT được chia sẻ trên tất cả các ứng dụng.
Vì vậy, bạn có thể hình dung nếu có nhiều ứng dụng, thì mỗi ứng dụng có thể giúp bạn tiết kiệm 8 MB.
Điều này sẽ tăng lên rất nhanh khi bạn cố gắng tiết kiệm dung lượng ổ đĩa và có một ứng dụng gọn gàng hơn.
Thứ hai, nó được duy trì.
Google cung cấp các bản sửa lỗi, giải quyết các vấn đề về trình điều khiển GPU mà bạn không cần phải làm, đồng thời mọi bản cập nhật bảo mật khác đều được cung cấp thông qua các bản cập nhật tự động.
Và như tôi đã đề cập, GPU nhanh hơn, vì vậy, bạn sẽ có GPU nhanh hơn 1,4 lần và chúng ta cũng sẽ tìm hiểu chi tiết hơn về điều đó.
Và từ góc độ phạm vi, chúng tôi có thể cung cấp cho các thiết bị Android cũ.
LiteRT trong Dịch vụ Play hỗ trợ tất cả các phiên bản Android từ Android 7 (ra mắt năm 2016) trở lên.
Và như Fergus sẽ cho bạn thấy, chúng tôi cũng đang mở rộng sang các thiết bị mới khác trong các trang trình bày tiếp theo.
Vậy, đây là phương tiện phân phối, và hãy nói về bước tiếp theo, thời gian chạy.
Vì vậy, LiteRT không phải là một công nghệ mới và cũng không phải là thử nghiệm.
TensorFlow Lite và LiteRT hiện đã chạy trong hơn 250.000 ứng dụng.
Hệ điều hành này hiện cũng chạy trên hơn 3,8 tỷ thiết bị.
Vì vậy, rất nhiều ứng dụng bạn đang dùng, có thể bạn không biết, đều chạy công nghệ này.
Và con số này cũng tương đương với hơn một nghìn tỷ suy luận mỗi ngày, đúng không?
Ở quy mô đó, chúng tôi chắc chắn đã gặp phải mọi vấn đề về chipset, chúng tôi đã có thể giải quyết các vấn đề về ROM hoặc trình điều khiển GPU và chúng tôi có giải pháp dành riêng cho bạn.
LiteRT cũng là công cụ mà Google chạy trên các ứng dụng chủ đạo của mình, trên các ứng dụng, nền tảng và thậm chí là một số thiết bị.
Hiệu ứng video ngắn trên YouTube, tính năng phân đoạn nền trong Meet, tính năng Làm rõ ảnh là một số ví dụ về trường hợp video theo thời gian thực và mô hình hình ảnh nặng đều chạy trên LiteRT.
Điều này cũng cực kỳ quan trọng vì việc làm cho các trường hợp sử dụng trở nên nhanh chóng và hấp dẫn đối với người dùng là cực kỳ quan trọng, phải không?
Vì vậy, đây là cùng một thời gian chạy mà chúng tôi đã tăng cường cho các tính năng hàng đầu này và đây là những gì bạn nhận được thông qua Dịch vụ Play.
Giờ thì hãy cùng tìm hiểu lý do nên dùng AI trên thiết bị.
Độ trễ, quyền riêng tư, hoạt động khi không có mạng hoặc chi phí thấp, nếu bạn quan tâm đến bất kỳ yếu tố nào trong số này, hãy chạy mô hình khi không có mạng, đúng không?
Có thể còn nhiều lý do khác, nhưng đây là một số lý do rõ ràng nhất mà chúng tôi đã nghe được về việc chạy trên thiết bị.
Việc chạy trên thiết bị cũng không phải lúc nào cũng miễn phí.
Tuy nhiên, việc này cũng có một số điểm khác biệt và thách thức.
Vì vậy, chúng ta cũng sẽ tìm hiểu một số thách thức này và có hướng đi cho bạn, đúng không?
Vậy còn hiệu suất thì sao? Như bạn đã thấy, đúng không, một số ví dụ về các ứng dụng trước đây, độ trễ và ngân sách bộ nhớ luôn eo hẹp, đúng không?
Video và âm thanh theo thời gian thực cần có hiệu suất cực cao.
Ngay cả các tính năng tương tác đơn giản cũng cần phải nhanh chóng.
Nếu không, bạn sẽ mất đi mức độ tương tác của người dùng.
Sự đa dạng về phần cứng: Có hàng trăm SoC với các cấu hình CPU, cấu hình GPU khác nhau.
Bạn không thể viết mã cho tất cả các trường hợp này, đúng không?
Làm thế nào để giải quyết những vấn đề đó?
Kích thước tệp APK: Việc đóng gói một môi trường thời gian chạy gốc cũng làm tăng kích thước của mỗi lượt tải xuống, điều này có thể ảnh hưởng đến tỷ lệ chuyển đổi của bạn.
Tuỳ chỉnh: Huấn luyện mô hình, chất lượng, kích thước mô hình, tất cả đều cực kỳ quan trọng trước khi bạn triển khai.
Vì vậy, việc xây dựng một ứng dụng quản lý thiết bị tuyệt vời trên thiết bị có thể gặp nhiều khó khăn.
Nhưng trong mọi trường hợp, chúng tôi đều muốn nền tảng này hỗ trợ bạn chứ không phải ngược lại, đúng không?
Danh mục sản phẩm AI trên thiết bị của Google được thiết kế để giải quyết những thách thức này, và chúng ta sẽ tìm hiểu về danh mục này trong phần tiếp theo.
Vì vậy, hôm nay chúng ta sẽ tập trung vào hai giải pháp đơn giản, đúng không?
Có hai cách dễ dàng để thêm AI trên thiết bị thông qua Dịch vụ Play.
Cách 1 là cách sử dụng Bộ công cụ học máy, đúng không?
Đây là các API thị giác và ngôn ngữ có thể sử dụng ngay, chỉ cần kiến thức chuyên môn hạn chế về học máy, nhiều mô hình được cung cấp và tất cả đều được phân phối thông qua Dịch vụ Play.
Chúng ta cũng sẽ tìm hiểu một số ví dụ về các trường hợp này trong các trang trình bày tiếp theo.
Đường dẫn tuỳ chỉnh, thông qua LiteRT.
LiteRT cho phép bạn sử dụng mô hình của riêng mình, chạy mô hình đó trên CPU, GPU.
Môi trường thời gian chạy cũng đến từ Dịch vụ Play.
Vì vậy, bạn không cần đóng gói tệp này trong tệp APK.
Đây không phải là lựa chọn một trong hai.
Họ cũng có thể cùng nhau cải thiện.
Và đó chính xác là những gì chúng ta sẽ xây dựng trong vài phút tới.
Trước tiên, hãy cùng tìm hiểu về những tính năng của Bộ công cụ học máy.
Sau đây là những tính năng có sẵn trong Bộ công cụ học máy.
Vì vậy, nếu bạn đã nghĩ đến một số tính năng đáp ứng nhu cầu của mình, thì đó là một điểm khởi đầu tuyệt vời và bạn đã có một khởi đầu thuận lợi.
Chúng tôi có phạm vi bao quát về thị giác, mã vạch, tài liệu, văn bản, tư thế, nhiều tính năng trong số này, các API ngôn ngữ như dịch, trả lời thông minh và thậm chí là trích xuất thực thể, đúng không?
Điểm mấu chốt là nhiều API thị giác và ngôn ngữ này đều chạy ngầm bằng LiteRT.
Vì vậy, nếu Bộ công cụ học máy đáp ứng được nhu cầu của bạn, thì bạn có thể bắt đầu tại đây.
Và khi không có, bạn có thể tự mang mô hình của mình đến.
Và đây là điểm mấu chốt: Bộ công cụ học máy và mô hình tuỳ chỉnh của bạn sẽ không phải là hai thời gian chạy, đúng vậy, như tôi đã đề cập.
Hãy coi hai API này như hai cánh cửa trước dẫn đến cùng một LiteRT sẽ chạy ngầm.
Vì vậy, LiteRT sẽ là môi trường thời gian chạy điều phối cả hai chức năng này.
Vì vậy, nếu ứng dụng của bạn đã sử dụng Bộ công cụ học máy từ Cửa hàng Play, hãy tiếp tục sử dụng.
Nếu không, chúng ta cũng sẽ tìm hiểu về đường dẫn LiteRT.
Giờ hãy cùng tìm hiểu những điểm mới của LiteRT.
Như tôi đã đề cập, LiteRT là một phiên bản cải tiến của TensorFlow Lite, đúng không?
Vậy nên, điểm cải tiến lớn nhất là GPU nhanh hơn.
GPU nhanh hơn hỗ trợ OpenCL, OpenGL và cũng hỗ trợ nhiều nền tảng, ngay cả đối với phần phụ trợ Metal.
Vì vậy, bạn chắc chắn có thể sử dụng tính năng này cho nhiều nền tảng nếu cần.
Cách này cũng đơn giản hơn.
Chúng tôi có một quy trình làm việc thống nhất để tăng tốc CPU, GPU và NPU.
CPU và GPU hiện có trong Dịch vụ Play, trong khi NPU được tích hợp thông qua LiteRT, và đây là công việc đang được tiến hành.
Vậy trước đây, mỗi trình tăng tốc đều có một chế độ thiết lập trình uỷ quyền khác nhau, đúng không?
Giờ đây, bạn chỉ cần thực hiện một lần.
Vì vậy, chỉ có một API tự động quay lại CPU và bạn không cần phải thiết lập uỷ quyền riêng.
Và bạn chỉ cần có các lệnh gọi trình tăng tốc để quản lý việc này một cách đơn giản hơn và ít mã hơn.
Nó cũng rất mạnh mẽ, cùng một mô hình chạy trên nhiều nền tảng, như tôi đã đề cập.
Tính linh hoạt sẽ đóng vai trò vô cùng quan trọng.
Vì vậy, định dạng .tflite vẫn giữ nguyên.
Nếu đã có sẵn một ứng dụng, bạn vẫn có thể sử dụng định dạng này.
Nếu đang xây dựng một ứng dụng mới, bạn có thể sử dụng lại định dạng tệp này.
Một điều thú vị nữa là chúng tôi hỗ trợ Interpreter API, vốn từng có trong TensorFlow Lite.
Vì vậy, nếu bạn muốn di chuyển theo từng giai đoạn, thì Interpreter API cũng được đưa vào LiteRT mới để giúp bạn dễ dàng di chuyển.
Đó là thời gian chạy.
Hãy cùng tìm hiểu những gì bạn có thể xây dựng bằng công cụ này.
Sau đây là những gì các ứng dụng Android đang xây dựng hiện nay.
Mọi thứ từ hiệu ứng camera, chỉnh sửa ảnh, nhập liệu thông minh, trò chơi và hình đại diện, phải không?
Nhiều ứng dụng trong số này sẽ cần có khả năng xử lý theo thời gian thực.
GPU đang gửi khung hình trực tiếp từ camera, nên việc đảm bảo mọi thứ diễn ra nhanh chóng và theo thời gian thực là rất quan trọng.
Một số mô hình chỉnh sửa ảnh cũng đang trở nên nặng hơn.
Tương tự, các tính năng AR/VR mà bạn đã thấy trong một số bản minh hoạ với kính cũng đều chạy LiteRT.
Đây cũng là thời gian chạy hỗ trợ các tính năng hàng đầu của Google và trong Dịch vụ Play, vì vậy, bạn có thể sử dụng tất cả những tính năng này mà không cần gói bất kỳ nội dung nào vào tệp APK.
Bây giờ, hãy cùng xây dựng một ứng dụng và Fergus sẽ hướng dẫn chúng ta cách thực hiện.
Hãy làm điều đó.
Cảm ơn bạn, Chintan.
Vì vậy, tôi sẽ nói một chút về những điểm mới của LiteRT trong Dịch vụ Google Play.
Trước khi chúng ta bắt đầu xây dựng, tôi muốn chia sẻ thêm một tin nữa: mọi thứ bạn vừa thấy giờ đây không chỉ chạy trên điện thoại, mà LiteRT trong Dịch vụ Play cũng có trên Wear OS và Android Automotive OS.
Vì vậy, bạn có thể chạy các mô hình trên thiết bị trong đồng hồ hoặc thiết bị đeo khác, hoặc trong chính ô tô.
Trước đây, bạn có thể dùng một ứng dụng trên điện thoại làm ứng dụng đồng hành với Wear, nhưng giờ đây, bạn có thể chạy ứng dụng đó ngay trên thiết bị đeo và cả trên Android Automotive.
Và bạn có cùng một API, cùng một mô hình .tflite, nhưng có nhiều nền tảng hơn.
Bạn không cần phải triển khai riêng cho từng kiểu dáng, mà chỉ cần sử dụng cùng một cách triển khai cho tất cả các thiết bị này.
Và sau đó, điểm hay của mô hình phân phối Dịch vụ Play là chúng tôi thực sự có thể điều chỉnh tính năng này cho phiên bản cũ để chạy trên các thiết bị cũ.
Vì vậy, đối với Android Automotive OS, chúng tôi hỗ trợ từ Android 11 (phát hành năm 2020) trở lên, còn đối với Wear OS, chúng tôi hỗ trợ từ Wear OS 4 trở lên.
Được rồi.
Bây giờ, tôi sẽ nói về hai lộ trình khác nhau: xây dựng ứng dụng mới và nâng cấp ứng dụng hiện có.
Đó là nội dung của phần còn lại trong bài nói chuyện này.
Vì vậy, tôi sẽ bắt đầu bằng một ứng dụng mẫu kết hợp việc sử dụng Bộ công cụ học máy với một mô hình GPU tuỳ chỉnh chạy trên LiteRT.
Sau đó, để nâng cấp một ứng dụng hiện có, bạn cần thực hiện 3 thay đổi nhỏ: thay đổi Gradle để cập nhật các phần phụ thuộc, thay đổi khởi chạy để bật LiteRT trong Dịch vụ Play, rồi chuyển từ API Trình diễn giải sang API CompiledModel.
Nhưng trước tiên, chúng ta sẽ làm điều đó với ứng dụng mới, vì việc nâng cấp sẽ có ý nghĩa hơn nhiều khi bạn đã biết mình đang nâng cấp lên phiên bản nào.
Vậy nên, hãy xây dựng một ứng dụng mới.
Sau đây là ứng dụng chúng ta sẽ xây dựng.
Tính năng này sẽ có chế độ xem trực tiếp qua camera, trong đó bạn sẽ luôn sắc nét và nền sẽ có phong cách nghệ thuật.
Vì vậy, chúng ta sẽ lấy khung hình của máy ảnh.
Chúng ta sẽ truyền trực tuyến hình ảnh từ khung hình camera thông qua tính năng phân đoạn ảnh chân dung tự chụp của Bộ công cụ học máy.
Đó là một trong những API có sẵn của Bộ công cụ học máy.
Và điều này sẽ tạo ra một mặt nạ tiền cảnh, về cơ bản sẽ cho biết điểm ảnh nào trong hình ảnh tương ứng với người trong hình ảnh.
Sau đó, chúng ta sẽ lấy mô hình tuỳ chỉnh, giống như một mô hình biến đổi phong cách, mô hình này sẽ áp dụng một phong cách cho hình ảnh.
Chúng ta sẽ áp dụng kiểu đó cho toàn bộ khung hình của camera, nhưng thực ra chúng ta chỉ quan tâm đến phần nền, vì cuối cùng chúng ta sẽ lấy khung hình gốc của camera, mặt nạ và nền kiểu, rồi kết hợp chúng bằng một logic đơn giản để có một khung hình tổng hợp, trong đó chúng ta giữ lại chủ thể và nền có kiểu.
Vì vậy, chúng tôi muốn sử dụng các API có sẵn và API tuỳ chỉnh để tạo sự khác biệt cho ứng dụng của mình.
Đây là phần đầu tiên mà chúng ta gọi API phân đoạn ảnh selfie của Bộ công cụ học máy.
// 1. Configure and create segmenter client
val segmenter = Segmentation.getClient(
SelfieSegmenterOptions.Builder()
.setDetectorMode(
SelfieSegmenterOptions.STREAM_MODE)
.build())
// 2. Prepare image & run inference
fun processFrame(mediaImage: Image) {
val image = InputImage.fromMediaImage(
mediaImage, /* rotationDegrees= */ 0)
segmenter.process(image)
.addOnSuccessListener { mask -> … }
}Vậy thì API này cũng giống như API thông thường, đúng không?
Đây là kiến thức cơ bản đối với nhà phát triển Android.
Bạn biết đấy, bạn chỉ cần xem tài liệu API hoặc yêu cầu Gemini xây dựng cho bạn.
Nhưng bạn biết đấy, việc này khá đơn giản.
Bạn tạo một ứng dụng khách, bạn truyền một số tuỳ chọn khi tạo ứng dụng khách.
Trong trường hợp này, chúng ta sẽ chỉ định chế độ truyền trực tuyến để có thể xử lý một luồng khung hình video.
Sau đó, bạn gọi phương thức xử lý này và lệnh gọi lại từ phương thức đó sẽ lấy mặt nạ được trả về, do tính năng phân đoạn ảnh chân dung tự chụp tính toán.
Và dữ liệu đầu vào là hình ảnh từ camera.
Và tất cả các API này đều sử dụng các loại cấp ứng dụng, không phải tensor thô, vì vậy, bạn thực sự đang lập trình ở cấp độ rất cao và điều đó thực sự đơn giản.
Đối với phần thứ hai, mô hình tuỳ chỉnh, chúng ta sẽ sử dụng mô hình PyTorch.
Tôi nghĩ Chintan lấy mô hình này từ một nền tảng như Kaggle hoặc Hugging Face…
Phải.
Đúng vậy, hoặc bạn có thể tự chuyển đổi.
Bạn có thể xây dựng mô hình của riêng mình.
Rất tiếc, tôi sẽ quay lại.
Đúng vậy, đây là hình ảnh của ngăn xếp.
Bạn có thể chuyển đổi và lượng tử hoá mô hình PyTorch để có được mô hình LiteRT.
Sau đó, bạn phân phối tệp đó cùng với ứng dụng của mình theo cách bạn muốn.
Mô hình này có thể được đóng gói dưới dạng một thành phần trong ứng dụng hoặc có thể được tải xuống riêng.
Cách nào cũng được.
Sau đó, mô hình này sẽ nằm trên thời gian chạy LiteRT trong Dịch vụ Play.
Sau đó, có các nhân CPU để tối ưu hoá trên CPU và ML Drift là tên của trình tăng tốc GPU.
Đúng vậy, như tôi đã nói, bạn có thể tự huấn luyện mô hình TFLite hoặc tìm một mô hình hiện có, cách nào cũng được.
Chỉ cần vài dòng Python là bạn có thể chuyển đổi từ PyTorch.
import litert_torch
model = my_models.Stylizer().eval()
# Convert with torch.export under the hood
edge_model = litert_torch.convert(
model, sample_inputs)
edge_model.export("stylizer_f32.tflite")Vì vậy, bạn cài đặt LiteRT-Torch bằng pip, gọi litert_torch.convert, truyền một số sample_inputs có thể là dữ liệu đầu vào ngẫu nhiên và xuất tệp TFLite.
Nhân tiện, LiteRT-Torch là tên mới của ai-edge-torch, nếu bạn đã quen thuộc với tên đó.
Sau đó, việc lượng tử hoá cũng rất đơn giản.
# Python
# previously ai_edge_quantizer
from litert_quantizer import quantizer, recipe
qt = quantizer.Quantizer("stylizer_f32.tflite")
# int8 weights, float activations
qt.load_quantization_recipe(
recipe.dynamic_wi8_afp32())
qt.quantize().export_model("stylizer_int8.tflite")Bạn nhập bộ lượng tử hoá và công thức từ LiteRT Quantizer.
Khi tạo bộ lượng tử hoá, bạn truyền vào mô hình dấu phẩy động ban đầu, bạn truyền vào một công thức, đó là công thức chuẩn mà chúng tôi khuyên dùng cho GPU, sử dụng trọng số số nguyên 8 bit, nhưng giữ nguyên các kích hoạt dưới dạng dấu phẩy động 32 bit.
Sau đó, bạn chỉ cần gọi hàm lượng tử hoá rồi gọi export_model để lưu mô hình đầu ra.
Và đó sẽ là một mô hình lượng tử hoá mà bạn có thể chạy, đồng thời sẽ có trọng số nhỏ hơn nhiều và thực thi hiệu quả hơn.
Đúng vậy, API CompiledModel GPU là nơi thực sự toả sáng.
Vì vậy, như Chintan đã đề cập, bạn biết đấy, tốc độ tăng đáng kể trên GPU TFLite cũ.
Các con số chính xác sẽ khác nhau một chút tuỳ theo từng mô hình, nhưng 1,4 lần là mức bạn có thể mong đợi.
Nhanh hơn đến 10 lần so với suy luận bằng CPU, nên đó là, bạn biết đấy, lợi ích lớn, đúng không?
Nếu bạn là mo- hầu hết các bạn đang sử dụng các mô hình hiện nay có thể đang chạy chúng trên CPU và bỏ lỡ hiệu suất gấp 10 lần mà bạn có thể nhận được từ GPU.
Vì vậy, đó là một động lực thực sự.
Điều gì giúp Gemini 1.5 Flash hoạt động nhanh?
Được rồi, chúng tôi hỗ trợ rất nhiều thứ, chẳng hạn như thực thi không đồng bộ để bạn có thể lấy một AHardwareBuffer và truyền trực tiếp hoặc một vùng đệm OpenGL từ quy trình kết xuất camera đó, truyền thẳng đến một vùng đệm tensor.
Tối ưu hoá không sao chép mà chúng tôi hỗ trợ, về cơ bản, bạn có thể xử lý mọi thứ, bạn biết đấy, với ngân sách độ trễ thấp như khi bạn phải xử lý mọi khung hình trong một khoảng thời gian, bạn biết đấy, vài chục mili giây, thì ngay cả việc sao chép bộ đệm bộ nhớ cũng có thể là một chi phí không hề nhỏ.
Vì vậy, đối với những ứng dụng có yêu cầu thực sự cao về thời gian thực, bạn nên sử dụng tính năng tối ưu hoá không sao chép. Chúng tôi hỗ trợ tính năng đó.
Và sau đó, như Chintan đã đề cập, đây là nhiều nền tảng hỗ trợ OpenGL, OpenCL và Metal, dưới dạng phần phụ trợ GPU.
Cuối cùng nhưng không kém phần quan trọng, trình tối ưu hoá ML Drift là một công cụ nguồn mở.
Thư viện này được cung cấp theo giấy phép Apache.
Gần đây, Google đã cung cấp công cụ này dưới dạng nguồn mở.
Được rồi, tiếp theo là mã ứng dụng.
// Kotlin
// Build once, off the main thread.
private val model: CompiledModel =
CompiledModel.create(
context.assets,
"stylizer_int8.tflite",
// Simple GPU setup!
CompiledModel.Options(Accelerator.GPU),
environment
)
// Reuse buffers across frames.
private val inputBuffers = model.createInputBuffers()
private val outputBuffers = model.createOutputBuffers()
fun stylize(input: FloatArray): FloatArray {
inputBuffers[0].writeFloat(input)
model.run(inputBuffers, outputBuffers) // sync
return outputBuffers[0].readFloat()
}Như bạn có thể thấy, nó khá nhỏ và đơn giản.
Vì vậy, bạn chỉ cần tạo mô hình một lần rồi sử dụng lại mô hình đó trong mọi khung hình.
Vì vậy, CompiledModel.create sẽ truyền vào tệp .tflite.
Bạn chỉ cần chỉ định rằng bạn muốn chạy trên GPU, sau đó tạo dữ liệu đầu vào và outputBuffers.
Sau đó, trong vòng lặp chính, nơi bạn thực sự xử lý mọi khung hình, bạn gọi model.run này để truyền dữ liệu đầu vào, đầu ra.
Sau khi bạn ghi vào inputBuffers, hãy gọi model.run, rồi đọc từ outputBuffers.
Được rồi.
À, đúng rồi, sau đó, nếu bạn chỉ chỉ định GPU ở đó, thì nó sẽ chạy trên GPU.
Nếu bạn cũng chỉ định CPU và GPU ở đó, thì hệ thống sẽ cố gắng chạy GPU.
Nếu không có GPU vì bất kỳ lý do gì, thì hệ thống sẽ quay lại sử dụng CPU.
Vì vậy, trong một số trường hợp, phương án dự phòng CPU có thể không đủ hiệu quả cho ứng dụng của bạn và đó là lúc bạn chỉ muốn chỉ định GPU như vậy.
Thông thường, bạn nên có một phương án dự phòng cho CPU.
Được rồi.
Vì vậy, chúng tôi đã xây dựng ứng dụng này bằng LiteRT đi kèm, tức là chưa sử dụng Dịch vụ Play.
Sau đây, tôi sẽ hướng dẫn bạn cách sử dụng LiteRT trong Dịch vụ Play.
Vì vậy, có ba thay đổi: thay đổi đầu tiên là thay đổi phần phụ thuộc.
// Easier with CompiledModel API: 3 steps
// 1. app/build.gradle: replace litert with play-services-litert
- implementation 'com.google.ai.edge.litert:litert:...'
+ implementation 'com.google.android.gms:play-services-litert:17.0.0' // also pulls in litert-apiBạn chỉ cần thay thế trong tệp Gradle hoặc bất cứ nơi nào khác, bất kể hệ thống xây dựng nào bạn đang sử dụng, bất cứ nơi nào khác bạn chỉ định các phần phụ thuộc của gói Maven, đó là những gì bạn sẽ thay đổi.
Bạn cũng xoá phần phụ thuộc litert hoặc bất kỳ phần phụ thuộc nào của gói TensorFlow Lite Maven cũ, rồi thay thế bằng play-services-litert này.
Thao tác này cũng sẽ lấy gói litert-api.
Bây giờ, nếu đang viết một lớp trung gian chỉ muốn phụ thuộc vào LiteRT nhưng không thực sự quan tâm đến việc thời gian chạy đến từ ứng dụng hay từ Dịch vụ Play, thì bạn chỉ cần phụ thuộc vào LiteRT API và lấy một môi trường làm tham số đầu vào.
Vì vậy, bước thứ hai là tham số môi trường.
Đó là nơi bạn cung cấp tính năng chèn phần phụ thuộc, về cơ bản là để chỉ định rằng bạn đang sử dụng, bạn muốn sử dụng LiteRT của Dịch vụ Play.
Vì vậy, bạn nhập gms.litert.LiteRt và gọi hàm khởi chạy, truyền vào ngữ cảnh, tức là hoạt động Android của bạn.
// 2. Initialize the LiteRT Environment from Play services (context = your Activity)
- val environment = Environment.create(...)
+ import com.google.android.gms.litert.LiteRt
+ val environment = LiteRt.initialize(context).await()
// 3. Pass environment whenever you call CompiledModel.create
// That's it! The rest of your app uses the normal CompiledModel APIs from litert-api.Và đó là một hoạt động không đồng bộ, vì vậy, bạn phải gọi .await hoặc để phần còn lại dựa trên lệnh gọi lại.
Sau đó, cuối cùng, khi đã có môi trường đó, bạn chỉ cần truyền môi trường đó bất cứ khi nào bạn gọi CompiledModel.create.
Và đó sẽ là yếu tố khiến ứng dụng sử dụng thời gian chạy LiteRT của Dịch vụ Play từ Dịch vụ Play.
Vậy là xong.
Đó là phần còn lại của ứng dụng sử dụng chính xác cùng một API LiteRT CompiledModel từ API LiteRT.
Phần còn lại của mã suy luận không thay đổi khi sử dụng Dịch vụ Play.
Và bạn thực sự có thể thực hiện quá trình di chuyển đó theo từng bước.
Bạn không cần phải thực hiện tất cả cùng một lúc mà có thể di chuyển từng thành phần một.
Nếu có một ứng dụng lớn, bạn nên di chuyển từng thành phần đang sử dụng LiteRT, sau đó bạn có thể di chuyển từng thành phần một, kiểm thử từng thành phần một.
Lưu ý duy nhất là bạn chỉ có thể tiết kiệm dung lượng khi xoá phần phụ thuộc cuối cùng trên thời gian chạy đi kèm.
Và nếu có, thì một lưu ý khác là bạn không nên kết hợp các đối tượng giữa LiteRT trong Dịch vụ Play và LiteRT đi kèm.
Vì vậy, nếu bạn đang nhận tensor, mô hình đã biên dịch hoặc trình diễn giải từ LiteRT trong Dịch vụ Play, thì bạn không nên truyền các đối tượng đó đến LiteRT đi kèm hoặc ngược lại.
Nhưng nếu không, việc kết hợp những thứ này sẽ hoạt động tốt.
Được rồi.
Đó là cách xây dựng một ứng dụng mới.
Bây giờ, tôi sẽ nói về cách nâng cấp một ứng dụng hiện có.
Vì vậy, có thể bạn đang có một ứng dụng sử dụng API Trình diễn giải.
Đây là API TFLite cũ hơn, sử dụng trình diễn giải làm lớp chính.
Vì vậy, đó là mã ở bên trái sử dụng API Trình diễn giải, còn ở bên phải, bạn sẽ thấy mã API CompiledModel mới.
// Dependencies (Gradle):
// play-services-tflite-java and/or litert (bundled)
// Init
TfLite.initialize(context).await()
// Load
val interpreterOptions =
InterpreterApi.Options().apply {
runtime = TfLiteRuntime.FROM_SYSTEM_ONLY
}
val interpreter =
InterpreterApi.create(modelFile, interpreterOptions)
// Prepare inputs/outputs
val inputs = …
val outputs = …
// Execute
interpreter.run(inputs, outputs)// Dependencies (Gradle):
// play-services-litert
// Init
val environment =
LiteRt.initialize(context).await()
// Load
val modelOptions = CompiledModel.Options(Accelerator.CPU)
val model =
CompiledModel.create(modelPath, modelOptions, environment)
// Prepare inputs/outputs
val inputBuffers = model.createInputBuffers()
val outputBuffers = model.createOutputBuffers()
// Execute
model.run(inputBuffers, outputBuffersVì vậy, bạn chỉ cần thay đổi TfLite.initialize thành LiteRt.initialize và giờ đây, thao tác này sẽ trả về một môi trường.
Sau đó, bạn truyền môi trường đến CompiledModel.create.
Vì vậy, đó là một thay đổi nhỏ, không làm tăng kích thước tệp APK.
Và bạn sẽ thấy, trong trang trình bày tiếp theo, chúng tôi sẽ hướng dẫn bạn cách thực hiện bằng GPU và đó chỉ là một lựa chọn khác.
Vì vậy, đây là mã bổ sung mà bạn cần để bật GPU.
// Dependencies (Gradle):
// play-services-tflite-java and/or litert (bundled)
// Init
val initOptions = TfLiteInitializationOptions.builder()
.setEnableGpuDelegateSupport(true).build()
TfLite.initialize(context, initOptions).await()
val useGpu =
TfLiteGpu.isGpuDelegateAvailable(context).await()
// Load
val interpreterOptions =
InterpreterApi.Options().apply {
runtime = TfLiteRuntime.FROM_SYSTEM_ONLY
}
if (useGpu) {
interpreterOptions.addDelegateFactory(
GpuDelegateFactory());
}
val interpreter =
InterpreterApi.create(modelFile, interpreterOptions)
// Prepare inputs/outputs
val inputs = …
val outputs = …
// Execute
interpreter.run(inputs, outputs)// Dependencies (Gradle):
// play-services-litert
// Init
val initOptions = LiteRtInitializationOptions.builder()
.setEnableGpu(true).build()
val environment = LiteRt.initialize(context, initOptions).await()
// Load
val modelOptions =
CompiledModel.Options(Accelerator.CPU, Accelerator.GPU)
val model =
CompiledModel.create(modelPath, modelOptions, environment)
// Prepare inputs/outputs
val inputBuffers = model.createInputBuffers()
val outputBuffers = model.createOutputBuffers()
// Execute
model.run(inputBuffers, outputBuffers)Như bạn thấy, mã trong API mới để bật GPU đơn giản hơn một chút so với mã trước đó.
Vì vậy, lệnh gọi đầu tiên đến setEnableGpu trong các tuỳ chọn khởi chạy LiteRT mà bạn truyền đến LiteRt.initialize sẽ khiến mã cho trình tăng tốc GPU được tải vào ứng dụng của bạn.
Sau đó, khi bạn tạo modelOptions và truyền các giá trị đó đến CompiledModel.create, bạn sẽ chỉ định trình tăng tốc nào sẽ được dùng cho một mô hình cụ thể, cho dù bạn muốn mô hình khác chỉ chạy trên GPU, hay GPU có CPU dự phòng, hay chỉ trên CPU.
Được rồi.
Đúng vậy, như bạn có thể thấy, việc bật GPU sẽ đơn giản hơn nhiều với API mới.
Vậy bạn thực sự nhận được gì?
Chintan sẽ cho bạn biết.
Được rồi.
Cảm ơn Fergus.
Vậy, hãy nói về những gì chúng ta nhận được, đúng không?
Như vậy, hãy nhớ rằng chúng ta đã nói về việc xây dựng một ứng dụng, vậy hãy xem chúng ta thực sự đã xây dựng được gì nhé.
Đó là tôi, và những gì chúng tôi đã làm ở đây là chúng tôi đã sử dụng Bộ công cụ học máy để tìm tôi, vì vậy, việc phân đoạn đang được thực hiện bằng một API chìa khoá trao tay như Bộ công cụ học máy.
Vậy là mô hình đã tìm thấy đầu của tôi ở đó.
Sau đó, LiteRT sử dụng một mô hình khác tương tự như mô hình biến đổi phong cách để vẽ nền.
Và những lợi ích khác như chúng tôi đã đề cập là bạn tiết kiệm được khoảng 8 MB dung lượng, giờ đây bạn có một thời gian chạy được dùng cho tất cả ứng dụng của mình, hoặc ít nhất là như thời gian chạy được chia sẻ ở đây, và bạn nhận được các bản cập nhật tự động, đồng thời bạn cũng có GPU nhanh hơn giúp bạn đạt được gần 30 khung hình/giây cho nội dung cần được hiển thị theo thời gian thực để mang lại trải nghiệm phong phú cho người dùng.
Một điều tuyệt vời nữa là bạn không cần phải làm tất cả những việc này theo cách thủ công.
Chúng tôi cũng vừa ra mắt một kỹ năng mới trong Android, về cơ bản là kỹ năng Android LiteRT giúp nâng cấp công nghệ học máy trên thiết bị chỉ trong vài phút, đúng không?
Vì vậy, bạn có thể làm một số việc sau: nâng cấp ứng dụng hiện có, tạo một ứng dụng mới, đồng thời nâng cấp ứng dụng để sử dụng tính năng tích hợp mới này của Dịch vụ Play.
Vì vậy, tất cả những điều này đều có sẵn.
Đường liên kết này có trên trang trình bày, trên GitHub và cũng sẽ xuất hiện trong tài liệu cũng như blog của chúng tôi.
Và đúng vậy, điều này cũng sẽ hữu ích cho những ai muốn sớm thực hiện thay đổi.
Sau đây, Fergus sẽ cho chúng ta biết bước tiếp theo.
Vì vậy, chúng tôi cam kết phát triển AI trên thiết bị bằng LiteRT.
Chúng tôi tiếp tục đầu tư đáng kể vào việc cải thiện khả năng tăng tốc GPU và phạm vi bao phủ của mô hình, đồng thời tiếp tục cung cấp các bản cập nhật thường xuyên cho LiteRT 2.x, cả cho LiteRT đi kèm nguồn mở và cho gói LiteRT Maven của Dịch vụ Play (LiteRT trong Dịch vụ Play).
Chúng tôi cũng sẽ tiếp tục cung cấp khả năng tương thích ngược.
Thời gian chạy của Dịch vụ Play sẽ tiếp tục hỗ trợ các ứng dụng được xây dựng bằng SDK cũ.
Vâng.
Bạn biết đấy, điều đó thực sự quan trọng đối với người dùng và cũng thực sự quan trọng đối với chúng tôi.
Đối với SDK LiteRT 1.x, các SDK này hiện đang ở chế độ bảo trì, vì vậy chỉ có các bản sửa lỗi bảo mật quan trọng.
NNAPI (đã ngừng hoạt động từ năm 2024) sẽ bị loại bỏ, có thể là từ năm 2027.
Vì vậy, nếu bạn đang sử dụng NNAPI, vui lòng chuyển sang sử dụng tính năng tăng tốc GPU hoặc tăng tốc NPU bằng LiteRT đi kèm.
Được rồi.
Vâng.
Vì vậy, bạn càng sớm chuyển sang phiên bản 2.x và CompiledModel thì sau này bạn càng ít việc phải làm.
Tóm lại, có 3 điều cần lưu ý.
Vì vậy, hãy xây dựng.
Hãy bắt đầu với Bộ công cụ học máy, và nếu bộ công cụ này đã đáp ứng được nhu cầu của bạn thì thật tuyệt vời.
Nhưng nếu không, hãy sử dụng LiteRT cho các mô hình tuỳ chỉnh của bạn.
Nâng cấp lên LiteRT trong Dịch vụ Google Play để tiết kiệm dung lượng APK và sử dụng thời gian chạy dùng chung.
Ngoài ra, hãy cân nhắc sử dụng API CompiledModel để suy luận GPU nhanh hơn và đơn giản hơn.
Vâng.
Mọi thông tin đều được ghi lại tại trang web tài liệu về LiteRT trên AI Edge theo URL ở đó.
Vậy nên, đúng vậy.
Cảm ơn các bạn đã tham gia cùng chúng tôi. Chúng tôi rất mong được thấy những sản phẩm mà các bạn sẽ tạo ra.
// 1. Configure and create segmenter client
val segmenter = Segmentation.getClient(
SelfieSegmenterOptions.Builder()
.setDetectorMode(
SelfieSegmenterOptions.STREAM_MODE)
.build())
// 2. Prepare image & run inference
fun processFrame(mediaImage: Image) {
val image = InputImage.fromMediaImage(
mediaImage, /* rotationDegrees= */ 0)
segmenter.process(image)
.addOnSuccessListener { mask -> … }
}import litert_torch
model = my_models.Stylizer().eval()
# Convert with torch.export under the hood
edge_model = litert_torch.convert(
model, sample_inputs)
edge_model.export("stylizer_f32.tflite")# Python
# previously ai_edge_quantizer
from litert_quantizer import quantizer, recipe
qt = quantizer.Quantizer("stylizer_f32.tflite")
# int8 weights, float activations
qt.load_quantization_recipe(
recipe.dynamic_wi8_afp32())
qt.quantize().export_model("stylizer_int8.tflite")// Kotlin
// Build once, off the main thread.
private val model: CompiledModel =
CompiledModel.create(
context.assets,
"stylizer_int8.tflite",
// Simple GPU setup!
CompiledModel.Options(Accelerator.GPU),
environment
)
// Reuse buffers across frames.
private val inputBuffers = model.createInputBuffers()
private val outputBuffers = model.createOutputBuffers()
fun stylize(input: FloatArray): FloatArray {
inputBuffers[0].writeFloat(input)
model.run(inputBuffers, outputBuffers) // sync
return outputBuffers[0].readFloat()
}// Easier with CompiledModel API: 3 steps
// 1. app/build.gradle: replace litert with play-services-litert
- implementation 'com.google.ai.edge.litert:litert:...'
+ implementation 'com.google.android.gms:play-services-litert:17.0.0' // also pulls in litert-api// 2. Initialize the LiteRT Environment from Play services (context = your Activity)
- val environment = Environment.create(...)
+ import com.google.android.gms.litert.LiteRt
+ val environment = LiteRt.initialize(context).await()
// 3. Pass environment whenever you call CompiledModel.create
// That's it! The rest of your app uses the normal CompiledModel APIs from litert-api.// Dependencies (Gradle):
// play-services-tflite-java and/or litert (bundled)
// Init
TfLite.initialize(context).await()
// Load
val interpreterOptions =
InterpreterApi.Options().apply {
runtime = TfLiteRuntime.FROM_SYSTEM_ONLY
}
val interpreter =
InterpreterApi.create(modelFile, interpreterOptions)
// Prepare inputs/outputs
val inputs = …
val outputs = …
// Execute
interpreter.run(inputs, outputs)// Dependencies (Gradle):
// play-services-litert
// Init
val environment =
LiteRt.initialize(context).await()
// Load
val modelOptions = CompiledModel.Options(Accelerator.CPU)
val model =
CompiledModel.create(modelPath, modelOptions, environment)
// Prepare inputs/outputs
val inputBuffers = model.createInputBuffers()
val outputBuffers = model.createOutputBuffers()
// Execute
model.run(inputBuffers, outputBuffers// Dependencies (Gradle):
// play-services-tflite-java and/or litert (bundled)
// Init
val initOptions = TfLiteInitializationOptions.builder()
.setEnableGpuDelegateSupport(true).build()
TfLite.initialize(context, initOptions).await()
val useGpu =
TfLiteGpu.isGpuDelegateAvailable(context).await()
// Load
val interpreterOptions =
InterpreterApi.Options().apply {
runtime = TfLiteRuntime.FROM_SYSTEM_ONLY
}
if (useGpu) {
interpreterOptions.addDelegateFactory(
GpuDelegateFactory());
}
val interpreter =
InterpreterApi.create(modelFile, interpreterOptions)
// Prepare inputs/outputs
val inputs = …
val outputs = …
// Execute
interpreter.run(inputs, outputs)// Dependencies (Gradle):
// play-services-litert
// Init
val initOptions = LiteRtInitializationOptions.builder()
.setEnableGpu(true).build()
val environment = LiteRt.initialize(context, initOptions).await()
// Load
val modelOptions =
CompiledModel.Options(Accelerator.CPU, Accelerator.GPU)
val model =
CompiledModel.create(modelPath, modelOptions, environment)
// Prepare inputs/outputs
val inputBuffers = model.createInputBuffers()
val outputBuffers = model.createOutputBuffers()
// Execute
model.run(inputBuffers, outputBuffers)