從蟑螂求生到AI Agent:用Python實(shí)現(xiàn)強(qiáng)化學(xué)習(xí)智能體開(kāi)發(fā)
蟑螂婆求生記一個(gè)被誤解的“害蟲(chóng)”如何成為AI Agent開(kāi)發(fā)的絕佳隱喻如果你最近在關(guān)注AI Agent智能體的開(kāi)發(fā)可能會(huì)被各種復(fù)雜的概念搞得暈頭轉(zhuǎn)向LLM、工具調(diào)用、記憶、規(guī)劃、反思……這些術(shù)語(yǔ)堆在一起讓人感覺(jué)構(gòu)建一個(gè)能自主行動(dòng)的智能體門檻高不可攀。但今天我想用一個(gè)你意想不到的“主角”——蟑螂來(lái)重新梳理這一切。別誤會(huì)這不是一篇生物學(xué)論文。在AI研究領(lǐng)域尤其是行為學(xué)和強(qiáng)化學(xué)習(xí)中“蟑螂”或類似的簡(jiǎn)單生物常被用作理解智能體Agent基礎(chǔ)原理的絕佳模型。它沒(méi)有復(fù)雜的思維目標(biāo)純粹覓食、避險(xiǎn)、求生行動(dòng)基于簡(jiǎn)單的感知-反饋循環(huán)。這恰恰是理解現(xiàn)代AI Agent最本質(zhì)的起點(diǎn)一個(gè)能感知環(huán)境、做出決策并執(zhí)行動(dòng)作以達(dá)成目標(biāo)的實(shí)體?!绑肫徘笊洝边@個(gè)項(xiàng)目本質(zhì)上是一個(gè)高度簡(jiǎn)化的AI Agent模擬沙盒。它剝離了華麗的大語(yǔ)言模型外殼直指智能體設(shè)計(jì)的核心骨架。通過(guò)它你將能透徹理解一個(gè)智能體為何需要記憶、如何規(guī)劃路徑、在復(fù)雜環(huán)境中怎樣做決策。這對(duì)于想從原理層面掌握Agent開(kāi)發(fā)而非僅僅調(diào)用API的開(kāi)發(fā)者來(lái)說(shuō)價(jià)值巨大。本文將帶你從零開(kāi)始用Python實(shí)現(xiàn)一個(gè)“蟑螂婆”求生模擬器。你會(huì)看到那些在LangChain、AutoGPT中看似高深的概念在這里是如何用幾十行代碼清晰呈現(xiàn)的。讀完本文你將能透徹理解Agent的核心三要素狀態(tài)State、動(dòng)作Action、獎(jiǎng)勵(lì)Reward。親手實(shí)現(xiàn)一個(gè)具備感知、決策、學(xué)習(xí)和簡(jiǎn)單記憶的模擬智能體。掌握將復(fù)雜Agent框架分解為可理解、可編碼的基礎(chǔ)模塊的思維方法。獲得一個(gè)可用于教學(xué)、實(shí)驗(yàn)或作為復(fù)雜Agent系統(tǒng)原型的代碼基底。1. 這篇文章真正要解決的問(wèn)題從“黑盒調(diào)用”到“白盒構(gòu)建”當(dāng)前很多開(kāi)發(fā)者接觸AI Agent的方式是直接使用LangChain、LlamaIndex等高級(jí)框架。這固然高效但也容易陷入“黑盒”困境我們知道輸入和輸出卻不清楚智能體內(nèi)部是如何“思考”和“決策”的。當(dāng)Agent行為出現(xiàn)偏差或需要為其定制特殊能力時(shí)這種理解缺失就會(huì)成為瓶頸?!绑肫徘笊洝表?xiàng)目要解決的正是這個(gè)“理解斷層”問(wèn)題。它不追求功能的強(qiáng)大而追求結(jié)構(gòu)的清晰。通過(guò)模擬一個(gè)在網(wǎng)格世界中求生尋找食物、躲避危險(xiǎn)的簡(jiǎn)單生物我們將直面Agent設(shè)計(jì)的幾個(gè)根本問(wèn)題感知Perception智能體如何“看”世界它接收到的信息狀態(tài)是什么格式的決策Decision-Making基于當(dāng)前感知和過(guò)去記憶它如何選擇下一個(gè)動(dòng)作是隨機(jī)探索還是基于經(jīng)驗(yàn)學(xué)習(xí)Learning一次成功的覓食或一次致命的碰撞如何影響它未來(lái)的行為目標(biāo)Goal如何定義“好”與“壞”獎(jiǎng)勵(lì)函數(shù)Reward Function就是智能體的“價(jià)值觀”。通過(guò)構(gòu)建這個(gè)微觀世界你將不再把Agent視為一個(gè)神秘的魔法盒而是一個(gè)由明確規(guī)則驅(qū)動(dòng)的程序?qū)嶓w。這是你從“框架使用者”邁向“架構(gòu)設(shè)計(jì)者”的關(guān)鍵一步。2. 基礎(chǔ)概念與核心原理智能體世界的“第一性原理”在深入代碼之前我們需要統(tǒng)一幾個(gè)最核心的概念。這些概念在所有Agent系統(tǒng)中通用無(wú)論是簡(jiǎn)單的“蟑螂婆”還是復(fù)雜的AutoGPT。2.1 智能體Agent與環(huán)境Environment這是最基礎(chǔ)的一對(duì)關(guān)系。智能體是做出決策的實(shí)體而環(huán)境是智能體所處的一切外部條件的總和。在我們的項(xiàng)目中環(huán)境一個(gè)二維網(wǎng)格世界其中散布著食物F、陷阱X和空位.。蟑螂婆C就在其中移動(dòng)。智能體就是“蟑螂婆”本身它能接收環(huán)境的局部信息并決定向上、下、左、右移動(dòng)。2.2 狀態(tài)State、動(dòng)作Action與獎(jiǎng)勵(lì)Reward這是描述智能體單次交互的核心三元組構(gòu)成了強(qiáng)化學(xué)習(xí)的基礎(chǔ)框架。狀態(tài)S在時(shí)間點(diǎn)t環(huán)境包括智能體自身的完整描述。對(duì)于“蟑螂婆”狀態(tài)就是整個(gè)網(wǎng)格地圖的快照以及她自身的位置。動(dòng)作A智能體在狀態(tài)S下可以執(zhí)行的操作。我們限定為{‘up’ ‘down’ ‘left’ ‘right’}。獎(jiǎng)勵(lì)R智能體執(zhí)行動(dòng)作A從狀態(tài)S轉(zhuǎn)移到新?tīng)顟B(tài)S‘后環(huán)境給出的一個(gè)標(biāo)量反饋。獎(jiǎng)勵(lì)函數(shù)的設(shè)計(jì)是Agent行為的指揮棒。吃到食物10正向獎(jiǎng)勵(lì)鼓勵(lì)該行為碰到陷阱-10負(fù)向獎(jiǎng)勵(lì)懲罰該行為移動(dòng)一步-1或-0.1生存成本鼓勵(lì)高效尋找食物2.3 策略Policy與價(jià)值Value智能體如何做決策這依賴于策略。策略π一個(gè)函數(shù)它接收當(dāng)前狀態(tài)S輸出每個(gè)可能動(dòng)作的概率分布。例如在某個(gè)位置策略可能建議{‘up’: 0.7 ‘right’: 0.3}表示向上移動(dòng)的概率是70%。價(jià)值V/Q評(píng)估一個(gè)狀態(tài)或一個(gè)“狀態(tài)-動(dòng)作對(duì)”的長(zhǎng)期好壞。狀態(tài)價(jià)值V(s)從狀態(tài)s開(kāi)始遵循當(dāng)前策略能獲得的累計(jì)獎(jiǎng)勵(lì)的期望。動(dòng)作價(jià)值Q(s a)在狀態(tài)s下執(zhí)行動(dòng)作a然后遵循當(dāng)前策略能獲得的累計(jì)獎(jiǎng)勵(lì)的期望。智能體通常選擇Q值最高的動(dòng)作。我們的“蟑螂婆”初期可以采用非常簡(jiǎn)單的策略如隨機(jī)探索后期可以引入基于Q表的簡(jiǎn)單學(xué)習(xí)。2.4 記憶Memory與規(guī)劃Planning這是讓智能體顯得“智能”的關(guān)鍵。記憶記住過(guò)去的經(jīng)歷狀態(tài)、動(dòng)作、獎(jiǎng)勵(lì)。這可以幫助它避免重復(fù)犯錯(cuò)如掉入同一個(gè)陷阱或者重復(fù)成功路徑。規(guī)劃不立即行動(dòng)而是在“腦?!蹦P椭心M未來(lái)幾步可能發(fā)生的情況選擇最優(yōu)路徑。我們的簡(jiǎn)易版本可能不涉及復(fù)雜規(guī)劃但會(huì)體現(xiàn)“利用記憶進(jìn)行決策”的思想。概念在“蟑螂婆”項(xiàng)目中的體現(xiàn)在高級(jí)Agent如AutoGPT中的體現(xiàn)環(huán)境二維網(wǎng)格地圖操作系統(tǒng)、瀏覽器、特定軟件API感知看到周圍格子是食物、陷阱還是墻讀取文件內(nèi)容、解析網(wǎng)頁(yè)信息、接收用戶指令動(dòng)作上下左右移動(dòng)調(diào)用一個(gè)Python函數(shù)、點(diǎn)擊一個(gè)按鈕、寫一段代碼獎(jiǎng)勵(lì)吃到食物10碰到陷阱-10任務(wù)完成度評(píng)分、用戶滿意度反饋、代碼運(yùn)行通過(guò)策略基于簡(jiǎn)單規(guī)則的決策如“看見(jiàn)食物就過(guò)去”由LLM生成的復(fù)雜行動(dòng)計(jì)劃記憶記住最近訪問(wèn)過(guò)的陷阱位置向量數(shù)據(jù)庫(kù)存儲(chǔ)的對(duì)話歷史和工具調(diào)用結(jié)果3. 環(huán)境準(zhǔn)備與前置條件我們將使用Python來(lái)實(shí)現(xiàn)這個(gè)模擬。選擇Python是因?yàn)槠浜?jiǎn)潔的語(yǔ)法和強(qiáng)大的科學(xué)計(jì)算生態(tài)非常適合快速原型開(kāi)發(fā)。所需環(huán)境操作系統(tǒng)Windows 10/11 macOS 或 Linux均可。Python版本3.8 或以上。建議使用3.8以確保語(yǔ)法的兼容性。核心庫(kù)numpy用于高效的數(shù)組操作代表我們的網(wǎng)格世界。randomPython標(biāo)準(zhǔn)庫(kù)用于生成隨機(jī)動(dòng)作和初始化環(huán)境??蛇xmatplotlib或curses用于更復(fù)雜的可視化。本文為簡(jiǎn)化將使用字符在控制臺(tái)打印。項(xiàng)目結(jié)構(gòu)我們將創(chuàng)建幾個(gè)Python文件來(lái)模塊化我們的代碼使其更清晰。cockroach_simulator/ ├── environment.py # 定義網(wǎng)格世界環(huán)境類 ├── agent.py # 定義蟑螂婆智能體類 ├── simulation.py # 主運(yùn)行和模擬循環(huán) └── requirements.txt # 項(xiàng)目依賴首先創(chuàng)建并激活一個(gè)虛擬環(huán)境推薦然后安裝唯一必須的依賴numpy。# 創(chuàng)建項(xiàng)目目錄并進(jìn)入 mkdir cockroach_simulator cd cockroach_simulator # 創(chuàng)建虛擬環(huán)境 (以venv為例) python -m venv venv # 激活虛擬環(huán)境 # Windows: venv\Scripts\activate # macOS/Linux: source venv/bin/activate # 創(chuàng)建requirements.txt并安裝numpy echo “numpy1.21.0” requirements.txt pip install -r requirements.txt4. 核心流程拆解從世界構(gòu)建到智能體奔跑整個(gè)模擬將遵循一個(gè)經(jīng)典循環(huán)環(huán)境初始化 - 智能體感知 - 智能體決策 - 執(zhí)行動(dòng)作 - 環(huán)境反饋 - 更新?tīng)顟B(tài)。我們將分步實(shí)現(xiàn)構(gòu)建世界environment.py創(chuàng)建一個(gè)網(wǎng)格隨機(jī)放置食物、陷阱和智能體起點(diǎn)。定義智能體agent.py賦予它感知、決策和更新記憶的能力。運(yùn)行模擬simulation.py將環(huán)境和智能體連接起來(lái)讓時(shí)間推進(jìn)觀察結(jié)果。引入學(xué)習(xí)agent.py進(jìn)階讓智能體從經(jīng)驗(yàn)中學(xué)習(xí)改進(jìn)策略。5. 完整示例與代碼實(shí)現(xiàn)5.1 第一步定義環(huán)境World環(huán)境是智能體活動(dòng)的舞臺(tái)。它需要提供幾個(gè)關(guān)鍵接口reset(): 重置環(huán)境到初始狀態(tài)。step(action): 接收智能體的動(dòng)作執(zhí)行它返回新的狀態(tài)、獎(jiǎng)勵(lì)和是否結(jié)束。render(): 以人類可讀的方式顯示當(dāng)前世界。創(chuàng)建文件environment.py# 文件路徑cockroach_simulator/environment.py import numpy as np import random class GridWorld: 一個(gè)簡(jiǎn)單的網(wǎng)格世界環(huán)境。 符號(hào)說(shuō)明 ‘C‘: 蟑螂婆 (智能體) ‘F‘: 食物 (獎(jiǎng)勵(lì) 10) ‘X‘: 陷阱 (獎(jiǎng)勵(lì) -10) ‘.‘: 空地 (獎(jiǎng)勵(lì) -1) ‘#‘: 墻 (不可通行本文暫不實(shí)現(xiàn)) def __init__(self width8 height6 num_food3 num_traps2): self.width width self.height height self.num_food num_food self.num_traps num_traps self.grid None self.agent_pos None self.food_positions [] self.trap_positions [] self.reset() def reset(self): 重置環(huán)境隨機(jī)放置食物、陷阱和智能體。 # 初始化一個(gè)全是空地的網(wǎng)格 self.grid np.full((self.height self.width) ‘.‘ dtype‘U1‘) # 隨機(jī)生成不重復(fù)的食物位置 all_positions [(r c) for r in range(self.height) for c in range(self.width)] self.food_positions random.sample(all_positions self.num_food) for pos in self.food_positions: self.grid[pos] ‘F‘ # 隨機(jī)生成不重復(fù)的陷阱位置不能與食物重合 remaining_positions [p for p in all_positions if p not in self.food_positions] self.trap_positions random.sample(remaining_positions self.num_traps) for pos in self.trap_positions: self.grid[pos] ‘X‘ # 隨機(jī)放置智能體不能與食物或陷阱重合 remaining_positions [p for p in remaining_positions if p not in self.trap_positions] self.agent_pos random.choice(remaining_positions) self.grid[self.agent_pos] ‘C‘ # 返回初始狀態(tài)這里我們返回智能體視野內(nèi)的局部狀態(tài)簡(jiǎn)化起見(jiàn)先返回整個(gè)網(wǎng)格的扁平化視圖 return self._get_state() def _get_state(self): 獲取當(dāng)前環(huán)境的狀態(tài)表示。 # 一個(gè)簡(jiǎn)單的狀態(tài)表示將網(wǎng)格展平為一維字符串。在實(shí)際復(fù)雜應(yīng)用中這里可以設(shè)計(jì)成特征向量。 return ‘|‘.join([‘‘.join(row) for row in self.grid]) def step(self action): 執(zhí)行一個(gè)動(dòng)作。 參數(shù) action: ‘up‘ ‘down‘ ‘left‘ ‘right‘ 返回 next_state: 執(zhí)行動(dòng)作后的新?tīng)顟B(tài) reward: 獲得的即時(shí)獎(jiǎng)勵(lì) done: 是否結(jié)束本輪例如生命耗盡或時(shí)間到 info: 額外信息如是否吃到食物 old_r old_c self.agent_pos new_r new_c old_r old_c # 計(jì)算新位置 if action ‘up‘ and old_r 0: new_r - 1 elif action ‘down‘ and old_r self.height - 1: new_r 1 elif action ‘left‘ and old_c 0: new_c - 1 elif action ‘right‘ and old_c self.width - 1: new_c 1 # 如果動(dòng)作會(huì)導(dǎo)致出界則留在原地并可能給予一個(gè)小的負(fù)獎(jiǎng)勵(lì)這里我們簡(jiǎn)單處理為允許 # 判斷新位置上的內(nèi)容 target_cell self.grid[new_r new_c] reward 0 done False info {‘hit‘: ‘nothing‘} # 計(jì)算獎(jiǎng)勵(lì)并更新網(wǎng)格 if target_cell ‘F‘: reward 10 info[‘hit‘] ‘food‘ # 食物被吃掉位置變空 self.grid[new_r new_c] ‘.‘ self.food_positions.remove((new_r new_c)) elif target_cell ‘X‘: reward -10 info[‘hit‘] ‘trap‘ done True # 碰到陷阱游戲結(jié)束 elif target_cell ‘.‘: reward -1 # 移動(dòng)成本 info[‘hit‘] ‘empty‘ # 注意如果新位置是‘C‘理論上不會(huì)發(fā)生或者出界了我們上面處理了則保持原位 # 更新智能體位置 if not done: # 如果沒(méi)掉陷阱就移動(dòng) self.grid[old_r old_c] ‘.‘ # 舊位置清空 self.grid[new_r new_c] ‘C‘ # 新位置放置智能體 self.agent_pos (new_r new_c) # 如果done為True掉陷阱智能體位置不動(dòng)但游戲結(jié)束。 # 檢查是否所有食物都被吃完作為另一個(gè)結(jié)束條件 if len(self.food_positions) 0: done True info[‘termination_reason‘] ‘a(chǎn)ll_food_eaten‘ elif info.get(‘hit‘) ‘trap‘: info[‘termination_reason‘] ‘fell_into_trap‘ next_state self._get_state() return next_state reward done info def render(self): 打印當(dāng)前網(wǎng)格狀態(tài)到控制臺(tái)。 print(‘-‘ * (self.width * 2 1)) for row in self.grid: print(‘|‘ ‘ ‘.join(row) ‘|‘) print(‘-‘ * (self.width * 2 1)) print(f“Agent at: {self.agent_pos} Food left: {len(self.food_positions)}“)關(guān)鍵邏輯解釋reset方法負(fù)責(zé)創(chuàng)建每一輪游戲的新地圖確保食物、陷阱和智能體初始位置不沖突。step方法是核心。它接收動(dòng)作計(jì)算新位置判斷獎(jiǎng)勵(lì)更新環(huán)境狀態(tài)并返回結(jié)果。注意獎(jiǎng)勵(lì)函數(shù)的設(shè)計(jì)10-10-1。_get_state方法將當(dāng)前網(wǎng)格轉(zhuǎn)換為一個(gè)字符串表示。這是智能體“感知”到的世界。在更復(fù)雜的實(shí)現(xiàn)中這里可以返回智能體周圍的局部視野或者提取成特征向量。render方法用于可視化方便我們調(diào)試和觀察。5.2 第二步定義智能體Agent智能體是決策的核心。我們首先實(shí)現(xiàn)一個(gè)完全隨機(jī)探索的“傻瓜”智能體然后再升級(jí)為一個(gè)有簡(jiǎn)單記憶和學(xué)習(xí)能力的版本。創(chuàng)建文件agent.py# 文件路徑cockroach_simulator/agent.py import random class SimpleRandomAgent: 一個(gè)完全隨機(jī)行動(dòng)的智能體用于基線測(cè)試。 def __init__(self actions[‘up‘ ‘down‘ ‘left‘ ‘right‘]): self.actions actions def choose_action(self state): 完全隨機(jī)選擇一個(gè)動(dòng)作。 return random.choice(self.actions) def learn(self state action reward next_state done): 隨機(jī)智能體不學(xué)習(xí)。 pass class QLearningAgent: 一個(gè)使用Q-Learning進(jìn)行學(xué)習(xí)的簡(jiǎn)單智能體。 它維護(hù)一個(gè)Q表字典記錄在特定狀態(tài)下采取每個(gè)動(dòng)作的預(yù)期價(jià)值。 def __init__(self actions learning_rate0.1 discount_factor0.9 exploration_rate0.2): self.actions actions self.lr learning_rate # 學(xué)習(xí)率控制新知識(shí)覆蓋舊知識(shí)的速度 self.gamma discount_factor # 折扣因子衡量未來(lái)獎(jiǎng)勵(lì)的重要性 self.epsilon exploration_rate # 探索率以多大概率隨機(jī)探索而非利用已知最佳 self.q_table {} # Q表鍵為狀態(tài)字符串值為該狀態(tài)下每個(gè)動(dòng)作的Q值字典 def _get_q_values(self state): 獲取一個(gè)狀態(tài)下所有動(dòng)作的Q值如果狀態(tài)未見(jiàn)過(guò)則初始化。 if state not in self.q_table: # 初始化該狀態(tài)下所有動(dòng)作的Q值為0或一個(gè)小的隨機(jī)值 self.q_table[state] {a: 0.0 for a in self.actions} return self.q_table[state] def choose_action(self state): ε-貪婪策略選擇動(dòng)作。 以 (1-ε) 的概率選擇當(dāng)前Q值最高的動(dòng)作利用 以 ε 的概率隨機(jī)選擇一個(gè)動(dòng)作探索。 if random.random() self.epsilon: # 探索隨機(jī)選 return random.choice(self.actions) else: # 利用選Q值最高的 q_values self._get_q_values(state) # 可能有多個(gè)動(dòng)作具有相同的最高Q值隨機(jī)選一個(gè) max_q max(q_values.values()) actions_with_max_q [a for a q in q_values.items() if q max_q] return random.choice(actions_with_max_q) def learn(self state action reward next_state done): Q-Learning更新規(guī)則。 Q(s a) Q(s a) lr * [reward gamma * max_a‘ Q(s‘ a‘) - Q(s a)] 如果游戲結(jié)束doneTrue則沒(méi)有未來(lái)的獎(jiǎng)勵(lì)。 current_q self._get_q_values(state)[action] if done: # 游戲結(jié)束沒(méi)有下一個(gè)狀態(tài) target reward else: # 計(jì)算下一個(gè)狀態(tài)的最大Q值 next_q_values self._get_q_values(next_state) max_next_q max(next_q_values.values()) target reward self.gamma * max_next_q # 更新Q值 self.q_table[state][action] current_q self.lr * (target - current_q)關(guān)鍵邏輯解釋SimpleRandomAgent是我們的基線它沒(méi)有任何智能純粹隨機(jī)移動(dòng)。用它來(lái)對(duì)比可以看出學(xué)習(xí)型智能體的進(jìn)步。QLearningAgent實(shí)現(xiàn)了經(jīng)典的Q-Learning算法。q_table是它的“記憶”和“知識(shí)庫(kù)”記錄了在特定state下采取每個(gè)action的長(zhǎng)期價(jià)值Q值。choose_action采用ε-貪婪策略在“利用已知最佳路徑”和“探索未知區(qū)域”之間取得平衡。這是智能體學(xué)習(xí)的關(guān)鍵。learn方法是學(xué)習(xí)的核心。它根據(jù)一次行動(dòng)的結(jié)果獎(jiǎng)勵(lì)和進(jìn)入的新?tīng)顟B(tài)來(lái)更新自己對(duì)舊有決策Q值的評(píng)估。公式Q(s,a) Q(s,a) α * [r γ * max Q(s‘a(chǎn)‘) - Q(s,a)]是強(qiáng)化學(xué)習(xí)的基石之一。5.3 第三步運(yùn)行模擬并觀察現(xiàn)在我們將環(huán)境和智能體連接起來(lái)運(yùn)行一個(gè)完整的模擬循環(huán)。創(chuàng)建文件simulation.py# 文件路徑cockroach_simulator/simulation.py from environment import GridWorld from agent import SimpleRandomAgent QLearningAgent import time def run_episode(env agent max_steps100 renderFalse delay0.3): 運(yùn)行一輪一個(gè)episode模擬。 state env.reset() total_reward 0 steps 0 done False if render: print(“\n 新一輪開(kāi)始 “) env.render() time.sleep(delay) while not done and steps max_steps: # 1. 智能體根據(jù)當(dāng)前狀態(tài)選擇動(dòng)作 action agent.choose_action(state) # 2. 環(huán)境執(zhí)行動(dòng)作返回反饋 next_state reward done info env.step(action) total_reward reward steps 1 # 3. 智能體從經(jīng)驗(yàn)中學(xué)習(xí) agent.learn(state action reward next_state done) # 4. 更新?tīng)顟B(tài) state next_state # 5. 可選渲染 if render: print(f“Step {steps}: Action ‘{action}‘ Reward {reward} Hit {info.get(‘hit‘)}“) env.render() time.sleep(delay) if render: termination_reason info.get(‘termination_reason‘ ‘max_steps_reached‘) print(f“ 本輪結(jié)束 “) print(f“總步數(shù) {steps} 總獎(jiǎng)勵(lì) {total_reward} 結(jié)束原因 {termination_reason}“) return total_reward steps def train_and_evaluate(agent_type‘q_learning‘ num_episodes500 eval_interval50): 訓(xùn)練智能體并定期評(píng)估其表現(xiàn)。 env GridWorld(width6 height4 num_food2 num_traps2) if agent_type ‘random‘: agent SimpleRandomAgent() elif agent_type ‘q_learning‘: agent QLearningAgent(actions[‘up‘ ‘down‘ ‘left‘ ‘right‘]) else: raise ValueError(“Unknown agent type“) print(f“開(kāi)始訓(xùn)練 {agent_type} 智能體共 {num_episodes} 輪...“) rewards_history [] steps_history [] for episode in range(1 num_episodes 1): # 隨著訓(xùn)練進(jìn)行可以逐漸降低探索率讓智能體更傾向于利用學(xué)到的知識(shí) if isinstance(agent QLearningAgent) and episode % 100 0: agent.epsilon max(0.01 agent.epsilon * 0.9) # 探索率衰減 # 每 eval_interval 輪進(jìn)行一次可視化評(píng)估 render_this_episode (episode % eval_interval 0) or (episode 1) or (episode num_episodes) total_reward steps run_episode( env agent max_steps50 renderrender_this_episode delay0.1 ) rewards_history.append(total_reward) steps_history.append(steps) if episode % 50 0: avg_reward sum(rewards_history[-50:]) / 50 print(f“Episode {episode:4d} | 最近50輪平均獎(jiǎng)勵(lì) {avg_reward:6.2f} | 探索率 {agent.epsilon:.3f}“) print(“\n訓(xùn)練結(jié)束“) # 你可以在這里添加繪制學(xué)習(xí)曲線的代碼使用matplotlib # 例如繪制 rewards_history 的變化可以看到智能體是否在學(xué)習(xí)。 if __name__ “__main__“: # 先看隨機(jī)智能體的表現(xiàn) print(“\n“ ““*50) print(“測(cè)試隨機(jī)智能體“) train_and_evaluate(agent_type‘random‘ num_episodes10 eval_interval5) print(“\n“ ““*50) print(“訓(xùn)練并測(cè)試Q-Learning智能體“) # 再看Q-Learning智能體的表現(xiàn) train_and_evaluate(agent_type‘q_learning‘ num_episodes300 eval_interval50)6. 運(yùn)行結(jié)果與效果驗(yàn)證現(xiàn)在讓我們運(yùn)行這個(gè)模擬看看“蟑螂婆”是如何從懵懂無(wú)知隨機(jī)亂撞逐漸學(xué)會(huì)求生尋找食物、避開(kāi)陷阱的。在項(xiàng)目根目錄下執(zhí)行python simulation.py預(yù)期輸出節(jié)選 測(cè)試隨機(jī)智能體 開(kāi)始訓(xùn)練 random 智能體共 10 輪... 新一輪開(kāi)始 ------------------------- | . . . . . . | | . F . X . . | | . . C . . . | | . . . F X . | ------------------------- Agent at: (2 2) Food left: 2 Step 1: Action ‘right‘ Reward -1 Hit empty ... 本輪結(jié)束 總步數(shù) 50 總獎(jiǎng)勵(lì) -50 結(jié)束原因 max_steps_reached ... Episode 10 | 最近10輪平均獎(jiǎng)勵(lì) -45.60 | 探索率 0.200 訓(xùn)練并測(cè)試Q-Learning智能體 開(kāi)始訓(xùn)練 q_learning 智能體共 300 輪... Episode 1 | 總獎(jiǎng)勵(lì) -28 結(jié)束原因 fell_into_trap ... Episode 50 | 最近50輪平均獎(jiǎng)勵(lì) -5.20 | 探索率 0.162 Episode 100 | 最近50輪平均獎(jiǎng)勵(lì) 8.32 | 探索率 0.118 Episode 150 | 最近50輪平均獎(jiǎng)勵(lì) 12.75 | 探索率 0.086 Episode 200 | 最近50輪平均獎(jiǎng)勵(lì) 15.10 | 探索率 0.063 Episode 250 | 最近50輪平均獎(jiǎng)勵(lì) 16.88 | 探索率 0.046 Episode 300 | 最近50輪平均獎(jiǎng)勵(lì) 17.50 | 探索率 0.034 訓(xùn)練結(jié)束如何判斷成功隨機(jī)智能體其總獎(jiǎng)勵(lì)通常在-50左右因?yàn)樽疃嘧?0步每步-1。它偶爾會(huì)撞到食物或陷阱但長(zhǎng)期平均獎(jiǎng)勵(lì)為負(fù)且波動(dòng)大。這代表了“沒(méi)有智能”的基線。Q-Learning智能體關(guān)鍵指標(biāo)是“最近N輪平均獎(jiǎng)勵(lì)”。觀察這個(gè)值的變化趨勢(shì)。訓(xùn)練初期平均獎(jiǎng)勵(lì)可能為負(fù)或略高于隨機(jī)智能體因?yàn)樗€在大量探索。訓(xùn)練中期平均獎(jiǎng)勵(lì)穩(wěn)步上升。這表明智能體正在學(xué)習(xí)它更頻繁地找到食物10并開(kāi)始避開(kāi)陷阱避免-10。訓(xùn)練后期平均獎(jiǎng)勵(lì)會(huì)趨近于一個(gè)較高的正值例如15-18。這意味著在50步的限制內(nèi)它通常能吃到1-2個(gè)食物并成功避開(kāi)陷阱。獎(jiǎng)勵(lì)從負(fù)到正并持續(xù)增長(zhǎng)是學(xué)習(xí)發(fā)生的最有力證據(jù)。如果運(yùn)行失敗第一步應(yīng)該看哪里檢查Python環(huán)境和依賴確認(rèn)已激活虛擬環(huán)境并安裝了numpy (pip list | grep numpy)。檢查文件路徑和導(dǎo)入確保simulation.py、environment.py、agent.py在同一目錄下。檢查語(yǔ)法錯(cuò)誤直接運(yùn)行單個(gè)文件看是否有報(bào)錯(cuò)例如python -m py_compile environment.py。查看具體報(bào)錯(cuò)信息Python的Traceback會(huì)明確指出錯(cuò)誤行和類型。7. 常見(jiàn)問(wèn)題與排查思路在實(shí)現(xiàn)和運(yùn)行此類模擬時(shí)你可能會(huì)遇到以下典型問(wèn)題問(wèn)題現(xiàn)象可能原因排查方式解決方案智能體永遠(yuǎn)學(xué)不會(huì)獎(jiǎng)勵(lì)不增長(zhǎng)學(xué)習(xí)率(lr)太高或太低折扣因子(gamma)不匹配探索率(epsilon)始終太高。打印Q表片段看值是否在更新。調(diào)整超參數(shù)觀察獎(jiǎng)勵(lì)曲線。嘗試經(jīng)典的超參數(shù)組合如lr0.1gamma0.9epsilon0.1。實(shí)現(xiàn)探索率衰減。智能體很快陷入局部最優(yōu)只吃最近食物探索不足過(guò)早地“利用”當(dāng)前知識(shí)。負(fù)獎(jiǎng)勵(lì)移動(dòng)成本太高導(dǎo)致它不敢探索。檢查訓(xùn)練后期的探索率是否已降為0。觀察其行動(dòng)軌跡是否重復(fù)。增加初始探索率或放慢探索率衰減速度。降低移動(dòng)成本如從-1改為-0.1。游戲很快結(jié)束掉陷阱陷阱懲罰(-10)相對(duì)于移動(dòng)成本(-1)不夠高智能體覺(jué)得“冒險(xiǎn)”代價(jià)不大。狀態(tài)表示過(guò)于簡(jiǎn)單無(wú)法區(qū)分陷阱附近的位置。查看info[‘termination_reason’]。增加渲染觀察智能體在陷阱附近的行為。大幅提高陷阱的負(fù)獎(jiǎng)勵(lì)如-50。改進(jìn)狀態(tài)表示例如將狀態(tài)改為智能體周圍3x3區(qū)域的編碼使其能“看見(jiàn)”附近的危險(xiǎn)。Q表過(guò)大內(nèi)存占用高網(wǎng)格世界較大狀態(tài)空間爆炸。我們使用整個(gè)網(wǎng)格的字符串作為狀態(tài)鍵導(dǎo)致每個(gè)不同的地圖布局都是一個(gè)新?tīng)顟B(tài)。打印len(agent.q_table)查看Q表大小。設(shè)計(jì)更具泛化性的狀態(tài)特征。例如不記錄整個(gè)網(wǎng)格而是記錄智能體相對(duì)最近食物和陷阱的方向和距離。這是解決實(shí)際復(fù)雜問(wèn)題的關(guān)鍵一步。收斂速度慢狀態(tài)空間大需要更多經(jīng)驗(yàn)輪數(shù)學(xué)習(xí)。獎(jiǎng)勵(lì)稀疏只有找到食物才有大獎(jiǎng)勵(lì)。增加訓(xùn)練輪數(shù)(num_episodes)。觀察平均獎(jiǎng)勵(lì)曲線是否在緩慢上升。引入更密集的獎(jiǎng)勵(lì)例如給予向食物方向移動(dòng)的小正獎(jiǎng)勵(lì)。使用神經(jīng)網(wǎng)絡(luò)代替Q表DQN但復(fù)雜度大大增加。8. 最佳實(shí)踐與工程建議將這個(gè)教學(xué)項(xiàng)目提升到更接近工程實(shí)踐的水平你需要考慮以下幾點(diǎn)8.1 狀態(tài)設(shè)計(jì)與特征工程這是影響智能體性能的最大因素。扁平化的網(wǎng)格字符串是一種“原始狀態(tài)”智能體很難從中學(xué)習(xí)規(guī)律。建議將狀態(tài)轉(zhuǎn)換為更具信息量的特征向量。例如def extract_features(agent_pos food_positions trap_positions grid_size): features [] # 特征1最近食物的相對(duì)方向one-hot編碼 # 特征2最近陷阱的相對(duì)方向 # 特征3智能體是否在邊界 # ... 將這些特征組合成一個(gè)數(shù)字列表 return features這樣即使食物和陷阱的位置變化只要相對(duì)關(guān)系相似智能體就能應(yīng)用之前學(xué)到的知識(shí)極大地提升了泛化能力。8.2 超參數(shù)調(diào)優(yōu)learning_ratediscount_factorexploration_rate等超參數(shù)需要仔細(xì)調(diào)整。建議編寫一個(gè)簡(jiǎn)單的網(wǎng)格搜索或隨機(jī)搜索腳本自動(dòng)嘗試多組參數(shù)選擇在驗(yàn)證集上平均獎(jiǎng)勵(lì)最高的一組。探索率衰減本文使用了簡(jiǎn)單的線性衰減更常用的方法是指數(shù)衰減或根據(jù)表現(xiàn)動(dòng)態(tài)調(diào)整。8.3 代碼結(jié)構(gòu)與可擴(kuò)展性抽象接口定義Environment和Agent的抽象基類確保新的環(huán)境和智能體實(shí)現(xiàn)能無(wú)縫接入模擬循環(huán)。配置化將世界大小、物品數(shù)量、獎(jiǎng)勵(lì)值、超參數(shù)等寫入配置文件如config.yaml避免硬編碼。日志與可視化除了控制臺(tái)打印應(yīng)將每輪的獎(jiǎng)勵(lì)、步數(shù)等記錄到文件并用matplotlib繪制學(xué)習(xí)曲線直觀展示訓(xùn)練過(guò)程。8.4 從模擬到真實(shí)Agent的思維遷移“蟑螂婆”項(xiàng)目中的所有概念都與現(xiàn)代LLM驅(qū)動(dòng)的Agent一一對(duì)應(yīng)我們的Q表-LLM的權(quán)重參數(shù)。都是存儲(chǔ)“知識(shí)”的地方。我們的choose_action-LLM的推理生成。都是基于當(dāng)前輸入狀態(tài)/提示產(chǎn)生輸出動(dòng)作/文本。我們的learn函數(shù)-LLM的訓(xùn)練/微調(diào)。都是通過(guò)反饋獎(jiǎng)勵(lì)/損失來(lái)更新內(nèi)部參數(shù)。我們的網(wǎng)格環(huán)境-Agent的操作環(huán)境如IDE、瀏覽器。都是智能體執(zhí)行動(dòng)作、獲得反饋的場(chǎng)所。理解了這個(gè)簡(jiǎn)單模型你再去看LangChain的AgentExecutor、AutoGPT的決策循環(huán)就會(huì)發(fā)現(xiàn)它們無(wú)非是在這個(gè)骨架上增加了更復(fù)雜的感知LLM理解、更豐富的動(dòng)作工具調(diào)用和更龐大的記憶向量數(shù)據(jù)庫(kù)。通過(guò)“蟑螂婆求生記”這個(gè)項(xiàng)目我們完成了一次AI Agent核心原理的“第一性原理”推導(dǎo)。你不再需要將Agent視為一個(gè)不可知的整體而是可以清晰地拆解為環(huán)境、狀態(tài)、動(dòng)作、獎(jiǎng)勵(lì)、策略、價(jià)值、記憶等模塊。每個(gè)模塊都有其明確的責(zé)任和實(shí)現(xiàn)方式。這個(gè)簡(jiǎn)單的模擬器可以成為你探索更復(fù)雜Agent技術(shù)的沙盒。接下來(lái)你可以嘗試增加環(huán)境復(fù)雜度加入墻、不同類型的獎(jiǎng)勵(lì)、會(huì)移動(dòng)的物體。實(shí)現(xiàn)更高級(jí)算法將Q表替換為神經(jīng)網(wǎng)絡(luò)Deep Q-Network處理更復(fù)雜的狀態(tài)。引入多智能體模擬多個(gè)“蟑螂婆”的協(xié)作與競(jìng)爭(zhēng)。連接真實(shí)世界將這個(gè)框架的思想用于設(shè)計(jì)一個(gè)能自動(dòng)操作某個(gè)軟件或網(wǎng)站的腳本Agent。真正的AI Agent開(kāi)發(fā)就是在這樣的基礎(chǔ)之上不斷迭代和復(fù)雜化。掌握了骨架你才能有方向地填充血肉。建議你將這個(gè)項(xiàng)目的代碼保存、修改、實(shí)驗(yàn)它是你理解一切更高級(jí)Agent框架的基石。

