iT邦幫忙

2026 iThome 鐵人賽

DAY 13
0
AI 自動化

情報進來,內容發出去:30 天拆一條每天真的在跑的 AI 內容產線系列 第 13

Day 13|逐字稿裡的一句話,什麼時候才算行動候選?

  • 分享至 

  • xImage
  •  

一筆 JSON,欄位齊全、型別正確、引用的來源片段真的存在、文字摘要也對得上。

它把「可以先評估是否整理檢查表」這句話標成了承諾。

前兩層檢查全部放行。抓到它的是第三層:一份跟輸入分開保存的合成標準答案。這是今天最重要的一個反例,也是為什麼「JSON 能解析」離「可以變成待辦」還很遠。

今天全文只守一條:模型可以從自然語言提出原始提案,但不能自己宣布提案已通過,更不能建立待辦。

接住第 12 天:知道是誰,不代表他答應負責

第 12 天把「這句是誰說的」做成可以暫停、跨程序續跑的分支。身分確認了,能寫的只有具名說話者中繼資料。

今天往前一步。逐字稿裡有人說「這個項目由我處理」,要具備哪些證據,才有資格變成一筆等人審的行動候選?

天數 新增能力 明確不做
12 身分分支保存複核請求,跨程序讀回決定再續跑 不判斷行動、不建立待辦
13 把原始提案驗成帶來源、可審或缺欄位的行動候選 不批准、不呼叫待辦工具
14 另做行動批准,交給假執行器並驗重送不重複建立 不碰使用者的真實待辦

知道說話者是誰,不代表他承諾負責;看到承諾,也不代表候選已獲准執行。這兩條批准不能沿用。

先承認一條接縫

第 10 天正文提的逐字稿包,跟第 12 天程式裡同名的 transcript-package.v1 不是同一個資料形狀。後者只有時間區段與匿名標記,而且 contains_transcript: false

所以今天沒有回頭替第 12 天補文字。我另開一份 day13-synthetic-transcript.v1:四段都明示為合成測試資料,沒有音訊、沒有真實會議、沒有真人身分,adapter_note 寫明不宣稱與前兩種格式相容。這是一個新的受控轉接測試,不是端到端整合。

全文只回答一個問題

一筆模型整理出的文字,要具備哪些可回查證據,才有資格成為等待人審的行動候選?

答案不是「JSON 能解析就好」。至少要分開回答五件事:模型到底提出了什麼、引用哪一版來源、哪些片段分別支持任務/承諾/負責人主張、缺了什麼、程式允許的下一步是什麼。

不比較模型,不調提示詞,也不證明任何真實會議曾出現同樣的句子。下面講。

模型的提案,和程式信任的候選,不是同一份資料

用生活的方式想:面試官寫的評語,和 HR 蓋章的錄取通知,是兩張紙。評語可以寫得很篤定,但「錄取」那個章不能由寫評語的人自己蓋。

放進工作流,就是兩份資料:

資料 可以包含 絕對不能由它自己填
raw-action-proposal.v1 行動文字、來源片段、語意訊號、發言者、負責人主張、原始期限文字 validation_state、批准、允許動作、工具能力、真人 person_ref
action-candidate.v1 經驗證的來源綁定、缺欄位、狀態、固定政策與能力上限 行動批准、待辦執行結果

如果讓模型在同一份輸出裡填 ready_for_action_reviewallowed_next_actions,模型就等於能替自己蓋章。今天的程式會拒收 approvedcreate_task、權限或身分注入欄位,再由本地政策產生可信狀態。

老實說,這次沒有真的呼叫模型。原始提案是手工固定的「模型輸出形狀」測試資料,execution_mode 標成 fixed_fixture_no_external_model。可信欄位由本機程式附加。今天測的是控制層,不是抽取能力。

語意和責任,要拆成三欄

討論、決定、承諾不是單選

方向初稿把 discussion_onlydecision_recordedcommitment_detected 做成一個單選狀態。後來發現這會抹掉真實的組合:一筆行動可能先被討論、再形成決定、最後有人承諾。三件事都發生過,單選只能留一個。

