頁智能體:從Persona2Web基準(zhǔn)到工程實(shí)踐)
1. 項(xiàng)目概述為什么我們需要一個“帶記憶”的網(wǎng)頁智能體最近幾年AI智能體AI Agent的概念火得一塌糊涂從自動寫代碼的Devin到能處理復(fù)雜任務(wù)的GPT-4o大家都在暢想一個由智能體接管我們?nèi)粘7爆嵐ぷ鞯奈磥?。其中網(wǎng)頁自動化智能體Web Agent是一個特別有潛力的方向——想象一下一個能幫你自動訂機(jī)票、比價購物、整理研究資料甚至管理社交媒體賬號的AI助手這能解放多少生產(chǎn)力。但是如果你真的去試用過市面上一些早期的網(wǎng)頁智能體demo或者嘗試用大語言模型LLM配合瀏覽器自動化工具自己搭建一個大概率會感到一陣失望。你會發(fā)現(xiàn)這些智能體表現(xiàn)得像個“金魚”只有7秒記憶。它可能能很好地執(zhí)行你當(dāng)前的一條指令比如“去電商網(wǎng)站搜索無線耳機(jī)”但它完全“不認(rèn)識”你。它不知道你過去喜歡買哪個品牌、你的預(yù)算是多少、你上次瀏覽時把什么商品加入了購物車又為什么沒買。每一次交互都是孤立的智能體需要你事無巨細(xì)地交代所有背景體驗(yàn)非常割裂遠(yuǎn)談不上“智能”。這正是“Persona2Web”這個基準(zhǔn)測試Benchmark要解決的核心問題。它不是一個具體的工具或產(chǎn)品而是一個用于衡量和推動“個性化網(wǎng)頁智能體”發(fā)展的標(biāo)尺。它的核心命題是一個真正有用的網(wǎng)頁智能體必須具備**基于用戶歷史User History進(jìn)行上下文推理Contextual Reasoning**的能力。這不僅僅是記住你的賬號密碼那么簡單而是要求智能體能夠理解你長期的行為模式、偏好和意圖并在新的任務(wù)中靈活運(yùn)用這些知識。舉個例子一個理想的個性化網(wǎng)頁智能體應(yīng)該能做到場景一你連續(xù)幾周都在旅游網(wǎng)站上搜索“日本京都紅葉季”的攻略和機(jī)票。某天你簡單地說“看看周末有什么好玩的地方”它應(yīng)該能優(yōu)先推薦京都周邊的短途旅行方案而不是泛泛地給你推一些本地公園。場景二你在視頻網(wǎng)站上歷史觀看了大量“Python機(jī)器學(xué)習(xí)教程”。當(dāng)你讓它“找點(diǎn)輕松的視頻看看”時它應(yīng)該能理解你的技術(shù)背景可能會推薦一些科技播客或輕松的編程挑戰(zhàn)視頻而不是完全無關(guān)的娛樂內(nèi)容。場景三你在電商平臺的歷史購物記錄顯示你偏愛某個特定品牌的運(yùn)動裝備且通常在季末打折時購入。當(dāng)新一季產(chǎn)品上市時智能體可以主動提醒你“您關(guān)注的品牌新品已上線根據(jù)您的習(xí)慣建議可以等待季末促銷預(yù)計在X周后。”Persona2Web基準(zhǔn)測試就是為了系統(tǒng)性地評估智能體在這些復(fù)雜、個性化的長周期交互場景中的表現(xiàn)。它通過構(gòu)建包含豐富用戶歷史檔案Persona和基于此的網(wǎng)頁任務(wù)來考驗(yàn)智能體是否真的“懂”用戶。這對于下一代AI應(yīng)用從“通用工具”走向“個人助理”至關(guān)重要。接下來我將深入拆解這個基準(zhǔn)的設(shè)計思路、核心挑戰(zhàn)以及我們?nèi)绾谓梃b其思想來構(gòu)建實(shí)用的個性化智能體。2. Persona2Web基準(zhǔn)的核心設(shè)計思路拆解要理解如何構(gòu)建一個個性化的網(wǎng)頁智能體我們首先需要理解Persona2Web這個基準(zhǔn)是如何“出題”的。它的設(shè)計邏輯直接反映了該領(lǐng)域的技術(shù)挑戰(zhàn)和評估重點(diǎn)。2.1 “用戶畫像”的構(gòu)建從靜態(tài)標(biāo)簽到動態(tài)歷史傳統(tǒng)的用戶畫像可能是“男性25-30歲科技愛好者”這樣的靜態(tài)標(biāo)簽。這對于廣告投放或許足夠但對于需要執(zhí)行復(fù)雜任務(wù)的智能體來說粒度太粗且缺乏可操作性。Persona2Web采用的是動態(tài)的、基于交互歷史的用戶畫像。這種畫像通常包含多個層次的信息顯式偏好用戶明確聲明的信息。例如在模擬環(huán)境中用戶可能直接說“我對乳糖不耐受”、“我的預(yù)算是5000元以內(nèi)”。隱式行為歷史通過記錄用戶過去的網(wǎng)頁交互行為來推斷。這是核心數(shù)據(jù)源包括瀏覽歷史訪問過哪些網(wǎng)站、頁面停留時長。搜索歷史輸入過哪些查詢詞點(diǎn)擊了哪些搜索結(jié)果。交互歷史點(diǎn)擊了哪些按鈕將什么商品加入了購物車或收藏夾給哪些內(nèi)容點(diǎn)了贊。交易歷史購買過什么商品消費(fèi)金額評價內(nèi)容。會話上下文當(dāng)前對話中已提及的信息和任務(wù)目標(biāo)。Persona2Web的“題目”就是基于這樣一份詳細(xì)的用戶歷史檔案生成的。例如基準(zhǔn)中可能包含這樣一個用戶畫像“用戶A在過去一個月內(nèi)在電商網(wǎng)站W(wǎng)上搜索了5次‘機(jī)械鍵盤’瀏覽了品牌X、Y、Z的產(chǎn)品詳情頁最終將品牌Y的某型號加入了購物車但未購買。期間用戶還搜索過‘腕托’和‘PBT鍵帽’?!?基于此任務(wù)可能是“為用戶A尋找一款適合長時間打字的機(jī)械鍵盤并考慮其歷史瀏覽偏好。”注意在實(shí)際研究或構(gòu)建中這些歷史數(shù)據(jù)通常是模擬生成的或是在嚴(yán)格匿名化、獲得用戶授權(quán)的前提下使用的合成數(shù)據(jù)集以規(guī)避隱私和安全風(fēng)險。我們自己在進(jìn)行技術(shù)探索時也必須嚴(yán)格遵守數(shù)據(jù)合規(guī)原則。2.2 任務(wù)設(shè)計衡量上下文推理能力的多維標(biāo)尺有了豐富的用戶畫像Persona2Web設(shè)計了多種任務(wù)類型來多維度考察智能體的“上下文推理”能力。這遠(yuǎn)不止是簡單的信息檢索。偏好滿足型任務(wù)這是最直接的一類。任務(wù)目標(biāo)明確需要利用用戶歷史偏好。例如“根據(jù)用戶過去的音樂收聽歷史為他創(chuàng)建一個包含10首歌曲的‘工作專注’播放列表。” 智能體需要理解用戶喜歡的歌手、曲風(fēng)甚至能從“工作”場景推斷出可能需要純音樂或節(jié)奏穩(wěn)定的歌曲。意圖推斷型任務(wù)這類任務(wù)更具挑戰(zhàn)性。用戶指令可能比較模糊或簡短需要智能體結(jié)合歷史進(jìn)行意圖補(bǔ)全。例如用戶歷史顯示他最近頻繁研究電動汽車和家用充電樁。當(dāng)前指令是“幫我查一下補(bǔ)貼政策。” 一個優(yōu)秀的智能體應(yīng)該能推斷出用戶想查的是“電動汽車購置補(bǔ)貼政策”或“充電樁安裝補(bǔ)貼”而不是泛泛地去搜索農(nóng)業(yè)補(bǔ)貼。矛盾消解與決策型任務(wù)用戶的歷史行為可能存在矛盾或當(dāng)前指令與歷史偏好有沖突智能體需要做出合理判斷。例如用戶歷史顯示他一直購買經(jīng)濟(jì)型酒店但本次任務(wù)是為“結(jié)婚紀(jì)念日預(yù)訂一個浪漫的晚餐和住宿”。智能體需要識別出這是一個特殊場景可能需要突破常規(guī)的“經(jīng)濟(jì)型”偏好去搜索具有浪漫氛圍、口碑好的高端餐廳和酒店并在執(zhí)行過程中可能需要向用戶確認(rèn)預(yù)算范圍。長周期規(guī)劃型任務(wù)任務(wù)可能需要多個步驟并且依賴不同時間點(diǎn)的歷史信息。例如“為我規(guī)劃一個健身計劃并購買所需的裝備?!?智能體需要先查看用戶過去購買的健身器材如已有啞鈴則無需重復(fù)購買、瀏覽過的健身教程了解其健身興趣方向然后綜合制定計劃并完成購物。Persona2Web通過為每類任務(wù)設(shè)置標(biāo)準(zhǔn)化的評估流程和成功標(biāo)準(zhǔn)如是否找到了符合歷史偏好的商品、是否正確推斷并執(zhí)行了用戶意圖為不同智能體模型提供了公平的“競技場”。2.3 評估指標(biāo)超越“任務(wù)完成率”對于一個簡單的“點(diǎn)擊登錄按鈕”的任務(wù)我們可以用“成功/失敗”來評估。但對于個性化推理任務(wù)評估要復(fù)雜得多。Persona2Web的評估體系通常包含任務(wù)完成率最基礎(chǔ)的指標(biāo)任務(wù)是否被成功執(zhí)行完畢。個性化契合度智能體的最終輸出/行動在多大程度上符合用戶的歷史畫像。這可能需要人工評估或利用一個經(jīng)過訓(xùn)練的“評判員”模型來打分。推理步驟的合理性智能體在決策過程中是否明確引用或考慮了用戶歷史其思考鏈Chain-of-Thought是否清晰、合理交互效率智能體用了多少步如網(wǎng)頁點(diǎn)擊、導(dǎo)航完成任務(wù)不必要的步驟越少效率越高。對模糊指令的魯棒性面對簡短、模糊的指令智能體能否通過結(jié)合歷史上下文給出令人滿意的執(zhí)行結(jié)果這套綜合評估體系推動著智能體研發(fā)不僅關(guān)注“能不能做”更關(guān)注“做得是不是貼合用戶心意”、“思考過程是不是聰明”。3. 構(gòu)建個性化網(wǎng)頁智能體的核心技術(shù)棧理解了評估標(biāo)準(zhǔn)我們來看看要構(gòu)建一個能在Persona2Web這類基準(zhǔn)上取得好成績的智能體需要哪些核心技術(shù)。這絕不僅僅是調(diào)用一個強(qiáng)大的LLM大語言模型API那么簡單。3.1 架構(gòu)總覽從感知到行動的閉環(huán)一個典型的個性化網(wǎng)頁智能體架構(gòu)可以看作一個強(qiáng)化學(xué)習(xí)循環(huán)主要包括以下模塊[用戶指令 當(dāng)前網(wǎng)頁狀態(tài)] - [感知模塊] - [記憶與用戶畫像模塊] - [推理與規(guī)劃模塊] - [行動模塊] - [執(zhí)行于真實(shí)瀏覽器] ^ | | v |_________________________[結(jié)果觀察與學(xué)習(xí)]_____________________________|3.2 記憶模塊智能體的“海馬體”這是實(shí)現(xiàn)個性化的核心。記憶模塊負(fù)責(zé)存儲、索引和檢索用戶歷史信息。記憶存儲不能把所有歷史記錄都無差別地塞給LLM因?yàn)樯舷挛拈L度有限。通常采用向量數(shù)據(jù)庫如ChromaDB, Pinecone, Weaviate來存儲歷史交互的嵌入向量。每條記憶可能包含原始文本如搜索詞、商品標(biāo)題、行為類型搜索、點(diǎn)擊、購買、時間戳、以及從原始文本提取的實(shí)體和關(guān)鍵詞。記憶檢索當(dāng)新任務(wù)到來時系統(tǒng)需要從海量記憶中快速找到最相關(guān)的部分。這通常通過計算當(dāng)前任務(wù)/指令的嵌入向量與記憶庫中的向量進(jìn)行相似度搜索來完成。這里的關(guān)鍵技巧在于“檢索查詢的構(gòu)建”。你不能直接用用戶的原始指令“找鍵盤”去搜索因?yàn)闅v史中可能有“鍵盤”、“機(jī)械鍵盤”、“靜音鍵盤”等多種相關(guān)記錄。更好的做法是用LLM先將指令擴(kuò)展成多個相關(guān)的搜索關(guān)鍵詞或問題再進(jìn)行向量檢索。記憶摘要與更新長期記憶會不斷增長需要定期摘要。例如將“過去兩周內(nèi)搜索了10次不同型號的機(jī)械鍵盤”摘要為“用戶近期對機(jī)械鍵盤有強(qiáng)烈的購買意向正在廣泛比價”。同時新的交互結(jié)果需要被結(jié)構(gòu)化后存入記憶庫形成閉環(huán)。實(shí)操心得記憶的“新鮮度”權(quán)重很重要。最近的行為通常比很久以前的行為更具參考價值。在向量檢索時可以給記憶條目加上一個隨時間衰減的權(quán)重因子或者簡單地將時間戳作為元數(shù)據(jù)在檢索后對結(jié)果按時間進(jìn)行重排序。3.3 推理與規(guī)劃模塊智能體的“大腦”這是LLM發(fā)揮主要作用的地方。該模塊接收用戶指令、當(dāng)前網(wǎng)頁的視覺/文本狀態(tài)以及從記憶模塊檢索到的相關(guān)用戶歷史然后輸出一個行動計劃。思維鏈與推理直接讓LLM輸出動作如“點(diǎn)擊id為‘search’的按鈕”是魯莽的。最佳實(shí)踐是讓LLM先進(jìn)行“思考”生成一個思維鏈。例如用戶指令“幫我找個適合編程的鍵盤?!睓z索到的記憶“用戶過去購買過品牌Y的鍵盤收藏過關(guān)于‘紅軸’和‘靜音’的文章?!盠LM推理鏈“用戶需要編程鍵盤。編程通常需要長時間打字舒適度和手感重要。歷史顯示用戶關(guān)注‘靜音’可能是在辦公室環(huán)境使用。他喜歡過品牌Y。因此我應(yīng)該優(yōu)先搜索品牌Y的靜音軸如靜音紅軸鍵盤并關(guān)注人體工學(xué)設(shè)計。”基于此推理再生成具體的網(wǎng)頁動作。任務(wù)分解與規(guī)劃復(fù)雜任務(wù)需要分解。LLM需要生成一個步驟序列。例如“預(yù)訂出差行程”可以分解為1) 查詢航班2) 查詢酒店考慮公司協(xié)議酒店歷史3) 租車考慮過往租車偏好。規(guī)劃時上一步的輸出可能作為下一步的輸入或約束條件。工具使用智能體需要知道它能做什么。我們需要為LLM定義一個“工具集”例如search_product(keywords, filters),read_product_details(),add_to_cart(),checkout()。LLM在規(guī)劃時需要決定在何時調(diào)用何種工具并生成正確的參數(shù)。這部分通常通過“函數(shù)調(diào)用”或“ReAct”模式來實(shí)現(xiàn)。3.4 感知與行動模塊智能體的“眼和手”網(wǎng)頁感知智能體需要“看到”網(wǎng)頁。主流方法有兩種DOM樹解析獲取網(wǎng)頁的HTML結(jié)構(gòu)提取文本和可交互元素的屬性如ID、類名、文本。優(yōu)點(diǎn)是信息結(jié)構(gòu)化輕量缺點(diǎn)是對復(fù)雜、動態(tài)渲染的頁面可能不完整。視覺感知對網(wǎng)頁進(jìn)行截圖使用多模態(tài)大模型如GPT-4V來“理解”屏幕內(nèi)容。這種方式更接近人類能理解視覺布局和圖標(biāo)含義但成本高、速度慢。混合模式是目前的主流先用輕量方法解析DOM獲取基礎(chǔ)信息對難以理解的復(fù)雜組件或需要視覺確認(rèn)的部分再調(diào)用視覺模型。行動執(zhí)行將規(guī)劃模塊輸出的抽象動作如“點(diǎn)擊登錄按鈕”轉(zhuǎn)化為瀏覽器自動化工具如Playwright, Selenium可執(zhí)行的具體指令。這需要精準(zhǔn)的元素定位。一個穩(wěn)健的策略是使用多種定位器后備方案優(yōu)先使用穩(wěn)定的># 創(chuàng)建虛擬環(huán)境可選 python -m venv persona_agent_env source persona_agent_env/bin/activate # Linux/Mac # persona_agent_env\Scripts\activate # Windows # 安裝核心依賴 pip install openai playwright chromadb beautifulsoup4 # 安裝Playwright瀏覽器驅(qū)動 playwright install chromium4.2 步驟一構(gòu)建用戶記憶存儲與檢索系統(tǒng)我們創(chuàng)建一個MemoryManager類來負(fù)責(zé)處理用戶歷史。import chromadb from chromadb.config import Settings from openai import OpenAI import json from datetime import datetime class MemoryManager: def __init__(self, openai_api_key, persist_directory./chroma_db): self.client OpenAI(api_keyopenai_api_key) # 初始化ChromaDB客戶端持久化存儲 self.chroma_client chromadb.PersistentClient(pathpersist_directory) # 獲取或創(chuàng)建集合collection以用戶ID區(qū)分 self.collection self.chroma_client.get_or_create_collection(nameuser_browsing_history) self.embedding_model text-embedding-3-small # 使用OpenAI的嵌入模型 def _get_embedding(self, text): 獲取文本的向量嵌入 response self.client.embeddings.create(modelself.embedding_model, inputtext) return response.data[0].embedding def add_memory(self, user_id, action_type, url, page_title, snippet, metadataNone): 添加一條用戶交互記憶 :param user_id: 用戶標(biāo)識 :param action_type: 行為類型如 view, search, add_to_cart :param url: 頁面URL :param page_title: 頁面標(biāo)題 :param snippet: 頁面關(guān)鍵內(nèi)容摘要如商品標(biāo)題、描述 :param metadata: 其他元數(shù)據(jù)如時間戳、價格等 if metadata is None: metadata {} metadata.update({ user_id: user_id, action_type: action_type, timestamp: datetime.now().isoformat(), url: url, title: page_title }) # 將核心信息拼接成文本用于生成向量 text_to_embed fTitle: {page_title}. Content: {snippet}. Action: {action_type}. embedding self._get_embedding(text_to_embed) # 生成一個唯一ID memory_id f{user_id}_{datetime.now().strftime(%Y%m%d%H%M%S%f)} # 存入向量數(shù)據(jù)庫 self.collection.add( ids[memory_id], embeddings[embedding], metadatas[metadata], documents[snippet] # 同時存儲原始文本便于召回后查看 ) print(fMemory added for user {user_id}: {action_type} on {page_title[:50]}...) def retrieve_relevant_memories(self, user_id, query, n_results5): 檢索與當(dāng)前查詢相關(guān)的用戶歷史記憶 :param query: 當(dāng)前任務(wù)或問題 :param n_results: 返回最相關(guān)的N條記憶 :return: 相關(guān)記憶的元數(shù)據(jù)列表 query_embedding self._get_embedding(query) # 在檢索時過濾特定用戶的歷史 results self.collection.query( query_embeddings[query_embedding], n_resultsn_results, where{user_id: user_id} # 關(guān)鍵使用元數(shù)據(jù)過濾用戶 ) # results 包含 ids, distances, metadatas, documents relevant_memories [] for i in range(len(results[ids][0])): memory_info { action: results[metadatas][0][i][action_type], title: results[metadatas][0][i][title], content: results[documents][0][i], time: results[metadatas][0][i][timestamp] } relevant_memories.append(memory_info) return relevant_memories4.3 步驟二實(shí)現(xiàn)網(wǎng)頁感知與自動化控制我們創(chuàng)建一個WebAutomator類使用Playwright來控制瀏覽器并提取頁面信息。from playwright.sync_api import sync_playwright from bs4 import BeautifulSoup class WebAutomator: def __init__(self, headlessFalse): self.playwright sync_playwright().start() self.browser self.playwright.chromium.launch(headlessheadless) self.context self.browser.new_context() self.page self.context.new_page() self.current_url None def navigate(self, url): 導(dǎo)航到指定URL self.page.goto(url, wait_untilnetworkidle) self.current_url url return self.get_page_info() def get_page_info(self): 獲取當(dāng)前頁面的結(jié)構(gòu)化信息 # 獲取頁面HTML html self.page.content() soup BeautifulSoup(html, html.parser) # 簡單提取標(biāo)題和正文可根據(jù)需要復(fù)雜化 title soup.title.string if soup.title else No Title # 提取主要文本內(nèi)容去除腳本和樣式 for script in soup([script, style]): script.decompose() text soup.get_text(separator , stripTrue) # 提取所有鏈接和按鈕簡化示例 interactive_elements [] for a in soup.find_all(a, hrefTrue): interactive_elements.append({type: link, text: a.get_text(stripTrue), href: a[href]}) for button in soup.find_all(button): interactive_elements.append({type: button, text: button.get_text(stripTrue)}) # 這里可以添加更復(fù)雜的DOM解析邏輯如識別商品列表、搜索框等 page_info { url: self.current_url, title: title, main_text: text[:1000], # 截取部分避免過長 interactive_elements: interactive_elements[:20] # 限制數(shù)量 } return page_info def perform_action(self, action_description): 根據(jù)自然語言描述執(zhí)行動作簡化版實(shí)際需要更復(fù)雜的解析 例如action_description 點(diǎn)擊‘登錄’按鈕 # 這是一個非常簡化的實(shí)現(xiàn)。實(shí)際應(yīng)用中需要結(jié)合LLM來解析描述并定位元素。 # 這里我們假設(shè)action_description直接是元素文本 try: self.page.click(ftext{action_description}) self.page.wait_for_load_state(networkidle) return True, f成功點(diǎn)擊{action_description} except Exception as e: return False, f操作失敗{e} def close(self): 關(guān)閉瀏覽器 self.context.close() self.browser.close() self.playwright.stop()4.4 步驟三集成LLM推理核心與主控循環(huán)這是智能體的“大腦”它將記憶、感知和行動串聯(lián)起來。class PersonalizedWebAgent: def __init__(self, openai_api_key, user_iddefault_user): self.memory_manager MemoryManager(openai_api_key) self.web_automator WebAutomator(headlessTrue) # 無頭模式運(yùn)行 self.llm_client OpenAI(api_keyopenai_api_key) self.user_id user_id # 定義系統(tǒng)提示詞塑造智能體的角色和能力 self.system_prompt f 你是一個個性化的網(wǎng)頁助手專門為用戶{self.user_id}服務(wù)。你的核心能力是利用用戶的過往瀏覽和交互歷史來更好地理解他的需求并完成網(wǎng)頁任務(wù)。 用戶的歷史記憶會以“相關(guān)歷史”的形式提供給你。請仔細(xì)分析這些歷史并將其融入你的思考和規(guī)劃中。 你的輸出必須是嚴(yán)格的JSON格式包含兩個字段 1. thought: 你的推理過程說明你是如何結(jié)合用戶歷史和當(dāng)前頁面信息來思考的。 2. action: 下一步要執(zhí)行的具體動作描述。如果是最終答案或無需操作則設(shè)為null。動作描述應(yīng)清晰如“在搜索框輸入‘靜音機(jī)械鍵盤’并回車”、“點(diǎn)擊商品鏈接‘品牌Y機(jī)械鍵盤’”。 當(dāng)前頁面信息會提供給你。 def run_task(self, user_task): 執(zhí)行一個用戶任務(wù) print(f\n 開始處理任務(wù): {user_task} ) # 1. 檢索相關(guān)歷史記憶 relevant_history self.memory_manager.retrieve_relevant_memories(self.user_id, user_task) history_str json.dumps(relevant_history, indent2, ensure_asciiFalse) # 2. 導(dǎo)航到起始頁面例如我們假設(shè)從電商首頁開始 print(導(dǎo)航到起始頁面...) page_info self.web_automator.navigate(https://www.example-mall.com) # 示例網(wǎng)站 page_info_str json.dumps(page_info, indent2, ensure_asciiFalse) # 3. 主循環(huán)觀察-思考-行動 max_steps 10 for step in range(max_steps): print(f\n--- 步驟 {step1} ---) # 構(gòu)建給LLM的提示 prompt f {self.system_prompt} 用戶當(dāng)前任務(wù){(diào)user_task} 相關(guān)用戶歷史 {history_str} 當(dāng)前頁面信息 {page_info_str} 請根據(jù)以上信息決定下一步行動。 # 調(diào)用LLM response self.llm_client.chat.completions.create( modelgpt-4-turbo, # 或使用 gpt-3.5-turbo 以節(jié)省成本 messages[{role: system, content: self.system_prompt}, {role: user, content: prompt}], response_format{type: json_object} # 強(qiáng)制JSON輸出 ) llm_response json.loads(response.choices[0].message.content) print(f智能體思考{llm_response[thought]}) # 4. 執(zhí)行動作或結(jié)束 if llm_response[action] is None: print(智能體認(rèn)為任務(wù)已完成或無法繼續(xù)。) # 可以在這里提取頁面信息作為最終答案 final_answer page_info[main_text][:500] # 簡化處理 print(f最終結(jié)果摘要{final_answer}) break else: print(f執(zhí)行動作{llm_response[action]}) success, message self.web_automator.perform_action(llm_response[action]) print(f動作結(jié)果{message}) if not success: print(動作執(zhí)行失敗重新觀察頁面...) # 觀察執(zhí)行后的新頁面狀態(tài) page_info self.web_automator.get_page_info() page_info_str json.dumps(page_info, indent2, ensure_asciiFalse) # 5. 可選將本次重要的交互作為記憶存儲 # 例如如果點(diǎn)擊了一個商品鏈接可以將其內(nèi)容存儲為記憶 if 商品 in llm_response[action] or view in llm_response[action].lower(): snippet page_info.get(main_text, )[:300] self.memory_manager.add_memory( user_idself.user_id, action_typeview_detail, urlpage_info[url], page_titlepage_info[title], snippetsnippet ) else: print(f達(dá)到最大步驟數(shù){max_steps}任務(wù)可能未完成。) self.web_automator.close() print( 任務(wù)處理結(jié)束 ) # 使用示例 if __name__ __main__: import os OPENAI_API_KEY os.getenv(OPENAI_API_KEY) # 請?jiān)O(shè)置你的API Key USER_ID user_123 # 首先模擬一些歷史瀏覽數(shù)據(jù)在實(shí)際應(yīng)用中這些數(shù)據(jù)來自真實(shí)記錄 agent PersonalizedWebAgent(OPENAI_API_KEY, USER_ID) # 假設(shè)之前用戶瀏覽過一些鍵盤 agent.memory_manager.add_memory(USER_ID, search, example-mall.com/search, 搜索結(jié)果 - 機(jī)械鍵盤, Cherry MX紅軸機(jī)械鍵盤靜音設(shè)計適合辦公) agent.memory_manager.add_memory(USER_ID, view, example-mall.com/product/xyz, 品牌Y 靜音紅軸機(jī)械鍵盤, 人體工學(xué)設(shè)計PBT鍵帽全鍵無沖) # 執(zhí)行一個個性化任務(wù) agent.run_task(我想買一個適合在辦公室用的鍵盤聲音要小。)這個原型雖然簡化但清晰地展示了個性化網(wǎng)頁智能體的核心工作流程記憶檢索 - 上下文感知 - LLM推理規(guī)劃 - 執(zhí)行動作 - 結(jié)果觀察與記憶更新。5. 實(shí)戰(zhàn)中遇到的典型問題與優(yōu)化策略在實(shí)際構(gòu)建和測試這類智能體時你會遇到許多預(yù)料之外的挑戰(zhàn)。以下是一些常見問題及解決思路。5.1 記憶檢索的“相關(guān)性”與“噪聲”問題問題向量檢索返回的記憶可能看似相關(guān)語義相似但對當(dāng)前任務(wù)并無幫助甚至?xí)a(chǎn)生誤導(dǎo)。例如用戶歷史中既有“購買靜音鍵盤”的記錄也有“維修機(jī)械鍵盤噪音大”的論壇瀏覽記錄。當(dāng)任務(wù)為“推薦鍵盤”時后者可能被檢索到但它是負(fù)面經(jīng)驗(yàn)智能體需要辨別。優(yōu)化策略元數(shù)據(jù)過濾與增強(qiáng)在存儲記憶時豐富元數(shù)據(jù)字段如情感傾向正面/負(fù)面/中性、信息類型產(chǎn)品特性、問題、評價、實(shí)體品牌、型號。檢索時可以結(jié)合向量相似度和元數(shù)據(jù)過濾。檢索后重排序先用向量檢索出Top-K個候選記憶例如K20然后使用一個更小、更快的LLM或一個交叉編碼器模型對每個候選記憶與當(dāng)前任務(wù)的相關(guān)性進(jìn)行精細(xì)打分重新排序。記憶摘要對于同一主題的多次交互如反復(fù)查看同一商品的不同型號定期進(jìn)行摘要形成一條“用戶對X類商品表現(xiàn)出持續(xù)興趣關(guān)注A、B特性”的高階記憶減少冗余和噪聲。5.2 網(wǎng)頁感知的“脆弱性”問題問題網(wǎng)頁結(jié)構(gòu)變化前端改版、動態(tài)加載內(nèi)容、驗(yàn)證碼、復(fù)雜交互如拖拽滑塊都會導(dǎo)致智能體“失明”或“癱瘓”。基于DOM的方法尤其脆弱因?yàn)樵氐腎D或類名可能隨時改變。優(yōu)化策略混合感知策略如前所述結(jié)合DOM解析和視覺感知。對于關(guān)鍵交互元素如購買按鈕、搜索框可以為其定義語義化的>