ประเด็นสำคัญ
- ข้อความมาจากไคลเอนต์ ดังนั้นให้ทำซ้ำการเรียกด้วย curl เพื่อดูบอดี้ข้อผิดพลาดและสถานะจริง
- HTTP 429 พร้อม code rate_limited หรือ concurrency เป็นสาเหตุที่พบบ่อยที่สุดบนบัญชีที่มีกิจกรรมสูง และสตรีมจะเก็บช่องของมันไว้จนกว่าจะสิ้นสุด
- ตรวจสอบ Base URL, คีย์, model ID uncensored, ขนาดบอดี้ (8 MB) และโทเคนรวม (100,000) ก่อนสิ่งอื่นใด
- ลองใหม่เฉพาะ 429 และการตัดการเชื่อมต่อ รอ Retry-After และรักษาความพร้อมใช้งานพร้อมกันไว้ภายใต้ขีดจำกัดคีย์
ข้อความนี้บอกคุณจริงๆ ว่าอะไร
หากคุณค้นหา ข้อผิดพลาดไม่ทราบสาเหตุจากการสตรีม LLM เรียนรู้เพิ่มเติม คุณอาจกำลังดูข้อความแจ้งเตือนหรือบรรทัดสีแดงในแชทหน้าเว็บ ปลั๊กอินแก้ไข หรือเฟรมเวิร์กเอเจนต์ คำพูดนี้มาจากไคลเอนต์นั้น มันหมายถึงแอปขอคำตอบแบบสตรีม มีบางอย่างผิดพลาดก่อนหรือระหว่างสตรีม และแอปไม่รู้ว่าอธิบายอย่างไร API รายงานปัญหาด้วยสถานะ HTTP และบอดี้ข้อผิดพลาด JSON และไคลเอนต์ได้ทิ้งรายละเอียดนั้นไปแล้ว
นั่นเป็นข่าวดี เพราะหมายความว่าคุณสามารถดึงรายละเอียดกลับมาได้ ส่งคำขอเดียวกันภายนอกไคลเอนต์ อ่านบรรทัดสถานะและบอดี้ และสาเหตุมักจะชัดเจนภายในหนึ่งหรือสองครั้ง หน้าเว็บนี้กล่าวถึงสาเหตุตามลำดับที่มักเกิดขึ้นใน API นี้ จากนั้นให้ไคลเอนต์สตรีมขนาดเล็กที่พิมพ์ข้อผิดพลาดจริงแทนที่จะซ่อนมัน
สิ่งหนึ่งที่ต้องจำไว้ตั้งแต่ต้น: คำขอสตรีมมีจุดล้มเหลวสองจุด มันสามารถล้มเหลวก่อนไบต์แรก เมื่อเซิร์ฟเวอร์ปฏิเสธคำขอ (คีย์ผิด, URL ผิด, ขีดจำกัด) หรือมันสามารถล้มเหลวระหว่างทาง เมื่อการเชื่อมต่อตัดหลังจากข้อความบางส่วนมาถึงแล้ว การแก้ไขแตกต่างกัน ดังนั้นให้สังเกตว่าคุณเห็นข้อใดสองข้อนี้ หากคำตอบไม่เคยเริ่มต้น ให้ดูส่วนที่สองถึงสี่ หากมันเริ่มต้นแล้วหยุด ให้ดูส่วนเกี่ยวกับพร็อกซีและเวลาหมดอายุ
ตรวจสอบ base URL, คีย์ API และโมเดลก่อน
ข้อผิดพลาดการสตรีมส่วนใหญ่ในการตั้งค่าใหม่เกิดจากความผิดพลาดเล็กๆ สามประการ ใช้เวลาเพียงเล็กน้อยในการตัดความเป็นไปได้
- Base URL ต้องเป็น
https://api.uncensoredllmhub.com/v1รวมถึง/v1และไม่มี/chat/completionsต่อท้าย ไคลเอนต์จะเพิ่มพาธเอง หากคุณวางเอนด์พอยต์เต็มลงในฟิลด์ที่คาดหวัง Base URL ไคลเอนต์จะขอพาธที่ไม่มีอยู่จริงและรายงานความล้มเหลวที่คลุมเครือ - คีย์ API. หัวข้อคือ
Authorization: Bearer YOUR_KEYช่องว่างที่เกินมา นิวไลน์ที่คัดลอกมาพร้อมกับคีย์ หรือคีย์จากบริการอื่น ล้วนทำให้เกิดความล้มเหลวแบบเดียวกัน สร้างหรือคัดลอกคีย์อีกครั้งจาก หน้าคีย์ API หากไม่แน่ใจ - Model ID. โมเดลเดียวคือ
uncensoredไคลเอนต์ที่มีตัวเลือกแบบเลื่อนลงมักเติมชื่อจากผู้ให้บริการรายอื่น พิมพ์ ID ด้วยตนเอง และเรียกGET /v1/modelsหากต้องการยืนยันว่าเซิร์ฟเวอร์แสดงรายการอะไร
วิธีทดสอบทั้งสามอย่างพร้อมกันคือการเรียกใช้ models การเรียกนี้ไม่สตรีม ดังนั้นจึงแยกปัญหาการเชื่อมต่อหรือคีย์ออกจากปัญหาการสตรีมได้:
curl -i https://api.uncensoredllmhub.com/v1/models -H "Authorization: Bearer $API_KEY"
หากผลลัพธ์นี้แสดงรายการปกติ URL และคีย์ถูกต้องและคุณสามารถหยุดสงสัยเกี่ยวกับสิ่งเหล่านั้นได้ หากล้มเหลว ให้แก้ไขปัญหานั้นก่อนแตะต้องอะไรเกี่ยวกับการสตรีม นอกจากนี้ ตรวจสอบว่าบัญชีของคุณมีเครดิต: API จะส่งยอดคงเหลือที่เหลือของคุณในหัวข้อความ X-Balance-USD ในการตอบสนอง ซึ่งสะดวกเมื่อคีย์หยุดทำงานกะทันหันหลังจากการใช้งานหนัก หน้า ราคา อธิบายการเติมเงิน และบัญชีใหม่สามารถขอเครดิตทดลองใช้ $0.50 ได้จากหน้าคีย์
ขีดจำกัดอัตราและการสตรีมที่ครอบครองช่อง
สาเหตุที่พบบ่อยที่สุดถัดไปคือ HTTP 429 มีสามรูปแบบ และไคลเอนต์ของคุณจะรวมทั้งหมดนั้นเป็นข้อความที่ไม่เป็นประโยชน์เดียวกัน
| สัญญาณ | ความหมาย | สิ่งที่ควรทำ |
|---|---|---|
429, code rate_limited | คำขอมากเกินไปต่อนาทีสำหรับคีย์ | ลดความเร็วลง; คีย์แบบเต็มอนุญาต 300 ต่อนาที คีย์ทดลองใช้ 60 |
429, code concurrency | คำขอที่ทำงานพร้อมกันมากเกินไป | จัดคิว; คีย์แบบเต็มอนุญาต 8 พร้อมกัน คีย์ทดลองอนุญาต 2 |
429 พร้อม Retry-After: 5 | การโอเวอร์โหลดชั่วคราวจากฝั่งบริการ | รอ 5 วินาที แล้วลองใหม่ |
ขีดจำกัดความพร้อมใช้งานคือสิ่งที่ทำให้ผู้คนประหลาดใจ เนื่องจากวิธีการทำงานของการสตรีม คำขอที่สตรีมจะครอบครองช่องของมันจนกว่าสตรีมจะสิ้นสุด ไม่ใช่จนกว่าโทเคนแรกจะมาถึง หากแอปของคุณเปิดสตรีมสำหรับข้อความทุกข้อความและไม่ปิดสตรีมเก่า ตัวอย่างเช่น เมื่อผู้ใช้เปลี่ยนหน้าและ UI ลืมที่จะยกเลิกคำขอ ช่องเหล่านั้นจะยังคงถูกครอบครอง บนคีย์ทดลองที่มีขีดจำกัด 2 สตรีมที่ทิ้งไว้สองอันก็เพียงพอที่จะทำให้ข้อความที่สามล้มเหลว
อาการสอดคล้องกัน ข้อความแรกๆ ทำงาน จากนั้นข้อผิดพลาดเริ่มขึ้น จากนั้นทุกอย่างทำงานอีกครั้งหลังจากรอไม่นาน หากตรงกับนั้น ให้ยกเลิกสตรีมที่คุณไม่ต้องการอีกต่อไป (AbortController ในเบราว์เซอร์ ปิดการตอบสนองในเซิร์ฟเวอร์) และจำกัดจำนวนคำขอพร้อมกันในโค้ดของคุณ ตัวแทนอัตโนมัติเป็นสาเหตุหลัก: ตัววางแผนที่ปล่อยการเรียกใช้ฟังก์ชันสิบครั้งพร้อมกันจะชนกับขีดจำกัดบนคีย์ทดลองทันที
หัวความตอบสนองช่วยให้คุณเห็นสถานะของคุณ X-RateLimit-Limit-Requests และ X-RateLimit-Limit-Concurrency แสดงขีดจำกัดที่ใช้กับคีย์ที่คุณใช้ และ X-Request-Id ระบุการเรียกหากต้องการถาม ฝ่ายสนับสนุน เกี่ยวกับมัน
ขนาดคำขอและความยาวของหน้าต่างบริบท
คำขออาจถูกปฏิเสธเนื่องจากใหญ่เกินไป ตัวเลขสองตัวสำคัญ บอดี้มีขนาดสูงสุด 8 MB และพรอมต์รวมกับการสร้างต้องพอดีกับหน้าต่างบริบท 100,000 โทเคน หน้าแชทที่ส่งการสนทนาทั้งหมดในทุกเทิร์นจะชนขีดจำกัดเหล่านี้ช้าๆ แล้วทั้งหมดพร้อมกัน: แชททำงานได้หนึ่งชั่วโมง จากนั้นข้อความยาวหรือไฟล์ที่วางทับจะทำให้เกิน และทุกเทิร์นหลังล้มเหลวเพราะประวัติยังคงอยู่ในคำขอ
หากข้อผิดพลาดเริ่มขึ้นหลังจากเซสชันที่ยาวนาน ให้ทดสอบด้วยการสนทนาใหม่สั้นๆ หากทำงานได้ ประวัติคือสาเหตุ ตัดประวัติโดยทิ้งรอบเก่า สรุปเป็นข้อความเดียว หรือเริ่มแชทใหม่ เอกสารที่วางไว้ขนาดใหญ่เป็นอีกตัวกระตุ้น ไฟล์ข้อความขนาดหลายร้อยกิโลไบต์ใช้ได้ แต่บล็อบ base64 หรือบันทึกขนาดใหญ่สามารถถึง 8 MB ได้เร็วกว่าที่คุณคาดคิด
คุณไม่จำเป็นต้องตั้งค่า max_tokens เนื่องจากการสร้างผลลัพธ์สามารถใช้ส่วนที่เหลือของหน้าต่างได้ หากคุณตั้งค่า ให้แน่ใจว่าโทเคนพรอมต์รวมกับ max_tokens น้อยกว่า 100,000 ไคลเอนต์ที่กำหนดค่า max_tokens ขนาดใหญ่ไว้ล่วงหน้าบนประวัติที่ยาวสามารถทำให้ผลรวมเกินหน้าต่างได้แม้ว่าพรอมต์เพียงอย่างเดียวดูเหมือนจะถูกต้อง
พร็อกซี การบัฟเฟอร์ และเวลาหมดอายุ
สตรีมมิงใช้ server-sent events: การตอบสนอง HTTP ที่มีอายุยืนที่ส่งชิ้นส่วนเล็กๆ ทีละชิ้นเมื่อถูกสร้างขึ้น สิ่งใดก็ตามที่อยู่ระหว่างคุณและ API ที่รอการตอบสนองทั้งหมดก่อนส่งต่อจะทำลายสิ่งนั้น ผลลัพธ์คือความเงียบนานตามด้วย burst หรือ timeout และข้อผิดพลาดทั่วไป
ค้นหาสิ่งเหล่านี้ในการตั้งค่าของคุณเอง:
- รีเวิร์สพร็อกซี หากคุณกำหนดเส้นทาง API ผ่าน nginx หรือพร็อกซีที่คล้ายกัน ให้ปิดการบัฟเฟอร์การตอบสนองสำหรับตำแหน่งนั้น และเพิ่มเวลาอ่านให้สูงกว่าคำตอบที่ยาวที่สุดที่คุณคาดหวัง คำตอบที่ยาวจากหน้าต่าง 100,000 โทเคนอาจใช้เวลาสักพัก
- พร็อกซีองค์กรหรือแอนติไวรัส บางตัวตรวจสอบ ทราฟฟิก HTTPS และเก็บบอดี้ ทดสอบจากฮอตสปอตโทรศัพท์เพื่อตัดประเด็นนี้ออก
- ฟังก์ชันแบบเซิร์ฟเวอร์เลส แพลตฟอร์มจำนวนมากจำกัดเวลาการทำงานหรือ buffer การตอบสนองเว้นแต่คุณจะเลือกสตรีมมิง หากสตรีมมิงตายที่จำนวนวินาทีเดียวกันทุกครั้ง เวลาจำกัดของแพลตฟอร์มน่าจะเป็นสาเหตุ
- ส่วนขยายเบราว์เซอร์และ VPN พบได้ยาก แต่อาจตัดการเชื่อมต่อที่ว่างอยู่
สัญญาณที่ชี้มาที่นี่คือข้อผิดพลาดตรงกลางคำตอบ โดยมีเวลาตัดที่เหมือนกันทุกครั้ง การจำกัดอัตราจะปฏิเสธคำขอตั้งแต่เริ่มต้น ดังนั้นการตัดกลางสตรีมที่เกิดขึ้นเสมอที่ เช่น 30 วินาที แทบไม่เกี่ยวข้องกับการจำกัดอัตรา
ไคลเอนต์ที่แสดงข้อผิดพลาดที่แท้จริง
ใช้เมื่อคุณต้องการความจริงแทนข้อความที่สุภาพ มันดักจับข้อยกเว้นของ OpenAI SDK พิมพ์สถานะและเนื้อหาข้อผิดพลาด และอ่านคำแนะนำการลองใหม่เมื่อมี
import time
from openai import OpenAI, APIConnectionError, APIStatusError, RateLimitError
client = OpenAI(
base_url="https://api.uncensoredllmhub.com/v1",
api_key="YOUR_API_KEY",
)
def stream_once(messages):
stream = client.chat.completions.create(
model="uncensored",
messages=messages,
stream=True,
)
for chunk in stream:
if chunk.choices and chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="", flush=True)
if getattr(chunk, "usage", None):
print("\n[usage]", chunk.usage)
messages = [{"role": "user", "content": "Write two sentences about harbours."}]
for attempt in range(4):
try:
stream_once(messages)
break
except RateLimitError as e:
wait = int(e.response.headers.get("retry-after", 5))
print("429:", e.body, "- waiting", wait, "s")
time.sleep(wait)
except APIStatusError as e:
print("status", e.status_code, e.body)
print("request id:", e.response.headers.get("x-request-id"))
break
except APIConnectionError as e:
print("connection problem:", e)
time.sleep(2)
แนวคิดเดียวกันใน Node พร้อมสัญญาณยกเลิกเพื่อให้สตรีมที่ถูกทิ้งปล่อยช่องว่าง:
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://api.uncensoredllmhub.com/v1",
apiKey: process.env.API_KEY,
});
const controller = new AbortController();
try {
const stream = await client.chat.completions.create(
{
model: "uncensored",
messages: [{ role: "user", content: "Write two sentences about harbours." }],
stream: true,
},
{ signal: controller.signal }
);
for await (const chunk of stream) {
process.stdout.write(chunk.choices[0]?.delta?.content ?? "");
}
} catch (err) {
console.error("status:", err.status, "body:", err.error);
}
// call controller.abort() when the user leaves the page
และคำสั่ง curl แบบดิบ ซึ่งตัดไคลเอนต์ออกทั้งหมด -N ปิดการบัฟเฟอร์ของ curl และ -i พิมพ์บรรทัดสถานะและส่วนหัว รวมถึง X-Request-Id:
curl -N -i https://api.uncensoredllmhub.com/v1/chat/completions -H "Authorization: Bearer $API_KEY" -H "Content-Type: application/json" -d '{"model":"uncensored","stream":true,"messages":[{"role":"user","content":"Say hello."}]}'
หาก curl ส่งข้อความได้ปกติแต่แอปของคุณไม่ทำงาน API มีสุขภาพดีและปัญหาอยู่ที่แอป ตัวกลาง หรือการตั้งค่า หาก curl แสดงสถานะ 429 หรือสถานะอื่น คุณทราบสาเหตุที่แน่นอนแล้ว
กฎการลองใหม่ที่ไม่ทำให้แย่ลง
การลองใหม่ช่วยกับปัญหาชั่วคราวและทำให้ปัญหาถาวรแย่ลง นโยบายสั้นๆ ช่วยคุณจากปัญหา
- ลองใหม่สำหรับ 429 และการเชื่อมต่อที่หลุด รอ
Retry-Afterเมื่อมี หากไม่มีให้ถอยหลังเป็นวินาทีและเพิ่มการสุ่มเพื่อให้ worker พร้อมกันไม่ลองใหม่พร้อมกัน - อย่าลองใหม่กับความล้มเหลวในการตรวจสอบสิทธิ์หรือคำขอที่ใหญ่เกินไป ผลลัพธ์จะไม่เปลี่ยนแปลง และการลองใหม่แต่ละครั้งเพิ่มสัญญาณรบกวน
- จำกัดจำนวนการลองเป็นสามหรือสี่ครั้ง จากนั้นแสดงข้อความข้อผิดพลาดที่แท้จริงให้ผู้ใช้
- จำกัดความพร้อมใช้งานพร้อมกันของคุณเองต่ำกว่าขีดจำกัดคีย์ semaphore ของ 6 บนคีย์แบบเต็มเหลือที่ว่างสำหรับเครื่องมือที่สองที่ใช้คีย์เดียวกัน
- หากสตรีมขาดกลางทาง ให้เก็บข้อความบางส่วน ส่งใหม่พร้อมข้อความนั้นเป็นข้อความผู้ช่วยและขอให้โมเดลดำเนินการต่อ แทนที่จะสร้างใหม่ตั้งแต่ต้น
คำขอที่ล้มเหลวหรือถูกปฏิเสธไม่คิดเงิน จึงดีบักด้วยการเรียกซ้ำไม่ทำให้เครดิตหมด การเรียกที่สำเร็จคิด $0.15 ต่อ 1M input tokens และ $0.50 ต่อ 1M output tokens รายละเอียดรูปแบบคำขออยู่ใน เอกสารประกอบ API
หากคุณทำทั้งหมดข้างต้นแล้วยังเห็นข้อความ ส่ง X-Request-Id ของการเรียกที่ล้มเหลวไปยัง หน้าสนับสนุน พร้อมเวลาของการลองและว่าการล้มเหลวเกิดขึ้นก่อนหรือหลังโทเคนแรก ข้อมูลนี้เพียงพอที่จะติดตามสิ่งที่เกิดขึ้น
