Skip to content

經驗取樣、追蹤波次與德爾菲輪次

在參與者入組數小時到數週後開放調查會話,通過電子郵件、Twilio 簡訊或 Prolific 訊息提醒參與者,並匯出依從率和響應延遲。

v2.13.0 新增

配置 schedule: 區塊後,Potato 會在參與者首次訪問之後開放簡短的調查會話;配置 notifications: 區塊後,每個會話開放時會通過電子郵件、簡訊或 Prolific 訊息發出通知。調查研究者用追蹤波次開展縱向樣本組研究,心理學和健康研究者用經驗取樣做日記研究和情緒研究,專家組則用德爾菲輪次就評價標準或指南達成共識。對每個會話,Potato 都會記錄答案、提示發出的時間、參與者首次操作表單的時間,以及該會話是已作答、已過期還是已錯過。

經驗取樣法(ESM)在一天中多次向參與者提出同樣的幾個簡短問題,詢問的是每次提示那一刻的狀態。健康研究者把同樣的設計稱為生態瞬時評估(EMA)。在德爾菲法中,一個專家組分多輪對同一批條目評分,每次重新評分前都會看到上一輪專家組的匿名答案。

  • 時區。 每位參與者在入組時選擇一個時區,入組頁面會預先填入瀏覽器報告的時區。"09:00" 這樣的時鐘時間按參與者所在時區放在每個當地日期上。
  • 渠道。 訊息可以經任意 SMTP 伺服器以電子郵件傳送,經 Twilio 以簡訊傳送,或傳送到參與者的 Prolific 收件箱。憑據只從環境變數讀取。
  • 聯絡方式。 Potato 只有在參與者對知情同意問題回答“是”之後才會索取電子郵件地址或電話號碼,並把這些地址儲存在輸出目錄之外,不進入任何匯出。

入組與會話計劃

每位參與者只經歷一次以下步驟:

  1. 參與者完成常規流程,包括知情同意、說明、標註和問卷。
  2. 流程結束時,入組頁面詢問時區;只有在參與者對同意問題回答“是”之後,才索取電子郵件地址或手機號碼。被篩查淘汰、未通過培訓或被注意力檢查攔下的參與者不會入組。
  3. Potato 在那一刻為該參與者算出每個會話和每條提醒,並儲存這份計劃。
  4. 一個後臺迴圈在每條訊息的到期時間傳送它,訊息附帶續答連結,點開即可登入並開啟對應會話。
  5. 參與者用研究連結回來時,會進入當前開放的會話,或進入一個狀態頁,頁面按參與者自己的時區顯示下一個會話何時開放。

計劃和時區在入組時就已確定。之後修改 waves 隻影響此後入組的參與者。拒絕被聯絡的參與者仍然會入組,只是收不到訊息,需要自己回到研究連結查詢開放的會話。

配置

下面的配置執行一項為期七天的經驗取樣研究,每天在 09:00 到 21:00 之間的隨機時間發出五次提示。常規流程是一個知情同意頁面和一道入組問題,參與者答完這道入組問題即完成入組:

yaml
annotation_task_name: "Daily mood study"
task_dir: .
output_annotation_dir: annotation_output
data_files: [data/intake.jsonl]
item_properties: {id_key: id, text_key: text}
user_config:
  allow_all_users: true
 
phases:
  order: [consent, annotation]
  consent:
    type: consent
    file: surveys/consent.json
  annotation:
    type: annotation
 
annotation_schemes:            # the intake questions, answered once
  - annotation_type: likert
    name: usual_mood
    description: "In general, how would you describe your mood?"
    size: 7
    min_label: "Very low"
    max_label: "Very good"
 
schedule:
  timezone: "America/Detroit"  # used when the browser reports no time zone
  seed: "daily-mood-2026"
  experience_sampling:
    title: "How are you right now?"
    days: 7
    start_day: 1               # first prompts on the day after enrollment
    daily_window: "09:00-21:00"
    signal: {per_day: 5, min_gap: 90m}
    expires_after: 30m
    questions:
      - {name: mood, annotation_type: likert, size: 7, required: true,
         description: "How do you feel right now?",
         min_label: "Very bad", max_label: "Very good"}
      - {name: company, annotation_type: radio, required: true,
         description: "Who are you with?",
         labels: ["Alone", "Family", "Friends", "Colleagues", "Strangers"]}
    reminders:
      - at: open
      - after_open: 15m
 