所以改成可並存的 semantic_signals[]discussiondecisioncommitmentunknown。資料完整度另外放在 validation_stateincompleteready_for_action_review。一軸記「看到哪些語意證據」,另一軸記「依這次測試政策能走到哪裡」,不再把缺欄位混成語意類別。

誰說了,和誰被指派,是兩欄

uttered_by 只回答:哪些匿名說話者講了被引用的片段。assignee_claim 才回答:提案聲稱誰負責,根據是什麼。兩者不能合併。

合成正常例裡,任務描述由 SPEAKER_SYNTHETIC_A 說出,承諾由 SPEAKER_SYNTHETIC_B 說出。程式只在三件事同時成立才接受 explicit_self_commitment:同一個承諾片段被標為 commitment,也被標為 assignee,而且該片段的說話者跟 assignee_claim.speaker_ref 相同。

即使全部成立,person_ref 仍是 null。匿名說話者沒有被自動升成真人姓名。這是第 11、12 天的邊界,今天不偷渡。

本例只測明示的自我承諾。第三人指派、委派、拒絕、共同負責、組織授權,都沒有涵蓋。

三層驗證,各擋一種錯

驗證層 具體檢查 擋不住什麼
形狀 必填、型別、列舉、額外欄位、識別碼、SHA-256 字串形狀 句子是否真的表示承諾
來源 來源版本、片段存在、文字摘要、發言者、跨片段參照 模型是否把討論誤標成承諾
合成測試政策 任務描述、承諾證據、明示負責人主張、缺欄位、允許下一步 Ci 真實組織的責任與批准規則

三層之外,還有一份跟輸入分開保存的合成標準答案,專門抓開場那種「形狀合法、來源也對,但語意標錯」的固定反例。

正式環境沒有隱藏的標準答案。那時候要靠評測資料或人審,不能假裝第三層已經證明語意為真。

為什麼形狀對了還要往下驗

OpenAI 的 Structured Outputs 指南把這個機制定位為「讓輸出遵循指定的 JSON Schema」,物件通常要列出必要欄位並禁止額外屬性。同一份指南另有一節「Handling mistakes」,明說結構化輸出仍可能包含錯誤;拒答會以另一種內容型別出現,不一定符合原 schema;incomplete 也要在程式裡獨立處理。

JSON Schema 2020-12 的規格自己也講得很直白:單靠結構驗證,可能不足以讓應用程式正確使用某些值。typerequiredenumadditionalProperties 能擋錯欄位;它們不會知道「這個我來處理」指的是誰。

所以今天可以說「成功分支的形狀可以被約束」,不能說「形狀合格就證明逐字稿真的有承諾」。拒答、截斷、空內容,也不能被改寫成「零筆正常候選」。

這次的形狀驗證是手寫的嚴格版本,沒有安裝通用 JSON Schema 驗證器。兩份 schema 都明列 Draft 2020-12 與固定 $id$id 是識別用的 URI,不保證可以下載。

三筆提案,三種結果

輸入是四段合成逐字稿,每段五秒,總長 20 秒:

▸ A 說:可以先評估是否整理發布前檢查表。

▸ A 說:決定保留發布前檢查表這個方向。

▸ A 說:請補上通知設定的檢查項目。

▸ B 說:這個項目由我處理。

固定的三筆原始提案,各引用不同片段:

原始提案 語意訊號 結果 為什麼
只討論要不要整理檢查表 discussion recorded_discussion 留軌跡,不產生候選
決定保留檢查表方向 decision incomplete_candidate 缺承諾證據與負責人參照
一段描述任務,下一段明示由自己處理 commitment ready_for_action_review 任務、承諾、負責人主張與三筆來源參照吻合

第二筆的 missing_fieldscommitment_evidenceassignee.speaker_ref。程式沒有替它補負責人,也沒有補期限。

第三筆引用了三筆來源參照:任務描述那段(角色 task_description)、承諾那段(角色 commitment)、同一段再標一次(角色 assignee)。三筆都要存在、摘要都要對,才走到 ready_for_action_review