相關(guān)新聞

10元低成本接入Codex:AI編程助手實(shí)戰(zhàn)指南與優(yōu)化技巧

10元低成本接入Codex:AI編程助手實(shí)戰(zhàn)指南與優(yōu)化技巧

最近很多開(kāi)發(fā)者都在尋找經(jīng)濟(jì)實(shí)惠的AI編程助手方案,特別是對(duì)于學(xué)生和獨(dú)立開(kāi)發(fā)者來(lái)說(shuō),動(dòng)輒每月幾十美元的費(fèi)用確實(shí)是個(gè)門檻。今天分享一個(gè)實(shí)測(cè)可用的Codex接入方案,不僅成本控制在10元以內(nèi),還能獲得接近ChatGPT的編程輔助體驗(yàn)。1. C…

2026/8/1 7:09:53 閱讀更多
Python+Django+Vue3構(gòu)建美食城數(shù)字化系統(tǒng)實(shí)踐

Python+Django+Vue3構(gòu)建美食城數(shù)字化系統(tǒng)實(shí)踐

1. 項(xiàng)目背景與核心價(jià)值在餐飲行業(yè)數(shù)字化轉(zhuǎn)型浪潮中,中小型美食城面臨三個(gè)典型痛點(diǎn):商戶管理分散、訂單處理低效、數(shù)據(jù)統(tǒng)計(jì)滯后。我們團(tuán)隊(duì)為某地標(biāo)美食街開(kāi)發(fā)的這套系統(tǒng),用PythonDjango處理復(fù)雜業(yè)務(wù)邏輯,配合Vue3構(gòu)建現(xiàn)代化前端&am…

