化腳本到智能體:構(gòu)建能“思考”的瀏覽器AI Agent)
1. 從“一路點(diǎn)到底”到“有腦子的操作”AI Agent與瀏覽器交互的范式轉(zhuǎn)變最近在折騰AI Agent項(xiàng)目時(shí)我發(fā)現(xiàn)一個(gè)挺有意思的現(xiàn)象很多開發(fā)者包括我自己在初期都容易陷入一個(gè)思維定式——把AI Agent操作瀏覽器這件事簡單粗暴地理解為“自動(dòng)化點(diǎn)擊”。我們給Agent一個(gè)目標(biāo)比如“去XX網(wǎng)站搜索某個(gè)商品并比價(jià)”然后Agent就開始執(zhí)行啟動(dòng)瀏覽器、輸入網(wǎng)址、找到搜索框、輸入關(guān)鍵詞、點(diǎn)擊搜索按鈕、滾動(dòng)頁面、抓取價(jià)格信息……整個(gè)過程看起來行云流水代碼跑得飛快。但只要你實(shí)際跑幾次尤其是在稍微復(fù)雜一點(diǎn)的網(wǎng)頁上翻車率會(huì)高得驚人。按鈕沒找到、彈窗沒處理、頁面加載超時(shí)、甚至點(diǎn)到了廣告或者完全無關(guān)的元素都是家常便飯。這讓我開始反思我們是不是把問題想得太簡單了讓AI Agent“接瀏覽器任務(wù)”核心真的只是模擬人類手指去“點(diǎn)”嗎顯然不是。一個(gè)只會(huì)機(jī)械點(diǎn)擊的Agent就像一個(gè)蒙著眼睛在迷宮里亂撞的人效率低下且充滿風(fēng)險(xiǎn)。真正的挑戰(zhàn)在于如何讓Agent具備“理解”和“決策”的能力。它需要“看見”網(wǎng)頁的結(jié)構(gòu)和內(nèi)容理解當(dāng)前所處的“狀態(tài)”判斷下一步最合理的“動(dòng)作”并能夠應(yīng)對(duì)各種“意外”。這遠(yuǎn)不止是自動(dòng)化腳本如Selenium、Playwright的升級(jí)版而是需要引入感知、認(rèn)知和規(guī)劃能力。所以“先別讓它一路點(diǎn)到底”這個(gè)提醒非常關(guān)鍵。它告誡我們在急于實(shí)現(xiàn)功能之前必須先搭建好讓Agent能“聰明”操作的基礎(chǔ)設(shè)施和決策邏輯。這篇文章我就結(jié)合自己踩過的坑和摸索出的經(jīng)驗(yàn)聊聊如何構(gòu)建一個(gè)不只是“會(huì)點(diǎn)”更是“會(huì)想”的瀏覽器AI Agent。2. 超越Selenium為AI Agent配備“眼睛”和“大腦”當(dāng)我們談?wù)揂I Agent操作瀏覽器時(shí)技術(shù)棧的選擇決定了它的能力上限。直接使用傳統(tǒng)的WebDriver如Selenium發(fā)送點(diǎn)擊命令相當(dāng)于只給了Agent一雙“盲手”。它不知道頁面是什么樣子也不知道點(diǎn)擊之后會(huì)發(fā)生什么。因此第一步是升級(jí)它的感知系統(tǒng)。2.1 視覺感知從DOM到屏幕理解的跨越最基礎(chǔ)的感知是獲取網(wǎng)頁的DOM文檔對(duì)象模型。通過瀏覽器開發(fā)者工具協(xié)議如Chrome DevTools Protocol, CDP或Playwright/Puppeteer這類現(xiàn)代庫我們可以輕松獲取到頁面的HTML結(jié)構(gòu)。但這遠(yuǎn)遠(yuǎn)不夠。一個(gè)按鈕可能在DOM里是一個(gè)div也可能是一個(gè)button它的CSS類名可能隨時(shí)變化它的位置可能因?yàn)轫憫?yīng)式布局而移動(dòng)。注意單純依賴XPath或CSS選擇器進(jìn)行元素定位是極其脆弱的。頁面的一次微小改版就可能導(dǎo)致整個(gè)腳本失效。這是“一路點(diǎn)到底”模式最容易崩潰的地方。因此我們需要更魯棒的感知方式視覺特征提取通過CDP截取頁面截圖或利用無頭瀏覽器渲染后的像素信息。結(jié)合計(jì)算機(jī)視覺CV技術(shù)Agent可以“看到”按鈕、輸入框、圖片等視覺元素及其在屏幕上的位置。開源庫如playwright本身就提供了強(qiáng)大的截圖和元素截圖能力。多模態(tài)信息融合將視覺信息與DOM信息、可訪問性樹Accessibility Tree信息結(jié)合起來??稍L問性樹包含了元素的角色role、名稱name、狀態(tài)等信息對(duì)于理解一個(gè)元素的“功能”非常有幫助。例如一個(gè)div在視覺上是一個(gè)按鈕在可訪問性樹中其角色role可能就是button。這為Agent理解“這是一個(gè)可點(diǎn)擊的按鈕”提供了多重證據(jù)。頁面狀態(tài)理解除了元素Agent還需要理解頁面整體狀態(tài)。例如“頁面是否加載完成”、“是否有模態(tài)彈窗遮擋了主要內(nèi)容”、“當(dāng)前URL是否已跳轉(zhuǎn)”。這些狀態(tài)判斷需要綜合網(wǎng)絡(luò)請(qǐng)求狀態(tài)、頁面加載事件、特定元素的存在性等多種信號(hào)。在我的實(shí)踐中我會(huì)采用一個(gè)分層感知策略基礎(chǔ)層通過Playwright同步獲取DOM和基礎(chǔ)元信息。增強(qiáng)層在關(guān)鍵決策點(diǎn)如找不到元素、操作后無預(yù)期反饋觸發(fā)一次全頁面或區(qū)域截圖使用輕量級(jí)的CV模型如基于CLIP的零樣本分類器或OCR工具如Tesseract來輔助識(shí)別。狀態(tài)層維護(hù)一個(gè)簡單的頁面狀態(tài)機(jī)記錄加載狀態(tài)、彈窗狀態(tài)、錯(cuò)誤狀態(tài)等。2.2 認(rèn)知與決策LLM作為“大腦”的集成邏輯有了“眼睛”看到的信息就需要“大腦”來理解并做出決策。這里的大型語言模型LLM扮演著核心角色。但絕不是簡單地把整個(gè)HTML扔給LLM然后問“下一步該點(diǎn)哪里”。那樣做成本高、速度慢且容易受到無關(guān)信息的干擾。一個(gè)高效的架構(gòu)是將任務(wù)分解信息提煉與抽象首先用一個(gè)預(yù)處理模塊從豐富的感知信息中提取出對(duì)決策關(guān)鍵的信息。這包括關(guān)鍵元素列表過濾掉裝飾性的div、span只保留具有交互可能性的元素如按鈕、鏈接、輸入框、下拉菜單。為每個(gè)元素生成一個(gè)簡化的描述例如“一個(gè)位于屏幕中央的藍(lán)色按鈕文本是‘提交訂單’”、“一個(gè)搜索輸入框當(dāng)前內(nèi)容為空”。頁面目標(biāo)摘要用一兩句話描述當(dāng)前頁面的主要功能和用戶可能的目標(biāo)。例如“這是一個(gè)電商商品詳情頁主要操作是選擇規(guī)格、加入購物車或立即購買?!睔v史操作上下文記錄最近幾次操作如“在搜索框輸入了‘手機(jī)’”、“點(diǎn)擊了‘搜索’按鈕”幫助LLM理解當(dāng)前操作所處的流程階段。結(jié)構(gòu)化動(dòng)作空間定義Agent可以執(zhí)行的動(dòng)作類型。這比無限的“點(diǎn)擊坐標(biāo)”要規(guī)范得多。例如CLICK(element_description): 點(diǎn)擊某個(gè)描述的元素。TYPE(element_description, text): 在某個(gè)輸入元素中輸入文本。SCROLL(direction): 向上/下/左/右滾動(dòng)。WAIT(condition): 等待某個(gè)條件如元素出現(xiàn)、頁面加載。NAVIGATE(url): 跳轉(zhuǎn)到新URL。EXTRACT(data_schema): 根據(jù)預(yù)定模式提取數(shù)據(jù)?;谔崾驹~Prompt的決策將提煉后的信息、任務(wù)目標(biāo)、可用動(dòng)作和歷史上下文組織成一個(gè)清晰的提示詞發(fā)送給LLM如GPT-4、Claude 3或本地部署的Llama 3。提示詞的任務(wù)是讓LLM輸出一個(gè)具體的、結(jié)構(gòu)化的動(dòng)作指令。一個(gè)簡化的決策Prompt示例你是一個(gè)網(wǎng)頁操作助手。當(dāng)前任務(wù)是在購物網(wǎng)站找到“無線藍(lán)牙耳機(jī)”并查看第一個(gè)商品詳情。 當(dāng)前頁面狀態(tài)這是一個(gè)電商網(wǎng)站首頁頂部有一個(gè)搜索框下方是商品分類橫幅。 最近操作無。 當(dāng)前頁面關(guān)鍵交互元素 1. 一個(gè)位于頂部的搜索輸入框placeholder是“搜索商品”。 2. 一個(gè)位于搜索框右側(cè)的“搜索”按鈕。 3. 多個(gè)商品分類圖片鏈接如“手機(jī)”、“電腦”、“家電”。 請(qǐng)根據(jù)任務(wù)和當(dāng)前狀態(tài)從以下動(dòng)作中選擇最合適的一個(gè)并嚴(yán)格按格式輸出 動(dòng)作列表[CLICK(元素描述), TYPE(元素描述, 文本), SCROLL(方向), WAIT(條件), NAVIGATE(URL)] 你的輸出格式必須是動(dòng)作: 參數(shù) 例如TYPE: 一個(gè)位于頂部的搜索輸入框placeholder是“搜索商品”, 無線藍(lán)牙耳機(jī)這樣LLM就從一個(gè)需要處理海量HTML的“苦力”變成了一個(gè)基于清晰上下文做選擇題的“指揮官”。決策的準(zhǔn)確性和效率都大幅提升。3. 構(gòu)建穩(wěn)健的操作循環(huán)從單次決策到任務(wù)完成單個(gè)“感知-決策”循環(huán)只是基礎(chǔ)。一個(gè)完整的瀏覽器任務(wù)如“比價(jià)”、“填寫表單”、“下載報(bào)告”由數(shù)十甚至上百個(gè)這樣的循環(huán)組成。如何確保這個(gè)循環(huán)能穩(wěn)健地運(yùn)行到底而不中途“死機(jī)”或“跑偏”是工程上的核心挑戰(zhàn)。3.1 狀態(tài)管理與異常處理機(jī)制“一路點(diǎn)到底”的腳本最怕意外。而一個(gè)智能Agent必須能處理意外。超時(shí)與重試任何操作如點(diǎn)擊、等待元素都必須設(shè)置超時(shí)。超時(shí)后不應(yīng)立即失敗而應(yīng)進(jìn)入異常處理流程。例如點(diǎn)擊后沒有觸發(fā)頁面跳轉(zhuǎn)或元素變化可能是網(wǎng)絡(luò)延遲或前端JS執(zhí)行慢。合理的策略是等待稍長時(shí)間后重新感知頁面狀態(tài)再次評(píng)估。意外彈窗處理Cookie同意框、登錄提醒、廣告彈窗是網(wǎng)頁的“陷阱”。在每次決策前感知層應(yīng)主動(dòng)檢查是否有這類彈窗出現(xiàn)??梢跃S護(hù)一個(gè)“常見干擾彈窗”的特征庫如包含“同意”、“Accept”、“登錄”等關(guān)鍵詞的模態(tài)框一旦檢測到優(yōu)先執(zhí)行關(guān)閉彈窗的操作CLICK(‘同意’按鈕)再繼續(xù)主任務(wù)。導(dǎo)航失敗與頁面錯(cuò)誤操作可能導(dǎo)致404頁面、服務(wù)器錯(cuò)誤5xx或網(wǎng)絡(luò)斷開。Agent需要能識(shí)別這些錯(cuò)誤狀態(tài)通過HTTP狀態(tài)碼、頁面標(biāo)題、特定錯(cuò)誤文本并執(zhí)行預(yù)設(shè)的恢復(fù)策略如返回上一頁、刷新頁面或終止任務(wù)并報(bào)告錯(cuò)誤。在我的架構(gòu)中操作循環(huán)的核心是一個(gè)while循環(huán)其內(nèi)部是一個(gè)狀態(tài)機(jī)# 偽代碼示意 current_state TASK_START task_success False max_steps 100 step_count 0 while not task_success and step_count max_steps: step_count 1 # 1. 感知獲取當(dāng)前頁面信息 page_info perceive_page(browser) # 2. 檢查異常狀態(tài)彈窗、錯(cuò)誤頁等 if check_for_interruptions(page_info): handle_interruption(page_info, browser) continue # 處理完后重新感知 # 3. 決策基于任務(wù)和當(dāng)前狀態(tài)決定下一步動(dòng)作 action llm_decision_maker(task_goal, page_info, action_history) # 4. 執(zhí)行動(dòng)作 result execute_action(action, browser) # 5. 驗(yàn)證與狀態(tài)更新 if verify_action_result(result, task_goal): # 動(dòng)作達(dá)到預(yù)期子目標(biāo) update_task_progress() if is_task_complete(): task_success True else: # 動(dòng)作未達(dá)到預(yù)期記錄并可能進(jìn)入恢復(fù)流程 handle_failed_action(action, result) # 6. 等待頁面穩(wěn)定短延遲 wait_for_page_stability()3.2 動(dòng)作執(zhí)行的可靠性與精確性即使決策正確執(zhí)行也可能出問題。CLICK動(dòng)作失敗的一個(gè)常見原因是元素定位不準(zhǔn)?;旌隙ㄎ徊呗圆灰灰蕾囈环N定位器。優(yōu)先使用role、name等可訪問性屬性其次是穩(wěn)定的id最后才是XPath或CSS selector。Playwright提供了get_by_role(),get_by_text(),get_by_label()等語義化定位方法比純XPath健壯得多。執(zhí)行前再確認(rèn)在發(fā)出點(diǎn)擊命令前可以再次檢查該元素是否依然可見、可點(diǎn)擊。這可以避免因頁面動(dòng)態(tài)變化而導(dǎo)致的“StaleElementReferenceException”元素過期錯(cuò)誤。智能等待執(zhí)行點(diǎn)擊、輸入等操作后頁面通常會(huì)發(fā)生改變。使用Playwright的wait_for_load_state(‘networkidle’)或等待特定元素出現(xiàn)/消失比固定的sleep時(shí)間更可靠。實(shí)操心得對(duì)于關(guān)鍵操作如提交訂單、支付確認(rèn)我會(huì)在動(dòng)作執(zhí)行后設(shè)置一個(gè)更長的“觀察期”并主動(dòng)感知頁面尋找“操作成功”或“操作失敗”的明確反饋元素如“訂單提交成功”提示框、錯(cuò)誤信息文本。這比單純等待頁面跳轉(zhuǎn)更穩(wěn)妥。4. 任務(wù)規(guī)劃與分解讓Agent知其所以然一個(gè)復(fù)雜的瀏覽器任務(wù)比如“預(yù)訂下周五從北京到上海的最便宜航班”如果直接丟給Agent它大概率會(huì)不知所措。我們需要教會(huì)Agent如何分解任務(wù)。4.1 高層任務(wù)規(guī)劃器在核心的“感知-決策”循環(huán)之上需要一個(gè)更高層的“規(guī)劃器”。這個(gè)規(guī)劃器本身也可以由LLM驅(qū)動(dòng)。它的輸入是用戶的自然語言指令輸出是一個(gè)可執(zhí)行的任務(wù)步驟列表或稱為子目標(biāo)序列。用戶指令“幫我預(yù)訂下周五從北京到上海的最便宜航班?!?規(guī)劃器輸出 1. 打開攜程旅行網(wǎng)首頁。 2. 在航班搜索區(qū)域設(shè)置出發(fā)城市為“北京”到達(dá)城市為“上?!比掌跒椤跋轮芪濉背丝蜑?成人。 3. 點(diǎn)擊“搜索”按鈕。 4. 在搜索結(jié)果頁將所有航班按價(jià)格從低到高排序。 5. 選擇價(jià)格最低的航班不考慮時(shí)間。 6. 進(jìn)入該航班的詳情頁。 7. 點(diǎn)擊“預(yù)訂”按鈕。 8. 在預(yù)訂頁面填寫乘機(jī)人信息使用預(yù)設(shè)模板。 9. 提交訂單。這個(gè)規(guī)劃不需要非常精確到每個(gè)DOM元素它提供的是戰(zhàn)略方向。核心的“感知-決策”循環(huán)則負(fù)責(zé)戰(zhàn)術(shù)執(zhí)行完成每一個(gè)子目標(biāo)。當(dāng)戰(zhàn)術(shù)執(zhí)行遇到無法逾越的障礙時(shí)例如頁面改版導(dǎo)致找不到排序按鈕可以將問題反饋給規(guī)劃器請(qǐng)求調(diào)整計(jì)劃。4.2 動(dòng)態(tài)規(guī)劃與 replanning計(jì)劃趕不上變化。Agent必須具備動(dòng)態(tài)重新規(guī)劃的能力。這可以通過幾種方式實(shí)現(xiàn)子目標(biāo)失敗重試如果完成一個(gè)子目標(biāo)如“點(diǎn)擊排序按鈕”多次失敗規(guī)劃器可以嘗試替代方案如“先提取所有航班價(jià)格信息在內(nèi)存中排序”。條件分支規(guī)劃器在制定計(jì)劃時(shí)可以預(yù)設(shè)條件分支。例如“如果搜索結(jié)果多于20條則先使用‘價(jià)格篩選’功能否則直接提取所有結(jié)果”。人類在環(huán)Human-in-the-loop對(duì)于關(guān)鍵決策點(diǎn)或無法處理的異常Agent可以暫停并生成一個(gè)清晰的問題向人類求助。例如“找到了三個(gè)‘預(yù)訂’按鈕分別位于頁面頂部、中部和底部我應(yīng)該點(diǎn)擊哪一個(gè)”。5. 安全、倫理與效率的邊界思考讓AI Agent自由操作瀏覽器如同賦予它一把鑰匙我們必須明確邊界在哪里。5.1 安全與權(quán)限沙箱最小權(quán)限原則運(yùn)行Agent的瀏覽器環(huán)境應(yīng)該是一個(gè)干凈的、隔離的配置文件或用戶數(shù)據(jù)目錄。不要使用存有重要密碼、Cookie的主瀏覽器配置文件。操作限制明確禁止某些危險(xiǎn)操作如下載可執(zhí)行文件、訪問file://協(xié)議下的本地敏感文件、進(jìn)行金融轉(zhuǎn)賬等。可以在動(dòng)作執(zhí)行層進(jìn)行過濾。請(qǐng)求限流對(duì)訪問同一網(wǎng)站的頻率進(jìn)行限制避免對(duì)目標(biāo)服務(wù)器造成DDoS攻擊也防止自己的IP被封鎖。5.2 倫理與合規(guī)性尊重robots.txtAgent應(yīng)首先檢查目標(biāo)網(wǎng)站的robots.txt文件尊重網(wǎng)站所有者設(shè)置的爬蟲規(guī)則。對(duì)于明確禁止爬取或自動(dòng)訪問的頁面應(yīng)停止任務(wù)。識(shí)別驗(yàn)證碼遇到驗(yàn)證碼時(shí)應(yīng)停止嘗試并上報(bào)而不是試圖繞過??梢钥紤]集成合規(guī)的人工打碼服務(wù)或直接終止任務(wù)。數(shù)據(jù)使用通過Agent獲取的數(shù)據(jù)其使用范圍必須符合網(wǎng)站的服務(wù)條款及相關(guān)法律法規(guī)。5.3 性能與成本優(yōu)化無頭模式與資源控制在不需要視覺感知的子任務(wù)中使用無頭Headless模式可以大幅節(jié)省內(nèi)存和CPU。合理配置瀏覽器啟動(dòng)參數(shù)禁用圖片、CSS甚至JavaScript如果任務(wù)不需要。LLM調(diào)用優(yōu)化這是主要的成本中心??梢酝ㄟ^以下方式優(yōu)化緩存對(duì)相同的頁面狀態(tài)和決策請(qǐng)求緩存LLM的回復(fù)。小模型分工使用小型、快速的模型如小型LLM或?qū)iT訓(xùn)練的模型處理常見的、模式化的決策如“點(diǎn)擊登錄按鈕”只有遇到復(fù)雜情況時(shí)才調(diào)用大模型。提示詞壓縮精心設(shè)計(jì)提示詞去除冗余信息使用更緊湊的格式描述頁面元素。構(gòu)建一個(gè)真正“有腦子”的瀏覽器AI Agent是一個(gè)融合了Web自動(dòng)化、計(jì)算機(jī)視覺、大語言模型和軟件工程的多層次挑戰(zhàn)。它的目標(biāo)不是替代Selenium而是在其之上構(gòu)建一個(gè)能理解、能思考、能應(yīng)對(duì)不確定性的智能體。從“一路點(diǎn)到底”的自動(dòng)化腳本升級(jí)到“觀察-思考-行動(dòng)”的智能循環(huán)這中間的每一步都需要我們對(duì)網(wǎng)頁交互的本質(zhì)、AI的能力邊界以及系統(tǒng)的穩(wěn)健性有更深的理解。這條路還很長但每解決一個(gè)像“彈窗處理”或“動(dòng)態(tài)元素定位”這樣具體的問題我們就離那個(gè)能真正像人一樣瀏覽網(wǎng)頁的智能助手更近了一步。