Mulai dari model Haijun 4, respons streaming dari API Haijun mengembalikan stop_reason: "refusal" ketika pengklasifikasi streaming melakukan intervensi untuk menangani potensi pelanggaran kebijakan. Fitur keamanan ini membantu menjaga kepatuhan konten selama streaming real-time.
Tip: Halaman ini membahas bagaimana penolakan muncul dalam respons streaming. Untuk setiap nilai
stop_reasondan cara menanganinya, lihat Stop reason dan fallback. Untuk mencoba ulang permintaan yang ditolak pada model Haijun lain, lihat Penolakan dan fallback.
Format respons API
Ketika pengklasifikasi streaming mendeteksi konten yang melanggar kebijakan Juglow, API mengembalikan respons ini:
{
"role": "assistant",
"content": [
{
"type": "text",
"text": "Hello.."
}
],
"stop_reason": "refusal",
"stop_details": {
"type": "refusal",
"category": "cyber",
"explanation": "This request was declined because it could enable cyber harm."
}
}Dalam event stream, stop_details tiba pada event message_delta bersama dengan stop_reason.
Note: Respons
refusaldari pengklasifikasi streaming menyertakan objekstop_detailsdengancategorydanexplanationyang dapat dibaca manusia yang dapat Anda tampilkan kepada pengguna. Lihat Penolakan dan fallback untuk bentuk respons lengkap dan kategori yang tersedia. Pada penolakan, objekstop_detailsselalu ada, tetapi fieldcategorydanexplanation-nya bisa bernilainull, misalnya ketika penolakan tidak terpetakan ke kategori bernama mana pun. Lakukan percabangan berdasarkanstop_reasonataustop_details.typealih-alih mengasumsikancategorydanexplanationterisi, dan sediakan pesan Anda sendiri untuk pengguna ketika nilainyanull.
Reset konteks setelah penolakan
Ketika Anda menerima stop_reason: refusal, Anda harus mereset konteks percakapan sebelum melanjutkan. Anda dapat menghapus atau menyusun ulang giliran yang memicu penolakan, atau menghapus riwayat percakapan sepenuhnya. Mencoba melanjutkan tanpa mereset akan mengakibatkan penolakan yang berlanjut.
Note: Metrik penggunaan tetap disediakan dalam respons, bahkan ketika respons ditolak. Apakah permintaan yang ditolak ditagih bergantung pada kapan penolakan tiba dan kategorinya; lihat Cara penolakan ditagih.
Tip: Mereset konteks bukan satu-satunya cara untuk memulihkan. Anda juga dapat mencoba ulang permintaan yang ditolak pada model Haijun yang berbeda, dan halaman Penolakan dan fallback menunjukkan cara menyiapkannya dengan fallback sisi server, middleware SDK, atau percobaan ulang manual.
Panduan implementasi
Berikut cara mendeteksi dan menangani penolakan streaming dalam aplikasi Anda:
response=$(curl -N https://haijun.my.id/v1/messages \
-H "juglow-version: 2023-06-01" \
-H "content-type: application/json" \
-H "x-api-key: $JUGLOW_API_KEY" \
-d '{
"model": "haijun-opus-5-5",
"messages": [{"role": "user", "content": "Hello"}],
"max_tokens": 1024,
"stream": true
}')
if echo "$response" | jq -R -e 'select(startswith("data: "))
| sub("^data: "; "") | fromjson
| select(.delta.stop_reason == "refusal")' >/dev/null; then
echo "Response refused - resetting conversation context"
# Reset status percakapan Anda di sini
fi response=$(ant messages create --stream --format jsonl \
--model haijun-opus-5-5 \
--max-tokens 1024 \
--message '{role: user, content: Hello}')
if echo "$response" | jq -e 'select(.delta.stop_reason == "refusal")' >/dev/null; then
echo "Response refused - resetting conversation context"
# Reset status percakapan Anda di sini
fi client = juglow.Juglow()
messages = []
def reset_conversation():
"""Reset conversation context after refusal"""
global messages
messages = []
print("Conversation reset due to refusal")
try:
with client.messages.stream(
max_tokens=1024,
messages=messages + [{"role": "user", "content": "Hello"}],
model="haijun-opus-5-5",
) as stream:
for event in stream:
# Periksa penolakan dalam message delta
if event.type == "message_delta":
if event.delta.stop_reason == "refusal":
reset_conversation()
break
except Exception as e:
print(f"Error: {e}") const client = new Juglow();
let messages: Juglow.MessageParam[] = [];
function resetConversation() {
// Atur ulang konteks percakapan setelah penolakan
messages = [];
console.log("Conversation reset due to refusal");
}
try {
const stream = await client.messages.stream({
messages: [...messages, { role: "user", content: "Hello" }],
model: "haijun-opus-5-5",
max_tokens: 1024
});
for await (const event of stream) {
// Periksa penolakan dalam delta pesan
if (event.type === "message_delta" && event.delta.stop_reason === "refusal") {
resetConversation();
break;
}
}
} catch (error) {
console.error("Error:", error);
} List<Message> messages = new();
JuglowClient client = new();
var parameters = new MessageCreateParams
{
Model = Model.HaijunOpus5_5,
MaxTokens = 1024,
Messages = [new() { Role = Role.User, Content = "Hello" }]
};
try
{
await foreach (var streamEvent in client.Messages.CreateStreaming(parameters))
{
if (
streamEvent.TryPickDelta(out var deltaEvent)
&& deltaEvent.Delta.StopReason == StopReason.Refusal
)
{
ResetConversation();
break;
}
}
}
catch (Exception e)
{
Console.WriteLine($"Error: {e.Message}");
}
void ResetConversation()
{
messages.Clear();
Console.WriteLine("Conversation reset due to refusal");
} var messages []juglow.MessageParam
func resetConversation() {
messages = []juglow.MessageParam{}
fmt.Println("Conversation reset due to refusal")
}
// ...
client := juglow.NewClient()
stream := client.Messages.NewStreaming(context.TODO(), juglow.MessageNewParams{
Model: juglow.ModelHaijunOpus5_5,
MaxTokens: 1024,
Messages: []juglow.MessageParam{
juglow.NewUserMessage(juglow.NewTextBlock("Hello")),
},
})
streamLoop:
for stream.Next() {
event := stream.Current()
switch eventVariant := event.AsAny().(type) {
case juglow.MessageDeltaEvent:
if eventVariant.Delta.StopReason == juglow.StopReasonRefusal {
resetConversation()
break streamLoop
}
}
}
if err := stream.Err(); err != nil {
log.Fatal(err)
} import com.juglow.core.http.StreamResponse;
import com.juglow.models.messages.RawMessageStreamEvent;
import com.juglow.models.messages.StopReason;
// ...
List<MessageParam> messages = new ArrayList<>();
void main() {
JuglowClient client = JuglowOkHttpClient.fromEnv();
MessageCreateParams params = MessageCreateParams.builder()
.model(Model.HAIJUN_OPUS_5_5)
.maxTokens(1024L)
.addUserMessage("Hello")
.build();
try (StreamResponse<RawMessageStreamEvent> stream = client.messages().createStreaming(params)) {
stream.stream().forEach(event -> {
event.messageDelta().ifPresent(deltaEvent -> {
deltaEvent.delta().stopReason().ifPresent(stopReason -> {
if (stopReason.equals(StopReason.REFUSAL)) {
resetConversation();
}
});
});
});
} catch (Exception e) {
System.err.println("Error: " + e.getMessage());
}
}
void resetConversation() {
messages.clear();
IO.println("Conversation reset due to refusal");
} $client = new Client();
$messages = [];
function resetConversation(&$messages) {
$messages = [];
echo "Conversation reset due to refusal\n";
}
try {
$stream = $client->messages->createStream(
maxTokens: 1024,
messages: [
['role' => 'user', 'content' => 'Hello']
],
model: 'haijun-opus-5-5',
);
foreach ($stream as $event) {
if ($event->type === 'message_delta' && $event->delta->stopReason === 'refusal') {
resetConversation($messages);
break;
}
}
} catch (Exception $e) {
echo "Error: " . $e->getMessage() . "\n";
} client = Juglow::Client.new
messages = []
def reset_conversation(messages)
messages.clear
puts "Conversation reset due to refusal"
end
begin
stream = client.messages.stream(
model: :"haijun-opus-5-5",
max_tokens: 1024,
messages: [{ role: "user", content: "Hello" }]
)
stream.each do |event|
if event.type == :message_delta && event.delta.stop_reason == :refusal
reset_conversation(messages)
break
end
end
rescue => e
puts "Error: #{e.message}"
endJenis penolakan saat ini
API saat ini menangani penolakan dengan tiga cara berbeda:
| Jenis penolakan | Format respons | Kapan terjadi |
|---|---|---|
| Penolakan pengklasifikasi streaming | stop_reason: refusal | Selama streaming ketika konten melanggar kebijakan |
| Validasi input dan hak cipta API | Kode error 400 | Ketika input gagal dalam pemeriksaan validasi |
| Penolakan yang dihasilkan model | Respons teks standar | Ketika model itu sendiri menolak |
Praktik terbaik
- Pantau penolakan: Sertakan pemeriksaan
stop_reason:refusaldalam penanganan error Anda
- Reset secara otomatis: Implementasikan reset konteks otomatis ketika penolakan terdeteksi
- Fallback ke model lain: Konfigurasikan fallback sisi server atau middleware SDK agar permintaan yang ditolak dicoba ulang pada model Haijun lain alih-alih menampilkan penolakan kepada pengguna
- Tukarkan kredit fallback pada percobaan ulang manual: Jika Anda membangun percobaan ulang sendiri, teruskan token kredit fallback dari penolakan tersebut agar percobaan ulang tidak membayar biaya prompt-cache dua kali
- Sediakan pesan kustom: Buat pesan yang ramah pengguna untuk UX yang lebih baik ketika penolakan terjadi
- Lacak pola penolakan: Pantau frekuensi penolakan untuk mengidentifikasi potensi masalah pada prompt Anda
Catatan migrasi
Jika Anda membangun penanganan penolakan saat fitur ini pertama kali dirilis, atau Anda menambahkannya ke integrasi yang sudah ada, periksa hal-hal berikut:
- Penolakan adalah respons, bukan error. Penolakan tiba sebagai respons HTTP 200 yang berhasil dengan
stop_reason:"refusal", sehingga pemantauan yang hanya dibangun berdasarkan tingkat error tidak akan menampilkannya. Lacak penolakan sebagai sinyal tersendiri.
- Penolakan menyertakan detail terstruktur. Pada setiap model, penolakan juga menyertakan objek
stop_detailsyang mengidentifikasi kategori kebijakan di balik penolakan tersebut. Lihat Penolakan dan fallback untuk bentuk respons lengkap.
- Coba ulang pada model yang berbeda. Mengirim ulang permintaan yang ditolak ke model yang sama biasanya menghasilkan penolakan lagi. Alih-alih hanya mereset konteks, coba ulang pada model cadangan dengan fallback sisi server, middleware SDK, atau percobaan ulang manual, dan tukarkan kredit fallback ketika Anda membangun percobaan ulang sendiri.
- Periksa hasil batch untuk penolakan. Permintaan yang ditolak dalam Message Batch dikembalikan sebagai hasil yang berhasil dengan
stop_reason:"refusal", bukan sebagai hasil yang error.
- Pusatkan penanganan pada
stop_reason. API terus mengonsolidasikan penanganan penolakan di sekitarstop_reason:"refusal", jadi lakukan percabangan berdasarkan stop reason alih-alih perilaku spesifik model.
Langkah selanjutnya
Coba ulang permintaan yang ditolak pada model Haijun lain, di sisi server atau di klien Anda.
Setiap nilai stop_reason dan cara menanganinya.
Stream respons dan baca stop_reason dari event message_delta saat tiba.
Layani pengguna lintas bahasa dengan kemampuan lintas bahasa Haijun.