ประเด็นสำคัญ
- ป้ายกำกับนี้ครอบคลุม URL paths, โครงสร้าง JSON ของคำขอและ response, การยืนยันตัวตนแบบ Bearer และ streaming แบบ SSE
- ป้ายกำกับนี้ไม่ได้ระบุว่าโมเดลใดจะตอบคำถาม, พฤติกรรมของโมเดล, หรือราคา
- การเปลี่ยนผู้ให้บริการโดยทั่วไปหมายถึงการเปลี่ยนค่าสองค่า: base URL และ API key
- ทดสอบการสตรีมมิง, เครื่องมือ, โหมด JSON และรหัสข้อผิดพลาด ก่อนที่จะพึ่งพาผู้ให้บริการ
คำตอบแบบสั้นๆ
เมื่อผู้ให้บริการระบุว่า API ของตนรองรับ OpenAI หมายความว่า API นั้นรับ HTTP request เดียวกันกับที่ไลบรารี OpenAI ส่ง และส่ง response กลับมาในรูปแบบเดียวกัน คุณยังใช้โค้ดเดิมได้ เพียงเปลี่ยน base URL และคีย์ API แล้วการเรียกใช้จะไปยังเซิร์ฟเวอร์อื่น
นั่นคือคำสัญญาทั้งหมด เป็นการระบุเกี่ยวกับอินเทอร์เฟซ เปรียบเสมือนการบอกว่าที่ชาร์จสองอันใช้ปลั๊กแบบเดียวกัน ไม่ได้บอกว่าคุณจะพบอะไรที่ปลายสายอีกฝั่ง โมเดล กฎความปลอดภัย ราคา และขีดจำกัดทั้งหมดถูกกำหนดโดยผู้ให้บริการ และมีความแตกต่างกันมาก
สิ่งที่ป้ายกำกับนี้ครอบคลุมจริง ๆ
ในทางปฏิบัติ ความเข้ากันได้กับ OpenAI คือรายการข้อกำหนดที่ชัดเจน หากผู้ให้บริการรองรับข้อกำหนดทั้งหมด โค้ดส่วนใหญ่จะทำงานได้โดยไม่ต้องแก้ไข
- เส้นทาง คำขอ chat จะไปที่
POST /v1/chat/completionsและรายการโมเดลมาจากGET /v1/models - การยืนยันตัวตน คีย์ API จะส่งผ่าน header
Authorization: Bearer - Body ของ request มีสตริง
model, อาร์เรย์messagesที่เป็น object พร้อมroleและcontent, และฟิลด์ sampling เพิ่มเติมเช่นtemperature,top_p,stopและseed - Body ของ response มี array
choicesที่มีข้อความจาก assistant,finish_reasonและ objectusageที่มีจำนวนโทเคน - สตรีมมิง เมื่อใช้
stream: trueเซิร์ฟเวอร์จะส่ง Server-Sent Events ซึ่งแต่ละ event จะมี JSON delta ขนาดเล็ก และลงท้ายด้วย marker สุดท้าย - ฟีเจอร์เพิ่มเติม การเรียกใช้ฟังก์ชัน, โหมด JSON และฟิลด์อื่น ๆ ที่ผู้ให้บริการเลือกที่จะรองรับ
เนื่องจากเครื่องมือจำนวนมากถูกเขียนขึ้นเพื่อรองรับรูปแบบนี้ จึงกลายเป็นเป้าหมายร่วม เครื่องแก้ไขโค้ด, กรอบงานเอเจนต์, หน้าเว็บบทบาทสมมติ และสคริปต์ทั่วไปต่างอนุญาตให้ระบุ base URL แบบกำหนดเอง และนั่นคือสิ่งที่ต้องการ
เหตุผลที่รูปแบบนี้กลายเป็นเป้าหมายร่วม
รูปแบบ chat completions ได้รับความนิยมเพราะเรียบง่ายและปรากฏขึ้นก่อนหน้า ผู้เขียนเครื่องมือที่รองรับรูปแบบนี้เพียงครั้งเดียวสามารถเข้าถึงแบ็กเอนด์ได้หลายแห่ง และผู้เขียนแบ็กเอนด์ที่รองรับรูปแบบนี้เพียงครั้งเดียวก็สามารถเข้าถึงเครื่องมือได้หลายแห่ง เป็นข้อตกลงที่ดีสำหรับทั้งสองฝ่าย ทำให้รูปแบบนี้คงอยู่ แม้ในบริการที่ไม่เกี่ยวข้องกับบริษัทที่ออกแบบรูปแบบนี้
สำหรับคุณในฐานะนักพัฒนา สิ่งนี้มีความหมายในทางปฏิบัติ โค้ดของคุณไม่จำเป็นต้องสร้างการเชื่อมต่อแบบใหม่สำหรับทุกผู้ให้บริการ คุณสามารถย้ายโปรโตไทป์ระหว่างเอนด์พอยต์ได้ภายในบ่ายวันเดียว เปรียบเทียบโมเดลสองตัวด้วยพรอมต์เดียวกัน หรือเก็บผู้ให้บริการสำรองไว้เมื่อผู้ให้บริการหลักทำงานช้า ค่าใช้จ่ายในการเปลี่ยนใจมีต่ำ ทำให้ทดลองใช้บริการใหม่ได้ง่ายโดยไม่ต้องผูกมัด
อีกด้านหนึ่งคือ พื้นผิวร่วมที่คล้ายกันบดบังความแตกต่างที่แท้จริง เนื่องจากเปลี่ยน API ได้ง่าย จึงมีแนวโน้มที่จะคิดว่าทุกอย่างที่อยู่หลัง URL นั้นเทียบเท่ากัน ซึ่งไม่ใช่เช่นนั้น และส่วนด้านล่างจะแสดงจุดที่ความแตกต่างมักปรากฏ
สิ่งที่ป้ายกำกับนี้ไม่ได้บอก
นี่คือจุดที่ผู้คนมักประหลาดใจ ป้ายกำกับนี้ไม่ได้ระบุทุกสิ่งที่กำหนดว่า API นั้นมีประโยชน์ต่อการทำงานของคุณหรือไม่
โมเดลที่อยู่เบื้องหลัง
เอนด์พอยต์ที่เข้ากันได้สามารถให้บริการโมเดลใดก็ได้ บางรายให้บริการโมเดลแบบเปิดน้ำหนัก บางรายส่งต่อไปยังผู้ให้บริการหลายราย บางรายห่อหุ้มโมเดลที่เป็นกรรมสิทธิ์ ความเข้ากันได้ไม่ได้หมายความว่าบริการนั้นดำเนินการโดย OpenAI และไม่ได้หมายความว่าโมเดลทำงานเหมือนโมเดลของ OpenAI ชื่อโมเดลที่คุณส่งใน model เป็นเพียงสตริงที่ผู้ให้บริการกำหนดขึ้น
พฤติกรรมการปฏิเสธ
กฎเกี่ยวกับเนื้อหาเป็นของโมเดลและผู้ให้บริการ ไม่ใช่ของโปรโตคอล API ที่เข้ากันได้สองรายการสามารถตอบกลับพรอมต์เดียวกันในทิศทางตรงกันข้ามได้ หากกรณีการใช้งานของคุณเป็นนิยาย บทบาทสมมติ หรือเนื้อหาผู้ใหญ่ที่ถูกต้องตามกฎหมายอื่น ๆ ให้ตรวจสอบสิ่งที่ผู้ให้บริการระบุเกี่ยวกับการปฏิเสธก่อนทำการเชื่อมต่อ
ความลึกของฟีเจอร์
ผู้ให้บริการบางรายใช้เฉพาะแชทเท่านั้น ในขณะที่รายอื่นเพิ่มเครื่องมือ โหมด JSON ความน่าจะเป็นของลอการิทึม หรือเอนด์พอยต์เพิ่มเติม หากไคลเอนต์ส่งฟิลด์ที่เซิร์ฟเวอร์เพิกเฉย ผลลัพธ์อาจไม่แสดงข้อผิดพลาดอย่างชัดเจน จึงมีความเป็นไปได้ที่การไม่ตรงกันจะเกิดขึ้นอย่างเงียบ ๆ
ขีดจำกัด ราคา และข้อผิดพลาด
ขีดจำกัดอัตรา ความยาวของหน้าต่างบริบท ขนาดสูงสุดของบอดี้ และราคาต่อโทเคน ล้วนเป็นการเลือกของผู้ให้บริการ บอดี้ของข้อผิดพลาดยังมีความแตกต่างกันแม้รหัสสถานะ HTTP จะตรงกัน ดังนั้นตรรกะการลองใหม่ควรใช้รหัสสถานะและเฮดเดอร์เป็นหลัก แทนที่จะใช้ข้อความในบอดี้
การทดสอบความเข้ากันได้อย่างรวดเร็ว
คุณสามารถตรวจสอบผู้ให้บริการได้ในไม่กี่นาทีด้วยคำขอสามรายการ โดยแทนที่คีย์ด้วยคีย์ของคุณเอง ตัวอย่างนี้ใช้ Base URL ของเว็บไซต์นี้
curl https://api.kimicode.top/v1/models \
-H "Authorization: Bearer YOUR_API_KEY"
curl https://api.kimicode.top/v1/chat/completions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "uncensored",
"messages": [{"role": "user", "content": "Reply with the word ready."}]
}'
การเรียกครั้งแรกยืนยันคีย์และแสดงรายการ ID ของโมเดล การเรียกที่สองตรวจสอบโครงสร้างของแชท จากนั้นทดสอบส่วนที่แอปพลิเคชันของคุณพึ่งพา: เพิ่ม "stream": true และสังเกตการส่งข้อมูลแบบเพิ่มทีละส่วน ส่งอาร์เรย์ tools หากใช้การเรียกใช้ฟังก์ชัน และตั้งค่า response_format เป็น {"type":"json_object"} หากต้องการผลลัพธ์ที่แยกวิเคราะห์ได้
ลองสร้างข้อผิดพลาดโดยเจตนา เช่น การใช้คีย์ที่ผิด คุณต้องการเห็นรหัส HTTP ที่ชัดเจนและบอดี้ข้อผิดพลาดแบบ JSON ที่ไคลเอนต์ของคุณสามารถจัดการได้
คำขอเดียวกันใน Node
SDK JavaScript ใช้ค่าสองค่าเดียวกัน นี่คือตัวอย่างการเรียกแบบสตรีมมิง ซึ่งเป็นรูปแบบที่อินเทอร์เฟซแชทส่วนใหญ่ใช้
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://api.kimicode.top/v1",
apiKey: process.env.API_KEY,
});
const stream = await client.chat.completions.create({
model: "uncensored",
stream: true,
messages: [{ role: "user", content: "Name three uses of SSE." }],
});
for await (const chunk of stream) {
process.stdout.write(chunk.choices[0]?.delta?.content ?? "");
}
หากการพิมพ์นี้แสดงข้อความทีละคำ แสดงว่าเส้นทางสตรีมมิงทำงานตั้งแต่ต้นจนจบ ลูปเดียวกันนี้สามารถใช้กับผู้ให้บริการที่เข้ากันได้ทุกราย ซึ่งเป็นจุดประสงค์หลักของรูปแบบนี้
ลักษณะการเปลี่ยนในโค้ด
ด้วย Python SDK ทางการ การเปลี่ยนแปลงมีเพียงสองอาร์กิวเมนต์ในการสร้างคอนสตรัคเตอร์ ส่วนที่เหลือของโปรแกรมของคุณยังคงเหมือนเดิม
from openai import OpenAI
client = OpenAI(
base_url="https://api.kimicode.top/v1",
api_key="YOUR_API_KEY",
)
resp = client.chat.completions.create(
model="uncensored",
messages=[{"role": "user", "content": "Summarize SSE in one sentence."}],
)
print(resp.choices[0].message.content)
Node SDK ใช้แนวคิดเดียวกันกับตัวเลือก baseURL และ apiKey เครื่องมือจำนวนมากอ่านค่า OPENAI_BASE_URL และ OPENAI_API_KEY จากสภาพแวดล้อม ดังนั้นคุณจึงสามารถเปลี่ยนได้โดยไม่ต้องแก้ไขโค้ดเลยในบางกรณี
อย่าลืมเปลี่ยนสตริงของโมเดลด้วย คำขอที่ระบุชื่อโมเดลที่เซิร์ฟเวอร์ใหม่ไม่ได้ให้บริการจะล้มเหลว และนั่นคือข้อผิดพลาดแรกพบที่พบบ่อยที่สุด
API ของเว็บไซต์นี้จัดอยู่ในประเภทใด
บริการนี้เป็น API แบบโฮสต์ที่เน้นเฉพาะข้อความ ซึ่งปฏิบัติตามรูปแบบของ OpenAI บริการนี้รันโมเดลแบบเปิดน้ำหนักหนึ่งโมเดล โดยดำเนินการโดยผู้ให้บริการอิสระและปรับแต่งให้ตอบกลับโดยไม่มีการปฏิเสธเนื้อหาสำหรับการใช้งานผู้ใหญ่ที่ถูกต้องตามกฎหมาย บริการนี้ไม่ใช่ API ทางการของผู้จำหน่ายโมเดลรายใดรายหนึ่ง และไม่ได้ส่งต่อระหว่างผู้ให้บริการหลายราย ID ของโมเดลคือ uncensored
บริการนี้รองรับสตรีมมิงผ่าน SSE โดยรายงานการใช้งานที่ส่วนท้าย รองรับ function calling โหมด JSON และส่งผ่าน temperature, top_p, stop, seed และค่าปรับต่าง ๆ หน้าต่างบริบทมีขนาด 100,000 โทเคน สำหรับพรอมต์และการสร้างผลลัพธ์รวมกัน บริการนี้ไม่สร้างรูปภาพหรือเสียง และไม่รองรับ embeddings หรือ fine-tuning มีกฎข้อเดียวที่ตายตัว: ไม่มีเนื้อหาทางเพศที่เกี่ยวข้องกับผู้เยาว์
การเรียกเก็บเงินเป็นแบบเติมเงินล่วงหน้าและคิดตามการใช้งานจริง: $0.15 ต่อ 1M โทเคนอินพุต และ $0.50 ต่อ 1M โทเคนเอาต์พุต โดยไม่มีแพ็กเกจรายเดือน คุณสามารถดูรายละเอียดได้ที่ หน้าราคา และ เอกสารประกอบจะอธิบายขั้นตอนการทำคำขอแรก หากคุณต้องการลองใช้งานโดยไม่เสียเงิน บัญชีใหม่สามารถรับเครดิตทดลองใช้ $0.50 ได้เพียงคลิกเดียวที่ หน้าคีย์ API
จุดบกพร่องทั่วไปของความเข้ากันได้
- Base URL ผิด URL ควรลงท้ายด้วย
/v1ไคลเอนต์จะเพิ่ม/chat/completionsเอง ดังนั้นการเพิ่มเข้าไปใน Base URL จะทำให้ได้ผลลัพธ์เป็น 404 - พารามิเตอร์ที่ไม่รองรับ หากไลบรารีส่งฟิลด์ที่เซิร์ฟเวอร์ไม่รู้จัก ให้ตรวจสอบว่าฟิลด์นั้นถูกปฏิเสธหรือถูกเพิกเฉย แล้วลบออก
- สตรีมมิงและความพร้อมกัน คำขอแบบสตรีมมิงจะครอบครองช่องการทำงานพร้อมกันจนกว่าสตรีมจะสิ้นสุด หากแอปของคุณเปิดสตรีมจำนวนมาก คุณอาจพบข้อผิดพลาด 429 ด้วยรหัส
concurrencyแม้จำนวนคำขอต่อนาทีของคุณจะต่ำก็ตาม - ลองใหม่เมื่อได้ 429 ให้ค่า 429 เป็นสัญญาณให้รอ เมื่อมีหัว
Retry-Afterอยู่ในคำตอบ ให้ปฏิบัติตามค่าดังกล่าว - การนับโทเคน อย่าสมมติว่าตัวแบ่งคำโทเคนของผู้ให้บริการอื่นตรงกัน อ่านวัตถุ
usageในคำตอบเพื่อดูตัวเลขที่ใช้เรียกเก็บเงิน
ไม่มีสิ่งใดเหล่านี้แก้ไขยากเมื่อคุณรู้ที่จะมองหา และส่วนใหญ่ลงเอยด้วยการอ่านข้อความแสดงข้อผิดพลาดครั้งแรกอย่างระมัดระวัง