notifications:
  dry_run: true                # pilot: render and log every message, send none
  base_url: "https://mood-study.example.org"
  channels:
    - type: log
    - type: twilio
      account_sid_env: TWILIO_ACCOUNT_SID
      auth_token_env: TWILIO_AUTH_TOKEN
      from_number: "+12025550143"
  contact:
    consent: {question: contact_consent, value: "Yes"}

這兩條提醒規則在提示開放時發出提示,並在 15 分鐘後給尚未作答的參與者再發一條訊息。設定 dry_run: true 時,Potato 會渲染每條 Twilio 訊息並填好收件人,在管理頁面上逐條列出,但一條也不投遞。試點結束後設置 dry_run: false。隨機提示時間由 seed、參與者 ID 和日期共同決定。每位參與者的抽取彼此獨立,事後也可以重新算出同樣的結果。

surveys/consent.json 中的知情同意頁面會提出 notifications.contact.consent 所指定的問題:

json
[
  {"name": "study_consent", "annotation_type": "radio",
   "description": "I agree to answer short surveys five times a day for seven days.",
   "labels": ["I agree", "I do not agree"],
   "label_requirement": {"required_label": ["I agree"]}},
  {"name": "contact_consent", "annotation_type": "radio",
   "description": "May we text you when each survey opens? Your number is kept apart from your answers and deleted when the study ends.",
   "labels": ["Yes", "No"],
   "label_requirement": {"required": true}}
]

啟動時,Potato 會檢查 contact_consent 是否在某個階段頁面上被提出,以及 Yes 是否是該問題的選項之一。YAML 中要給 "Yes" 加引號,因為 YAML 1.1 會把不帶引號的 Yes 讀成布林值,而同意值為 true 或 false 會導致校驗失敗。value 也可以是一個列表,列出所有允許聯絡的答案。

經驗取樣選項

experience_sampling 鍵預設值含義
days必填取樣天數,1 到 366
start_day1第一個取樣日,從入組當天起算,0 表示入組當天
daily_window"09:00-21:00"提示所在的當地時間視窗
signal.per_day使用 signal 時必填每天的隨機提示次數,1 到 48
signal.min_gap60m兩次提示之間的最短間隔,不小於 expires_after
interval.every無在視窗開始時發一次提示,此後每隔該間隔再發一次
interval.times無固定的當地時鐘時間,例如 ["10:00", "14:00", "20:00"]
expires_after30m每次提示保持開放的時長,至少一分鐘
questions、questions_file二者必選其一提示中的問題(見下文的會話問題一節)
reminders[{at: open}]at: open、after_open 和 before_close。before_open 會被拒絕
title"Short survey"顯示在提示頁面和訊息中
intro無問題上方的文字

一項研究只能在 signal(訊號觸發,隨機時間)和 interval(間隔觸發,固定時間)中選用一個。interval 區塊只能在 every 和 times 中選用一個。時長寫作 30m、48h、7d 或 2w,也可以寫成秒數。

無法放進每日視窗的計劃會校驗失敗。五次提示、間隔 90 分鐘,需要四段 90 分鐘的間隔,再加上最後一次提示保持開放的 30 分鐘,也就是視窗中的 6 小時 30 分鐘。同樣間隔下九次提示需要 12 小時 30 分鐘,在 12 小時的視窗中會校驗失敗。interval.every 長於視窗,或固定時間之間的間隔小於 expires_after,也會以同樣的方式失敗。

Potato 對每一天都把每日視窗放在參與者所在時區的該當地日期上。因此在時鐘調整的那一天,視窗仍然是當地時間 09:00 到 21:00。隨機時間在所有滿足兩個條件的排列中均勻抽取:相鄰提示至少間隔 min_gap,最後一次提示在視窗內關閉。狀態頁面顯示當天的視窗,從不顯示下一次隨機提示的時間。入組時已經過去的提示時間會被略去。

追蹤波次

縱向樣本組研究使用 waves。下面的部分割槽塊替換上文配置中的 schedule,增加一週和一個月兩次追蹤:

