iT邦幫忙

2026 iThome 鐵人賽

DAY 3
0
Vibe Coding

agent工作流系列 第 5

【Day 5】怎麼應用Context Engineering:打造高效的上下文壓縮、過濾與狀態管線

  • 分享至 

  • xImage
  •  

在昨天的文章中,我們拆解了 Context Engineering 的核心
我們知道Agent的上下文不該被動堆疊,而需要透過一套動態機制進行調度

今天我們進入實戰篇:如何將 Write(寫入)、Select(篩選)、Compress(壓縮)、Isolate(隔離)這四大支柱,落實到具體的 Python 程式碼中?


一、四大支柱在Agent生命週期中的分工

以一個Agent工作流迴圈為例,資料的流轉與處理節點如下:

[環境/用戶輸入] 
       │
       ▼
 1. Write (寫入)   ──> 結構化記錄至狀態儲存庫 (State/Checkpoints)
       │
       ▼
 2. Select (篩選)  ──> 根據當前任務動態檢索相關記憶與工具 Schema
       │
       ▼
 3. Compress (壓縮) ──> 剪裁工具 Raw Output 與摘要過長歷史
       │
       ▼
 4. Isolate (隔離)  ──> 建立子任務獨立視窗,防止跨節點噪音污染
       │
       ▼
 [LLM 決策與執行]

ps 這些節點你可以依照自己任務來對調、使用

二、實戰 1:Write(寫入)——結構化狀態與記憶沉澱

不要將對話單純當作字串拼接,必須使用具備語意結構的狀態物件(State)進行寫入與持久化,明確分離「系統指令」、「使用者意圖」與「工具執行軌跡」

from typing import List, Dict, Any
from dataclasses import dataclass, field

@dataclass
class AgentState:
    session_id: str
    system_rules: str
    user_facts: Dict[str, Any] = field(default_factory=dict)  # 長期使用者畫像
    messages: List[Dict[str, Any]] = field(default_factory=list)  # 對話軌跡
    scratchpad: List[Dict[str, Any]] = field(default_factory=list)  # 當前任務暫存

# 實作 Write:明確分類寫入,而非混雜堆疊
def write_user_fact(state: AgentState, key: str, value: Any) -> None:
    state.user_facts[key] = value

def write_interaction(state: AgentState, role: str, content: str) -> None:
    state.messages.append({"role": role, "content": content})

# 範例調用
state = AgentState(session_id="sess_001", system_rules="你是電商客服助理。")
write_user_fact(state, "membership_tier", "VIP")
write_interaction(state, "user", "我想查詢耳機訂單,並辦理換貨。")

三、實戰 2:Select(篩選)——動態工具剪枝與按需檢索

當系統掛載了數十個工具時,每一輪把所有工具Schema通通塞進Context會大幅消耗Token並增加模型幻覺

我們應該在執行前依據使用者最新意圖進行 動態工具挑選(Tool Pruning)

# 系統所有的工具池
AVAILABLE_TOOLS = {
    "track_order": {"name": "track_order", "desc": "查詢物流與訂單狀態"},
    "apply_refund": {"name": "apply_refund", "desc": "辦理訂單退貨退款"},
    "apply_exchange": {"name": "apply_exchange", "desc": "辦理商品換貨"},
    "reset_password": {"name": "reset_password", "desc": "發送密碼重設信件"},
    "query_faq": {"name": "query_faq", "desc": "查詢常見問題知識庫"}
}

def select_relevant_tools(user_query: str) -> List[Dict[str, Any]]:
    """
    根據意圖關鍵字或向量檢索,僅挑選與當下任務相關的工具
    """
    selected = []
    if "訂單" in user_query or "物流" in user_query:
        selected.append(AVAILABLE_TOOLS["track_order"])
    if "退" in user_query:
        selected.append(AVAILABLE_TOOLS["apply_refund"])
    if "換" in user_query:
        selected.append(AVAILABLE_TOOLS["apply_exchange"])
    
    # 若無特定匹配,默認注入 FAQ 工具
    return selected if selected else [AVAILABLE_TOOLS["query_faq"]]

