Chuyển đến nội dung chính

AI chạy trên thiết bị trong Flutter: cái gì vừa với một chiếc điện thoại

Lời chào mời thật sự hấp dẫn: không API key, không tính tiền theo token, không vòng gọi mạng, và dữ liệu người dùng không bao giờ rời khỏi máy. Với một ứng dụng ghi chú, một bàn phím, hay bất cứ thứ gì đụng tới hồ sơ sức khoẻ hoặc tài chính, riêng điểm cuối cùng đã đủ quyết định kiến trúc.

Rồi bạn nhìn vào những con số. Một mô hình ngôn ngữ nhỏ đã lượng tử hoá là gói tải về một tới ba gigabyte, cần giữ phần lớn chỗ đó trong RAM khi chạy, và sinh token với tốc độ khiến một API năm 2019 phải ngượng. Cả hai bức tranh đều đúng. Vấn đề là bức nào áp dụng cho tính năng của bạn.

Cái gì thật sự chạy tốt trên điện thoại

Những tác vụ mà một model nhỏ cục bộ thật sự làm tốt hẹp hơn các bản demo gợi ý, và chúng tụ quanh một tính chất: đầu vào ngắn, đầu ra ngắn, không cần kiến thức về thế giới.

Tác vụKhả thi trên thiết bịVì sao
Phân loại văn bản, nhận diện ý địnhRất tốtModel tí hon, thường còn chẳng phải LLM
Embedding cho tìm kiếm ngữ nghĩa cục bộRất tốtModel nhỏ, chạy một lần mỗi tài liệu, không sinh văn bản
Gợi ý tự hoàn thành, đoán cụm từ tiếp theoTốtĐầu ra ngắn, nhạy độ trễ, hưởng lợi khi chạy cục bộ
Tóm tắt một ghi chú ngắnDùng đượcVài trăm token vào và ra
Chuyển giọng nói thành chữTốtModel chuyên dụng đã chín, runtime tối ưu tốt
Phân loại ảnh, OCRRất tốtKhông phải model ngôn ngữ; đã giải quyết trên thiết bị từ lâu
Chat mởKémNgười dùng so nó với model tiên tiến và nó thua
Bất cứ thứ gì mang tính dữ kiệnKémKiến thức thế giới của model 2B tham số vừa mỏng vừa sai đầy tự tin
Phân tích tài liệu dàiKémCả cửa sổ ngữ cảnh lẫn bộ nhớ đều cạn
Sinh codeKémKhoảng cách chất lượng lớn nhất chính là ở đây

Kiểu hỏng phổ biến nhất không nằm ở kỹ thuật mà nằm ở kỳ vọng. Nếu giao diện trông như một trợ lý chat, người dùng sẽ mang kỳ vọng dành cho model tiên tiến tới một model nhỏ hơn cả nghìn lần. Hãy đóng khung tính năng thật hẹp — “gợi ý thẻ”, “viết lại câu này”, “tìm trong ghi chú của tôi” — và cũng model đó sẽ được đọc là tốt.

Ba con số quyết định tính khả thi

Trước khi viết bất kỳ dòng code nào, hãy đối chiếu tính năng của bạn với chúng:

  1. Dung lượng tải về. Một model 2B tham số lượng tử hoá 4 bit rơi vào tầm vài gigabyte. Bạn không thể đóng gói nó trong bundle ứng dụng: cả hai chợ ứng dụng đều giới hạn thấp hơn nhiều, và một bản cài 2GB giết tỉ lệ chuyển đổi bất kể thế nào. Nó phải là gói tải theo yêu cầu, tức là cần một giao diện cho việc đó, hỗ trợ tải tiếp, và một phương án cho người dùng từ chối tải.
  2. RAM đỉnh. Trọng số model phải nằm trong bộ nhớ suốt quá trình suy luận, cộng với KV cache lớn dần theo độ dài ngữ cảnh. Trên một máy Android tầm trung 4GB, đây mới là ràng buộc thật sự cắn. Vượt quá nó không suy giảm êm ái — hệ điều hành giết ứng dụng của bạn, và giết đúng trên những máy bạn ít kiểm thử nhất.
  3. Token mỗi giây. Tốc độ sinh trên chip di động chỉ nhanh hơn tốc độ đọc của người vài lần trên máy tốt, và chậm hơn trên máy tệ. Cộng với thời gian nạp vài giây khi model nguội, điều này loại bỏ mọi thứ cần cảm giác tức thì, trừ khi bạn giữ model luôn nóng — mà làm vậy lại kéo vấn đề bộ nhớ quay lại.