三條路的 external_model_callstask_executor_callspublish_calls 全部是 0。期限沒有出現在任何片段裡,所以保存 raw_text: nullstatus: not_stated。程式沒有補一個看起來合理的日期。

可審候選的最小形狀

{
  "schema_version": "action-candidate.v1",
  "candidate_id": "candidate-proposal-synthetic-commitment",
  "action_text": "補上通知設定的檢查項目",
  "semantic_signals": ["commitment"],
  "uttered_by": ["SPEAKER_SYNTHETIC_A", "SPEAKER_SYNTHETIC_B"],
  "assignee": {
    "speaker_ref": "SPEAKER_SYNTHETIC_B",
    "person_ref": null,
    "basis": "explicit_self_commitment"
  },
  "deadline": { "raw_text": null, "status": "not_stated" },
  "validation_state": "ready_for_action_review",
  "missing_fields": [],
  "policy_id": "synthetic-review-policy.v1",
  "allowed_next_actions": ["request_action_review"],
  "forbidden_capabilities": ["create:task", "publish:content"]
}

這是精簡節錄,完整檔另含每個片段的 SHA-256 文字摘要。欄位是本文設計,不是供應商標準。

ready_for_action_review 的意思只有「可以送人審」。不是已批准。allowed_next_actions 只有一項,forbidden_capabilities 明寫不能建待辦、不能發布。

六份產物,讓每一步都能回查

synthetic-transcript.json
  ├─ synthetic-gold.json
  └─ raw-action-proposals.json
       ├─ action-candidates.json
       ├─ artifact-manifest.json
       └─ validation-trace.json

逐字稿保存輸入片段;標準答案跟模型輸入分開;原始提案明示沒有呼叫模型;候選檔保留三筆判定與唯一一筆可進人審的候選;產物清單記錄使用與產生的摘要;軌跡逐層保存通過、缺欄位或停止的原因。

軌跡裡有五道 gate:response_statusraw_proposal_shapesource_bindingsynthetic_test_policysynthetic_gold_oracle。每一道都寫下自己的結果。

只保存最後一行待辦文字,會失去前面所有判斷依據。W3C PROV-DM 把來源追溯拆成實體、活動、代理者,以及使用、產生、衍生等關係。放到今天:合成逐字稿、原始提案、已驗證候選是不同實體;擷取與確定性驗證是不同活動。這份產物清單借用這個拆法,沒有映射完整 PROV 約束,不能稱為 PROV 相容。

記錄這些關係,也不會自動讓內容成真。

正常路徑之外,故意弄壞八種輸入

變異 預期結果
來源片段不存在 evidence_segment_not_found
文字摘要與片段不符 evidence_text_digest_mismatch
舊提案套到新版來源 stopped_source_stale
負責人主張與承諾片段說話者不同 assignee_evidence_mismatch
缺必要欄位 proposal_shape_invalid
夾帶 approvedcreate_task proposal_capability_injection
模型回應形狀為拒答/截斷/空內容 分別停止,不補候選
Day 12 身分決定冒充行動提案 proposal_shape_invalid
合法形狀把討論誤標成承諾 合成標準答案回報 semantic_gold_mismatch

原因碼是本篇範例介面,不是任何規格或研究的共同錯誤碼。這批專項測試我這次跑是 16 條全過。

最後一條測試是重播:讀回同一份已保存的 raw-action-proposals.json,再跑一次確定性驗證器,比對 replay_digest 相同,而且不修改輸入。

這裡的「重播」定義得很窄。OpenAI 的 API 概覽明示模型輸出有變異性,不同模型快照的提示行為也可能改變;固定版本並建立評測能提升一致性,但不是逐位元重現的保證。所以再問模型一次,是一次新的抽取執行,應有新的執行識別、模型版本與原始回應,不能拿來證明舊結果可重播。

摘要能抓什麼

