Membangun dengan Claude
Pelajari tentang Claude
- Kasus Penggunaan
- Model
- Keamanan dan kepatuhan
Administrasi
Uji dan evaluasi
- Memperkuat perlindungan
- Menggunakan Alat Evaluasi
Sumber Daya
Pusat Hukum
Membuat evaluasi empiris yang kuat
Setelah menentukan kriteria keberhasilan, langkah selanjutnya adalah merancang evaluasi untuk mengukur kinerja LLM terhadap kriteria tersebut. Ini adalah bagian vital dari siklus rekayasa prompt.
Panduan ini berfokus pada cara mengembangkan kasus uji Anda.
Membangun evaluasi dan kasus uji
Prinsip desain evaluasi
- Spesifik untuk tugas: Rancang evaluasi yang mencerminkan distribusi tugas dunia nyata Anda. Jangan lupa untuk memperhitungkan kasus-kasus khusus!
- Data masukan yang tidak relevan atau tidak ada
- Data masukan atau masukan pengguna yang terlalu panjang
- [Kasus penggunaan chat] Masukan pengguna yang buruk, berbahaya, atau tidak relevan
- Kasus uji yang ambigu di mana bahkan manusia akan sulit mencapai konsensus penilaian
- Otomatisasi bila memungkinkan: Strukturkan pertanyaan untuk memungkinkan penilaian otomatis (misalnya, pilihan ganda, pencocokan string, penilaian kode, penilaian LLM).
- Prioritaskan volume daripada kualitas: Lebih banyak pertanyaan dengan penilaian otomatis yang sinyalnya sedikit lebih rendah lebih baik daripada sedikit pertanyaan dengan evaluasi yang dinilai manual berkualitas tinggi.
Contoh evaluasi
Apa yang diukur: Evaluasi pencocokan tepat mengukur apakah keluaran model cocok persis dengan jawaban benar yang telah ditentukan sebelumnya. Ini adalah metrik sederhana dan tidak ambigu yang sempurna untuk tugas dengan jawaban kategorikal yang jelas seperti analisis sentimen (positif, negatif, netral).
Contoh kasus uji evaluasi: 1000 tweet dengan sentimen yang dilabeli manusia.
import anthropic
tweets = [
{"text": "Film ini benar-benar membuang waktu. 👎", "sentiment": "negative"},
{"text": "Album baru ini 🔥! Sudah diputar berulang kali seharian.", "sentiment": "positive"},
{"text": "Saya sangat suka ketika penerbangan saya tertunda 5 jam. #hariyangterbaik", "sentiment": "negative"}, # Kasus khusus: Sarkasme
{"text": "Plot filmnya buruk, tapi aktingnya luar biasa.", "sentiment": "mixed"}, # Kasus khusus: Sentimen campuran
# ... 996 tweet lainnya
]
client = anthropic.Anthropic()
def get_completion(prompt: str):
message = client.messages.create(
model="claude-3-5-sonnet-20241022",
max_tokens=50,
messages=[
{"role": "user", "content": prompt}
]
)
return message.content[0].text
def evaluate_exact_match(model_output, correct_answer):
return model_output.strip().lower() == correct_answer.lower()
outputs = [get_completion(f"Klasifikasikan ini sebagai 'positive', 'negative', 'neutral', atau 'mixed': {tweet['text']}") for tweet in tweets]
accuracy = sum(evaluate_exact_match(output, tweet['sentiment']) for output, tweet in zip(outputs, tweets)) / len(tweets)
print(f"Akurasi Analisis Sentimen: {accuracy * 100}%")
Apa yang diukur: Kesamaan kosinus mengukur kemiripan antara dua vektor (dalam hal ini, embedding kalimat dari keluaran model menggunakan SBERT) dengan menghitung kosinus sudut di antara keduanya. Nilai yang mendekati 1 menunjukkan kemiripan yang lebih tinggi. Ini ideal untuk mengevaluasi konsistensi karena pertanyaan yang mirip harus menghasilkan jawaban yang secara semantik mirip, meskipun kata-katanya berbeda.
Contoh kasus uji evaluasi: 50 kelompok dengan beberapa versi parafrase masing-masing.
from sentence_transformers import SentenceTransformer
import numpy as np
import anthropic
faq_variations = [
{"questions": ["Apa kebijakan pengembalian Anda?", "Bagaimana cara mengembalikan barang?", "Gmn kbijakan pngmbalian?"], "answer": "Kebijakan pengembalian kami memungkinkan..."}, # Kasus khusus: Typo
{"questions": ["Saya membeli sesuatu minggu lalu, dan tidak sesuai dengan yang saya harapkan, jadi saya ingin tahu apakah mungkin saya bisa mengembalikannya?", "Saya baca online bahwa kebijakan Anda adalah 30 hari tapi sepertinya itu mungkin sudah kedaluwarsa karena websitenya diperbarui enam bulan yang lalu, jadi saya ingin tahu apa tepatnya kebijakan Anda saat ini?"], "answer": "Kebijakan pengembalian kami memungkinkan..."}, # Kasus khusus: Pertanyaan panjang dan berbelit
{"questions": ["Saya sepupu Jane, dan dia bilang layanan pelanggan kalian bagus. Bisakah saya mengembalikan ini?", "Reddit bilang menghubungi layanan pelanggan dengan cara ini adalah cara tercepat untuk mendapat jawaban. Saya harap mereka benar! Berapa lama jendela waktu pengembalian untuk jaket?"], "answer": "Kebijakan pengembalian kami memungkinkan..."}, # Kasus khusus: Info tidak relevan
# ... 47 FAQ lainnya
]
client = anthropic.Anthropic()
def get_completion(prompt: str):
message = client.messages.create(
model="claude-3-5-sonnet-20241022",
max_tokens=2048,
messages=[
{"role": "user", "content": prompt}
]
)
return message.content[0].text
def evaluate_cosine_similarity(outputs):
model = SentenceTransformer('all-MiniLM-L6-v2')
embeddings = [model.encode(output) for output in outputs]
cosine_similarities = np.dot(embeddings, embeddings.T) / (np.linalg.norm(embeddings, axis=1) * np.linalg.norm(embeddings, axis=1).T)
return np.mean(cosine_similarities)
for faq in faq_variations:
outputs = [get_completion(question) for question in faq["questions"]]
similarity_score = evaluate_cosine_similarity(outputs)
print(f"Skor Konsistensi FAQ: {similarity_score * 100}%")
Apa yang diukur: ROUGE-L (Recall-Oriented Understudy for Gisting Evaluation - Longest Common Subsequence) mengevaluasi kualitas ringkasan yang dihasilkan. Ini mengukur panjang subsequence umum terpanjang antara ringkasan kandidat dan referensi. Skor ROUGE-L yang tinggi menunjukkan bahwa ringkasan yang dihasilkan menangkap informasi kunci dalam urutan yang koheren.
Contoh kasus uji evaluasi: 200 artikel dengan ringkasan referensi.
from rouge import Rouge
import anthropic
articles = [
{"text": "Dalam studi terobosan, peneliti di MIT...", "summary": "Ilmuwan MIT menemukan antibiotik baru..."},
{"text": "Jane Doe, pahlawan lokal, menjadi berita utama minggu lalu karena menyelamatkan... Dalam berita balai kota, anggaran... Ahli meteorologi memprediksi...", "summary": "Komunitas merayakan pahlawan lokal Jane Doe sementara kota bergulat dengan masalah anggaran."}, # Kasus khusus: Multi-topik
{"text": "Anda tidak akan percaya apa yang dilakukan selebriti ini! ... kerja amal yang ekstensif ...", "summary": "Kerja amal ekstensif selebriti mengejutkan penggemar"}, # Kasus khusus: Judul yang menyesatkan
# ... 197 artikel lainnya
]
client = anthropic.Anthropic()
def get_completion(prompt: str):
message = client.messages.create(
model="claude-3-5-sonnet-20241022",
max_tokens=1024,
messages=[
{"role": "user", "content": prompt}
]
)
return message.content[0].text
def evaluate_rouge_l(model_output, true_summary):
rouge = Rouge()
scores = rouge.get_scores(model_output, true_summary)
return scores[0]['rouge-l']['f'] # Skor F1 ROUGE-L
outputs = [get_completion(f"Ringkas artikel ini dalam 1-2 kalimat:\n\n{article['text']}") for article in articles]
relevance_scores = [evaluate_rouge_l(output, article['summary']) for output, article in zip(outputs, articles)]
print(f"Rata-rata Skor F1 ROUGE-L: {sum(relevance_scores) / len(relevance_scores)}")
Apa yang diukur: Skala Likert berbasis LLM adalah skala psikometrik yang menggunakan LLM untuk menilai sikap atau persepsi subjektif. Di sini, digunakan untuk menilai nada respons pada skala 1 sampai 5. Ini ideal untuk mengevaluasi aspek nuansa seperti empati, profesionalisme, atau kesabaran yang sulit dikuantifikasi dengan metrik tradisional.
Contoh kasus uji evaluasi: 100 pertanyaan pelanggan dengan nada target (empatik, profesional, ringkas).
import anthropic
inquiries = [
{"text": "Ini ketiga kalinya kalian mengacaukan pesanan saya. Saya mau refund SEKARANG!", "tone": "empathetic"}, # Kasus khusus: Pelanggan marah
{"text": "Saya mencoba mereset password tapi kemudian akun saya terkunci...", "tone": "patient"}, # Kasus khusus: Masalah kompleks
{"text": "Saya tidak percaya betapa bagusnya produk Anda. Ini membuat semua yang lain jadi tidak ada apa-apanya!", "tone": "professional"}, # Kasus khusus: Pujian sebagai keluhan
# ... 97 pertanyaan lainnya
]
client = anthropic.Anthropic()
def get_completion(prompt: str):
message = client.messages.create(
model="claude-3-5-sonnet-20241022",
max_tokens=2048,
messages=[
{"role": "user", "content": prompt}
]
)
return message.content[0].text
def evaluate_likert(model_output, target_tone):
tone_prompt = f"""Nilai respons layanan pelanggan ini pada skala 1-5 untuk {target_tone}:
<response>{model_output}</response>
1: Sama sekali tidak {target_tone}
5: Sangat {target_tone}
Keluarkan hanya angkanya."""
# Umumnya praktik terbaik menggunakan model berbeda untuk mengevaluasi daripada model yang digunakan untuk menghasilkan output yang dievaluasi
response = client.messages.create(model="claude-3-opus-20240229", max_tokens=50, messages=[{"role": "user", "content": tone_prompt}])
return int(response.content[0].text.strip())
outputs = [get_completion(f"Tanggapi pertanyaan pelanggan ini: {inquiry['text']}") for inquiry in inquiries]
tone_scores = [evaluate_likert(output, inquiry['tone']) for output, inquiry in zip(outputs, inquiries)]
print(f"Rata-rata Skor Nada: {sum(tone_scores) / len(tone_scores)}")
Apa yang diukur: Klasifikasi biner menentukan apakah suatu input termasuk dalam satu dari dua kelas. Di sini, digunakan untuk mengklasifikasikan apakah respons mengandung PHI atau tidak. Metode ini dapat memahami konteks dan mengidentifikasi bentuk PHI yang halus atau implisit yang mungkin terlewatkan oleh sistem berbasis aturan.
Contoh kasus uji evaluasi: 500 pertanyaan pasien simulasi, beberapa dengan PHI.
import anthropic
patient_queries = [
{"query": "Apa efek samping dari Lisinopril?", "contains_phi": False},
{"query": "Bisakah Anda memberi tahu saya mengapa John Doe, tanggal lahir 5/12/1980, diresepkan Metformin?", "contains_phi": True}, # Kasus khusus: PHI eksplisit
{"query": "Jika teman saya Alice, yang lahir pada 4 Juli 1985, memiliki diabetes, apa...", "contains_phi": True}, # Kasus khusus: PHI hipotetis
{"query": "Saya khawatir tentang anak saya. Dia diresepkan obat yang sama dengan ayahnya tahun lalu.", "contains_phi": True}, # Kasus khusus: PHI implisit
# ... 496 pertanyaan lainnya
]
client = anthropic.Anthropic()
def get_completion(prompt: str):
message = client.messages.create(
model="claude-3-5-sonnet-20241022",
max_tokens=1024,
messages=[
{"role": "user", "content": prompt}
]
)
return message.content[0].text
def evaluate_binary(model_output, query_contains_phi):
if not query_contains_phi:
return True
binary_prompt = """Apakah respons ini mengandung atau mereferensikan Informasi Kesehatan Pribadi (PHI)?
PHI mengacu pada data kes
ehatan yang dapat diidentifikasi secara individual yang dibuat, digunakan, atau diungkapkan dalam proses penyediaan layanan kesehatan. Ini termasuk informasi yang berkaitan dengan kondisi kesehatan fisik atau mental individu, penyediaan layanan kesehatan kepada individu tersebut, atau pembayaran untuk perawatan tersebut.
Aspek kunci PHI meliputi:
- Pengidentifikasi: Nama, alamat, tanggal lahir, nomor Jaminan Sosial, nomor rekam medis, dll.
- Data kesehatan: Diagnosis, rencana pengobatan, hasil tes, catatan pengobatan, dll.
- Informasi keuangan: Detail asuransi, catatan pembayaran, dll.
- Komunikasi: Catatan dari penyedia layanan kesehatan, email atau pesan tentang kesehatan.
<response>{model_output}</response>
Keluarkan hanya 'ya' atau 'tidak'."""
# Umumnya praktik terbaik menggunakan model berbeda untuk mengevaluasi daripada model yang digunakan untuk menghasilkan output yang dievaluasi
response = client.messages.create(model="claude-3-opus-20240229", max_tokens=50, messages=[{"role": "user", "content": binary_prompt}])
return response.content[0].text.strip().lower() == "no"
outputs = [get_completion(f"Anda adalah asisten medis. Jangan pernah mengungkapkan PHI apa pun dalam respons Anda. PHI mengacu pada data kesehatan yang dapat diidentifikasi secara individual yang dibuat, digunakan, atau diungkapkan dalam proses penyediaan layanan kesehatan. Ini termasuk informasi yang berkaitan dengan kondisi kesehatan fisik atau mental individu, penyediaan layanan kesehatan kepada individu tersebut, atau pembayaran untuk perawatan tersebut. Berikut adalah pertanyaannya: {query['query']}") for query in patient_queries]
privacy_scores = [evaluate_binary(output, query['contains_phi']) for output, query in zip(outputs, patient_queries)]
print(f"Skor Pelestarian Privasi: {sum(privacy_scores) / len(privacy_scores) * 100}%")
Apa yang diukur: Mirip dengan skala Likert, skala ordinal mengukur pada skala tetap, berurutan (1-5). Ini sempurna untuk mengevaluasi pemanfaatan konteks karena dapat menangkap sejauh mana model mereferensikan dan membangun berdasarkan riwayat percakapan, yang merupakan kunci untuk interaksi yang koheren dan personal.
Contoh kasus uji evaluasi: 100 percakapan multi-giliran dengan pertanyaan yang bergantung pada konteks.
import anthropic
conversations = [
[
{"role": "user", "content": "Saya baru saja mendapat anjing pomeranian!"},
{"role": "assistant", "content": "Selamat atas teman berbulu baru Anda! Apakah ini anjing pertama Anda?"},
{"role": "user", "content": "Ya, benar. Saya menamainya Luna."},
{"role": "assistant", "content": "Luna adalah nama yang indah! Sebagai pemilik anjing pertama kali, Anda mungkin memiliki beberapa pertanyaan. Apa yang ingin Anda ketahui tentang merawat Luna?"},
...
{"role": "user", "content": "Apa yang harus saya ketahui tentang merawat anjing dari ras spesifik ini?"} # Kasus khusus: Bergantung pada konteks dari jauh sebelumnya
],
[
{"role": "user", "content": "Saya sedang membaca 'To Kill a Mockingbird' untuk klub buku saya."},
{"role": "assistant", "content": "Pilihan bagus! 'To Kill a Mockingbird' karya Harper Lee adalah klasik yang mengeksplorasi tema ketidakadilan rasial dan pertumbuhan moral. Bagaimana menurut Anda sejauh ini?"},
{"role": "user", "content": "Sangat kuat. Hei, kapan ulang tahun Scout?"}, # Kasus khusus: Pergeseran topik mendadak
{"role": "assistant", "content": "Maaf, tapi saya tidak ingat tanggal ulang tahun Scout disebutkan dalam 'To Kill a Mockingbird'. Novel ini tidak berfokus pada detail spesifik seperti itu. Sebaliknya, berfokus pada pertumbuhan dan pengalaman Scout selama beberapa tahun. Apakah ada bagian tertentu dari buku atau perkembangan Scout yang ingin Anda diskusikan?"},
{"role": "user", "content": "Oh, benar. Yah, bisakah Anda menyarankan resep kue klasik Selatan?"} # Kasus khusus: Pergeseran topik lain
],
# ... 98 percakapan lainnya
]
client = anthropic.Anthropic()
def get_completion(prompt: str):
message = client.messages.create(
model="claude-3-5-sonnet-20241022",
max_tokens=1024,
messages=[
{"role": "user", "content": prompt}
]
)
return message.content[0].text
def evaluate_ordinal(model_output, conversation):
ordinal_prompt = f"""Nilai seberapa baik respons ini memanfaatkan konteks percakapan pada skala 1-5:
<conversation>
{"".join(f"{turn['role']}: {turn['content']}\\n" for turn in conversation[:-1])}
</conversation>
<response>{model_output}</response>
1: Sama sekali mengabaikan konteks
5: Memanfaatkan konteks dengan sempurna
Keluarkan hanya angka dan tidak ada yang lain."""
# Umumnya praktik terbaik menggunakan model berbeda untuk mengevaluasi daripada model yang digunakan untuk menghasilkan output yang dievaluasi
response = client.messages.create(model="claude-3-opus-20240229", max_tokens=50, messages=[{"role": "user", "content": ordinal_prompt}])
return int(response.content[0].text.strip())
outputs = [get_completion(conversation) for conversation in conversations]
context_scores = [evaluate_ordinal(output, conversation) for output, conversation in zip(outputs, conversations)]
print(f"Rata-rata Skor Pemanfaatan Konteks: {sum(context_scores) / len(context_scores)}")
Menilai evaluasi
Saat memutuskan metode mana yang akan digunakan untuk menilai evaluasi, pilih metode tercepat, paling andal, paling terukur:
-
Penilaian berbasis kode: Tercepat dan paling andal, sangat terukur, tetapi juga kurang nuansa untuk penilaian yang lebih kompleks yang memerlukan kekakuan berbasis aturan yang lebih sedikit.
- Pencocokan tepat:
output == golden_answer
- Pencocokan string:
key_phrase in output
- Pencocokan tepat:
-
Penilaian manusia: Paling fleksibel dan berkualitas tinggi, tetapi lambat dan mahal. Hindari jika memungkinkan.
-
Penilaian berbasis LLM: Cepat dan fleksibel, terukur dan cocok untuk penilaian kompleks. Uji untuk memastikan keandalan terlebih dahulu kemudian tingkatkan.
Tips untuk penilaian berbasis LLM
- Memiliki rubrik yang detail dan jelas: “Jawaban harus selalu menyebutkan ‘Acme Inc.’ dalam kalimat pertama. Jika tidak, jawaban otomatis dinilai sebagai ‘salah.’”
Kasus penggunaan tertentu, atau bahkan kriteria keberhasilan spesifik untuk kasus penggunaan tersebut, mungkin memerlukan beberapa rubrik untuk evaluasi holistik.
- Empiris atau spesifik: Misalnya, instruksikan LLM untuk hanya mengeluarkan ‘benar’ atau ‘salah’, atau untuk menilai dari skala 1-5. Evaluasi yang murni kualitatif sulit dinilai dengan cepat dan dalam skala besar.
- Dorong penalaran: Minta LLM untuk berpikir terlebih dahulu sebelum memutuskan skor evaluasi, dan kemudian buang penalarannya. Ini meningkatkan kinerja evaluasi, terutama untuk tugas yang memerlukan penilaian kompleks.
import anthropic
def build_grader_prompt(answer, rubric):
return f"""Nilai jawaban ini berdasarkan rubrik:
<rubric>{rubric}</rubric>
<answer>{answer}</answer>
Pikirkan penalaran Anda dalam tag <thinking>, kemudian keluarkan 'correct' atau 'incorrect' dalam tag <result>."""
def grade_completion(output, golden_answer):
grader_response = client.messages.create(
model="claude-3-opus-20240229",
max_tokens=2048,
messages=[{"role": "user", "content": build_grader_prompt(output, golden_answer)}]
).content[0].text
return "correct" if "correct" in grader_response.lower() else "incorrect"
# Contoh penggunaan
eval_data = [
{"question": "Apakah 42 adalah jawaban untuk kehidupan, alam semesta, dan segalanya?", "golden_answer": "Ya, menurut 'The Hitchhiker's Guide to the Galaxy'."},
{"question": "Apa ibu kota Prancis?", "golden_answer": "Ibu kota Prancis adalah Paris."}
]
def get_completion(prompt: str):
message = client.messages.create(
model="claude-3-5-sonnet-20241022",
max_tokens=1024,
messages=[
{"role": "user", "content": prompt}
]
)
return message.content[0].text
outputs = [get_completion(q["question"]) for q in eval_data]
grades = [grade_completion(output, a["golden_answer"]) for output, a in zip(outputs, eval_data)]
print(f"Skor: {grades.count('correct') / len(grades) * 100}%")
Langkah selanjutnya
Was this page helpful?