轉發原文標題:《我在 Project89 內看到下一代 Agent 框架》
先說結論,@project_89 採用一種全新的方式來設計 Agent 框架, 這是一個針對遊戲開發的高性能的 Agent 框架,與目前使用的 Agent 框架相比更加模塊化也有更好的性能。
這篇文章花了很長的時間來寫,試圖讓所有人都懂這個框架相比傳統 Agent 框架在架構上做了什麼升級,前後改了很多次才有了這個版本,但是文中仍然有些部分太過技術,我沒能很好的進一步通俗化,如果你對文章改進有任何建議歡迎留下你的評論。
這是一篇技術博客,所以我們先來看看這個founder的技術實力
Founder在做project89之前做了這個項目:https://github.com/Oneirocom/Magick,也是一款利用AI進行編程的軟件同時shaw也是這個項目排名第四的開發者,在shaw的履歷裡也可以看到這個項目
左上:project89的founder , 右下: lalaune 就是ai16z的shaw
而今天我們主要來介紹下 project89 裡面的高性能 Agent Framework:
https://github.com/project-89/argOS
從遊戲領域的應用來看
目前採用ECS架構的遊戲有:
區塊鏈遊戲:Mud、Dojo
傳統遊戲: 守望先鋒、星際公民等等
而且目前主流的遊戲引擎也在往ECS的方向進化比如Unity
ECS(Entity-Component-System)是一種在遊戲開發與模擬系統中常用的架構模式。它將數據與邏輯徹底分離,以便在大規模可擴展場景下高效管理各種實體及其行為:
Entity(實體)
• 僅僅是一個 ID(數字或字符串),不包含任何數據或邏輯。
• 可以根據需要,掛載不同的組件來賦予它各種屬性或能力。
Component(組件)
• 用來存儲實體的具體數據或狀態。
System(系統)
• 負責執行與某些組件相關的邏輯。
以一個具體的Agent行動的例子來理解這套體系:
在 ArgOS 中將每一個Agent看成一個 Entity,它可以註冊不同的組件,比如在下面這幅圖裡,我們這個Agent擁有以下四個組件:
Agent Component: 主要存儲類似 Agent 名稱,模型名字等等基礎信息
Perception Component: 主要用來存儲感知到的外界數據
Memory Component: 主要用來存儲 Agent Entity的Memory數據,類似做過的事情等等
Action Component: 主要存儲要執行的 Action 數據
System 的工作流程:
接著我們就得到一個每個Component數據 都被更新的 Update Agent Entity
4.所以我們可以看到這裡面System 主要負責定義要對哪些Component 執行對應的處理邏輯。
而且很明顯在 project89 裡面它是一個世界裡面充斥著各種類型的 Agent,比如有些Agent不僅僅擁有以上的基礎能力還有做計劃的能力。
那麼就會如下面這個圖所示:
但是實際的 system 執行流程不是我們想象的 Perception System執行完之後調用 Memory System 這種傳統做法,不同System之間是不存在調用關係的,每個System都會在一個規定的週期內執行一次,比如:
文章到這裡都是基於我對ArgOS 的理解大大簡化了它的架構方便大家更好理解,接下來我們來看真實的ArgOS.
ArgOS之中為了讓 Agent 可以進行更加深度的思考執行更復雜的任務,設計了很多Component,以及很多System.
並且ArgOS之中將System分為“三種層次” (ConsciousnessLevel):
1)有意識(CONSCIOUS) 系統
2)潛意識(SUBCONSCIOUS) 系統
3)無意識(UNCONSCIOUS) 系統
所以在 ArgOS之中是將不同的System根據ConsciousnessLevel劃分,來規定這個System多久之後執行一次。
為什麼要這麼設計呢?
因為ArgOS之中各個system之間的關係極其複雜,如下圖:
1 PerceptionSystem負責從外界或其他實體那裡收集“刺激”(stimuli),並將其更新到代理(Agent)的 Perception 組件中。
判斷刺激是否顯著變化,根據穩定度、處理模式 (ACTIVE/REFLECTIVE/WAITING) 等做相應更新。
最終為後續的 ExperienceSystem、ThinkingSystem 等提供“當前感知”的信息。
2 ExperienceSystem將 PerceptionSystem 收集到的 Stimuli 轉換為更加抽象的“體驗”(Experience)。
會調用 LLM 或規則邏輯 (extractExperiences) 來識別新的體驗,並存儲到 Memory 組件。
去重、篩選、校驗體驗,同時通過 eventBus 觸發“experience”事件給其他系統或外部監聽者。
3 ThinkingSystem智能體自身的“思考”系統。
從 Memory、Perception 等組件裡提取當前狀態,通過 generateThought(…) 與 LLM / 規則邏輯生成“思考結果”(ThoughtResult)。
根據思考結果,可能:
• 更新 Memory 中的 thoughts (思考歷史)。
• 觸發新的 Action(放到 Action.pendingAction[eid])。
• 改變 agent 的外在 Appearance(表情、姿勢等),並生成相關 Stimulus 讓其他實體“看到”變化。
4 ActionSystem若某個 Agent 的 Action.pendingAction 非空,則通過 runtime.getActionManager().executeAction(…) 來真正執行動作。
執行完後將結果寫回 Action.lastActionResult,並通知房間或其他實體。
也會藉此產生 CognitiveStimulus(認知刺激),以便後續系統“知道”該動作已完成,或可以納入記憶。
5 GoalPlanningSystem週期性地評估 Goal.current[eid] 列表中目標的進度,或檢查外部/自身記憶是否出現重大變化 (detectSignificantChanges)。
當需要新目標或進行目標調整時,通過 generateGoals(…) 生成並寫入 Goal.current[eid]。
同時更新在進度中 (in_progress) 的目標,若符合完成或失敗條件就改變狀態,並向相應 Plan 發出完成/失敗信號。
6 PlanningSystem對“已有目標”(Goal.current[eid])生成或更新 Plan(執行計劃)。
如果檢測到某些目標沒有對應的活動中 (active) 計劃,則通過 generatePlan(…) 產生一個包含若干 steps 的執行路線圖,並將其寫入 Plan.plans[eid]。
也會在目標完成或失敗時更新與其關聯的 Plan 狀態,併產生相應認知刺激。
7 RoomSystem處理與房間(Room)相關的更新:
• 獲取房間內的佔用者列表 (occupants),為每位 agent 生成“外觀(appearance)”刺激,讓其他實體“看到”他的外貌或動作。
• 創建房間環境 Stimulus (如貼切的“房間氛圍”信息) 並進行關聯。
確保當 Agent 處於某個空間環境時,其他正在感知該空間的實體可以感知到他的外貌變化。
8 CleanupSystem定期查找並移除標記了 Cleanup 組件的實體。用於回收不再需要的 Stimulus 或其他對象,防止 ECS 中遺留大量無效的實體。
下面的場景示例展示了各個 System 如何在一回合(或幾幀)內依次配合完成一次完整流程。
場景準備:世界(World)中存在一個 Agent (EID=1),正在“Active”狀態,且處在某個 Room (EID=100)。
該 Room 裡新出現了一個道具“MagicSword”,生成了相應的 Stimulus。
“我看到了 MagicSword,也許能撿起來看看它能幹什麼…”該思考結果包含一個待執行的 Action:{ tool: “pickUpItem”, parameters: { itemName: “MagicSword” } }
ThinkingSystem 將此 Action 寫入 Action.pendingAction[1]。
若有 appearance 改動(例如“面帶好奇的表情”),則更新 Appearance 併產生視覺刺激。
通過 runtime.getActionManager().executeAction(“pickUpItem”, 1, { itemName: “MagicSword” }, runtime) 執行“拾取”動作邏輯。得到結果:{ success: true, message: “你撿起了魔法劍” },更新到 Action.lastActionResult[1],並觸發「action」事件廣播給房間(100)。
同時產生認知刺激 (type=“action_result”),寫入 Memory 或讓 ThinkingSystem 下個回合捕獲。
如果已完成,則把關聯的 Plan [status] 置為 “completed”;或若目標要擴展後續流程 (“研究魔法劍”),則生成更多步驟。
若 agent(1) 外觀改變(比如 Appearance.currentAction = “holding sword”),就創建新的「appearance」視覺刺激,讓其他在同房間的 Agent2, Agent3 知道“agent1 拿起了劍”。
• 感知環境變化(Perception) → 記錄或轉化為內在經驗(Experience) → 自我思考並決策(Thinking) → 付諸行動(Action) → 動態調整目標與計劃(GoalPlanning + Planning) → 同步環境(Room) → 及時回收無用實體(Cleanup)
在 ECS 中,每個實體 (Entity) 可擁有若干組件 (Component)。根據在系統中的性質和生命週期,大致可以將組件分為以下幾類:
1 核心身份類 (Identity-Level Components)
• Agent / PlayerProfile / NPCProfile 等
• 用來唯一標識實體、存放核心角色或單位信息,一般需要持久化到數據庫。
2 行為與狀態類 (Behavior & State Components)
• Action, Goal, Plan, ProcessingState 等
• 代表了實體當前要做的事情或目標,以及對外部命令、內部思維的響應狀態。
• 包含 pendingAction, goalsInProgress, plans, 以及在隊列中的思考或任務等。
• 通常為中/短期狀態,很多會隨著遊戲回合或業務週期動態變化。
• 是否需要落庫視情況而定。如果希望斷點續跑,可能定期寫入數據庫。
3 感知與記憶類 (Perception & Memory Components)
• Perception, Memory, Stimulus, Experience 等
• 記錄了實體感知到的外部信息 (Stimuli),以及感知後提煉成的體驗 (Experiences)。
• Memory 往往可積累大量數據,例如對話記錄、事件歷史等;常常需要做持久化。
• Perception 可能是實時或臨時信息,多為短期內有效,可根據需求決定是否寫入數據庫(比如只存重要的感知事件)。
4 環境與空間類 (Room, OccupiesRoom, Spatial, Environment, Inventory 等)
• 代表房間、環境、位置、物品容器等信息。
• Room.id、OccupiesRoom、Environment 等字段常常需要持久化,如房間首頁描述、地圖結構等。
• 不斷變化的組件 (比如 Entity 在不同房間之間移動) 可以做事件式或定期寫入。
5 外觀與交互類 (Appearance, UIState, Relationship 等)
• 記錄實體對外的“可見”或“交互”部分,如 Avatar, pose, facialExpression, 與其他實體的社交關係網絡等。
• 一部分可只在內存中處理(實時表現),另一部分(比如關鍵社交關係)可能要持久化。
6 輔助或運維類 (Cleanup, DebugInfo, ProfilingData 等)
• 用於標記哪些實體需要回收 (Cleanup)、或者記錄調試信息 (DebugInfo) 以便在監控和分析時使用。
• 一般只在內存中存在,很少會同步到數據庫 unless 日誌或審計需要。
上面已經介紹
有了Component和 System 之外我們其實還缺少一個資源管理者,比如如何訪問數據庫,當狀態更新有衝突怎麼處理等等。
左側 Systems (PerceptionSystem、ExperienceSystem、ThinkingSystem 等):
• 每個系統在 ECS 循環中被 SimulationRuntime 調度執行,查詢並處理自己關心的實體(通過組件條件)。
• 在執行邏輯時,需要和 Managers 進行交互,例如:
右側 Managers (EventBus、RoomManager、StateManager、EventManager、ActionManager、PromptManager 等):
• 提供系統級功能,基本不主動“驅動”邏輯,而是被 Systems 或 Runtime 調用。
• 典型示例:
• 是所有 Systems 的“調度者”,啟動或停止不同層級(Conscious/Subconscious等)的系統循環;
• 也在構造階段創建 Managers 並傳給各 System 使用。
• 特別注意它還和 ComponentSync (CS) 交互,用於在回收實體時同步移除組件或事件訂閱。
結論:
每個 System 會在需要時通過對應的 Manager 讀寫數據或調用服務,而 Runtime 則在更高層面統一調度所有 System 與 Manager 的生命週期及行為。
在 ECS 中,Systems 是真正執行邏輯的地方,而數據庫讀寫可以通過一個“持久化管理器 (PersistenceManager / DatabaseManager)”或“狀態管理器 (StateManager)”來完成。大致流程可如下:
1 啟動或加載時 (Initial Load)
• StateManager / PersistenceManager 從數據庫加載 Agents、Rooms、Goals 等核心持久化組件的數據,創建對應實體 (Entities) 並初始化相關組件字段。
• 例如,讀取一批 agent 記錄插入 ECS 世界,給他們初始化 Agent、Memory、Goal 等組件。
2 ECS 運行時 (Systems Update Loop)
• 系統在每個幀 (或回合) 內做事情:PerceptionSystem 收集“感知”並寫到 Perception 組件 (多為短期不落庫)。
ExperienceSystem 把新的“認知體驗”寫入 Memory.experiences,若是關鍵體驗可能同時調用 StateManager 做立即存儲,或打上“needsPersistence”標記以便後續批量寫入。
ThinkingSystem / ActionSystem / GoalPlanningSystem 等根據組件內容做決策並更新 ECS 中的字段。
如果某些組件 (比如 Goal.current) 發生重大變更且需要持久化(例如新的長遠目標),通過組件監聽或系統事件,通知 StateManager 將該字段寫入數據庫。
3 定期或事件驅動的持久化 (Periodic or Event-Driven)
• 可以在系統中的某些關鍵點(如目標計劃發生更新或Agent發生重要事件)時,調用 PersistenceManager.storeComponentData(eid, “Goal”) 這類接口進行落庫。
• 也可以在 CleanupSystem 或定時器裡,讓 StateManager 掃描含有“needsPersistence”標記的組件或實體,一次性寫回數據庫。
• 此外,日誌或審計數據(如動作歷史、思考日誌)也可在這裡進行歸檔存儲。
4 退出或斷點保存 (Manual or Shutdown Save)
• 當服務器或進程要關閉時,通過 StateManager.saveAll() 將還沒寫入的數據統一寫入數據庫,以確保下次加載能恢復 ECS 狀態。
• 對於一些單機/離線場景,也可以手動觸發存檔。
以下給一個簡單的場景,演示組件和數據庫交互的可能方式:
1 啟動時:StateManager.queryDB(“SELECT * FROM agents”) → 得到一批 agent 記錄,依次為每條記錄創建 Entity (EID=x),並給其初始化 Agent、Memory、Goal 等組件字段。
同時從 “rooms” 表裡加載房間信息,創建 Room 實體。
2 運行階段:PerceptionSystem 在某個房間檢測到事件“MagicSword 出現”,寫入 Perception.currentStimuli[eid]。ExperienceSystem 將 Stimuli 轉化為 Experience,賦值到 Memory.experiences[eid]。ThinkingSystem 通過 Memory、Goal 等信息決定執行下一步行動,生成 Action.pendingAction[eid]。ActionSystem 執行該動作後,將結果寫到 Memory 或 Action.lastActionResult。若這是一次重大劇情事件,會把 Memory.experiences[eid] 的最新部分標記為 needsPersistence。StateManager 在一段時間後發現 Memory.experiences[eid] 帶有 “needsPersistence”,則將其寫入數據庫(INSERT INTO memory_experiences …)。
3 停止或斷點:基於 ECS 或系統調度,在“服務器關閉”時調用 StateManager.saveAll(),把仍在內存中的關鍵組件字段(Agent, Memory, Goal 等)它們的最新狀態寫進數據庫。下次重啟時,就能從數據庫中加載並恢復 ECS 的世界狀態。
• 將組件分類,既方便在項目中清晰地管理實體數據,也能幫助我們控制“需要持久化”與“僅在內存中存在”的數據邊界。
• 與數據庫的交互通常由一個專門的 Manager(如 StateManager)來處理,Systems 在需要讀寫數據庫時通過它進行操作,避免在 System 裡直接寫 SQL 或類似底層語句。
• 這樣能同時享受到 ECS 在邏輯上的高效與靈活,以及數據庫帶來的持久化、斷點續跑與數據統計分析優勢。
整個架構的亮點在於:
每個System都是獨立運行的,不會跟其他的System之間有調用關係,因此即便我們希望實現Agent的“感知環境變化(Perception) → 記錄或轉化為內在經驗(Experience) → 自我思考並決策(Thinking) → 付諸行動(Action) → 動態調整目標與計劃(GoalPlanning + Planning) → 同步環境(Room) → 及時回收無用實體(Cleanup) ” 能力的時候,各個System在功能上會有很多互相依賴的點,但是我們依然可以通過ECS架構把整體結構成各個互不相關的System,每個System依然可以獨立運行,不會跟其他的System有人和耦合關係。
我想這也是為什麼Unity這幾年越來越往ECS架構遷移最主要的原因。
如下圖:
同時如果你在開發過程中希望增加新的功能,也不會對其他的System有任何影響,可以很輕易的把自己希望的功能加載進去。
另外當前這種架構的性能其實會比傳統面向對象架構的性能強很多,這在遊戲圈是一個公認的事實,因為ECS的設計更加適合進行併發,那麼當我們在複雜的Defai場景下,採用ECS架構也有可能會更有優勢,特別是希望採用Agent做量化交易的場景下,ECS也會有用武之地(不僅僅是在Agent遊戲場景下)。
從我個人的觀點來看,這是一個極其模塊化,性能極其優秀的框架,同時代碼質量也很高並且包含了很好的設計文檔,不過可惜的是 $project89 項目一直缺少對這個框架的宣傳,因此我才花了很長的時間(4天)寫了這篇文章,我覺得好的東西還是值得被發現,明天應該還會發一個英文版本,希望能有更多的遊戲團隊或者 Defai 團隊開到這個框架,為大家提供一種新的潛在的架構選擇!
Mời người khác bỏ phiếu
轉發原文標題:《我在 Project89 內看到下一代 Agent 框架》
先說結論,@project_89 採用一種全新的方式來設計 Agent 框架, 這是一個針對遊戲開發的高性能的 Agent 框架,與目前使用的 Agent 框架相比更加模塊化也有更好的性能。
這篇文章花了很長的時間來寫,試圖讓所有人都懂這個框架相比傳統 Agent 框架在架構上做了什麼升級,前後改了很多次才有了這個版本,但是文中仍然有些部分太過技術,我沒能很好的進一步通俗化,如果你對文章改進有任何建議歡迎留下你的評論。
這是一篇技術博客,所以我們先來看看這個founder的技術實力
Founder在做project89之前做了這個項目:https://github.com/Oneirocom/Magick,也是一款利用AI進行編程的軟件同時shaw也是這個項目排名第四的開發者,在shaw的履歷裡也可以看到這個項目
左上:project89的founder , 右下: lalaune 就是ai16z的shaw
而今天我們主要來介紹下 project89 裡面的高性能 Agent Framework:
https://github.com/project-89/argOS
從遊戲領域的應用來看
目前採用ECS架構的遊戲有:
區塊鏈遊戲:Mud、Dojo
傳統遊戲: 守望先鋒、星際公民等等
而且目前主流的遊戲引擎也在往ECS的方向進化比如Unity
ECS(Entity-Component-System)是一種在遊戲開發與模擬系統中常用的架構模式。它將數據與邏輯徹底分離,以便在大規模可擴展場景下高效管理各種實體及其行為:
Entity(實體)
• 僅僅是一個 ID(數字或字符串),不包含任何數據或邏輯。
• 可以根據需要,掛載不同的組件來賦予它各種屬性或能力。
Component(組件)
• 用來存儲實體的具體數據或狀態。
System(系統)
• 負責執行與某些組件相關的邏輯。
以一個具體的Agent行動的例子來理解這套體系:
在 ArgOS 中將每一個Agent看成一個 Entity,它可以註冊不同的組件,比如在下面這幅圖裡,我們這個Agent擁有以下四個組件:
Agent Component: 主要存儲類似 Agent 名稱,模型名字等等基礎信息
Perception Component: 主要用來存儲感知到的外界數據
Memory Component: 主要用來存儲 Agent Entity的Memory數據,類似做過的事情等等
Action Component: 主要存儲要執行的 Action 數據
System 的工作流程:
接著我們就得到一個每個Component數據 都被更新的 Update Agent Entity
4.所以我們可以看到這裡面System 主要負責定義要對哪些Component 執行對應的處理邏輯。
而且很明顯在 project89 裡面它是一個世界裡面充斥著各種類型的 Agent,比如有些Agent不僅僅擁有以上的基礎能力還有做計劃的能力。
那麼就會如下面這個圖所示:
但是實際的 system 執行流程不是我們想象的 Perception System執行完之後調用 Memory System 這種傳統做法,不同System之間是不存在調用關係的,每個System都會在一個規定的週期內執行一次,比如:
文章到這裡都是基於我對ArgOS 的理解大大簡化了它的架構方便大家更好理解,接下來我們來看真實的ArgOS.
ArgOS之中為了讓 Agent 可以進行更加深度的思考執行更復雜的任務,設計了很多Component,以及很多System.
並且ArgOS之中將System分為“三種層次” (ConsciousnessLevel):
1)有意識(CONSCIOUS) 系統
2)潛意識(SUBCONSCIOUS) 系統
3)無意識(UNCONSCIOUS) 系統
所以在 ArgOS之中是將不同的System根據ConsciousnessLevel劃分,來規定這個System多久之後執行一次。
為什麼要這麼設計呢?
因為ArgOS之中各個system之間的關係極其複雜,如下圖:
1 PerceptionSystem負責從外界或其他實體那裡收集“刺激”(stimuli),並將其更新到代理(Agent)的 Perception 組件中。
判斷刺激是否顯著變化,根據穩定度、處理模式 (ACTIVE/REFLECTIVE/WAITING) 等做相應更新。
最終為後續的 ExperienceSystem、ThinkingSystem 等提供“當前感知”的信息。
2 ExperienceSystem將 PerceptionSystem 收集到的 Stimuli 轉換為更加抽象的“體驗”(Experience)。
會調用 LLM 或規則邏輯 (extractExperiences) 來識別新的體驗,並存儲到 Memory 組件。
去重、篩選、校驗體驗,同時通過 eventBus 觸發“experience”事件給其他系統或外部監聽者。
3 ThinkingSystem智能體自身的“思考”系統。
從 Memory、Perception 等組件裡提取當前狀態,通過 generateThought(…) 與 LLM / 規則邏輯生成“思考結果”(ThoughtResult)。
根據思考結果,可能:
• 更新 Memory 中的 thoughts (思考歷史)。
• 觸發新的 Action(放到 Action.pendingAction[eid])。
• 改變 agent 的外在 Appearance(表情、姿勢等),並生成相關 Stimulus 讓其他實體“看到”變化。
4 ActionSystem若某個 Agent 的 Action.pendingAction 非空,則通過 runtime.getActionManager().executeAction(…) 來真正執行動作。
執行完後將結果寫回 Action.lastActionResult,並通知房間或其他實體。
也會藉此產生 CognitiveStimulus(認知刺激),以便後續系統“知道”該動作已完成,或可以納入記憶。
5 GoalPlanningSystem週期性地評估 Goal.current[eid] 列表中目標的進度,或檢查外部/自身記憶是否出現重大變化 (detectSignificantChanges)。
當需要新目標或進行目標調整時,通過 generateGoals(…) 生成並寫入 Goal.current[eid]。
同時更新在進度中 (in_progress) 的目標,若符合完成或失敗條件就改變狀態,並向相應 Plan 發出完成/失敗信號。
6 PlanningSystem對“已有目標”(Goal.current[eid])生成或更新 Plan(執行計劃)。
如果檢測到某些目標沒有對應的活動中 (active) 計劃,則通過 generatePlan(…) 產生一個包含若干 steps 的執行路線圖,並將其寫入 Plan.plans[eid]。
也會在目標完成或失敗時更新與其關聯的 Plan 狀態,併產生相應認知刺激。
7 RoomSystem處理與房間(Room)相關的更新:
• 獲取房間內的佔用者列表 (occupants),為每位 agent 生成“外觀(appearance)”刺激,讓其他實體“看到”他的外貌或動作。
• 創建房間環境 Stimulus (如貼切的“房間氛圍”信息) 並進行關聯。
確保當 Agent 處於某個空間環境時,其他正在感知該空間的實體可以感知到他的外貌變化。
8 CleanupSystem定期查找並移除標記了 Cleanup 組件的實體。用於回收不再需要的 Stimulus 或其他對象,防止 ECS 中遺留大量無效的實體。
下面的場景示例展示了各個 System 如何在一回合(或幾幀)內依次配合完成一次完整流程。
場景準備:世界(World)中存在一個 Agent (EID=1),正在“Active”狀態,且處在某個 Room (EID=100)。
該 Room 裡新出現了一個道具“MagicSword”,生成了相應的 Stimulus。
“我看到了 MagicSword,也許能撿起來看看它能幹什麼…”該思考結果包含一個待執行的 Action:{ tool: “pickUpItem”, parameters: { itemName: “MagicSword” } }
ThinkingSystem 將此 Action 寫入 Action.pendingAction[1]。
若有 appearance 改動(例如“面帶好奇的表情”),則更新 Appearance 併產生視覺刺激。
通過 runtime.getActionManager().executeAction(“pickUpItem”, 1, { itemName: “MagicSword” }, runtime) 執行“拾取”動作邏輯。得到結果:{ success: true, message: “你撿起了魔法劍” },更新到 Action.lastActionResult[1],並觸發「action」事件廣播給房間(100)。
同時產生認知刺激 (type=“action_result”),寫入 Memory 或讓 ThinkingSystem 下個回合捕獲。
如果已完成,則把關聯的 Plan [status] 置為 “completed”;或若目標要擴展後續流程 (“研究魔法劍”),則生成更多步驟。
若 agent(1) 外觀改變(比如 Appearance.currentAction = “holding sword”),就創建新的「appearance」視覺刺激,讓其他在同房間的 Agent2, Agent3 知道“agent1 拿起了劍”。
• 感知環境變化(Perception) → 記錄或轉化為內在經驗(Experience) → 自我思考並決策(Thinking) → 付諸行動(Action) → 動態調整目標與計劃(GoalPlanning + Planning) → 同步環境(Room) → 及時回收無用實體(Cleanup)
在 ECS 中,每個實體 (Entity) 可擁有若干組件 (Component)。根據在系統中的性質和生命週期,大致可以將組件分為以下幾類:
1 核心身份類 (Identity-Level Components)
• Agent / PlayerProfile / NPCProfile 等
• 用來唯一標識實體、存放核心角色或單位信息,一般需要持久化到數據庫。
2 行為與狀態類 (Behavior & State Components)
• Action, Goal, Plan, ProcessingState 等
• 代表了實體當前要做的事情或目標,以及對外部命令、內部思維的響應狀態。
• 包含 pendingAction, goalsInProgress, plans, 以及在隊列中的思考或任務等。
• 通常為中/短期狀態,很多會隨著遊戲回合或業務週期動態變化。
• 是否需要落庫視情況而定。如果希望斷點續跑,可能定期寫入數據庫。
3 感知與記憶類 (Perception & Memory Components)
• Perception, Memory, Stimulus, Experience 等
• 記錄了實體感知到的外部信息 (Stimuli),以及感知後提煉成的體驗 (Experiences)。
• Memory 往往可積累大量數據,例如對話記錄、事件歷史等;常常需要做持久化。
• Perception 可能是實時或臨時信息,多為短期內有效,可根據需求決定是否寫入數據庫(比如只存重要的感知事件)。
4 環境與空間類 (Room, OccupiesRoom, Spatial, Environment, Inventory 等)
• 代表房間、環境、位置、物品容器等信息。
• Room.id、OccupiesRoom、Environment 等字段常常需要持久化,如房間首頁描述、地圖結構等。
• 不斷變化的組件 (比如 Entity 在不同房間之間移動) 可以做事件式或定期寫入。
5 外觀與交互類 (Appearance, UIState, Relationship 等)
• 記錄實體對外的“可見”或“交互”部分,如 Avatar, pose, facialExpression, 與其他實體的社交關係網絡等。
• 一部分可只在內存中處理(實時表現),另一部分(比如關鍵社交關係)可能要持久化。
6 輔助或運維類 (Cleanup, DebugInfo, ProfilingData 等)
• 用於標記哪些實體需要回收 (Cleanup)、或者記錄調試信息 (DebugInfo) 以便在監控和分析時使用。
• 一般只在內存中存在,很少會同步到數據庫 unless 日誌或審計需要。
上面已經介紹
有了Component和 System 之外我們其實還缺少一個資源管理者,比如如何訪問數據庫,當狀態更新有衝突怎麼處理等等。
左側 Systems (PerceptionSystem、ExperienceSystem、ThinkingSystem 等):
• 每個系統在 ECS 循環中被 SimulationRuntime 調度執行,查詢並處理自己關心的實體(通過組件條件)。
• 在執行邏輯時,需要和 Managers 進行交互,例如:
右側 Managers (EventBus、RoomManager、StateManager、EventManager、ActionManager、PromptManager 等):
• 提供系統級功能,基本不主動“驅動”邏輯,而是被 Systems 或 Runtime 調用。
• 典型示例:
• 是所有 Systems 的“調度者”,啟動或停止不同層級(Conscious/Subconscious等)的系統循環;
• 也在構造階段創建 Managers 並傳給各 System 使用。
• 特別注意它還和 ComponentSync (CS) 交互,用於在回收實體時同步移除組件或事件訂閱。
結論:
每個 System 會在需要時通過對應的 Manager 讀寫數據或調用服務,而 Runtime 則在更高層面統一調度所有 System 與 Manager 的生命週期及行為。
在 ECS 中,Systems 是真正執行邏輯的地方,而數據庫讀寫可以通過一個“持久化管理器 (PersistenceManager / DatabaseManager)”或“狀態管理器 (StateManager)”來完成。大致流程可如下:
1 啟動或加載時 (Initial Load)
• StateManager / PersistenceManager 從數據庫加載 Agents、Rooms、Goals 等核心持久化組件的數據,創建對應實體 (Entities) 並初始化相關組件字段。
• 例如,讀取一批 agent 記錄插入 ECS 世界,給他們初始化 Agent、Memory、Goal 等組件。
2 ECS 運行時 (Systems Update Loop)
• 系統在每個幀 (或回合) 內做事情:PerceptionSystem 收集“感知”並寫到 Perception 組件 (多為短期不落庫)。
ExperienceSystem 把新的“認知體驗”寫入 Memory.experiences,若是關鍵體驗可能同時調用 StateManager 做立即存儲,或打上“needsPersistence”標記以便後續批量寫入。
ThinkingSystem / ActionSystem / GoalPlanningSystem 等根據組件內容做決策並更新 ECS 中的字段。
如果某些組件 (比如 Goal.current) 發生重大變更且需要持久化(例如新的長遠目標),通過組件監聽或系統事件,通知 StateManager 將該字段寫入數據庫。
3 定期或事件驅動的持久化 (Periodic or Event-Driven)
• 可以在系統中的某些關鍵點(如目標計劃發生更新或Agent發生重要事件)時,調用 PersistenceManager.storeComponentData(eid, “Goal”) 這類接口進行落庫。
• 也可以在 CleanupSystem 或定時器裡,讓 StateManager 掃描含有“needsPersistence”標記的組件或實體,一次性寫回數據庫。
• 此外,日誌或審計數據(如動作歷史、思考日誌)也可在這裡進行歸檔存儲。
4 退出或斷點保存 (Manual or Shutdown Save)
• 當服務器或進程要關閉時,通過 StateManager.saveAll() 將還沒寫入的數據統一寫入數據庫,以確保下次加載能恢復 ECS 狀態。
• 對於一些單機/離線場景,也可以手動觸發存檔。
以下給一個簡單的場景,演示組件和數據庫交互的可能方式:
1 啟動時:StateManager.queryDB(“SELECT * FROM agents”) → 得到一批 agent 記錄,依次為每條記錄創建 Entity (EID=x),並給其初始化 Agent、Memory、Goal 等組件字段。
同時從 “rooms” 表裡加載房間信息,創建 Room 實體。
2 運行階段:PerceptionSystem 在某個房間檢測到事件“MagicSword 出現”,寫入 Perception.currentStimuli[eid]。ExperienceSystem 將 Stimuli 轉化為 Experience,賦值到 Memory.experiences[eid]。ThinkingSystem 通過 Memory、Goal 等信息決定執行下一步行動,生成 Action.pendingAction[eid]。ActionSystem 執行該動作後,將結果寫到 Memory 或 Action.lastActionResult。若這是一次重大劇情事件,會把 Memory.experiences[eid] 的最新部分標記為 needsPersistence。StateManager 在一段時間後發現 Memory.experiences[eid] 帶有 “needsPersistence”,則將其寫入數據庫(INSERT INTO memory_experiences …)。
3 停止或斷點:基於 ECS 或系統調度,在“服務器關閉”時調用 StateManager.saveAll(),把仍在內存中的關鍵組件字段(Agent, Memory, Goal 等)它們的最新狀態寫進數據庫。下次重啟時,就能從數據庫中加載並恢復 ECS 的世界狀態。
• 將組件分類,既方便在項目中清晰地管理實體數據,也能幫助我們控制“需要持久化”與“僅在內存中存在”的數據邊界。
• 與數據庫的交互通常由一個專門的 Manager(如 StateManager)來處理,Systems 在需要讀寫數據庫時通過它進行操作,避免在 System 裡直接寫 SQL 或類似底層語句。
• 這樣能同時享受到 ECS 在邏輯上的高效與靈活,以及數據庫帶來的持久化、斷點續跑與數據統計分析優勢。
整個架構的亮點在於:
每個System都是獨立運行的,不會跟其他的System之間有調用關係,因此即便我們希望實現Agent的“感知環境變化(Perception) → 記錄或轉化為內在經驗(Experience) → 自我思考並決策(Thinking) → 付諸行動(Action) → 動態調整目標與計劃(GoalPlanning + Planning) → 同步環境(Room) → 及時回收無用實體(Cleanup) ” 能力的時候,各個System在功能上會有很多互相依賴的點,但是我們依然可以通過ECS架構把整體結構成各個互不相關的System,每個System依然可以獨立運行,不會跟其他的System有人和耦合關係。
我想這也是為什麼Unity這幾年越來越往ECS架構遷移最主要的原因。
如下圖:
同時如果你在開發過程中希望增加新的功能,也不會對其他的System有任何影響,可以很輕易的把自己希望的功能加載進去。
另外當前這種架構的性能其實會比傳統面向對象架構的性能強很多,這在遊戲圈是一個公認的事實,因為ECS的設計更加適合進行併發,那麼當我們在複雜的Defai場景下,採用ECS架構也有可能會更有優勢,特別是希望採用Agent做量化交易的場景下,ECS也會有用武之地(不僅僅是在Agent遊戲場景下)。
從我個人的觀點來看,這是一個極其模塊化,性能極其優秀的框架,同時代碼質量也很高並且包含了很好的設計文檔,不過可惜的是 $project89 項目一直缺少對這個框架的宣傳,因此我才花了很長的時間(4天)寫了這篇文章,我覺得好的東西還是值得被發現,明天應該還會發一個英文版本,希望能有更多的遊戲團隊或者 Defai 團隊開到這個框架,為大家提供一種新的潛在的架構選擇!