你請 Agent 比較三家供應商,它交出漂亮的推薦,卻把空白運費當成零。換一個更大的模型之前,先問:題目給的資料,真的足以做出決定嗎?Information Support Graph(資訊支援圖)就是把「答案需要哪些前提、前提在哪裡」攤開檢查的方法。
這篇寫給第一次設計 Agent 任務、也願意照著複製小段程式的新手。概念從零解釋;操作需要電腦已有 Python 3。你會用三份 CSV(逗號分隔的純文字資料檔)做一個虛構採購題,親手注入缺值、矛盾與不可讀來源,再檢查修補有沒有把答案一起塞給解題者。
方法背景來自 2026 年 10 月 27 日的 WorkFactory 論文;下方程式與採購數字是 AlphaLab 自製練習,採單次採購總成本,與論文的多年期成本案例分開。2026 年 11 月 2 日,我們執行了這份規則檢查程式與算術核對,範圍是資料診斷,沒有呼叫模型或重跑訓練。
先說結論:可解任務=前提齊全+來源可達+推導留給解題者
可解任務=前提齊全+來源可達+推導留給解題者。把它想成一道料理考題:食材、份量、限制要交代清楚,烹調與調味則留給考生。缺了一袋食材,不能只用成品不好吃來判定廚藝;把成品也放進材料包,又失去考試的意義。
- 先倒推:每項交付需要什麼資料,再問檔案是否存在。
- 分開檢查:欄位有值、跨檔一致、實際讀得到,各是一關。
- 修補前提:補運費、對齊同一份報價;總成本和推薦仍讓解題者完成。
一、Information Support Graph 是什麼?先分清「事實」與「工作」
在 WorkFactory 中,圖包含資訊單位、承載它的資料位置,以及資訊之間的支援關係;一項結果也可能同時需要多個前提。資訊會區分已提供、需外取、待解題者推導,以及建題內部使用的內容。原論文的 附錄 B說明了這個邊界:任務需要的事實要能取得,待算的結果仍由解題者產生。
套進本篇的練習,「訂購一百個」是輸入,「總成本」是待算結果;quotes.csv 是載體,supplier=C 那一列則是具體位置。若只寫「看附件」,卻沒指出哪一欄,你還要再問一次:讀者能從同一份材料找到相同的數值嗎?
這張圖關心「憑什麼得出答案」。Graph Engineering 工作圖關心誰先做、誰等誰;Agent Harness則安排工具與執行迴圈。畫出一條執行箭頭,仍要另外核對箭頭所需的資料是否存在。
二、先倒推交付物:三份 CSV 各自負責什麼?
我們的題目是:買一百個 BOX,等級至少二、交期最多八天;在合格供應商裡選總成本最低者,同價按代號排序。全部金額採美元,運費按件,設定費只收一次;這個虛構題排除稅、折扣與其他費用。這些規則先寫清楚,解題者才不必猜。
①「採購清單」:數量和限制
痛點是「最便宜」沒有範圍。解法是把需求固定在 requirements.csv:quantity 是數量,min_grade 是最低等級,max_days 是最長交期,currency 是幣別。驗收時,每一項合格判斷都應回指這一列。
②「報價單」:原料數值
痛點是單價低,結帳卻未必低。quotes.csv 分開列 unit_price、freight_per_unit 和 setup_fee。本題的計算關係是 quantity × (unit_price + freight_per_unit) + setup_fee。這是計算規則,並未替任何供應商填好總成本。
③「同一張身分證」:對齊對象與範圍
痛點是兩份資料看似相近,實際指向不同規格。profiles.csv 以 supplier + sku 對齊等級與交期。本題明定兩檔描述同一個當期報價,因此同欄應一致;真實採購若有不同日期、數量區間或運送條款,先把這些範圍加進識別條件,別急著判資料互相打架。