2026/8/1 7:09:53 閱讀更多
SHEIN 標(biāo)簽緊急整改|現(xiàn)成合規(guī)標(biāo)簽直接用

SHEIN 標(biāo)簽緊急整改|現(xiàn)成合規(guī)標(biāo)簽直接用

各位 SHEIN 全托管商家注意!平臺(tái)更新歐盟、英國(guó)站點(diǎn)標(biāo)簽合規(guī)規(guī)則,標(biāo)簽不合規(guī)會(huì)出現(xiàn)新品無(wú)法上架、老品下架、倉(cāng)庫(kù)拒收貨物,直接影響出貨與銷量,請(qǐng)全員抓緊落地整改。 一、硬性時(shí)間節(jié)點(diǎn),錯(cuò)過(guò)必踩坑 1.7.27 起自查&…

2026/8/1 7:09:53 閱讀更多
C++11多線程編程實(shí)戰(zhàn):從std::thread入門到線程池構(gòu)建

C++11多線程編程實(shí)戰(zhàn):從std::thread入門到線程池構(gòu)建

1. 從“單兵作戰(zhàn)”到“協(xié)同作戰(zhàn)”:為什么我們需要多線程? 如果你寫過(guò)一些C程序,尤其是涉及到界面響應(yīng)、網(wǎng)絡(luò)通信或者大量數(shù)據(jù)處理時(shí),大概率遇到過(guò)這樣的場(chǎng)景:程序在執(zhí)行一個(gè)耗時(shí)操作(比如讀取一個(gè)大文件、進(jìn)…

2026/8/1 9:19:58 閱讀更多
編程用哪個(gè)AI大模型好?實(shí)測(cè)GPT-5.6和Claude的真實(shí)體驗(yàn)

編程用哪個(gè)AI大模型好?實(shí)測(cè)GPT-5.6和Claude的真實(shí)體驗(yàn)

最近被問(wèn)得最多的一個(gè)問(wèn)題:寫代碼到底用哪個(gè)AI模型好?ChatGPT、Claude、Gemini、Grok,每個(gè)都有人吹,每個(gè)都有人踩。我自己折騰了一圈,發(fā)現(xiàn)最大的問(wèn)題不是"哪個(gè)最強(qiáng)",而是"哪個(gè)最適合你的場(chǎng)景…

2026/8/1 9:09:57 閱讀更多
AMAT 0100-02186 I/O 分配 PCB

AMAT 0100-02186 I/O 分配 PCB

AMAT 0100-02186 I/O分配PCB板是應(yīng)用材料(Applied Materials)公司生產(chǎn)的一款用于半導(dǎo)體設(shè)備的I/O信號(hào)分配電路板。該型號(hào)(0100-02186)的核心特點(diǎn)如下:專用于Endura等半導(dǎo)體工藝腔室。集成信號(hào)路由與分配功能。連接控制…

2026/8/1 0:09:33 閱讀更多
Nissei Corp FFMN-32L-10-T0 40AX 三相異步電動(dòng)機(jī)

Nissei Corp FFMN-32L-10-T0 40AX 三相異步電動(dòng)機(jī)

Nissei Corp FFMN-32L-10-T0 40AX 三相異步電動(dòng)機(jī)是日本日清(Nissei)品牌的一款工業(yè)用三相異步電機(jī),適用于自動(dòng)化設(shè)備及通用機(jī)械驅(qū)動(dòng)。該型號(hào)(FFMN-32L-10-T0 40AX)的核心特點(diǎn)如下:三相交流異步電動(dòng)機(jī)。額定…

2026/8/1 0:09:33 閱讀更多
AMAT 0100-02186 I/O 分配 PCB

AMAT 0100-02186 I/O 分配 PCB

AMAT 0100-02186 I/O分配PCB板是應(yīng)用材料(Applied Materials)公司生產(chǎn)的一款用于半導(dǎo)體設(shè)備的I/O信號(hào)分配電路板。該型號(hào)(0100-02186)的核心特點(diǎn)如下:專用于Endura等半導(dǎo)體工藝腔室。集成信號(hào)路由與分配功能。連接控制…

2026/8/1 0:09:33 閱讀更多
Nissei Corp FFMN-32L-10-T0 40AX 三相異步電動(dòng)機(jī)

Nissei Corp FFMN-32L-10-T0 40AX 三相異步電動(dòng)機(jī)

Nissei Corp FFMN-32L-10-T0 40AX 三相異步電動(dòng)機(jī)是日本日清(Nissei)品牌的一款工業(yè)用三相異步電機(jī),適用于自動(dòng)化設(shè)備及通用機(jī)械驅(qū)動(dòng)。該型號(hào)(FFMN-32L-10-T0 40AX)的核心特點(diǎn)如下:三相交流異步電動(dòng)機(jī)。額定…

2026/8/1 0:09:33 閱讀更多