Product Management
Đăng nhập
ESC

Nhập từ khóa để tìm kiếm

↑↓ Di chuyển
Enter Mở
ESC Đóng

Bài 3 — Cho agent 'nhìn' trang: DOM, selector & accessibility tree

Đã đọc 0/10 mục · còn khoảng 4 phút
Cách chúng tôi ghi nhận

Một mục được tính là đã đọc khi nó nằm giữa màn hình đủ lâu so với độ dài của nó (bảng và sơ đồ tính một nửa), bạn vẫn đang cuộn hoặc bấm phím, và bạn đã thấy tới cuối mục. Lướt nhanh hoặc để tab mở không được tính. Chúng tôi chỉ lưu thời gian đọc từng mục — không lưu gì khác.

Agent không thể hành động nếu không hiểu trang đang có gì. Bài này dạy cách biểu diễn trạng thái trang cho LLM: khác biệt giữa DOM thô, selector, và accessibility tree — và tại sao cách biểu diễn quyết định độ chính xác.

Ba cách agent "nhìn" một trang

  • Screenshot (pixel): ảnh chụp màn hình. Dùng cho computer-use hoặc khi trang phức tạp về thị giác. Nhược: LLM phải đoán tọa độ, dễ sai, tốn token ảnh.
  • DOM thô (HTML): đầy đủ nhưng khổng lồ, đầy thẻ nhiễu — nhồi hết vào LLM sẽ vượt context và lẫn thông tin.
  • Accessibility tree: cây mô tả các phần tử tương tác (button, link, textbox) kèm nhãn — gọn, có ngữ nghĩa, lý tưởng cho LLM.
# Lấy accessibility tree gọn cho LLM đọc
snapshot = page.accessibility.snapshot()
# -> { role: 'button', name: 'Đăng nhập', ... }

Selector: cách trỏ chính xác vào phần tử

Playwright ưu tiên locator bền vững thay vì CSS/XPath dễ gãy:

page.get_by_role("button", name="Export")      # theo vai trò + nhãn (bền nhất)
page.get_by_label("Email")                      # theo label form
page.get_by_text("Tải xuống")                    # theo text hiển thị
page.locator("#export-btn")                      # theo id (khá bền)
page.locator("div.x1a > span:nth-child(3)")      # CSS sâu (DỄ GÃY)

Thứ tự ưu tiên: role > label > text > id > CSS/XPath. Càng gần cách con người mô tả nút, càng bền khi giao diện đổi.

Gắn nhãn phần tử cho agent chọn

Mẫu phổ biến: đánh số các phần tử tương tác rồi cho LLM chọn theo số — giảm rủi ro so với đoán tọa độ.

[0] button "Đăng nhập"
[1] textbox "Email"
[2] textbox "Mật khẩu"
[3] link "Quên mật khẩu?"
LLM trả về: action=click, index=1  (nhập email)

Các bước xây lớp "quan sát"

  • Sau mỗi hành động, chờ trang ổn định (page.wait_for_load_state).
  • Trích accessibility tree, lọc bỏ phần tử ẩn/không tương tác.
  • Gán index cho từng phần tử còn lại.
  • Kèm URL hiện tại + tiêu đề trang để LLM biết bối cảnh.
  • Nếu trang nặng thị giác (canvas, bản đồ) → bổ sung screenshot.

Khung tư duy: "Ngôn ngữ nào cho tác vụ nào"

Form, bảng, nút rõ ràng      -> accessibility tree (rẻ, chính xác)
Canvas, ảnh, bố cục thị giác  -> screenshot
Hai cái trên đều thiếu        -> kết hợp cả tree + screenshot

Ví dụ cụ thể

Tác vụ "bấm nút Export tháng 6": nếu chỉ dùng screenshot, LLM có thể trả tọa độ lệch 10px và bấm nhầm ô bên cạnh. Dùng accessibility tree, agent thấy rõ [7] button "Export" và chọn index 7 — chính xác, không phụ thuộc độ phân giải.

Kỹ thuật rút gọn trạng thái để tiết kiệm token

Một trang thật có thể có hàng trăm phần tử. Nhồi hết vào prompt vừa đắt vừa nhiễu. Hãy áp dụng các mẹo sau khi xây lớp observe:

- Chỉ giữ phần tử TƯƠNG TÁC (button, link, input, select, checkbox)
- Bỏ phần tử ẩn (display:none, visibility:hidden, opacity:0)
- Cắt bớt nhãn quá dài (giữ ~80 ký tự đầu)
- Gộp nhóm lặp lại (vd 50 dòng bảng -> mô tả "bảng 50 dòng" + vài dòng mẫu)
- Ưu tiên phần tử đang trong viewport nếu trang quá dài

Mục tiêu: cho LLM đủ thông tin để quyết định, không hơn. Trạng thái càng gọn, quyết định càng nhanh, rẻ và ít nhiễu.

Đồng bộ giữa index và hành động

Một lỗi tinh vi: nếu bạn đánh index rồi trang thay đổi (một phần tử mới chèn vào giữa) trước khi agent hành động, index cũ trỏ nhầm phần tử. Cách phòng: chụp lại và đánh index ngay trước mỗi hành động, không tái dùng index từ vòng trước. Luôn giữ ánh xạ index → locator trong cùng một lần observe.

Sai lầm thường gặp

  • Nhồi toàn bộ HTML thô vào LLM: vượt context, tốn tiền, và LLM lạc giữa rừng thẻ.
  • Chỉ dựa vào tọa độ pixel cho web có DOM: mong manh, gãy khi đổi độ phân giải hay zoom.
  • Dùng CSS selector sâu (div>div>span:nth-child(4)): đổi layout một chút là gãy.
  • Không lọc phần tử ẩn: agent chọn nút display:none rồi click thất bại khó hiểu.
  • Quên cập nhật trạng thái sau hành động: agent quyết định dựa trên ảnh cũ của trang.
Đã "nhìn" được, bài sau ta ráp vòng lặp observe–think–act hoàn chỉnh.

Học xong bài này rồi? Tạo tài khoản miễn phí để lưu lại — lần sau vào là biết ngay đang dở ở đâu, và học hết khóa thì có chứng chỉ. Lưu tiến độ của tôi