Hãy đo cả ba trên máy tệ nhất bạn định hỗ trợ, đừng đo trên điện thoại dùng để phát triển. Khoảng cách giữa một flagship hiện tại và một máy Android tầm trung ba năm tuổi lớn hơn mọi tối ưu bạn sẽ áp dụng.

Tầng runtime

Flutter không có engine suy luận sẵn, nên mọi hướng tiếp cận đều đi qua code nền tảng:

  • Google AI Edge (LiteRT và tác vụ LLM inference của MediaPipe) là con đường trực tiếp nhất cho các model họ Gemma trên cả Android và iOS.
  • Gói flutter_gemma trên pub.dev bọc lại stack đó cho Dart, và là đường ngắn nhất tới một bản prototype chạy được. Hãy đọc README của nó để biết nền tảng được hỗ trợ và hình dạng API hiện tại trước khi thiết kế xung quanh nó — các plugin cộng đồng ở mảng này thay đổi rất nhanh.
  • Core ML trên nền tảng Apple cho hiệu suất phần cứng tốt nhất trên iOS, đổi lại là một nhánh code riêng cho Apple và một bước chuyển đổi model.
  • ONNX Runtime là lựa chọn di động nhất nếu bạn đã có model ONNX và cần cả desktop lẫn di động.
  • Method channel tới llama.cpp cho bạn nhiều lựa chọn model nhất và nhiều quyền kiểm soát nhất, kèm nhiều code nền tảng phải bảo trì nhất. Chỉ đáng làm nếu các lựa chọn đóng gói sẵn không hỗ trợ model của bạn.

Chọn cái nào cũng được, nhưng hãy tách nó sau một interface ngay từ ngày đầu:

abstract interface class LocalInference {
  Future<bool> isAvailable();
  Future<void> load({void Function(double progress)? onProgress});
  Stream<String> generate(String prompt, {int maxTokens = 256});
  Future<void> unload();
}

Hai bản cài đặt — một bản thật và một bản dự phòng chạy qua đám mây — nằm sau interface đó là thiết kế sống sót được. Mảng này thay đổi đủ nhanh để runtime bạn chọn hôm nay khó là runtime bạn phát hành sau hai năm, và interface chính là thứ ngăn điều đó thành một cuộc viết lại.

Luồng chạy: phần lập trình viên Flutter hay làm sai

Suy luận là thao tác CPU/GPU chạy dài. Chạy nó trên main thread của nền tảng là bạn đóng băng giao diện; độ giật không hề tinh tế.

  • Suy luận native phải chạy trên luồng nền ở phía native. Isolate của Dart không giúp gì ở đây — công việc không nằm trong Dart.
  • Hãy stream kết quả qua channel theo từng token thay vì trả về một chuỗi hoàn chỉnh, vì đúng những lý do trải nghiệm khiến streaming quan trọng khi gọi API.
  • Mọi xử lý trước và sau ở phía Dart mà tốn kém đo được — tách token, parse, định dạng một kết quả dài — nên nằm trong isolate.
  • Hãy xử lý việc ứng dụng chạy nền: trên iOS, phải lường trước suy luận bị treo, và thiết kế cho tình huống lần sinh dừng giữa chừng và không bao giờ tiếp tục.

Pin và nhiệt là ràng buộc có thật

Suy luận kéo dài là một trong những thứ nặng nhất mà ứng dụng có thể bắt điện thoại làm. Sinh văn bản liên tục làm máy nóng lên thấy rõ và rút pin với tốc độ mà người dùng sẽ quy trách nhiệm cho đúng ứng dụng của bạn — một cách chính xác.