來源整體版本與每段文字摘要分開保存:來源換版就停止,片段文字變了也拒收。摘要相同只表示這次沒有偵測到內容差異;它不能證明發言真的發生、說話者是誰、某人有權承諾,或候選已經獲准。

算摘要之前,JSON 要先有固定表示。這次沿用專案內的受控做法:遞迴排序物件鍵再算 SHA-256,只處理固定 fixture 的有限值型別。可以說同一份保存輸入在本程式中重算一致;不能說已跨語言符合 RFC 8785。

為什麼不做「一句話是不是行動項目」的二元分類

這不是我發明的拆法。2006 年 Purver、Ehlen、Niekrasz 研究會議裡的行動項目,就沒有把它標成一句話的是/否。他們把相關發言拆成任務描述、時間範圍、負責人、同意四類,並指出同一句可能同時扮演多種角色,同一個行動項目的角色也可能分散在多句。

隔年的後續研究把行動項目描述成「對某項任務的公開承諾」:先找出提議、討論、承諾發生的子對話,再抽任務摘要。任務描述與屬性常分散在多個發言。這是為什麼正常合成例刻意把任務放在一段、承諾放在下一段,並要求兩段來源參照都存在。

決定也一樣。Fernández 等人把決策偵測建模成多人對話裡的結構問題:不同發言在討論與採納時扮演不同角色。所以今天保留 decision 訊號,但不自動補承諾。固定決定例有行動文字,仍因缺 commitment_evidenceassignee.speaker_ref 停在 incomplete

還有一個歷史數字值得放著提醒自己。Morgan 等人 2006 年在 ICSI 會議錄音上偵測行動項目,F-measure 是 31.92%,摘要明列語料高度不平衡、標註者一致性低。這個數字不能拿來跟今天的模型比,它只說明一件事:「什麼算行動項目」本身就需要明確定義。語意標準答案、錯誤案例、人審、來源回查,都是因為這個。

AIMU 研究在 22 場 ICSI 會議、約 21K 發言上標了 10 種預先定義的意圖,也標行動相關參數,並強調判斷要看上下文。今天借用的只有責任拆法:原始提案保留語意訊號、行動文字、負責人主張、期限原文與來源片段。不把那 10 種意圖搬成分類表,也不宣稱重跑過該資料集。

這些論文都是當年資料與方法的結果。它們給的是問題的拆法,不是今天任何模型的準確率。

這次證明了什麼,沒證明什麼

證明了:

1/ 三筆固定提案在確定性驗證器下得到三種不同結果,討論不成候選、決定缺欄位、跨片段承諾可送人審。

2/ 形狀合法、來源可回查的錯標,會被分開保存的合成標準答案抓到。

3/ 八種壞輸入各有停止原因,沒有一種被補成候選。

4/ 重播同一份保存輸入,結果摘要相同,輸入不變。

沒證明的:

▸ 任何模型的抽取能力。原始提案是手工固定的形狀測試資料,沒有呼叫模型。

▸ 真實會議、真人、真實政策。synthetic-review-policy.v1 是教學政策。

▸ 第三人指派、委派、拒絕、共同負責。只測了明示的自我承諾。

▸ 與第 10、12 天資料形狀的相容性。今天是獨立轉接器。

下一篇:候選要拿到執行資格,得另一份批准

今天最後只交出一筆綁定來源版本的 action-candidate.v1allowed_next_actions 只有 request_action_review。它沒有 approved,沒有 task_created,也沒有待辦工具可以呼叫。

Day 14 才新增另一份行動批准,把批准範圍、候選版本、來源版本綁在一起;再交給假執行器,驗證相同批准重送不會建立兩次、相同識別碼換內容必須衝突。

第 12 天的身分確認,仍然不能沿用成行動批准。

參考資料


上一篇
Day 12|不知道是誰,不用整條重跑:具名分支怎麼暫停再繼續?
下一篇
Day 14|行動批准後建立待辦,重跑為什麼不能建立兩次?
系列文
情報進來,內容發出去:30 天拆一條每天真的在跑的 AI 內容產線18
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言