- API web gửi yêu cầu ngôn ngữ tự nhiên tới Gemini Nano được tích hợp trong Chrome, có thể dùng cho các tác vụ như hỏi đáp, phân loại, lọc nội dung, trích xuất lịch trình và trích xuất liên hệ
- Trước khi dùng cần tải riêng mô hình, và chỉ hoạt động khi đáp ứng các điều kiện chạy như OS được hỗ trợ, dung lượng lưu trữ, GPU hoặc bộ nhớ CPU
- Có thể kiểm tra khả năng sử dụng phiên bằng
LanguageModel.availability(), sau đó chuẩn bị bằng create(), và dùng initialPrompts·append()·clone() để tiếp nối hoặc phân nhánh ngữ cảnh
- Đầu vào có thể nhận text, image, audio nhưng đầu ra hiện chỉ hỗ trợ text;
prompt() trả về phản hồi hoàn chỉnh còn promptStreaming() trả về phản hồi dạng stream
- Cung cấp mô hình thực thi để xử lý AI on-device ngay trong trình duyệt, bao gồm đầu ra có cấu trúc dựa trên
responseConstraint, quản lý cửa sổ ngữ cảnh, chính sách quyền hạn và xử lý đa phương thức
Tổng quan
- Đây là API hoạt động bằng cách gửi yêu cầu ngôn ngữ tự nhiên tới Gemini Nano tích hợp trong Chrome, phù hợp cho các trường hợp như hỏi đáp trên trang web, phân loại bài viết, lọc nội dung, trích xuất lịch trình và trích xuất liên hệ
- Dù Chrome đã tích hợp API, mô hình vẫn cần tải riêng; trước lần sử dụng đầu tiên cần xem Google's Generative AI Prohibited Uses Policy
- Trước khi dùng AI tạo sinh, nên tham khảo People + AI Guidebook
- Có thể nhận typing cho TypeScript qua gói @types/dom-chromium-ai
- Nhà phát triển Chrome Extensions cần xóa quyền origin trial đã hết hạn
aiLanguageModelOriginTrial
Phần cứng và điều kiện chạy
- Prompt API·Summarizer API·Writer API·Rewriter API·Proofreader API chỉ hoạt động trên Chrome khi đáp ứng các điều kiện nhất định
- Hệ điều hành được hỗ trợ là Windows 10/11, macOS 13+, Linux và ChromeOS; với ChromeOS chỉ hỗ trợ trên thiết bị Chromebook Plus từ Platform 16389.0.0 trở lên
- Chrome for Android, iOS và ChromeOS trên thiết bị không phải Chromebook Plus hiện chưa hỗ trợ API dựa trên Gemini Nano
- Dung lượng lưu trữ yêu cầu ít nhất 22GB trống trên volume chứa profile Chrome
- Mô hình có thể chạy bằng GPU hoặc CPU
- GPU cần VRAM hơn 4GB
- CPU cần RAM từ 16GB và ít nhất 4 nhân CPU
- Prompt API dùng đầu vào âm thanh bắt buộc cần GPU
- Mạng chỉ cần kết nối không giới hạn hoặc không tính phí theo dung lượng khi tải mô hình lần đầu
- Sau đó việc dùng mô hình không cần kết nối mạng
- Dữ liệu khi dùng mô hình sẽ không được gửi tới Google hay bên thứ ba
- Kích thước mô hình có thể thay đổi theo các bản cập nhật trình duyệt; kích thước hiện tại có thể xem tại
chrome://on-device-internals
- Nếu sau khi tải xong mà dung lượng trống giảm xuống dưới 10GB, mô hình sẽ bị xóa khỏi thiết bị và sẽ được tải lại khi điều kiện được đáp ứng trở lại
Bắt đầu sử dụng và chuẩn bị mô hình
- Có thể kiểm tra khả năng sử dụng bằng
LanguageModel.availability()
availability() phải nhận cùng các tùy chọn sẽ được truyền sau này vào prompt() hoặc promptStreaming()
- Một số mô hình có thể không hỗ trợ một số modality hoặc ngôn ngữ nhất định, nên việc khớp tùy chọn là rất quan trọng
- Việc tải mô hình và tạo phiên bắt đầu bằng
create() sau khi xác nhận user activation
- Nếu đang tải xuống, nên nhận sự kiện tiến trình để thông báo tình trạng tải cho người dùng
- Trên localhost có thể bật cờ Chrome để dùng API AI tích hợp
chrome://flags/#optimization-guide-on-device-model
chrome://flags/#prompt-api-for-gemini-nano-multimodal-input
- Sau đó cần Relaunch hoặc khởi động lại Chrome
- Nếu gặp lỗi có thể tham khảo khắc phục sự cố localhost
Tạo phiên và thiết lập cơ bản
- Phiên được tạo bằng
LanguageModel.create()
- Trong Prompt API cho Chrome Extensions, có thể điều chỉnh topK và temperature theo từng phiên bằng tùy chọn
params() trả về defaultTopK, maxTopK, defaultTemperature, maxTemperature
- Khi khởi tạo phiên mới,
topK và temperature phải hoặc cùng được chỉ định, hoặc cùng bị bỏ qua
create() có thể nhận AbortSignal qua trường signal để hủy phiên
Ngữ cảnh và cấu hình prompt
- Có thể đưa ngữ cảnh hội thoại trước đó vào bằng
initialPrompts để tiếp tục phiên đã lưu sau khi khởi động lại trình duyệt
- Mảng prompt có thể đồng thời chứa các vai trò
system, user, assistant
- Nếu đặt
prefix: true cho tin nhắn assistant cuối cùng, có thể điền sẵn một phần phản hồi để dẫn mô hình ra đúng định dạng đầu ra mong muốn
- Ví dụ có thể điền sẵn chuỗi mở đầu của code block TOML để cố định định dạng đầu ra
- Sau khi tạo phiên có thể dùng
append() để nạp thêm ngữ cảnh trước
- Khác với
initialPrompts, cách này cho phép tiếp tục tích lũy ngữ cảnh sau khi phiên đã được tạo
append() chỉ hoàn tất sau khi prompt được xác thực, xử lý và thêm vào
- Nếu prompt không thể thêm, promise sẽ bị từ chối
Modality đầu vào/đầu ra và đa ngôn ngữ
- Khi tạo phiên có thể đặt định dạng và ngôn ngữ đầu vào/đầu ra dự kiến bằng
expectedInputs và expectedOutputs
type của expectedInputs hỗ trợ text, image, audio
type của expectedOutputs hiện chỉ cho phép text
- Ngôn ngữ được thiết lập bằng mảng
languages, và Prompt API nhận "en", "ja", "es"
- Hỗ trợ thêm ngôn ngữ đang được phát triển
- Ở phía đầu vào có thể đưa ngôn ngữ của system prompt và một hoặc nhiều ngôn ngữ của user prompt
- Ở phía đầu ra có thể chỉ định một hoặc nhiều ngôn ngữ đầu ra
- Khi gặp đầu vào hoặc đầu ra không được hỗ trợ, có thể phát sinh DOMException
"NotSupportedError"
Đầu vào đa phương thức
- Có thể dùng cho các tác vụ như phiên âm âm thanh hoặc tạo mô tả ảnh, caption, alt text
- Demo liên quan
- Đầu vào âm thanh hỗ trợ các kiểu sau
- Đầu vào hình ảnh hỗ trợ các kiểu sau
- Trong ví dụ, hệ thống đưa đồng thời
Blob ảnh và HTMLCanvasElement để so sánh hai tư liệu hình ảnh, rồi tiếp tục nhận phản hồi giọng nói của người dùng bằng AudioBuffer
Đầu ra có cấu trúc và ràng buộc
- Có thể dùng đầu ra có cấu trúc bằng cách đưa JSON Schema vào
responseConstraint của prompt() hoặc promptStreaming()
- Có thể xem tính năng liên quan tại structured output
- Ví dụ đưa vào schema boolean để buộc mô hình chỉ trả lời
true hoặc false cho việc bài đăng có liên quan đến gốm hay không
- Khi triển khai cũng có thể đưa JSON Schema hoặc regex vào như một phần của thông điệp; trong trường hợp đó nó sẽ dùng một phần của context window
- Nếu truyền tùy chọn
responseConstraint vào session.measureContextUsage(), có thể đo xem điều kiện ràng buộc tiêu tốn bao nhiêu ngữ cảnh
- Có thể tránh hành vi này bằng tùy chọn
omitResponseConstraintInput
- Trong trường hợp đó, nên kèm hướng dẫn về định dạng đầu ra mong muốn ngay trong prompt
Cách thực thi prompt
- Nếu dự kiến phản hồi ngắn, dùng
prompt() để nhận kết quả hoàn chỉnh trong một lần
- Nếu dự kiến phản hồi dài, dùng
promptStreaming() để nhận kết quả từng phần qua stream
promptStreaming() trả về ReadableStream
- Cả
prompt() và promptStreaming() đều có thể nhận signal làm tham số thứ hai để hủy prompt đang chạy
Quản lý phiên
- Mỗi phiên giữ ngữ cảnh của cuộc hội thoại, nên các tương tác trước đó sẽ ảnh hưởng tới phản hồi sau này
- Mỗi phiên có số token tối đa có thể xử lý, và có thể kiểm tra mức dùng hiện tại cùng giới hạn qua
session.contextUsage và session.contextWindow
- Nếu cửa sổ ngữ cảnh bị tràn bởi prompt mới, phần đầu của cuộc hội thoại ngoại trừ system prompt sẽ bị xóa theo từng cặp hỏi-đáp để giải phóng chỗ
- Có thể phát hiện tình huống này qua sự kiện
contextoverflow của phiên
- Nếu ngay cả khi xóa lịch sử hội thoại vẫn không đủ token,
prompt() hoặc promptStreaming() sẽ thất bại với QuotaExceededError, và sẽ không có gì bị xóa
requested: số token mà đầu vào chiếm dụng
contextWindow: số token khả dụng
- Có thể tham khảo thêm tại session management
Sao chép và kết thúc phiên
- Có thể dùng
clone() để sao chép phiên hiện có và tạo nhánh hội thoại
- Phiên được sao chép sẽ giữ nguyên ngữ cảnh hiện có và các prompt ban đầu
clone() cũng có thể nhận AbortSignal qua trường signal
- Nếu không còn cần phiên nữa, có thể giải phóng tài nguyên bằng
destroy()
- Khi phiên đã bị hủy, nó sẽ không thể dùng tiếp và các tác vụ đang chạy cũng bị dừng
- Vì việc tạo phiên có thể tốn thời gian, nếu dự định gửi prompt thường xuyên thì nên giữ lại phiên
Chính sách quyền và giới hạn môi trường thực thi
- Mặc định, Prompt API chỉ dùng được trong window cấp cao nhất và các iframe cùng origin với nó
- Với iframe cross-origin, có thể ủy quyền truy cập bằng thuộc tính Permission Policy
allow="language-model"
- Hiện tại Prompt API không dùng được trong Web Workers
- Vì việc xác định tài liệu chịu trách nhiệm kiểm tra trạng thái permissions policy cho từng worker là phức tạp
Demo và tài liệu tham khảo
- Demo ứng dụng web
- Cũng có extension demo để thử nghiệm cho Chrome Extensions
Hiệu năng và phản hồi
- Prompt API cho web vẫn đang trong quá trình phát triển
- Để đạt hiệu năng tối ưu, nên tham khảo các best practice của session management
- Các kênh phản hồi triển khai
1 bình luận
Ý kiến trên Hacker News
API này có vẻ cực kỳ hợp với ý tưởng de-snarkifier mà tôi đã nghĩ đến từ lâu
Mạng xã hội có thể kích thích trí tuệ và cũng có thứ để học, nhưng rất dễ bị cuốn vào cãi vã ý thức hệ và flame war dù mình không muốn. Việc hao tổn cảm xúc để cãi nhau với người lạ trên internet gần như là một sự lãng phí vốn con người
Nếu có API như thế này, có lẽ có thể làm một tiện ích mở rộng trình duyệt để trước khi hiển thị bài viết, nó chỉ làm dịu những cách diễn đạt công kích hoặc mỉa mai, còn thông tin thực tế thì vẫn giữ nguyên. Thậm chí còn có thể đi xa hơn, biến giọng điệu càng hung hăng thì lại càng nghe lố bịch hoặc kém năng lực
Như vậy người đọc sẽ được bảo vệ khỏi những lời công kích cá nhân từ người lạ, còn người viết cũng không còn động lực cư xử thô lỗ. Nếu ai cũng dùng bộ lọc như vậy thì cũng chẳng còn lý do để ganh đua xem ai cay độc hơn
Vẫn đủ dinh dưỡng, nhưng cảm giác là chẳng có gì đặc biệt ngon miệng
Điều tôi muốn là loại sạch tiêu đề câu click và quảng cáo, chỉ hiện các tiêu đề khô khan mang tính sự thật
Với bất kỳ chủ đề nào, chỉ cần một bài cốt lõi và vài bình luận thực sự có giá trị là đủ, còn lại phần lớn chỉ là nhiễu mà tôi không muốn xem
Tình trạng mạng xã hội bây giờ tệ đến mức tôi gần như không dùng nữa, và HN từng là ngoại lệ duy nhất, nhưng giờ ở đây cũng có vẻ đang đi theo hướng tương tự vì AI bão hòa. Dù vậy, cứ cách vài tuần tôi vẫn lãng phí vài tiếng ở đây, và tôi muốn cắt hẳn cả điều đó
Lý tưởng nhất là lọc hoặc tóm tắt để loại bỏ 98% nội dung, và theo thời gian internet chỉ còn là thứ tôi dùng khi chủ động đi tìm kiếm. Về cơ bản tôi muốn loại bỏ phần lớn tính giải trí của internet để dồn thời gian và năng lượng về cho đời thực và các nguồn chất lượng cao như sách
Tiện ích này là một công cụ crowdsourcing nhằm giảm bớt tính giật gân, nhưng tôi có cảm giác một số người đóng góp hàng đầu có thể là bot LLM
Tuy vậy, những thứ như thế này khi va vào thực tế thì rất khó lường, và kể cả có thành công thì cũng có khả năng vận hành khá khác với cách người ta tưởng tượng ban đầu
Tôi không nhịn được nên đã vội làm một nguyên mẫu Snarknada, đồng thời xem xét cả mô hình độ trễ thấp lẫn khả năng về độ chính xác
Đây chính xác là lý do tôi cho rằng on-device là phù hợp cho kiểu use case này. Nếu làm dịu cả một feed cuộn vô tận bằng API đám mây thì chi phí token sẽ lớn đến mức nhà phát triển khó mà gánh nổi. Chưa kể việc người dùng không muốn gửi feed cá nhân hay DM của họ lên máy chủ bên thứ ba chỉ để chỉnh lại tông giọng cũng là điều hoàn toàn dễ hiểu
Nếu đưa việc này vào trong thiết bị, Semantic Mutation tần suất cao có thể lần đầu trở nên khả thi cả về chi phí lẫn kỹ thuật. Nếu ai đó làm thứ này nghiêm túc hơn cái nguyên mẫu PM mang tính đồ chơi của tôi và gặp phải những điểm ma sát cụ thể, tôi rất muốn được nghe. Điều đó sẽ giúp ích cho việc ưu tiên roadmap
[1]: Nếu bạn dùng coding agent (Cursor, Claude Code, v.v.) thì tôi khuyên nên trỏ đến https://www.npmjs.com/package/built-in-ai-skills-md-agent-md. Nhiều model hiện vẫn được huấn luyện trên namespace window.ai đã lỗi thời, nên file skill này giúp chúng dùng đúng API hiện tại
Tôi là người dẫn dắt công việc thiết kế API này, và trước khi nghỉ hưu tôi cũng đã viết một bài tổng hợp các cân nhắc thiết kế liên quan
https://domenic.me/builtin-ai-api-design/
Ngoài ra tôi cũng muốn biết liệu khi làm những thứ như thế này, các trình duyệt có đang phối hợp với nhau theo kiểu thực tế công việc, chứ không chỉ ở cấp độ W3C, để căn chỉnh những điểm chung hay không. Suy cho cùng thì ngành này cũng khá nhỏ
Cái này thực sự chạy được, và tôi đã phát hành nó để dùng cho local inference rồi
Với các tác vụ LLM nhẹ như tìm kiếm, nó dùng được như một kiểu ollama nhà nghèo. Ưu điểm lớn nhất là miễn phí, giữ được quyền riêng tư, và gần như không đòi hỏi người dùng làm gì cả, nên rất phù hợp để mang suy luận cục bộ đến cho người dùng không chuyên kỹ thuật
Tuy nhiên trải nghiệm người dùng thực tế lại không tốt. Kích thước tải model lớn hơn bản thân trình duyệt vài bậc độ lớn, và phải hoàn tất quá trình đó trước khi nhận được token đầu tiên
Việc này có vẻ khó được giải quyết cho đến khi hệ điều hành có thể cung cấp ổn định các model được nhúng sẵn từ trước, và các API kiểu này có thể gắn vào đó
Vấn đề lớn hơn là trên phần lớn PC phổ thông, model vừa quá nhỏ vừa quá chậm. Tôi đã thử thay đổi câu chữ của một game phiêu lưu văn bản infocom theo thời gian thực, nhưng hiện tại trên nhiều PC nó chậm đến mức không thực tế
Nó hơi giống cách bittorrent nhận các mảnh tệp từ nhiều host khác nhau. Các layer dùng chung vẫn phải tải, nhưng thời gian đến token đầu tiên có thể tỷ lệ theo kích thước đang hoạt động chứ không phải toàn bộ kích thước
Dĩ nhiên như vậy sẽ không còn là suy luận offline hoàn toàn nữa, nhưng với một tính năng web trong trình duyệt thì có lẽ đó không phải yếu tố cốt lõi
Tuy nhiên, nếu model lớn hơn trình duyệt rất nhiều và phải tải xuống trước token đầu tiên, tôi muốn hỏi liệu điều đó có nghĩa là lazy download hay không. Nếu người dùng ở lần gọi đầu tiên phải chờ đến khi tải xong thì trải nghiệm có vẻ khá kinh khủng
Tôi cũng tò mò liệu Chrome có hiện kiểu hộp thoại trạng thái tải xuống để bớt gây rối hay không, và dung lượng đĩa thực tế là bao nhiêu
Nhìn bề ngoài thì có vẻ thứ này dùng Gemini Nano, nhưng Gemma 4 E2B/E4B mới nhất trông tốt hơn nhiều, nên trước mắt có thể phát hành bản lượng tử hóa qua tiện ích mở rộng sẽ hợp lý hơn
Nguồn:
Nếu Gemma 4 hoặc Gemini Nano tương ứng vẫn chưa có trong Chrome thì tôi đoán là sắp có rồi
Và bài này được cập nhật lần cuối vào 2025-09-21, khi đó đã là Gemini Nano 3 rồi
Có ghi rằng Prompt API hoạt động bằng cách gửi yêu cầu ngôn ngữ tự nhiên đến Gemini Nano trong trình duyệt
Trên Edge thì có lẽ sẽ là Phi4
Nhìn theo một khía cạnh khác thì đây có vẻ là cách hay để các script JS độc hại đẩy việc sinh token sang cho những khách truy cập không hề hay biết
Cũng sẽ thú vị nếu xem liệu có thể phân tán xử lý bằng mô hình subagent hay cấu trúc kiểu RLM hay không: chia nhỏ prompt lớn thành nhiều phần, gửi tới nhiều trình duyệt, mỗi bên xử lý một mảnh nhỏ rồi ghép thành kết quả hữu ích
Hạ tầng kỹ thuật lẫn kinh doanh cũng sẽ trở nên cực kỳ phức tạp, nên nếu đã muốn đẩy prompt sang trình duyệt người dùng thì có lẽ cứ dùng Chrome API cho đúng cách còn hơn. Tôi cũng nghi ngờ việc offload prompt phía máy chủ sang các model yếu như vậy thực sự sẽ có ý nghĩa trong bao nhiêu trường hợp
Mà nếu thực sự muốn làm thế thì WebGPU cũng đã có từ rất lâu rồi
Đây có vẻ là một bước tiến tới Model API đúng nghĩa, nhưng hiện tại vẫn chỉ là một bước nhỏ
Nó cũng làm tôi nghĩ đến Foundation Models của Apple
Nhiều tích hợp AI tập trung vào giao tiếp văn bản hoặc kiểu chat, nhưng thực tế có không ít phần mềm hưởng lợi ở giao diện phi văn bản
Cuối cùng thì tôi nghĩ OS và trình duyệt nên cung cấp API quản lý model, để ứng dụng có thể truy cập cả model on-device lẫn model từ xa qua một giao diện đơn giản
Nếu điều này được chuẩn hóa đa nền tảng thì sẽ rất tuyệt, và vì còn phải bao gồm cả di động nên về thực tế, phía có thể đẩy mạnh chuyện này nhiều nhất có lẽ vẫn là Apple và Google. Meta có thể đi theo sau, hoặc ngược lại là đi trước cũng không chừng
Điểm cốt lõi là nó không được là thứ chỉ dành cho một model đang được quảng bá cụ thể
Ứng dụng phải có thể truy vấn rồi chọn model phù hợp để dùng
(1) https://developer.apple.com/documentation/foundationmodels
Dĩ nhiên đây vẫn còn là giai đoạn đầu
https://github.com/mozilla/standards-positions/issues/1067
Chúng tôi đang dùng nó để tóm tắt hồi tưởng hackday
https://remotehack.space/previous-hacks/
Chỉ là một script nhỏ đọc RSS feed rồi tạo tóm tắt thành bài viết, nhưng nó khá hợp với website tĩnh. Sau này tôi muốn mở rộng để đặt thêm nhiều câu hỏi khác nhau cho cùng một nội dung
LLM cục bộ mà trình duyệt truy cập được thì tốt cho quyền riêng tư, nhưng nếu mỗi trình duyệt lại gắn API này với một model khác nhau thì cơn ác mộng kiểm thử có lẽ còn tệ hơn bây giờ
Cuối cùng rất có thể phần lớn implementation sẽ căn theo Gemini Nano, nên tôi cũng tự hỏi liệu chuyện này có càng kéo người dùng về phía Chrome hay không
Trên thực tế prompt không hề bất khả tri với model, nên một prompt được tinh chỉnh kỹ cho Gemini Nano 3 v2025 có thể âm thầm giảm hiệu năng trên model phía Gecko. Nhưng API lại thậm chí không cung cấp khả năng dò tìm năng lực để phân nhánh xử lý
Như vậy còn tệ hơn cả WebGL, vốn ít nhất còn cho phép truy vấn hỗ trợ extension. Phát hành tính năng phụ thuộc vào chất lượng prompt của một model bị giấu tên và phiên bản sau trình duyệt cũng giống như phát hành phần mềm mà tính năng bị quyết định bởi cuốn từ điển người dùng đã cài
Tôi nghĩ Gemini Nano không phải open weights như Gemma thì phải
Không biết đã có ai làm chưa, nhưng tôi muốn thử dump trọng số model