yaml
schedule:
  timezone: "America/Detroit"
  waves:
    - name: week1
      title: "One-week follow-up"
      offset: 7d
      at: "09:00"              # local clock time on day 7
      window: 48h
      questions:
        - {name: changed_view, annotation_type: radio, required: true,
           description: "Since last week, has your view changed?",
           labels: ["No", "A little", "A lot"]}
      reminders:
        - before_open: 12h
        - at: open
        - before_close: 12h
      completion_code: "FOLLOWUP-DONE"
    - name: month1
      offset: 30d
      at: "09:00"
      window: 72h
      questions_file: surveys/followup.json

設定 at 後,即使中間時鐘有調整,每個波次也會在指定那天的當地時間 09:00 開放,此時 offset 必須是整數天。不設定 at 時,offset: 7d 表示經過七天的實際時長,夏令時切換會讓當地開放時間移動一小時。"09:00" 這樣的時鐘時間要加引號。YAML 1.1 會把不帶引號的 10:30 讀成數字 630,而 Potato 會把 630 理解為午夜後的分鐘數。

waves 鍵預設值含義
name必填簡短 ID,最多 40 個字母、數字、_ 或 -,用於匯出
title取 name顯示給參與者,也用於訊息
offset0距入組的時間
at無入組後第 offset 天的當地時鐘時間
window必填波次保持開放的時長,至少一分鐘
questions、questions_file二者必選其一該波次的問題
reminders[{at: open}]訊息何時發出
completion_code無參與者提交該波次後顯示的程式碼,例如用於在第二項 Prolific 研究中領取報酬
intro無問題上方的文字

德爾菲輪次

德爾菲研究使用 delphi。下面的部分割槽塊替換經驗取樣配置中的 schedule,data/criteria.json 儲存一個由 {"id", "text"} 條目組成的列表:

yaml
schedule:
  timezone: "UTC"
  delphi:
    title: "Guideline criteria"
    items_file: data/criteria.json
    scale: {min: 1, max: 9, min_label: "Not important", max_label: "Essential"}
    comments: true
    max_rounds: 3
    round_length: 72h
    gap: 12h
    start: "2026-11-16T09:00:00-05:00"
    min_panel: 3
    stop:
      iqr_at_most: 1
      changed_share_below: 0.15
    reminders:
      - at: open
      - before_close: 24h

各輪次對整個專家組統一進行。第 1 輪在 start 開放;未設定 start 時,在使用該配置的伺服器首次啟動時開放,Potato 會在重啟後保留這個時間。之後每一輪在上一輪關閉 gap 之後開放。在第 2 輪期間入組的專家組成員直接加入第 2 輪,能看到第 1 輪的反饋,但其中沒有自己的評分。停止接收訊息的專家組成員仍會收到每一輪,只是沒有提醒。

從第 2 輪起,每個條目會顯示上一輪的以下資訊:

  • 中位數,以及中間一半評分(Q1 到 Q3)在量表上的陰影帶,並標出該成員自己的評分。
  • 評分人數。
  • 其他專家組成員的匿名評論,順序對每位成員固定。成員自己的評論不會回顯給本人。

評分人數少於 min_panel 的條目不顯示彙總,也不顯示評論。有了這個閾值,小型專家組的評分就無法追溯到某一個人。當前輪次的評分從不預先填入。

當一輪在其時間視窗結束時關閉,或管理員在 /admin/schedule 上提前關閉該輪時,Potato 會計算每個條目的 n、中位數、均值、Q1、Q3 和四分位距(IQR)。四分位數在順序統計量之間做線性插值,也就是 R 中的 type 7 方法,同時也是 NumPy 的預設方法。從第 2 輪起,Potato 還會計算 median_change 和 changed_share。median_change 是中位數變化的絕對值,changed_share 是在兩輪中都給該條目評過分的成員裡改變了評分的比例。一個條目滿足至少一項已配置的標準時,即視為已穩定:

stop 鍵類型視為已穩定的條件
iqr_at_most共識IQR 不超過該值
median_change_at_most穩定性,從第 2 輪起中位數相比上一輪的變動不超過該值
changed_share_below穩定性,從第 2 輪起改變評分的成員比例低於該值,取值 0 到 1

研究在所有條目都已穩定的第一輪之後停止,或在達到 max_rounds 後停止。沒有 stop 區塊時,研究會跑滿 max_rounds 輪。停止原因會顯示在專家組成員的狀態頁面和管理頁面上。