Quan trọng hơn, tải kéo dài kích hoạt giảm xung vì nhiệt, và các con số benchmark của bạn sẽ không còn đúng sau hai phút sử dụng. Hãy đo một workload kéo dài, đừng đo một lần chạy nguội duy nhất.

Các cách giảm nhẹ thực dụng: đừng bao giờ sinh mang tính đầu cơ, chặn cứng độ dài đầu ra, giải phóng model sau một khoảng không hoạt động, và cân nhắc dời việc nặng theo lô — lập chỉ mục cả kho ghi chú, sinh embedding cho mọi tài liệu — sang lúc máy đang sạc và rảnh.

Thiết kế lai thường mới là câu trả lời đúng

Chỉ cục bộ và chỉ đám mây đều tệ hơn phương án ở giữa khá hiển nhiên:

  • Cục bộ cho những việc nhỏ, thường xuyên, riêng tư, nhạy độ trễ — phân loại, embedding, tự hoàn thành, tìm kiếm trên dữ liệu của chính người dùng.
  • Đám mây cho việc khó — tài liệu dài, suy luận thật sự, mọi thứ cần kiến thức cập nhật về thế giới.
  • Cục bộ làm phương án dự phòng khi offline, suy giảm nhưng vẫn dùng được, với giao diện nói thẳng rằng nó đang chạy ở chế độ offline.

Đây chính là quyết định định tuyến giống như khi chọn giữa model API nhỏ và lớn, cộng thêm hai số hạng trong phương trình: đường cục bộ có chi phí biên bằng không và quyền riêng tư tuyệt đối, và nó vẫn dùng được khi không có mạng. Hãy cân những điều đó với một khoảng cách chất lượng lớn hơn nhiều so với giữa hai model đám mây.

Dù bạn xây gì, hãy nói cho người dùng biết chế độ nào đã tạo ra câu trả lời. “Được tạo ngay trên máy bạn” là một điểm đáng quảng cáo khi nó đúng, còn giấu đi sự phân biệt này sẽ biến lợi thế riêng tư thành vấn đề niềm tin ngay lần đầu có người phát hiện một request mạng.

Câu hỏi thường gặp

Tôi có thể đóng gói model trong bundle ứng dụng không?

Chỉ với model thật sự nhỏ — bộ phân loại, model embedding, model giọng nói. Model ngôn ngữ phải tải theo yêu cầu.

Model cục bộ có cần cập nhật không?

Có, và bạn cần một phương án đánh phiên bản cùng di trú cho nó. Hãy tính trước là việc tải về sẽ xảy ra nhiều hơn một lần.

Chạy trên thiết bị thì tự động riêng tư phải không?

Phần suy luận thì đúng. Hãy kiểm tra xem ứng dụng có đang ghi prompt và đầu ra lên analytics không, việc đó âm thầm phá vỡ cam kết.

Còn Flutter web và desktop?

Desktop dễ hơn — nhiều RAM, cắm điện. Web hiện chưa thực tế với model ngôn ngữ; riêng dung lượng tải đã loại rồi.

Kiểm thử việc này trong CI thế nào?

Bạn không thể kiểm thử chất lượng suy luận một cách có ý nghĩa trên máy ảo. Hãy kiểm thử interface bằng bản cài đặt giả, và chạy kiểm tra với model thật trên một dàn nhỏ thiết bị vật lý.


Năng lực runtime, API của các gói và giới hạn nền tảng mô tả ở đây lấy từ tài liệu được liên kết phía trên và thay đổi rất nhanh — hãy kiểm chứng chi tiết hiện hành, nhất là với các gói cộng đồng, trước khi chốt thiết kế. Bảng đánh giá tác vụ, ba con số khả thi, hướng dẫn về luồng chạy và khuyến nghị thiết kế lai là đánh giá của riêng tôi từ việc xây tính năng chạy trên thiết bị bằng Flutter; hãy tự đo trên các máy đích của bạn.


Bài viết gốc đăng tại FlutterCook. Bản trên đó là bản được cập nhật mới nhất.

Nhận xét

Bài đăng phổ biến từ blog này

