跳至主要內容

指南

模擬使用者

腳本化的對話以一個從不作出反應的使用者來測試您的助理。模擬使用者會作出反應:一個模型扮演每個案例所描述的人,根據您的助理剛說的話寫出下一則訊息,並在目標達成或放棄時停下。Oloproof 記錄雙方之間傳遞的內容,像量測任何對話一樣量測它,並且只有在人們認定模擬使用者真實之後,才讓閘門依據它作出決策。教學示範了一個客服台與模擬顧客的對話。

角色設定

每個案例的輸入包含一個角色設定(persona):使用者是誰,想要什麼,知道什麼。

{"id": "c25", "input": {"persona": {
  "description": "A retired teacher who ordered a cookbook last week. Writes short, polite messages.",
  "goal": "Have the order of a cookbook delivered to my new address.",
  "facts": {"order": "B-35", "postcode": "10275"}
}}}
  • description 和 goal 是必需的。寫一個讀者只憑對話就能核對的目標:「讓商店開始退款」可以根據助理說的話來判定,「拿到退款」則不行,因為錢是之後才入帳的。
  • facts 是使用者知道、只在對話需要時才透露的資訊,例如訂單編號。您的助理從不會看到角色設定。
  • opening 是使用者的第一則訊息,逐字照錄,用於每個系統都應以同樣方式被問候的情況。
  • max_turns 限制這個使用者的訊息則數,覆寫專案的設定。

角色設定是資料集內容:它包含在套件摘要中,對依據它量測的每個系統都相同。

宣告模擬使用者

扮演每個角色設定的模型在系統上宣告,與評審一樣:

system:
  name: support-desk
  callable: desk:talk
  simulated_user:
    provider: openai_compatible
    base_url: http://localhost:11434/v1
    model: qwen2.5vl
    max_turns: 6

每個欄位都在設定參考中。本機模型不花錢;託管模型對它寫的每則訊息計費,它的 token 記錄在對話旁邊,從不計入您的系統的成本。

您的系統保留自己的迴圈

Oloproof 不驅動對話。您的系統索取使用者的第一則訊息,以它平時回答使用者的方式回答,並把每個回答交回去以取得下一則訊息:

from oloproof import current_case

def talk(case):
    user = current_case().simulated_user()
    message = user.opening()
    while message is not None:
        message = user.reply(my_assistant.answer(message))
    return {}

一旦使用者停下,reply 回傳 None。您的系統可以用 user.end(answer) 自己結束對話,就像轉交給真人那樣;async def 系統則 await aopening()、areply(answer) 和 aend(answer)。Oloproof 把經過該控制代碼傳遞的內容記錄為 conversation/v1,把對話如何結束記錄為 simulated_user/v1,並拒絕來自您的系統的這兩者(SDK 參考)。

對話如何結束

在您的系統每次回答之後,都會單獨向模擬使用者的模型提一個問題,溫度為 0,且不帶周圍的角色扮演:這個回答是否完成了目標。如果完成了,對話以 goal_reached 結束。否則使用者寫出下一則訊息,或者離開(user_left),直到它已傳送 max_turns 則訊息(turn_limit)。如果系統沒有回答最後一則訊息就停下,對話會處於 unanswered 狀態並被截斷。

單獨提問正是讓小型本機模型可用的原因:扮演一個角色設定和判斷目標是否達成是兩項不同的任務,被要求在一次回覆中同時完成兩者的模型,往往會在目標達成後繼續閒聊,或者在已經滿意時說自己要離開。

量測對話

對話是單位:每個評估器對每段對話給出一個結論,因此每個區間、比較和閘門都原樣適用。

類型通過條件
conversation_completed您的系統回答了每則訊息
goal_reached目標檢查發現目標已達成
turns_to_goal在使用者的 max_turns 則訊息之內做到了這一點
every_turn每個回答都滿足宣告的條件:必須包含或不得包含的詞、一個模式、一個長度
conversation_judge一個評判整段對話紀錄的模型評審讓它通過,前提是已對照人的標籤驗證過

重複(replicates:)會遇到以不同種子初始化的使用者,因此一個角色設定就是多段對話。模擬使用者的版本(它的模型、提示詞、溫度和預算)是每次執行的快取鍵的一部分,因此換一個模擬使用者會重新量測您的系統。

驗證模擬使用者

基於模擬使用者得出的結果,只有在模擬使用者與真實使用者相似的程度上才適用於真實使用者。因此,對於使用者是模擬出來的執行,每條規則都是 INSUFFICIENT_EVIDENCE,附帶 simulated_user_not_validated,直到人們認定它的對話真實為止:

oloproof labels export RUN_ID --criterion simulated_user_realistic --sample 30 --local --out realism.csv
oloproof labels import realism.csv
oloproof simulated-users RUN_ID

表格展示每段抽中的對話,以及角色設定和對話如何結束。當一個真實顧客可能寫出使用者一方的內容,並在那裡、以那種方式結束對話時,標註者把 passed 標為是,這也涵蓋了目標檢查:目標沒有達成卻以 goal_reached 結束的對話是不真實的。當真實對話所占比例的精確下界達到 release.yaml 中的 minimum_simulated_user_realism 時,該模擬使用者即在該套件上通過驗證。抽中但未標註的對話算作不真實,而一段對話只有在每位標註它的人都認為真實時才算真實。

一次驗證涵蓋一個模擬使用者版本在一個套件上的情況,無論它與哪個系統對話,因此依據同樣的角色設定量測的候選會依據基準的標籤作出決策。新的模型、提示詞設定或角色設定集需要新的標籤。設定 require_validated_evaluators: false 會在沒有這些標籤的情況下依據模擬使用者作出決策,這是知情的選擇。

模擬與真實並列

oloproof simulated-users RUN_ID --real REAL_RUN_ID 把模擬對話的樣貌與一次真實對話的執行(作為 conversation/v1 重播的日誌聊天紀錄)並列展示:使用者傳送了多少則訊息,訊息有多長,回答有多長,對話被截斷的頻率,以及模擬對話是如何結束的。這部分僅作描述,從不作出決策:比較兩個未配對的樣本需要一種 Oloproof 尚未採納的方法。用它來發現真實感標籤遺漏的東西,例如模擬使用者用一句整齊的話寫出的內容,真實使用者會分散在三則訊息裡。

不支援的功能

  • 在託管工作區中依據模擬使用者作出決策:在它的審查佇列能夠自行抽取並封存真實感標籤之前,它的決策一直暫緩。
  • 基於模擬對話與真實對話比較結果的閘門。
  • 對話內部的輪次級比率,以及從某個輪次開始重播對話。
  • 為 HTTP 系統提供模擬使用者:迴圈由您的系統自己的程式碼執行,所以它必須是可呼叫物件。