delphi 鍵預設值含義
items、items_file二者必選其一內聯的 [{id, text}],或一個 JSON、JSONL 或 YAML 檔案
scale{min: 1, max: 9}整數評分量表,最多 21 個點,可選 min_label 和 max_label
commentstrue每個條目一條可選評論,最多 2,000 個字元,匿名展示給專家組
max_rounds3輪數上限,1 到 10
round_length必填每一輪開放的時長
gap0一輪關閉到下一輪開放之間的時間
start伺服器首次啟動時第 1 輪何時開放,採用帶 UTC 偏移的 ISO 8601 格式
min_panel3顯示一個條目的彙總和評論所需的評分數
stop無停止標準
reminders[{at: open}]訊息何時發出
title"Delphi round"顯示在每輪頁面上,後接輪次編號
intro無條目上方的文字

會話問題

波次和提示中的問題寫法與標註方案相同,可以內聯寫在 questions 下,也可以放在一個 JSON 或 YAML 的 questions_file 中,路徑相對於配置檔案。每個問題都需要 name、annotation_type、description,以及 required: true 或 label_requirement: {required: true} 二者之一。六種問題類型接受以下鍵:

類型鍵與預設值
radiolabels(至少兩個)、horizontal
multiselectlabels(至少兩個)
likertsize(2 到 11)、min_label、max_label
slidermin_value(0)、max_value(100)、starting_value(取 min_value)、step(1)、min_label、max_label
numbermin_value、max_value、integer
textmultiline(true)、max_length(1000,最多 4,000)

使用該類型列表以外的鍵會校驗失敗。與 slider 標註方案不同,會話中的 slider 接受 min_label 和 max_label。滑塊只有在參與者移動過之後才算已作答,伺服器會拒絕超出問題選項或取值範圍的答案。Potato 按會話把會話答案儲存在 <output_annotation_dir>/scheduling/schedule.sqlite 中,而不是 user_state.json 中。在上文的配置中,一位參與者對每道提示問題最多可以作答 35 次,每次提示一次。

提醒

每個波次、經驗取樣區塊和德爾菲區塊都接受一個 reminders 列表,列表由四種規則組成:

規則訊息何時發出
{at: open}視窗開放時
{before_open: 12h}視窗開放前 12 小時
{after_open: 2h}視窗開放後 2 小時,前提是該會話尚未作答
{before_close: 12h}視窗關閉前 12 小時,前提是該會話尚未作答

會話已作答或已關閉時,Potato 會跳過提醒;會話開放後,也會跳過 before_open 提醒。在參與者入組之前就已到期的提醒不會發送。after_open 或 before_close 的偏移量必須短於視窗。經驗取樣不接受 before_open,因為那條訊息會提前透露一次隨機提示。

通知

下面的部分割槽塊替換上文配置中的 notifications,通過電子郵件和 Prolific 收件箱傳送訊息,併為提示設定了自定義文本:

yaml
notifications:
  base_url: "https://mood-study.example.org"
  channels:
    - type: log
    - type: smtp
      host: smtp.example.org
      port: 587
      security: starttls        # starttls, ssl, or none
      username_env: POTATO_SMTP_USER
      password_env: POTATO_SMTP_PASSWORD
      from: "Mood study <mood-study@example.org>"
    - type: prolific
      token_env: PROLIFIC_API_TOKEN
  templates:
    prompt:
      subject: "{study}: a short survey is open"
      body: "Please answer within {time_left}: {link}\n\nStop messages: {stop_link}"
  contact:
    consent: {question: contact_consent, value: "Yes"}
    delete_after_study: true

每種渠道類型最多出現一次:

渠道投遞目標鍵與預設值
log伺服器日誌和管理頁面,含完整文本和連結。不向參與者投遞任何內容無
smtp入組時填寫的電子郵件地址host(必填)、from(必填)、security(starttls)、port(587;使用 ssl 時為 465)、username_env 和 password_env(兩個都設或都不設)、timeout(20 秒)
twilio入組時填寫的手機號碼,以簡訊傳送account_sid_env(TWILIO_ACCOUNT_SID)、auth_token_env(TWILIO_AUTH_TOKEN)、from_number(一個 E.164 號碼)和 messaging_service_sid_env 二者必選其一、timeout(20)
prolific參與者的 Prolific 收件箱,按 Prolific 參與者 ID 傳送token_env(PROLIFIC_API_TOKEN)、study_id(未設定時取參與者的 STUDY_ID)、timeout(30)