5 concepts every Flutter dev should know

  Phụ lục: State management architecture Testing IDE Shortcuts Platform channel Maintaining a project Tôi đã làm việc với Flagship trong một thời gian dài, và đây là những điều mà tôi phát hiện ra là điều cần phải có đối với bất kỳ nhà phát triển Flagship nào, về tổng thể nó sẽ khiến bạn trở thành một nhà phát triển Flagship giỏi trong thời gian dài. 1. State management architecture Đây là một trong những chủ đề quan trọng nhất trong cộng đồng thiết bị rung, nó khá quan trọng nếu bạn muốn duy trì một dự án rung kích thước trung bình hoặc lớn. Nó sẽ giúp tạo một dự án suôn sẻ và thêm các tính năng mới một cách hoàn hảo.  2. Testing Đây là một chủ đề duy nhất mà tôi không hiểu tại sao nó lại quan trọng trước đó trong sự nghiệp của tôi, nhưng khi tôi tiến lên trong sự nghiệp của mình và có kinh nghiệm với nhiều dự án và vấn đề xảy ra trong môi trường sản xuất. Tôi đã nhận ra một cách khó khăn, tại sao điều này lại quan trọng như vậy. Nếu bạn vẫn muốn có thêm lý do để cân nhắc thử...

Thiết kế giao diện với DotNetBar (Phần 1)

Đây là phiên bản DotNetBar hỗ trợ C# và Visual Basic https://www.dropbox.com/s/wx80jpvgnlrmtux/DotNetBar.rar  , phiên bản này hỗ trợ giao diện Metro cực kỳ “dễ thương” Các bạn load về và cài đặt, khi cài đặt xong sẽ có source code mẫu của tất cả các control. Để sử dụng được các control của DotNetBar các bạn nhớ add item vào controls box. Thiết kế giao diện với DotNetBar, giao diện sẽ rất đẹp. Link các video hướng dẫn chi tiết cách sử dụng và coding: http://www.devcomponents.com/dotnetbar/movies.aspx Hiện tại DotNetBar có rất nhiều công cụ cực mạnh, trong đó có 3 công cụ dưới đây: DotNetBar for Windows Forms Requires with Visual Studio 2003, 2005, 2008, 2010 or 2012.   DotNetBar for WPF Requires with Visual Studio 2010 or 2012 and Windows Presentation Foundation.   DotNetBar for Silverlight Requires with Visual Studio 2010 or 2012 and Silverlight. Dưới đây là một số hình ảnh về các control trong DotnetBar.   Metro User Interface  controls with Metro Tiles, toolba...

2026 👏 Google miễn phí một năm gói AI Plus cho sinh viên Việt Nam 🇻🇳🇻🇳🇻🇳

Chúc mừng anh em 👏 Google miễn phí một năm gói AI Plus cho sinh viên Việt Nam 🇻🇳🇻🇳🇻🇳 Đối tượng là sinh viên đại học từ 18–24 tuổi (bao gồm sinh viên mới và sinh viên từng dùng gói AI Pro 2025). Lưu ý là cần xác minh tư cách sinh viên hàng năm. Khi nhận gói, anh em có được các ưu đãi sau: 🔖 Nâng cấp bộ nhớ đám mây lên 400GB. 🔖 Nhân đôi hạn mức truy cập mô hình AI. 🔖 Mở quyền trải nghiệm tính năng tạo video bằng Gemini Omni. Lưu ý chương trình chỉ dành cho sinh viên đủ điều kiện. Hạn nhận ưu đãi: 31 tháng 12, 2026. Các bạn cần có phương thức thanh toán hợp lệ khi đăng ký. Google AI Plus sẽ tự động tính phí 132.000 ₫/tháng sau khi thời gian dùng thử kết thúc, trừ phi bạn đã huỷ trước đó. Huỷ bất cứ lúc nào. CÁC BƯỚC THỰC HIỆN CHI TIẾT 🔹Bước 1: Truy cập cổng đăng ký chương trình 🔖 Mở trình duyệt và truy cập vào trang chính thức: gemini.google/students/ 🔖 Đăng nhập vào Tài khoản Google cá nhân của bạn. 🔖 Nhấn vào nút "Claim your student plan at no cost" (hoặc Nhận gó...