# 根據 "我想查詢耳機訂單,並辦理換貨",僅挑選 track_order 與 apply_exchange
active_tools = select_relevant_tools("我想查詢耳機訂單,並辦理換貨。")

四、實戰 3:Compress(壓縮)——工具輸出過濾與歷史濃縮

外部API或資料庫回傳的Raw Data動輒數千Token,直接注入會污染Context。我們必須在進入LLM前進行瘦身與提煉

import json

# 模擬外部 API 回傳的肥大資料
raw_tool_payload = {
    "status": "success",
    "timestamp": 1755678900,
    "debug_id": "trace-8899-xyz",
    "server_node": "tw-node-03",
    "order_data": {
        "order_id": "ORD-1001",
        "item": "降噪藍牙耳機",
        "amount": 3200,
        "delivery_status": "DELIVERED",
        "warehouse_logs": ["scan_in", "pack_done", "out_for_delivery"]
    }
}

def compress_tool_output(payload: Dict[str, Any]) -> str:
    """
    僅保留決策必備欄位,移除 trace、log 等系統雜訊
    """
    data = payload.get("order_data", {})
    compressed = {
        "order_id": data.get("order_id"),
        "item": data.get("item"),
        "status": data.get("delivery_status")
    }
    return json.dumps(compressed, ensure_ascii=False)

# 壓縮後僅剩 45 字元:{"order_id": "ORD-1001", "item": "降噪藍牙耳機", "status": "DELIVERED"}
cleaned_context = compress_tool_output(raw_tool_payload)

五、實戰 4:Isolate(隔離)——多節點工作流的上下文沙盒

在複雜的多步驟工作流(如「驗證身份 ➔ 查詢訂單 ➔ 產生退換貨單」)中,每個子Agent節點應該擁有獨立純淨的上下文,避免將 A 節點冗長的中間推論過程帶入 B 節點

def run_isolated_subtask(global_state: AgentState, task_name: str, task_input: str) -> str:
    """
    建立隔離的 Context 沙盒,執行完畢後只回傳結構化結論給主工作流
    """
    # 建立沙盒上下文,不繼承全量歷史對話
    sandboxed_context = {
        "role": f"你是專門處理【{task_name}】的子節點",
        "user_tier": global_state.user_facts.get("membership_tier"),
        "task_input": task_input
    }
    
    # 模擬子節點執行完畢後的精簡輸出
    subtask_result = f"審核通過:{global_state.user_facts.get('membership_tier')} 用戶享有免運換貨權限。"
    
    # 僅將最終結果寫回全域狀態,中間運算過程不污染主對話
    global_state.messages.append({"role": "assistant", "content": subtask_result})
    return subtask_result

六、實戰總結:Context 四大機制的工程矩陣

支柱 核心目標 實作策略 解決痛點
Write (寫入) 結構化分層記錄 分離 System Rules、User Facts 與對話軌跡 避免狀態混亂與非結構化文字丟失
Select (篩選) 精準載入最小必要資訊 動態挑選 2~3 個相關 Tool Schema,意圖分流 防止工具定義吃光 Token 與誤觸發
Compress (壓縮) 提高單位 Token 資訊密度 撰寫 Tool Adapter 清洗 Raw Data、過期對話摘要 避免 Context Poisoning 與長文本延遲
Isolate (隔離) 子任務上下文沙盒化 各節點使用獨立視窗,只向主流程傳遞結論 阻斷中間除錯訊息與噪音跨節點污染

小結與下集預告

透過 Write ➔ Select ➔ Compress ➔ Isolate 四大工程手段,我們能有效駕馭龐大資料流,確保 Agent 在每一輪決策時都能看見「最純淨、最關鍵」的上下文

然而,即使Context管理得再好,如果LLM輸出的文字依然隨意、無法保證欄位完整性,下游程式碼在解析時就會頻繁遭遇報錯(如 JSON 格式損壞)

明天 【Day 6】甚麼是 Structured Output Engineering,我們將探討如何利用JSON Schema、Pydantic 與Type-safe機制,從根本上強制約束LLM的輸出格式!


上一篇
【Day 4】甚麼是 Context Engineering
系列文
agent工作流5
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言