Panduan
Tutorial: layanan dukungan menghadapi pelanggan simulasi
Evaluasi asisten percakapan terhadap pengguna yang bereaksi terhadap apa yang dikatakannya. Tiga puluh pelanggan simulasi, masing-masing dengan sebuah tujuan dan fakta yang mereka ketahui, bercakap dengan layanan dukungan sebuah toko; Oloproof mengukur apakah masing-masing mendapatkan apa yang mereka cari, menahan setiap keputusan sampai seseorang menilai pelanggan simulasi itu realistis, lalu memutuskan sebuah rilis dan sebuah perbandingan. Setiap langkah berjalan di mesin ini tanpa model dan tanpa jaringan, dan sebuah langkah opsional menggantikan pelanggan dengan model sungguhan.
Apa yang akan Anda bangun
Layanan dukungan sebuah toko menangani pengembalian dana, pertanyaan pengiriman, dan perubahan alamat. Tiga pertanyaan menentukan apakah sebuah versi boleh dirilis:
- Apakah setiap pelanggan mendapatkan apa yang mereka cari? goal_reached, dari pemeriksaan setelah setiap jawaban.
- Apakah ada jawaban yang menjanjikan apa yang tidak dapat dijanjikan toko? every_turn membaca setiap jawaban untuk mencari kata "guarantee".
- Dapatkah jawaban-jawaban itu dipercaya untuk mengatakan sesuatu tentang pelanggan nyata? Hanya setelah seseorang membaca sampel percakapan dan menilai pelanggan simulasi itu realistis.
Istilah seperti kasus, eksekusi, gerbang, dan suite didefinisikan di Konsep inti; segala hal tentang pengguna simulasi ada di Pengguna simulasi.
Prasyarat
- Python 3.11 atau yang lebih baru, dan Oloproof:
python3 -m venv .venv
. .venv/bin/activate
pip install oloproof- Proyek contoh, yang disertakan dalam paket. Salin ke direktori baru dan bekerjalah di sana:
oloproof init --example simulated-users support-desk
cd support-desk- Port 8797 kosong untuk pengguna simulasi pengganti (ubah di kedua tempat jika tidak).
Setiap langkah hingga "Opsional: model sungguhan sebagai pelanggan" bersifat offline dan deterministik: tanpa kunci API, tanpa akun penyedia, tanpa biaya.
File-filenya
support-desk/
desk.py the support desk under test (baseline)
desk_v2.py the candidate change
user_server.py a stand-in simulated user speaking the OpenAI API on 127.0.0.1
oloproof.yaml the suite: the simulated user and four evaluators
release.yaml rules for a run, with the realism bar
compare.yaml a rule for a comparison
data/customers.jsonl 30 personas
labels/realism_verdicts.csv one person's realism verdicts on the baseline's conversations
fill_realism.py copies those verdicts into a labelling sheet
logged.py replays logged chats with human agents
real.yaml a suite of 20 of those chats
logged_release.yaml a rule for the logged chats
data/logged_chats.jsonl the 20 chatsJalankan setiap perintah dari support-desk/.
Layanan dukungan memegang loop-nya sendiri
# desk.py (excerpt)
def talk(case: dict[str, Any]) -> dict[str, Any]:
user = current_case().simulated_user()
desk = Desk()
message = user.opening()
while message is not None:
message = user.reply(desk.answer(message))
return {"need": desk.need, "order": desk.order}Layanan dukungan meminta pesan pertama pelanggan, menjawabnya, dan menyerahkan kembali setiap jawaban untuk mendapatkan pesan berikutnya, sampai pelanggan berhenti. Ia tidak pernah melihat persona. Oloproof merekam apa yang berlangsung di antara keduanya; layanan dukungan sendiri tidak merekam apa pun. Baseline ini tidak dapat mengubah alamat pengiriman, dan menjanjikan pengembalian dana "guaranteed within 5 days".
Persona-personanya
Setiap kasus adalah satu pelanggan: 12 menginginkan pengembalian dana, 10 ingin tahu kapan pesanan tiba, dan 8 telah pindah alamat. Contohnya:
{"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"}}}}Pelanggan memberikan nomor pesanan dan kode pos hanya ketika diminta. Tiga persona juga menetapkan opening, pesan pertama mereka kata demi kata.
Suite-nya
version: 1
project: support-desk
dataset: data/customers.jsonl
system:
name: support-desk
version: baseline
callable: desk:talk
# A model plays each case's persona; here the stand-in in user_server.py.
simulated_user:
provider: openai_compatible
model: stand-in-user
base_url: http://127.0.0.1:8797/v1
max_turns: 6
evaluators:
# The desk answered every message the customer sent.
- type: conversation_completed
# The customer said they got what they came for.
- type: goal_reached
# ... within three of their own messages.
- type: turns_to_goal
max_turns: 3
# No answer promises what the shop cannot promise.
- type: every_turn
criterion: no_promises
not_contains: [guarantee]
casefold: truePengguna simulasi pengganti
Pengguna simulasi adalah model yang memerankan setiap persona. Di sini ia adalah user_server.py, yang berbicara dengan API yang sama di 127.0.0.1 dan bukan model: server ini membaca persona dari prompt yang dikirim Oloproof, menyatakan tujuannya, memberikan nomor pesanan atau kode posnya ketika diminta, pergi ketika layanan dukungan tidak dapat membantu, dan, ketika ditanya apakah tujuannya tercapai, menjawab ya ketika jawaban terakhir layanan dukungan diawali dengan "Done:". Jalankan di terminal kedua dan biarkan tetap berjalan:
python user_server.py --port 8797Kebijakannya
version: 1
confidence_level: 0.95
block_on: [FAIL, INSUFFICIENT_EVIDENCE, MANUAL_REVIEW]
require_validated_evaluators: true
minimum_simulated_user_realism: 0.80
rules:
- id: no-promises
metric: no_promises
kind: observed_count
max_failures: 0
- id: resolved
metric: goal_reached
min: 0.80Tidak ada jawaban yang boleh berjanji. Setidaknya 80% pelanggan harus mencapai tujuannya, yang diputuskan hanya ketika batas bawah interval melampaui 80%. Dan tidak ada aturan yang memutuskan atas pelanggan simulasi sampai orang-orang menilai setidaknya 80% percakapan mereka realistis, dengan jenis batas bawah yang sama.
Jalankan
oloproof runGate: BLOCK (exit 3)
│ no-promises │ no_promises │ INSUFFICIENT_EVIDENCE │ simulated_user_not_validated │
│ resolved │ goal_reached │ INSUFFICIENT_EVIDENCE │ simulated_user_not_validated │
│ conversation_completed │ 100.0% │ [88.4%, 100.0%] │ 30 / 30 observed · 0 missing · 0 excluded │
│ goal_reached │ 73.3% │ [54.1%, 87.8%] │ 22 / 30 observed · 0 missing · 0 excluded │
│ goal_within_3_turns │ 73.3% │ [54.1%, 87.8%] │ 22 / 30 observed · 0 missing · 0 excluded │
│ no_promises │ 60.0% │ [40.6%, 77.4%] │ 18 / 30 observed · 0 missing · 0 excluded │Setiap pelanggan dijawab, 22 dari 30 mencapai tujuannya, dan 12 percakapan memuat sebuah janji. Belum ada yang diputuskan: pelanggan-pelanggan ini disimulasikan, dan belum ada yang memeriksa bahwa mereka berperilaku seperti pelanggan nyata.
Baca pelanggan simulasi
oloproof simulated-users RUN_ID Realism: no conversation has been drawn and labelled yet.
Not validated: nothing labelled yet, against a bar of 80.0%.
Features (median [quartiles]; descriptive, never a gate):
user messages 2 [1, 2]
user message length 49 [10, 67]
How the simulated conversations ended: goal_reached 73%, user_left 27%Delapan yang pergi adalah pelanggan yang telah pindah alamat: baseline tidak dapat mengubah alamat.
Beri label realisme pada percakapan
Ambil sampel acak dari percakapan eksekusi ke dalam sebuah lembar, minta seseorang membaca masing-masing, beserta persona dan cara percakapan itu berakhir, dan menandai apakah pelanggan nyata bisa saja menulis sisi pelanggan dan mengakhirinya di titik itu, dengan cara itu. Di sini fill_realism.py menggantikan orang itu, dengan menyalin putusannya dari labels/realism_verdicts.csv:
oloproof labels export RUN_ID --criterion simulated_user_realistic --sample 30 --local --out realism.csv
python fill_realism.py realism.csv
oloproof labels import realism.csv
oloproof simulated-users RUN_ID Realism: 29 of 30 drawn conversations labelled realistic (30 labelled), [82.8%, 99.9%] at 95%
Validated: the lower bound clears the bar of 80.0%.Orang itu menilai satu percakapan tidak realistis: pelanggan c05 membuka dengan "Order: F-15. Refund.", yang terbaca seperti formulir, bukan seperti seseorang. Dengan 29 dari 30, batas bawah eksaknya adalah 82.8%, di atas ambang, sehingga aturan kini boleh memutuskan atas pelanggan-pelanggan ini.
oloproof gate RUN_ID --policy release.yamlno-promises: FAIL (observed_failures_exceed_limit)
resolved: INSUFFICIENT_EVIDENCE (interval_overlaps_threshold)
Gate: BLOCK (exit 1)Lakukan perubahan nyata
desk_v2.py mengubah alamat begitu ia memiliki pesanan dan kode pos yang baru, dan mengatakan bahwa ia telah memulai pengembalian dana yang "usually arrives within 5 days" alih-alih menjanjikannya. Salin menimpa desk.py, tetapkan version: candidate di bawah system di oloproof.yaml, biarkan pengganti tetap berjalan, lalu:
oloproof runGate: ALLOW (exit 0)
│ no-promises │ no_promises │ PASS │ observed_failures_within_limit │
│ resolved │ goal_reached │ PASS │ lower_bound_meets_minimum │Kandidat bertemu pelanggan simulasi yang sama pada suite yang sama, sehingga realisme yang diukur pada percakapan baseline mencakupnya: satu validasi mencakup satu pengguna simulasi pada satu suite, sistem mana pun yang diajaknya bercakap.
Bandingkan kandidat dengan baseline
oloproof compare CANDIDATE_RUN_ID BASELINE_RUN_ID --policy compare.yamlgoal_reached: +26.7 points [+1.2, +54.1] · 30 paired · 0 missing · 0 excluded
resolves-more goal_reached superiority PASS difference_above_zeroSetiap pelanggan bertemu kedua layanan dukungan, sehingga perbandingannya berpasangan, pelanggan demi pelanggan.
Simulasi di samping yang nyata
Label realisme menilai setiap percakapan secara tersendiri. Menempatkan pelanggan simulasi di samping pelanggan nyata menunjukkan apa yang dapat terlewat oleh sebuah sampel. real.yaml memutar ulang 20 obrolan yang dilakukan agen manusia toko itu dengan pelanggan nyata:
oloproof run --config real.yaml --policy logged_release.yaml
oloproof simulated-users BASELINE_RUN_ID --real REAL_RUN_ID simulated (run_01M52Q1C) real (run_01M52Q25)
user messages 2 [1, 2] 3 [3, 4]
user message length 49 [10, 67] 13 [4, 32]Pelanggan nyata mengirim lebih banyak pesan yang lebih pendek: mereka mengatakan apa yang mereka inginkan dalam tiga baris, sementara pengganti mengatakannya dalam satu kalimat rapi. Itu layak diketahui tentang pengguna simulasi mana pun, dan di sini tidak pernah memutuskan apa pun: membandingkan dua sampel yang tidak berpasangan memerlukan metode yang belum diterima Oloproof.
Opsional: model sungguhan sebagai pelanggan
Langkah ini meninggalkan jalur offline. Langkah ini memerlukan model chat: secara lokal, Ollama (ollama pull qwen2.5vl, atau model chat apa pun), tanpa kunci dan tanpa biaya; di cloud, provider: anthropic atau openai dengan api_key_env, ditagih per pesan. Di oloproof.yaml, arahkan pengguna simulasi ke model itu:
simulated_user:
provider: openai_compatible
model: qwen2.5vl
base_url: http://localhost:11434/v1
max_turns: 6Ollama menjawab satu permintaan dalam satu waktu, jadi tetapkan concurrency: {system: 1} dan timeout_s beberapa menit. Model yang berbeda adalah pengguna simulasi yang berbeda: label realisme di atas tidak mencakupnya, sehingga percakapannya memerlukan sampelnya sendiri sebelum aturan apa pun memutuskan atasnya.
Sepuluh persona, yang diperankan qwen2.5vl di mesin ini terhadap layanan dukungan kandidat, mencapai tujuannya dalam 8 percakapan, sementara pengganti mencapainya dalam ke-30 percakapan. Model itu menemukan apa yang tidak dapat ditemukan pengganti: dua pelanggan menanyakan "status" dan "shipping status" pesanan mereka, kata-kata yang tidak dikenal layanan dukungan, dan setiap kali mendapat sapaannya kembali. Satu kehabisan pesan. Layanan dukungan memahami percobaan ketiga pelanggan yang lain, dan pelanggan itu tetap pergi: pemeriksaan tujuan, sebuah penilaian model, melewatkan jawabannya. Label realisme adalah tempat hal itu terlihat: pelanggan nyata yang diberi tahu kapan pesanannya tiba tidak pergi dengan kecewa. Tidak seperti pengganti, model itu juga sering memberikan nomor pesanannya sebelum diminta, dan menulis satu pesan yang lebih panjang ketika pengganti menulis dua pesan pendek.
Pemecahan masalah
| Gejala | Penyebab dan perbaikan |
|---|---|
| Setiap aturan bernilai INSUFFICIENT_EVIDENCE dengan simulated_user_not_validated | Belum ada yang memberi label pada percakapan pengguna simulasi ini pada suite ini, atau proporsi yang realistis tidak melampaui ambang. Beri label pada sebuah sampel seperti di atas. |
| a case for a simulated user needs a 'persona' object in its input | Sebuah kasus tidak memiliki persona, atau persona berada di bawah kunci lain: tetapkan persona_field. |
| provider connection failed dari setiap kasus | Pengganti tidak berjalan, atau mendengarkan di port lain selain yang disebut base_url. |
| the simulated user's goal check answered ... | Model tidak menjawab pemeriksaan tujuan dengan ya atau tidak. Coba model lain, atau yang lebih besar. |
| conversation/v1 is written by Oloproof | Layanan dukungan merekam percakapan itu sendiri. Hapus itu: Oloproof merekam apa yang melewati pengguna simulasi. |
Keterbatasan
- Pelanggan pengganti adalah sebuah aturan. Percakapannya menunjukkan mekanismenya; percakapan model sungguhan lebih berantakan, seperti yang ditunjukkan langkah opsional.
- Tercapai atau tidaknya tujuan adalah penilaian model pengguna simulasi, yang diperiksa hanya melalui label realisme.
- Ruang kerja yang di-hosting belum memutuskan atas pengguna simulasi.
- Pelanggan simulasi bukan pelanggan nyata: pengguna simulasi yang tervalidasi adalah bukti tentang pelanggan yang mirip dengan persona-personanya, sejauh orang-orang menilainya realistis, dan tidak lebih jauh.