面向 TMC 與 OTA 的代理式 AI 旅遊訂位
我們打造了一個自主旅遊訂位代理,其控制流程是確定性 Python。模型只負責解析行程請求並撰寫回覆。每一步訂位都會登錄補償動作,因此當飯店費率在機票開票後過期時,代理會在 24 小時窗口內作廢機票,並交給旅客誠實的替代方案,而不是讓他們滯留。
100%
終端狀態一致,由建構保證
固定種子、200 情境合成批次,對照 LLM-in-control 基準的 65%
0 / 0
滯留旅客、被呈現的捏造訂位
同一批次,對照基準的 40 與 30
$3.25
每次訂位的平均 GDS 搜尋花費
對照基準 $7.57;GDS 按次搜尋計費,Lufthansa 於 2026 年 1 月 1 日調升費用
所有情境皆為模擬 GDS 與 CRS 上的合成資料;機場代碼與飯店名稱是真實形貌的測試夾具,並非即時庫存或真實訂位。
兩者都不是模型智商失效。兩者都已是 2026 年的缺陷類別。
代理開了機票,飯店步驟失敗,沒有補償邏輯時它仍說「一切就緒。」有人只拿到機票、沒有房間。再完美的模型,若沒有任何東西作廢機票,仍會讓旅客滯留。
它捏造一間看似合理的飯店並完成訂位。該物業從未存在於 CRS。在到達旅客之前沒有任何檢查,因為在推理迴圈裡,模型既是提案者也是裁判。
更好的模型修不好這件事,因為這些失效是基礎設施與使用事件,與模型品質無關。費率在兩次 API 呼叫之間過期。開票後 hold 被拒絕。搜尋風暴燒光毛利。隨機推理會對此疊加:十個步驟各 90% 可靠度,端到端大約只剩 34%,而 GPT-4 搭配 ReAct 完成真實多日行程的比例為 0.6%(TravelPlanner,OSU NLP,arXiv 2402.01622)。你無法靠提示詞走出疊加的隨機失效。
而且部署者擁有代理所做的每一句陳述。在 Moffatt v. Air Canada(BC Civil Resolution Tribunal,2024 年 2 月 14 日)中,該航空公司因其聊天機器人捏造喪親票政策而被判賠償 $812.02,「AI 是獨立實體」的主張被駁回。
控制流程是手寫的 Python 狀態機,約十個節點。LLM 被限制在兩項葉節點工作。兩者之間的一切都是確定性的。
input → extract(LLM 葉節點)→ search → policy gate → verify gate → hold → ticket → hotel-book → commit
模型將自然語言意圖解析為 Pydantic 型別化的 TripRequest (出發地、目的地、日期、旅客、艙等、飯店)。該型別化物件是 LLM 產出的唯一結構化產物。它可透過 Pydantic AI 替換供應商,並在沒有金鑰時以確定性 stub 完全離線執行。
企業政策以純 Python 述詞存在:僅限經濟艙、每航段 $600 票價上限、偏好承運人(United、American、Delta)、每晚 $350 飯店上限。超出政策的選項在實體上無法呈現,因為它們在顯示前就被過濾,而不是事後標記。未知票價家族採失效保護,視為高於政策而非默默當成經濟艙。沒有符合政策的航班時,代理升級到人工佇列,而不是虛張聲勢。
每一間飯店皆對照 CRS,以 property_id。模型捏造的物業根本不在 CRS 中,因此會被拒絕且永不呈現,訂位進入終端狀態 abstained。閘道拒絕未確認的庫存;它不會要求模型為自己的輸出打分。
每一步向前都會在執行當下登錄其反向動作。例如開票會登錄「作廢機票,24 小時窗口」。步驟 N 失敗時,補償從 N-1 往下到 1 依反向順序執行,然後代理才回報。這就是示範與產品的分野,因為它讓部分失敗不會變成滯留的顧客。
即時計數器以每航段 $3.25 追蹤 GDS 搜尋花費,因為計費的是搜尋,而不只是訂位。L2B 快取與延遲搜尋讓花費持平,而投機代理會反覆再搜尋並燒光毛利。每一筆訂位寫入僅附加的 JSON 事件日誌,可匯出為 audit-<pnr>.json,內容包含模型與版本、型別化行程請求、每一個節點裁決、每一次 Saga 補償、EU AI Act Article 50 揭露旗標,以及終端狀態。
四個按鈕,與同一情境上真實的 LLM-in-control 基準並排。下方每張截圖皆擷取自正在運行的應用程式。
「ORD 到 SFO,下星期二,市中心一晚,公司政策。」狀態機跑過每個節點,依 property_id 對照 CRS 確認 Hyatt Regency SF,搜尋計量表在一次快取搜尋上維持 $3.25。終端狀態:confirmed,附帶 PNR。
請求點名了一間捏造物業「Tabacon Springs Eco-Lodge」,這個名稱混合兩家真實度假村,依設計沒有 property_id。閘道找不到 CRS 相符項,拒絕呈現。代理誠實棄權:「我無法確認該物業」,而不是再捏造一間。
飯店費率在機票已經開票後過期。在我們這邊 Saga 觸發:在 24 小時窗口內作廢機票、釋放 hold,並誠實回覆機票已免費作廢,且附上替代方案。終端狀態:rolled back,旅客安全。同一情境的基準讓機票維持已開出、不提供補償,並發出虛假的「一切就緒」,這正是等待發生的 Air Canada 先例。
按一下即可匯出 audit-<pnr>.json:模型與版本、型別化行程請求、每一個節點及其確定性裁決、每一次 Saga 補償、EU AI Act Article 50 揭露旗標(透明度義務自 2026 年 8 月 2 日起適用),以及終端狀態。
同一批 200 筆合成訂位、一個固定種子(42),以及相同注入的基礎設施失效,分別跑過兩種架構。情境組合為 50% 順利、20% hotel-fail-after-ticket、15% hallucinated-entity、15% search-storm。我們的保證由建構成立;基準的失效從同一份資料浮現。
基準是在相同情境上運行的真實 ReAct 風格 LLM-in-control 代理,是誠實錨點而非稻草人。下方數字來自固定種子、200 情境合成批次(benchmark.py,seed 42,n=200)。
| 指標 | 確定性代理(我們的) | 基準(LLM-in-control) |
|---|---|---|
| 終端狀態一致 | 100.0% | 65.0% |
| 滯留旅客 | 0 | 40 |
| 被呈現的捏造訂位 | 0 | 30 |
| 每次訂位的平均 GDS 搜尋花費 | $3.25 | $7.57 |
這 100%、0 與 0 是在此固定種子合成批次上由建構成立,並非開放世界的正式環境保證。主張狹窄且耐久:部分訂位永不顯示為 confirmed,旅客永不滯留。$3.25 對 $7.57 的差距是在任何模型品質下都成立的毛利數字。
保證並非來自信任模型。在本示範中,控制流程是確定性 Python,每一步向前都會在執行當下登錄補償動作。當某一步在開票後失敗,引擎以反向執行那些補償(Saga),在 24 小時窗口內作廢機票,並誠實回報。旅客永不只拿到機票、沒有房間,因為清理不取決於模型決定要不要做。
不會。本示範中的 GDS、CRS、開票與付款全部是 stub 並模擬。測試夾具轉接器是 V1 整合,背後沒有即時的 Amadeus、Sabre 或 Duffel 帳戶。示範證明的是控制流程架構與補償邏輯,不是正式環境訂位管線。
這正是 Saga 被打造來處理的案例。開票在執行當下登錄自己的反向動作(在 24 小時窗口內作廢機票)。若飯店費率在 commit 前過期,引擎依反向順序觸發補償,免費作廢機票、釋放 hold,並交給旅客誠實的替代方案。終端狀態是 rolled back,不是 confirmed,也不是 stranded。
驗證閘道在呈現之前,依 property_id 對照 CRS 確認每一個物業。當本示範的請求點名一間捏造物業時,閘道找不到 CRS 相符項,拒絕呈現,代理誠實棄權而不是完成訂位。閘道不是事後標記虛構飯店;它讓該飯店在實體上無法呈現。
ReAct 風格代理讓 LLM 掌管交易,因此由它決定何時搜尋、訂位與開票,而且沒有閘道、也沒有補償邏輯。在同一固定種子、200 情境合成批次上,該基準呈現了捏造庫存,並讓機票維持已開出、沒有回滾,發出虛假的「一切就緒」。在這裡,LLM 是只解析意圖並撰寫回覆的型別化葉節點;確定性程式碼擁有流程,每一步都帶著自己的復原。
部署者擁有其代理所做的每一句陳述。在 Moffatt v. Air Canada(BC Civil Resolution Tribunal,2024 年 2 月 14 日)中,該航空公司因其聊天機器人捏造喪親票政策而被判賠償 $812.02,「那是 AI 所為」抗辯被駁回。示範匯出每筆訂位的 JSON 稽核軌跡,含模型與版本、每一個節點裁決、每一次 Saga 補償,以及 EU AI Act Article 50 揭露旗標,因此代理做過什麼事後可檢查。
支撐本示範的研究——架構、驗證設計,以及企業藍圖。
完整解決方案
探索代理式 AI 旅遊訂位解決方案 →讓旅客滯留、捏造飯店的那些失效,是基礎設施事件,不是模型智商問題。
若你的團隊正在衡量 LLM 在高風險訂位代理中該落在哪裡,以及如何讓部分失敗不變成 Air Canada 式的責任,我們很願意對照彼此的思路。問題是全產業的,答案也會是。