三、Information Support Graph 實作:先建立材料包
先在新空資料夾,將下列程式存成 make_lab.py,再執行 python3 make_lab.py;Windows 若以 Python Launcher 啟動,可用 py -3 make_lab.py。程式會建立 isg-lab,已存在就停止,避免蓋掉上一輪練習。CSV 用純文字編輯器保存;手動編輯時保留欄名、半形逗號與小數點。
from pathlib import Path
root = Path('isg-lab')
root.mkdir() # Stop if it already exists; do not overwrite a prior run.
files = {
'requirements.csv': '''sku,quantity,min_grade,max_days,currency
BOX,100,2,8,USD
''',
'quotes.csv': '''supplier,sku,unit_price,freight_per_unit,setup_fee,grade,lead_days,currency,source
A,BOX,9,1,100,2,7,USD,profiles.csv
B,BOX,8,1,0,2,10,USD,profiles.csv
C,BOX,10,0.5,0,3,5,USD,profiles.csv
''',
'profiles.csv': '''supplier,sku,grade,lead_days
A,BOX,2,7
B,BOX,2,10
C,BOX,3,5
''',
'TASK.txt': '''Use only TASK.txt and the three CSV files in this directory.
Choose one supplier for 100 BOX units. Minimum grade is 2 and maximum
lead time is 8 days. All quotes are for the same current offer and in USD.
Use requirements.csv as the requirement record. Each quote must agree
with its profile on grade and lead_days, and its source must be readable.
Total = quantity * (unit_price + freight_per_unit) + setup_fee.
No tax, discount, or other charges apply in this fictional exercise.
Choose the lowest total among eligible suppliers; break equal totals
by supplier ID ascending. Do not treat a blank price as zero.
If required evidence is missing or contradictory, report the blocker
and do not finalize a ranking. Write RESULT.md with the eligibility,
cost calculation and source row for each supplier, then your decision.
'''
}
for name, body in files.items():
(root / name).write_text(body, encoding='utf-8')
print('Created isg-lab: TASK.txt + 3 CSV files')
這時先別加 total_cost 或 winner 欄。給解題者的範圍是 TASK.txt 和三份 CSV;出題者可另畫支援圖、保存答案本,放在工作目錄之外。若 Agent 同時能讀上層目錄,單靠文字說「不要看」不構成隔離;試跑時要用工具或執行環境限制讀取範圍。
四、用一個小檢查器,找出三種阻塞
把下面程式存成材料包外的 check_inputs.py。在同一個父資料夾執行 python3 check_inputs.py isg-lab。程式以 Python 的 DictReader按欄名讀資料,並用 Decimal從字串檢查數值;newline="" 遵循 CSV 官方文件的開檔方式。
import csv
import sys
from decimal import Decimal
from pathlib import Path
root = Path(sys.argv[1]).resolve()
def require(ok, message):
if not ok:
raise ValueError(message)
def read(name, fields):
with (root / name).open(encoding='utf-8-sig', newline='') as f:
reader = csv.DictReader(f)
require(reader.fieldnames == fields.split(), name + ': schema')
rows = list(reader)
require(bool(rows), name + ': empty file')
for row in rows:
require(None not in row and all(v is not None and v.strip()
for v in row.values()), name + ': missing value')
return rows
def number(text, integer=False, positive=False):
n = Decimal(text)
require(n.is_finite() and n >= 0, 'invalid number: ' + text)
require(not integer or n == n.to_integral_value(), 'not an integer')
require(not positive or n > 0, 'must be positive')
return n
try:
reqs = read('requirements.csv',
'sku quantity min_grade max_days currency')
require(len(reqs) == 1, 'expected one requirement')
req = reqs[0]
number(req['quantity'], integer=True, positive=True)
number(req['min_grade'], integer=True)
number(req['max_days'], integer=True)
profiles = read('profiles.csv', 'supplier sku grade lead_days')
quotes = read('quotes.csv', 'supplier sku unit_price freight_per_unit '
'setup_fee grade lead_days currency source')
keys = lambda rows: [(r['supplier'], r['sku']) for r in rows]
require(len(set(keys(profiles))) == len(profiles), 'duplicate profile')
require(len(set(keys(quotes))) == len(quotes), 'duplicate quote')
require(set(keys(quotes)) == set(keys(profiles)), 'unmatched supplier')
require(len(quotes) == 3, 'expected three suppliers')
profile_map = dict(zip(keys(profiles), profiles))
for q in quotes:
label = q['supplier'] + ': '
require(q['sku'] == req['sku'], label + 'SKU mismatch')
require(q['currency'] == req['currency'], label + 'currency mismatch')
for field in ['unit_price', 'freight_per_unit', 'setup_fee']:
number(q[field])
p = profile_map[(q['supplier'], q['sku'])]
for field in ['grade', 'lead_days']:
require(number(q[field], integer=True) ==
number(p[field], integer=True), label + field + ' conflict')
source = (root / q['source']).resolve()
require(source.parent == root, label + 'source outside workspace')
with source.open(encoding='utf-8-sig') as f:
f.read()
require(source == root / 'profiles.csv', label + 'unexpected source')
print('PASS: declared inputs are filled, consistent and readable')
except (ValueError, OSError, csv.Error, ArithmeticError) as exc:
print('BLOCKED:', exc)
sys.exit(1)
原始材料應出現 PASS: declared inputs are filled, consistent and readable。這句話刻意限縮在已宣告的檢查:欄位、識別鍵、數字、同一報價的一致性與本機來源可讀。它不會判斷真實供應商說的是不是真話,也不會讀懂任意新題目的自然語言,更未評分最終推薦。
①「漏一塊拼圖」:把 C 的運費清空
痛點是空格被默認成零。在 quotes.csv 的 C 列,把 freight_per_unit 的 0.5 刪掉,保留左右逗號。再跑檢查器,應得到 BLOCKED: quotes.csv: missing value。這表示當前題目要求的成本前提缺失;先補回可信數值,再談誰更便宜。
②「同一張單據說兩種話」:改 A 的交期
先還原 C 的運費,再把報價檔 A 的 lead_days 從 7 改為 9,供應商檔保留七天。預期是 BLOCKED: A: lead_days conflict。這裡故意讓矛盾跨過八天門檻:若直接挑比較有利的數值,就可能改變資格。確認原始報價後,只修正有依據的那一份。
③「有地址,門卻打不開」:改來源檔名
還原 A 的七天,再將 C 的 source 改成 missing-evidence.csv。重跑應收到 BLOCKED 與找不到檔案的訊息。錯誤路徑依你的電腦而異。本次用本機缺檔模擬取證失敗;它沒有測量網站、登入限制或網路狀態。實際外部來源則須保存網址、時間、工具錯誤與存取條件。
來源檢查還用 Path.resolve()展開實際路徑,再限制在材料包內,避免把 ../ 指到別處。這是本練習的路徑檢查;真正隔離 Agent 的檔案權限,仍由你使用的執行環境設定。
五、修好資料後再解題:把三張成績單分開
AlphaLab 本次跑過原始材料、三種單獨注入的缺陷,以及各自還原後的版本:原始與還原版通過,缺值、交期矛盾、缺檔各被阻擋。這七次是同一個確定性程式的檢查紀錄;它們支持「這些規則抓得到這三種缺陷」,不構成 Agent 成功率或一般任務完整性的估計。
真正的解題試跑,要開全新工作階段,只掛載目前的 TASK.txt 和三份 CSV,要求交出 RESULT.md。別附上舊診斷、答案本或前次輸出。若工具無法限制可見範圍,就先把這一輪標為未完成隔離驗收,別把它混入乾淨試跑。
WorkFactory 的修補流程也保留解題工作:修正阻塞資料後,重新執行探查,而非直接交出完成的推薦。沿用這個原則,本題只補原始欄位;不要因為 C 難算,就把它從候選者刪除,或新增「選 C」提示。
- 環境單:哪些必需資訊已提供、是否一致、是否能讀取?缺陷指向哪個檔案、列與欄?
- 工具單:記成功呼叫數與總呼叫數,例如成功讀檔次數/全部讀檔嘗試;保留每次失敗的類型。尚未執行就記「未測」,不要填零或滿分。
- 成果單:打開 RESULT.md,核對資格、算式、引用列與最後選擇。另記是否杜撰缺值;工具回合較少只是一項過程觀察。
這個拆法也符合 Anthropic 的 Agent 評估說明對執行紀錄與最終環境成果的區分。聊天說「完成」是一段文字,檔案確實存在且內容合格,才是這一題的交付證據。想設計多題回歸,可接著讀 AI Evals 七步教學。
完成自己的解答後再核對:A 的成本是 100 × (9 + 1) + 100 = 1,100 美元;B 是九百美元,但十天超過限制;C 是 100 × (10 + 0.5) = 1,050 美元,等級與交期合格,所以本題選 C。這份答案放在文章供讀者自查,請別把本段或整篇文章交進解題工作區。
六、三個常見誤判:別把題目修成送分題
第一個是把合理分歧當缺陷。本題要求同一份當期報價一致,交期衝突才會阻塞;若題目本來就是「調查兩份報價為何不同」,矛盾可能正是工作材料。先問衝突是否妨礙最低交付,或只是需要解釋的證據。
第二個是把檢查通過當萬用保證。這支檢查器固定對應一個 SKU、三家供應商與本機來源。換成多幣別、分批交貨、階梯價格,就要新增範圍、公式與驗收條件;先讓新規則在刻意做錯的樣本上失敗,再相信通過結果。
第三個是把修補後變好全算給模型。比較模型時,固定材料版本、工具權限、提示與預算;比較修補時,固定解題配置。先把資料改動與模型改動拆成兩組對照,才說得清楚改善來自哪裡。需要判斷既有示範是否偷看答案,可接著讀 Trajectory2Gym 的可見證據練習。
常見問題:八個先講答案的判斷
1. 一定要安裝 WorkFactory 才能畫圖嗎?
本篇練習直接用紙筆與 Python 標準函式庫。WorkFactory 倉儲提供研究脈絡;這裡的三份 CSV 與檢查器由 AlphaLab 自行設計,請分開看待。
2. 它和知識圖譜有什麼差別?
先看用途。這裡從一項交付倒推必要前提與位置,目的是檢查任務支援;不用先替整間公司的所有知識建模。
3. 有空白欄,就一定整題不可解嗎?
看它是否必要。備註空白與必要運費空白,後果不同;本題刻意把宣告的欄位都設為必填,換題要重新定義。
4. 缺運費時,Agent 可以合理估算嗎?
要先看題目是否允許。本題要求可比較的確定成本,應回報缺口;若另設估算任務,需提供估算規則並把估計值標清楚。
5. 所有跨檔差異都要改成一樣嗎?
先對齊對象與範圍。不同日期、規格或交貨條件可以有不同數值;本例才明定兩檔屬於同一報價。
6. 來源檔讀得到,就證明資料正確嗎?
還要驗內容。程式可驗路徑與欄位,真實取證還須確認來源身分、適用期間與那一列究竟支持什麼。
7. 程式出現 PASS,表示 Agent 已經合格嗎?
尚未評到這一層。接著收 RESULT.md,按資格、算術與證據評分;把未跑的模型測試留為未測。
8. 可以把支援圖和答案都放進工作區嗎?
要配合測試目的。若要測從原始資料自行解題,答案與舊診斷放在外部;若任務是審查既有分析,已算出的結果可以成為待審材料,但那是另一張考卷。
給新手的三個重點
- 先畫「交付物需要什麼」,再整理「我有什麼檔案」。
- 每次只注入一種缺陷,保存修補前後的 CSV 與檢查輸出。
- 環境、工具、成果各留一張單;修好前提後,重新讓解題者做自己的工作。
接著閱讀
左右滑動查看更多推薦
下一步:今天先刪掉一個必需數值
建立材料包、清空 C 的運費、確認檢查器真的阻擋,再補回原數值重跑。記住前提齊全+來源可達+推導留給解題者:當你能說清楚缺的是哪一項證據,下一次 Agent 卡住,就有一個具體的修正起點。更多練習可從 AlphaLab AI 專區挑選,或到 AlphaLab 課程建立完整的學習路線。






