รายการตรวจสอบก่อนเริ่มงาน
ตรวจสอบรายการนี้ก่อนเพื่อป้องกันปัญหาที่ต้องย้อนกลับมาแก้ไข
- อีเมลที่สามารถรับข้อความได้ เพื่อใช้ลงทะเบียน
- สภาพแวดล้อมการทำงานอย่างน้อยหนึ่งอย่างในเครื่องของคุณ: Python 3, JDK 15 ขึ้นไป (ตัวอย่างใช้ text blocks), Go หรือ PHP ที่มี curl extension
- ยืนยันว่าคุณอายุ 18 ปีขึ้นไป เนื่องจากบริการนี้เปิดให้เฉพาะผู้ใช้ผู้ใหญ่เท่านั้น
- เข้าใจว่าบริการนี้ให้เพียงการสนทนาข้อความล้วน: มีเพียงโมเดลเดียว ไม่มีฟีเจอร์เวกเตอร์ รูปภาพ เสียง หรือการปรับแต่งโมเดล
- เตรียมการเก็บคีย์ API ในตัวแปรสภาพแวดล้อม อย่าเขียนลงในโค้ดและอย่า commit เข้า repository
ข้อกำหนดของ API มีเพียงเล็กน้อย: URL คือ https://api.wushenchaapi.com/v1 และรองรับรูปแบบ JSON ของ OpenAI ทำให้คุณสามารถนำ request body เดิมที่เคยเขียนไว้มาใช้ได้เลย
ประมาณการเวลา: การลงทะเบียนใช้เวลาหนึ่งนาที การติดตั้งสภาพแวดล้อมขึ้นอยู่กับเครื่องของคุณ และการเรียกใช้ครั้งแรกใช้เวลาไม่เกินสามสิบวินาที หากนานกว่านี้ ให้ตรวจสอบเครือข่ายหรือคีย์ API และไปที่รายการตรวจสอบข้อผิดพลาดในท้ายหน้า ลำดับการตรวจสอบควรเป็น: models ก่อน chat, แบบ synchronous ก่อน streaming และตรวจสอบแต่ละขั้นตอนให้เสร็จก่อนจึงไปขั้นตอนถัดไป
ลงทะเบียนและรับคีย์ API
ไปที่ /get-api-key/ และลงทะเบียนด้วยอีเมลพร้อมรหัสผ่าน คีย์ API จะปรากฏทันทีหลังลงทะเบียน สำเนาไว้ใช้งานทันที มีรายละเอียดสำคัญดังนี้:
- แต่ละบัญชีมีคีย์ API ได้เพียงหนึ่งคีย์
- สามารถสร้างคีย์ใหม่ได้ แต่คีย์เก่าจะหมดอายุทันที ควรปรับใช้คีย์ใหม่ในบริการที่ทำงานอยู่ก่อนแล้วเมื่อเปลี่ยนคีย์
- บัญชีใหม่จะได้รับเครดิตทดลองใช้มูลค่า $0.50 ซึ่งมีอายุการใช้งาน 7 วัน และไม่จำเป็นต้องกรอกข้อมูลการชำระเงิน
- เมื่อเครดิตทดลองใช้หมดอายุหรือหมดมูลค่า การเรียกใช้ API จะส่ง status code 402 พร้อม error code
no_creditคุณสามารถเติมเครดิตแบบเติมเงินล่วงหน้าเพื่อใช้งานต่อ โดยเครดิตนี้ไม่มีวันหมดอายุ
ตั้งค่าคีย์ API ในตัวแปรสภาพแวดล้อม: บน macOS/Linux ให้รัน export API_KEY=your_api_key ส่วน Windows PowerShell ใช้ $env:API_KEY="your_api_key" ตัวอย่างทั้งหมดในหน้านี้จะอ่านค่าจาก API_KEY
ขั้นตอนที่หนึ่ง: ตรวจสอบการเชื่อมต่อด้วย /v1/models
อย่าเพิ่งส่งการสนทนา ให้ใช้ GET request แบบไม่มีค่าใช้จ่ายเพื่อตรวจสอบว่า URL, เครือข่าย และคีย์ API ทำงานถูกต้องหรือไม่:
curl https://api.wushenchaapi.com/v1/models \
-H "Authorization: Bearer $API_KEY"หากได้รับ status code 200 พร้อมรายการโมเดล (มีเพียง uncensored) แสดงว่าการเชื่อมต่อสำเร็จ หากได้ 401 แสดงว่าคีย์ API ผิดพลาดหรือไม่ได้ส่ง หากเกิด timeout ให้ตรวจสอบเครือข่ายและ proxy ของเครื่องคุณ การแยกการตรวจสอบการเชื่อมต่อออกจากโครงสร้างของ request เป็นวิธีที่ประหยัดเวลาที่สุด
Python: requests
ไม่ต้องใช้ SDK เพียงใช้ requests.post ก็เพียงพอ ระวังสามจุดนี้: ต้องตั้งค่า timeout; ตรวจสอบ r.ok ก่อนดึงข้อมูล choices; และเมื่อเกิดข้อผิดพลาด body ของ error จะมีรูปแบบ {"error":{"code":...,"message":...}}
import os
import requests
url = "https://api.wushenchaapi.com/v1/chat/completions"
headers = {
"Authorization": "Bearer " + os.environ["API_KEY"],
"Content-Type": "application/json",
}
payload = {
"model": "uncensored",
"messages": [{"role": "user", "content": "用两句话描述一场雨夜里的追逐戏。"}],
"max_tokens": 300,
}
r = requests.post(url, headers=headers, json=payload, timeout=120)
print(r.status_code)
data = r.json()
if r.ok:
print(data["choices"][0]["message"]["content"])
print(data["usage"])
else:
print(data["error"]["code"], data["error"]["message"])เมื่อสำเร็จ ข้อมูล usage จะประกอบด้วย prompt_tokens และ completion_tokens แนะนำให้พิมพ์ค่าเหล่านี้ทุกครั้งที่พัฒนาเพื่อติดตามต้นทุน
วิเคราะห์โครงสร้าง JSON ของ request
ทั้งสี่ภาษาส่ง JSON รูปแบบเดียวกัน ให้ทำความเข้าใจโครงสร้างนี้ก่อน การเขียนโค้ดในภาษาต่างๆ จึงเป็นเพียงการแปลโครงสร้างนี้
| ฟิลด์ | จำเป็น | คำอธิบาย |
|---|---|---|
| model | ใช่ | ตั้งค่าคงที่เป็น uncensored |
| messages | ใช่ | เป็นอาร์เรย์ แต่ละรายการต้องมี role และ content โดย role สามารถเป็น system, user หรือ assistant |
| max_tokens | ไม่ | ค่าเริ่มต้นคือ 2048 และค่าสูงสุดต่อครั้งคือ 16,000 หากต้องการสร้างข้อความยาวต้องปรับค่านี้เอง |
| temperature / top_p / stop | ไม่ | พารามิเตอร์การสุ่มตัวอย่างมาตรฐาน ส่งผ่านค่าไปยัง API โดยตรง |
| stream | ไม่ | เมื่อตั้งค่าเป็น true จะใช้การสตรีมผ่าน SSE |
ส่วนที่คุณมักอ่านในคำตอบมีสามส่วน: choices[0].message.content คือเนื้อหา, choices[0].finish_reason บอกว่าจบปกติหรือถูกตัดเนื่องจากความยาว, และ usage คือจำนวนโทเคนที่ใช้ในคำขอนี้ การอ่านทั้งสามส่วนถือเป็นขั้นตอนการเชื่อมต่อที่ครบถ้วน
โปรดจำข้อจำกัดอีกสองข้อนี้: ขนาดของ body ในคำขอต้องไม่เกิน 8 MB และแต่ละคีย์ API จะจำกัดอยู่ที่ 300 คำขอต่อนาที สำหรับงานแบบแบตช์ อย่าส่งคำขอพร้อมกันทั้งหมดในคราวเดียว ควรกำหนดขีดจำกัดความพร้อมกันไว้ล่วงหน้า
Java: java.net.http
JDK 11 มี HttpClient มาให้แล้ว ไม่ต้องพึ่งพาไลบรารีอื่น ด้านล่างใช้บล็อกข้อความของ JDK 15 เพื่อเขียน JSON หากใช้เวอร์ชันต่ำกว่าสามารถเปลี่ยนเป็นการต่อสตริงหรือใช้ไลบรารี JSON ที่คุณคุ้นเคยในการจัดรูปแบบ
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
public class Demo {
public static void main(String[] args) throws Exception {
String key = System.getenv("API_KEY");
String body = """
{"model":"uncensored",
"messages":[{"role":"user","content":"写一段两百字以内的悬疑小说开头。"}],
"max_tokens":400}
""";
HttpRequest req = HttpRequest.newBuilder(
URI.create("https://api.wushenchaapi.com/v1/chat/completions"))
.timeout(Duration.ofSeconds(120))
.header("Authorization", "Bearer " + key)
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(body))
.build();
HttpResponse<String> resp = HttpClient.newHttpClient()
.send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(resp.statusCode());
System.out.println(resp.body());
}
}หมายเหตุ: เมื่อเนื้อหามีภาษาจีน BodyPublishers.ofString จะเข้ารหัสเป็น UTF-8 โดยอัตโนมัติ ไม่ต้องจัดการเพิ่มเติม สำหรับการใช้งานจริง ให้ทำให้ HttpClient เป็นแบบ Singleton เพื่อใช้งานซ้ำ อย่าสร้างใหม่ทุกคำขอ
Go: net/http
ไลบรารีมาตรฐานของ Go ก็เพียงพอแล้ว สิ่งสำคัญคืออย่าใช้ http.DefaultClient โดยไม่ตั้งค่า timeout มิฉะนั้น goroutine จะค้างอยู่ตลอดหากฝั่งตรงข้ามตอบสนองช้า
package main
import (
"bytes"
"fmt"
"io"
"net/http"
"os"
"time"
)
func main() {
body := []byte(`{"model":"uncensored","messages":[{"role":"user","content":"给一个反派角色写三句独白。"}],"max_tokens":300}`)
req, err := http.NewRequest("POST", "https://api.wushenchaapi.com/v1/chat/completions", bytes.NewReader(body))
if err != nil {
panic(err)
}
req.Header.Set("Authorization", "Bearer "+os.Getenv("API_KEY"))
req.Header.Set("Content-Type", "application/json")
client := &http.Client{Timeout: 120 * time.Second}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
out, _ := io.ReadAll(resp.Body)
fmt.Println(resp.StatusCode, string(out))
}อ่าน body ของการตอบกลับจนจบด้วย io.ReadAll ก่อนทำการแยกวิเคราะห์ เมื่อต้องการจัดการข้อมูลแบบโครงสร้าง ให้กำหนด struct ที่ตรงกันแล้วใช้ encoding/json ในการดีซีเรียไลซ์ โดยฟิลด์ที่เกี่ยวข้องคือ choices, message, content และ usage
PHP: curl
PHP ใช้ส่วนขยาย curl กับ json_encode อย่าลืมใส่ JSON_UNESCAPED_UNICODE มิฉะนั้นข้อความภาษาจีนจะถูกแปลงเป็น \uXXXX ซึ่งแม้จะทำงานได้แต่จะอ่านยากตอนดีบัก
<?php
$payload = [
"model" => "uncensored",
"messages" => [["role" => "user", "content" => "写一首八行的现代诗,主题是末班地铁。"]],
"max_tokens" => 300,
];
$ch = curl_init("https://api.wushenchaapi.com/v1/chat/completions");
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 120,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv("API_KEY"),
"Content-Type: application/json",
],
CURLOPT_POSTFIELDS => json_encode($payload, JSON_UNESCAPED_UNICODE),
]);
$res = curl_exec($ch);
if ($res === false) {
die("curl 错误: " . curl_error($ch) . "\n");
}
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
echo $status, "\n";
$data = json_decode($res, true);
echo $data["choices"][0]["message"]["content"] ?? $res, "\n";โปรดแยกแยะความล้มเหลวสองประเภท: หาก curl_exec คืนค่า false แสดงว่าเป็นปัญหาชั้นเครือข่าย; หากคืนค่าเนื้อหาแต่สถานะไม่ใช่ 200 แสดงว่าเป็นปัญหาชั้น API ให้ตรวจสอบ error.code
จุดที่มักพลาดในการเรียกใช้ครั้งแรก
- 401: เขียน Header เป็น
Authorization: คีย์ APIโดยลืมใส่คำนำหน้าBearerหรือตัวแปรสภาพแวดล้อมไม่ทำงานในเทอร์มินัลที่เปิดใหม่ - 404: ขาด
/v1ในเส้นทาง หรือพิมพ์chat/completionsผิด - 400: ข้อมูล JSON ไม่ถูกต้อง หรือการกำหนดค่า prompt พร้อม max_tokens เกินขีดจำกัด 100,000 โทเคน
- 402: ยอดเงินหมดหรือเครดิตทดลองใช้หมดอายุ
- ข้อความถูกตัด: ค่าเริ่มต้นของ
max_tokensคือ 2048 และค่าสูงสุดต่อครั้งคือ 16,000 หากต้องการเขียนบทความยาวๆ ต้องตั้งค่าให้ใหญ่ขึ้นอย่างชัดเจน - ต้องการสตรีม: เพิ่ม
"stream": trueใน body ของคำขอ การตอบกลับจะเป็นรูปแบบ SSE และจะมีบล็อกข้อมูลพร้อม usage แทรกเข้ามาอัตโนมัติที่ตอนท้าย
เมื่อทดสอบผ่านแล้ว ให้ดู การเขียนพรอมต์ เพื่อปรับปรุงคุณภาพผลลัพธ์ หรือตรวจสอบ คู่มือแก้ไขข้อผิดพลาด เมื่อพบข้อผิดพลาด รายละเอียดพารามิเตอร์ครบถ้วนอยู่ที่ เอกสาร และราคาอยู่ที่ หน้าราคา
หลังจากทดสอบผ่านแล้ว ให้เพิ่มสามสิ่งนี้ก่อนนำระบบขึ้นใช้งานจริง
ตัวอย่างในคู่มือเป็นเวอร์ชันขั้นต่ำที่ใช้งานได้จริง หากต้องการนำไปใช้ในบริการ คุณจำเป็นต้องเพิ่มสามส่วนนี้
- เวลาหมด: ตัวอย่างกำหนดเวลาไว้ 120 วินาที เนื่องจากข้อความยาวๆ ใช้เวลานานในการสร้าง หากธุรกิจของคุณรอแบบ synchronous ให้ปรับเวลาให้สั้นลงตามความทนทานของหน้าเว็บ และใช้การสตรีมเพื่อให้ผู้ใช้เห็นข้อความได้ทันที
- การแยกเส้นทางข้อผิดพลาด: สถานะ 401, 402, 403 เป็นข้อผิดพลาดที่ลองใหม่ก็ไม่ได้ผล ต้องแจ้งเตือนหรือแจ้งผู้ใช้; ส่วน 429 และ 503 จึงควรทำการถอยหลังและลองใหม่ วิธีการเขียนเฉพาะเจาะจงมีอยู่ในคู่มือแก้ไขข้อผิดพลาด ไม่ขอกล่าวถึงที่นี่
- การบันทึกปริมาณการใช้งาน: บันทึกข้อมูล usage จากทุกการตอบกลับเป็นหนึ่งบรรทัดในล็อก โดยบันทึกเฉพาะตัวเลขเท่านั้น อย่าเก็บเนื้อหาของผู้ใช้ในล็อก ข้อมูลนี้จะใช้สำหรับการตรวจสอบยอดเงินสิ้นเดือนและค้นหาการใช้ที่ผิดปกติ
ขอเน้นเรื่องการจัดการคีย์อีกครั้ง: คีย์มีเพียงตัวเดียว หากมีการรั่วไหลจะต้องสร้างคีย์ใหม่ ซึ่งจะทำให้บริการทั้งหมดที่กำลังใช้งานอยู่หยุดทำงานทันที ดังนั้นอย่ากระจายคีย์ไปไว้ในสคริปต์หรือการตั้งค่าของเครื่องหลายเครื่อง ให้เก็บไว้ที่จุดกำหนดค่าคีย์กลางเพียงแห่งเดียวเพื่อความสะดวกในการเปลี่ยน
สุดท้ายคือขอบเขตเนื้อหา: เนื้อหาผู้ใหญ่ที่เหมาะสม, นิยายสมมติ และหัวข้อที่มีข้อโต้แย้งจะไม่ถูกปฏิเสธ แต่เนื้อหาทางเพศที่เกี่ยวข้องกับเด็กจะถูกบล็อกทันทีโดยคืนค่าสถานะ 403 รวมถึงกรณีสมมติและบทบาทสมมติด้วย หากแอปของคุณมุ่งเน้นผู้ใช้งานผู้ใหญ่ แนะนำให้ตรวจสอบอายุผู้ใช้ในขั้นตอนการลงทะเบียนของคุณเอง
สุดท้ายนี้ขอเสนอลำดับการตรวจสอบด้วยตนเอง ซึ่งสามารถติดไว้ข้างจอภาพได้: ตรวจสอบว่าคีย์อยู่ในตัวแปรสภาพแวดล้อมหรือไม่; ตรวจสอบว่า models ทำงานได้หรือไม่; ตรวจสอบว่า body ของคำขอเป็น JSON ที่ถูกต้องหรือไม่; ตรวจสอบว่า model เป็น uncensored หรือไม่; ตรวจสอบว่า max_tokens เพียงพอหรือไม่; ตรวจสอบว่า finish_reason ในข้อมูลตอบกลับเป็น stop หรือ length; ตรวจสอบว่ามีการบันทึก usage หรือไม่ หากทั้งเจ็ดรายการเป็นสีเขียว แสดงว่าการเชื่อมต่อเสร็จสมบูรณ์