Prolific 渠道只能聯絡到從 Prolific 來的參與者。Potato 在傳送訊息時才讀取每個 *_env 鍵所指定的變數。如果 YAML 在 password、token 或 account_sid 這類鍵下直接寫了憑據,Potato 會在啟動時停止。缺少的變數會在啟動時記入日誌,之後該渠道上的每條訊息都會失敗,並報出該變數的名稱。啟動 Potato 之前,先在伺服器環境中設定這些變數:

bash
export POTATO_SMTP_USER="mood-study@example.org"
export POTATO_SMTP_PASSWORD="<your SMTP password>"
export PROLIFIC_API_TOKEN="<your Prolific API token>"
notifications 鍵預設值含義
dry_runfalse在每個渠道上渲染每條訊息並填好收件人,將每條訊息記為 dry_run,但不投遞
base_urlhttp://localhost:<port>連結中使用的公開地址。除非開啟了 dry_run,否則使用 log 以外的任何渠道時都必填
channels無上表中的渠道
contact.consent配置渠道時必填{question, value},即階段頁面上的同意問題和允許聯絡的答案
contact.delete_after_studytrue參與者不再有剩餘會話時,刪除其聯絡方式
templates內建每類訊息的文本

模板類別有 before_open、open、reminder(用於 after_open 和 before_close)、prompt(經驗取樣提示的開放訊息)和 delphi_round。每個類別都接受 subject 和 body。佔位符有 {study}、{session}、{opens}、{closes}、{time_left}、{link} 和 {stop_link}。Potato 按參與者的時區顯示 {opens} 和 {closes},模板中出現未知佔位符時會在啟動時停止。簡訊只使用正文,上限是 Twilio 的 1,600 個字元;Prolific 訊息會把主題和正文合在一起。

Potato 在傳送每條訊息之前先在資料庫中認領它,因此即使經歷重啟,或有第二個伺服器程序,也不會把同一條訊息傳送兩次。傳送中途被打斷的訊息會被標記為失敗,不會重發。遇到臨時性錯誤時,只要會話仍然開放,Potato 會在 5 分鐘後和再過 10 分鐘後重試,總共最多嘗試三次。臨時性錯誤指 SMTP 連線錯誤,以及 Twilio 或 Prolific 返回的 429 或 5xx 響應。其他錯誤會立即判為失敗。

全域排程設定

schedule 鍵預設值含義
timezoneUTC瀏覽器未報告時區時,入組頁面預選的 IANA 時區
seed空混入隨機提示時間和德爾菲評論順序的文本
poll_seconds30後臺迴圈的執行頻率,1 到 3,600 秒
schedulertrue隨伺服器執行後臺迴圈
waves、experience_sampling、delphi無至少需要一個

後臺迴圈負責傳送到期的訊息、開放和關閉德爾菲輪次,以及刪除已完成參與者的聯絡方式。設定 scheduler: false 時,在管理員於 /admin/schedule 上按下 Send due messages now 或向 /admin/api/schedule/tick 傳送 POST 請求之前,不會發出任何訊息。只有 notifications 區塊而沒有 schedule 區塊會校驗失敗。

續答連結與聯絡方式

續答連結(/s/<token>)會讓參與者登入並開啟一個會話,在該會話關閉時失效。連結用 POTATO_SCHEDULE_LINK_KEY 以 HMAC-SHA256 簽名;未設定該變數時,使用一次性生成並儲存在 <task_dir>/.potato/scheduling/link.key 中的隨機金鑰。伺服器可能在全新磁碟上重啟時,應設定該變數。參與者停止接收訊息時,Potato 會讓此前發給該參與者的所有連結失效。

電子郵件地址和電話號碼儲存在 <task_dir>/.potato/scheduling/contacts.sqlite 中,檔案許可權為 0600,位於標註輸出目錄之外。沒有任何匯出器、資料歸檔或部署包會讀取這個聯絡方式儲存,通知日誌也只記錄渠道,從不記錄地址。如果主機每次重啟都會清空磁碟,地址就會丟失,該主機上的參與者也不會再收到訊息。

參與者可以在狀態頁面上,或通過每條訊息中的退訂連結停止接收訊息。退訂連結開啟的是一個確認頁面,只有頁面上的按鈕才會刪除聯絡方式,因此開啟連結的郵件掃描程式不會讓任何人退訂。設定 delete_after_study: true 時,參與者沒有開放中或即將開放的會話後,其聯絡方式就會被刪除;德爾菲研究則會保留聯絡方式,直到專家組完成全部輪次。

