透過電話驗證
當代理必須確認已儲存的組織資訊是否仍然正確,且撥打該組織公佈的電話號碼是驗證的唯一方法時,請使用此技能。
verify-by-phone 是一個驗證工作流程技能。它對每個記錄發起一次且僅一次公開的 CALL-E 外撥通話,從通話記錄中提取帶有逐字支援區段的答案,使用透明的匹配權重算術將其與已儲存的記錄進行比對,並返回校準後的信心值或明確的棄權。其設計目標是建立一個永不將不確定的電話答案轉換成自信的資料庫寫入的代理。
使用時機
在以下情況使用此技能:
- 驗證提供者目錄列表:該診所是真實的、可聯繫的、接受新患者、接受特定保險計劃
- 檢查已儲存的商業記錄(營業時間、服務、可用性)是否仍然符合實際情況
- 重新整理任何以電話為事實來源且記錄可能過時的資料集
- 必須誠實記錄「未知」結果而不是猜測的工作流程
- 一次處理一筆記錄,且需有人類授權的接收方列表
不應使用的情況
請勿使用此技能來:
- 撥打未公開或虛假的電話;每一通電話都會在一開始就表明自己是自動化助手以及撥打原因
- 撥打無線或個人號碼;驗證目標為已公佈的組織電話線路
- 進行行銷、銷售、潛在客戶開發或任何推廣性質的外撥
- 在未經每筆記錄的人類授權情況下批次撥打列表
- 直接從通話結果覆寫已儲存的記錄;輸出是一個帶有證據的裁決,寫入決定權仍由操作員掌握
- 猜測受訪者未提供的答案;如果通話未產生可用的答案,結果就是棄權,而這才是正確的輸出
同意與揭露規則
這些是承載性的規則,並非樣板文字:
- 通話開始時,在一開始就同時表明 AI 身份和通話目的,並宣佈通話可能被錄音。
- 如果受訪者反對與自動來電者通話,通話應立即感謝並結束。結果將拒絕記錄為無法驗證的結果。
- 等待時間有上限。如果受訪者要求來電者等待,它會短暫等待,然後回報結果,而不是無限期等待。
- 代理絕不會捏造未被提供的資訊,無論是在通話中或結果中。具體來說:診所經常會要求來電者提供姓名、出生日期、保險會員或卡號碼,或就診原因。代理會明確表示它沒有這些資訊,因為這是目錄驗證電話而非預約請求,然後重複它打電話要問的問題。佔位符屬於捏造。
- 語音信箱不算答案。如果接通語音信箱或答錄機,通話會立即結束,不留下任何訊息:無法從錄音中確定目錄事實,而且沒有人應該在他們的線路上聽到機器人的留言。
- 通話是資訊驗證,絕非推銷。將每通電話視為在需全員同意的錄音要求下進行。
驗證工作流程
- 首先使用
scripts/calibrate.py根據標記的場景資料校準棄權門檻,讓「有信心」具有可衡量的意義:在預設層級下,真實答案在保留資料上至少有 90% 的機率落在預測集內。它會印出步驟 6 所需的qhat。此步驟無需憑證或通話即可運行,因此可以提前執行一次,無需進行任何撥號。 - 收集要驗證的記錄:組織名稱、E.164 格式的公開電話號碼,以及要檢查的聲明(例如接受新患者、接受某特定計劃)。
- 確認操作員授權對這個特定號碼進行這次特定通話。
- 使用
scripts/place_verify_call.py建立通話任務。該腳本預設會進行一次試運行,列印出確切的任務和接收者而不進行撥號;只有在試運行看起來正確後,才傳遞--live參數。 - 使用
scripts/poll_result.py輪詢最終結果,該腳本會將完整的內容保存到本地檔案。 - 使用步驟 1 產生的
--qhat參數執行scripts/extract_answer.py來提取答案。每個提取的欄位都帶有支援它的逐字記錄文字區段和字元偏移量。含糊的答案(「我想是」)會以被稀釋的可信度分數保留其極性。無回應的對話(打錯電話、拒絕、「稍後再打」)永遠不算答案。只有在校準後的預測集是單一值且該值不是「unknown」時,才會提供答案;否則結果就是棄權。省略--qhat將會對所有內容棄權,並將輸出標記為uncalibrated,因為沒有校準依據的門檻無法保證任何結果。 - 使用
scripts/reconcile_record.py與儲存的記錄進行比對:每個相符的欄位會增加有記錄的證據權重,每個不符的欄位則會減少,最終裁決為已驗證、已矛盾或無法驗證。
維護說明
此技能中的腳本是 Attest 後端(原始碼儲存庫中的 backend/app)參考實作的獨立副本。它們刻意保持小巧,以便技能安裝時不需依賴該儲存庫。
該副本是強制性的,而非僅是承諾。原始碼儲存庫中的 tests/test_skill_parity.py 會對相同的通話記錄執行此技能的提取器和後端的提取器,如果它們在答案、引用區段的字元偏移量或提示詞典本身有任何不一致,測試就會失敗。此說明的早期版本要求人類手動重新同步,但副本仍然出現了漂移:後端學會了信任對話中最後一個提示並將「沒問題」解讀為同意,而此腳本仍然信任第一個提示,因此一個簡單的「不,我們不收」在這裡導致棄權,而在那裡卻給出了答案。
快速開始
pip install calle-ai
# 1. 首先校準門檻。印出步驟 5 所需的 qhat。
python3 scripts/calibrate.py --data references/sample-scenarios.jsonl --alpha 0.1
# 2. 試運行:列印出任務和遮罩後的接收者,不進行任何撥號。
python3 scripts/place_verify_call.py \
--org "範例諮詢中心" \
--phone "+15550101234" \
--claim-accepting-new-patients yes \
--claim-plan "範例健康 PPO"
# 3. 實際撥打通話(需要 CALLE_API_KEY)。
python3 scripts/place_verify_call.py ... --live
# 4. 等待最終的內容。
python3 scripts/poll_result.py --call-id call_abc123 --out result.json
# 5. 提取帶有文字區段支援的答案,並由校準後的門檻進行門控。
python3 scripts/extract_answer.py --payload result.json --qhat 0.750
# 6. 與儲存的記錄進行比對。
python3 scripts/reconcile_record.py --payload result.json \
--claim-accepting-new-patients yes --claim-plan-accepted yes
此技能中的所有範例號碼均為保留的虛構號碼。試運行路徑和捆綁的場景資料意味著除了步驟 3 之外,所有操作都不需要任何憑證或實際通話。
輸出範例
extract_answer.py 會為每個聲明輸出一個 JSON 物件:
{
"claim": "accepting_new_patients",
"answer": "yes",
"trust_score": 0.9,
"hedged": false,
"span": {"turn": 6, "text": "有啊。", "char_start": 0, "char_end": 3},
"abstain": false,
"gate": "conformal(qhat=0.750)"
}
棄權會保持相同的結構,但 "abstain": true,原因可能是校準後的預測集包含多個標籤,或是提取器完全找不到任何答案("answer": "unknown")。gate 欄位會指出做出決策的門檻,當未提供 --qhat 時則顯示 uncalibrated,這是在這種情況下無論說了什麼,每個聲明都會棄權的唯一情況。reconcile_record.py 會加上匹配權重算術和一個裁決。每個欄位都必須附帶一個支援的文字區段或一個明確的棄權。
副作用與取消
- 副作用:每次執行
--live時,會對操作員提供的號碼撥出一通外撥電話。沒有遞迴;此技能中沒有排程器。 - 費用:每次實際執行會產生一次付費的 CALL-E 通話。試運行是免費的。
- 取消:CALL-E 不提供取消通話的功能,因此停止的時機是在使用
--live之前。預設的試運行模式正是為了這個原因而存在。 - 資料:內容會寫入操作員指定的本地檔案。電話號碼會在控制台輸出中被遮罩。除了 CALL-E API 本身之外,此技能不會將結果傳輸到任何地方。
參考資料
references/api-notes.md:此技能所依賴的、透過經驗觀察到的 CALL-E 內容結構和 API 行為,包括透過測試而非文件發現的事實。references/verification-protocol.md:完整的揭露腳本、外撥驗證通話的法律立場,以及為何棄權是核心設計決策。references/sample-scenarios.jsonl:由scripts/calibrate.py使用的標記虛構場景資料,以便在校準時無需任何憑證或通話。