Чек-лист перед началом работы
Пройдитесь по списку заранее, чтобы избежать возвратов в процессе.
- Действующий адрес электронной почты для регистрации.
- На вашем компьютере установлена любая из сред: Python 3, JDK 15+ (для примера с текстовыми блоками), Go или PHP с расширением curl.
- Убедитесь, что вам исполнилось 18 лет, так как сервис предназначен только для совершеннолетних пользователей.
- Помните, что сервис предназначен исключительно для текстовых диалогов: здесь доступна только одна модель, без поддержки векторов, изображений, аудио или дообучения.
- Подготовьте сохранение ключа в переменных окружения, не записывайте его в исходный код и тем более не коммитьте в репозиторий.
Спецификация API минимальна: адрес https://api.wushenchaapi.com/v1 совместим с форматом OpenAI chat completion, поэтому вы можете использовать ваши старые тела запросов без изменений.
Ожидаемое время: регистрация — одна минута, установка среды зависит от вашего компьютера, первый запрос занимает не более тридцати секунд. Если по истечении этого времени результат ещё не получен, скорее всего, проблема в сети или ключе. Перейдите к списку устранения неполадок в конце статьи. Действуйте строго по порядку: сначала models, затем chat; сначала синхронно, затем потоковая передача. Подтверждайте каждый шаг, прежде чем переходить к следующему.
Регистрация и получение ключа
Откройте /get-api-key/ и зарегистрируйтесь, указав адрес электронной почты и пароль. После завершения регистрации ключ отображается сразу; просто скопируйте его. Обратите внимание на следующие детали:
- У каждого аккаунта есть только один ключ.
- Ключ можно перегенерировать, но старый ключ немедленно становится недействительным. Перед заменой ключа на продакшене убедитесь, что новое значение уже развёрнуто.
- Новый аккаунт получает пробный баланс $0.50, действительный в течение 7 дней; никакая платёжная информация не требуется.
- По истечении срока действия пробного баланса или при его исчерпании запросы возвращают статус 402 с кодом ошибки
no_credit. Пополните предоплаченный баланс, чтобы продолжить работу. Это не подписка, и баланс не истекает.
Сохраните ключ в переменной окружения: macOS / Linux: export API_KEY=ваш_ключ; Windows PowerShell: $env:API_KEY="ваш_ключ". Все примеры ниже используют значение из API_KEY.
Шаг 1: проверка доступности через /v1/models
Не спешите отправлять диалоговые запросы. Сначала выполните бесплатный GET-запрос, чтобы убедиться, что адрес, сеть и ключ работают корректно:
curl https://api.wushenchaapi.com/v1/models \
-H "Authorization: Bearer $API_KEY"Возврат статуса 200 и списка моделей (содержащего только uncensored) означает успешное подключение. Статус 401 указывает на неверный ключ или его отсутствие; тайм-аут требует проверки сети и прокси на вашем компьютере. Разделение проблем подключения и структуры запроса — лучшая привычка для ускорения интеграции.
Python: requests
Без SDK: одного requests.post достаточно. Важно: укажите timeout; проверяйте r.ok перед доступом к choices; при ошибке тело: {"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. Разберитесь в его структуре, и перевод на любой язык будет простым.
| Поле | Обязательно | Описание |
|---|---|---|
| model | Да | Фиксированное значение: uncensored. |
| messages | Да | Массив объектов, каждый из которых содержит role и content. Допустимые значения role: system, user, assistant. |
| max_tokens | Нет | Значение по умолчанию — 2048, максимальное ограничение на один запрос — 16,000. Для генерации длинных текстов необходимо увеличить это значение вручную. |
| temperature / top_p / stop | Нет | Стандартные параметры выборки, передаются без изменений. |
| stream | Нет | При значении true используется потоковая передача через SSE. |
В ответе вы будете читать три поля: choices[0].message.content — это текст, choices[0].finish_reason — причина завершения (нормальная или обрезка по длине), usage — использование токенов. Для полноценной интеграции необходимо прочитать все три поля.
Запомните ещё два жёстких ограничения: тело запроса не должно превышать 8 МБ, лимит составляет 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 как синглтон, не создавая его для каждого запроса.
Go: net/http
Стандартная библиотека Go также вполне подходит. Главное — не используйте http.DefaultClient без установки таймаута, иначе при зависании сервера 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))
}Прочитайте тело ответа полностью с помощью 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: Заголовок записан как
Authorization: ключ, пропущен префиксBearer; или переменная окружения не подгрузилась в новом терминале. - 404: В URL отсутствует путь
/v1или неправильно набран путьchat/completions. - 400: JSON некорректен или суммарный размер промпта и max_tokens превышает лимит в 100,000 токенов.
- 402: Закончился баланс или истёк срок действия пробного периода.
- Вывод обрезан:
max_tokensпо умолчанию равен 2048, максимум — 16,000. Для генерации длинных текстов необходимо явно увеличить это значение. - Нужна потоковая передача: добавьте в тело запроса
"stream": true. Ответ приходит через SSE, в конце автоматически добавляется блок данных с usage.
После успешного запуска изучите форматирование промптов для улучшения качества вывода. При ошибках обращайтесь к справочнику по кодам ошибок. Полное описание параметров — в документации, цены — на странице с ценами.
После того как запросы начнут работать, перед запуском в продакшен добавьте три элемента
Примеры в этом руководстве — минимально рабочая версия. Для интеграции в реальный сервис необходимо добавить как минимум три элемента.
- Тайм-аут. В примере установлено 120 секунд, так как генерация длинных текстов действительно медленная. Если ваш сценарий требует синхронного ожидания, сократите тайм-аут до приемлемого значения и используйте потоковую передачу, чтобы пользователь видел текст сразу.
- Разделение ошибок. Ошибки 401, 402, 403 не требуют повторных попыток — отправляйте алерт или сообщение пользователю. Повторные попытки с backoff уместны только для 429 и 503. Детали см. в руководстве по устранению ошибок.
- Учёт расходов. Записывайте в лог значение usage из каждого ответа. В лог заносите только цифры, не сохраняйте пользовательский контент. Эти данные понадобятся для сверки счетов в конце месяца и анализа аномальных расходов.
Ещё раз о управлении ключами: ключ только один. После утечки его можно только перегенерировать, а перегенерация приведёт к одновременному отключению всех работающих сервисов. Поэтому не разбрасывайте его по конфигурациям множества скриптов и машин, а храните централизованно в одном месте для ключей, чтобы при замене ничего не упустить.
Границы контента: допустимый контент для взрослых, художественная литература и спорные темы не блокируются. Однако контент сексуального характера с участием несовершеннолетних всегда блокируется с кодом 403, даже в ролевых играх. Если ваше приложение для взрослых, добавьте проверку возраста в процесс регистрации.
Порядок самопроверки: есть ли ключ в переменной окружения; доступны ли models; является ли тело запроса валидным JSON; является ли модель uncensored; достаточно ли max_tokens; finish_reason — stop или length; записан ли usage. Если все семь пунктов зелёные, интеграция завершена.