錯過與過期的會話

會話在其時間視窗結束時關閉,伺服器會拒絕關閉後提交的答案。Potato 把已關閉的會話記為以下三種狀態之一:

  • answered(已作答)表示參與者在關閉前提交了該會話。
  • expired(已過期)表示參與者打開了會話或開始作答,但在關閉前沒有提交。
  • missed(已錯過)表示會話開放期間參與者一次也沒有開啟過。

Potato 不會為已關閉的會話重新安排時間,該會話尚未發出的提醒也會被跳過。參與者開啟舊連結時,會看到該會話何時關閉、下一個會話何時開放;如果下一個會話是隨機提示,則不顯示開放時間。依從率等於已作答會話數除以已關閉會話數,按參與者和會話類型分別計算。

管理頁面

訪問 /admin/schedule 需要管理員 API 金鑰或 RBAC 管理員角色。頁面顯示每位參與者的時區、同意情況、依從率、響應延遲中位數和下一個會話,按狀態列出每條訊息,並給出 log 和 dry_run 訊息的完整文本。德爾菲輪次會連同條目統計一起顯示。頁面上的按鈕對應下面的 POST 端點:

端點方法作用
/admin/api/scheduleGET以 JSON 返回頁面資料,不含地址
/admin/api/schedule/tickPOST立即傳送到期的訊息
/admin/api/schedule/delphi/close_roundPOST關閉當前開放的德爾菲輪次
/admin/api/schedule/contact/<participant>/deletePOST刪除一位參與者的聯絡方式

匯出

會話答案不是條目標註,主匯出不包含會話答案。schedule 匯出改為寫出若干附屬表,每張表都有一個 participant 列,其 ID 與主匯出中的 user_id 相同:

bash
python -m potato.export --config config.yaml --format schedule --output out/
檔案行
schedule_sessions.csv每位參與者的每個會話一行,另有每位參與者一行 enrolment,對應常規流程
schedule_compliance.csv按參與者和會話類型各一行,含 sessions、closed、answered、expired、missed、compliance、median_latency_seconds
schedule_notifications.csv每條計劃中的訊息,含 session_id、rule、template、channel、due_at_utc、status、attempts、sent_at_utc、detail。不含地址,也不含訊息文本
delphi_ratings.csv僅限德爾菲研究,含 participant、round、item、rating、comment
delphi_rounds.csv僅限德爾菲研究,按輪次和條目各一行,含 n、median、q1、q3、iqr、mean、median_change、changed_share、settled、opens_at_utc、closed_at_utc、round_status、stop_reason

德爾菲評分寫入 delphi_ratings.csv,各輪會話出現在 schedule_sessions.csv 中,帶有狀態和響應延遲。schedule_sessions.csv 的列如下:

列含義
kindwave、prompt、round 或 enrolment
session_id、wave、day、prompt、round、title該行對應哪個會話。day 是從 1 起算的取樣日,prompt 是當天的第幾次提示
timezone參與者的時區
opens_at_utc、closes_at_utc、opens_at_local、closes_at_local時間視窗,分別以 UTC 和當地時間表示
statusanswered、expired、missed、open、started 或 upcoming(入組行為 enrolled)
prompt_at_utc開放訊息發出的時間;未傳送訊息時為視窗開始時間
opened_at_utc、first_answer_at_utc、submitted_at_utc參與者開啟頁面、首次操作表單和提交的時間
latency_seconds從 prompt_at_utc 到首次作答
response_seconds從首次作答到提交
reminder_channels參與者接收訊息的渠道,位於入組行
answer.<name>每個問題一列,多選答案用 ; 連線

示例

bash
python potato/flask_server.py start examples/advanced/experience-sampling/config.yaml -p 8000

這個示例用 log 渠道和一個空跑(dry run)的 Twilio 渠道執行上文的取樣計劃。/admin/schedule 上的管理頁面會列出每次提示的續答連結。examples/advanced/two-wave-panel/ 和 examples/advanced/delphi-study/ 兩個資料夾分別包含一個帶一週追蹤的樣本組研究和一個三輪德爾菲研究。

延伸閱讀

實現細節請參閱源文件。