Zaktualizowano
Budowanie aplikacji w języku chińskim: prompty, kontrola skryptu i UTF-8
Wdrażanie funkcji w języku chińskim to głównie problem lokalizacji, a nie modelowania. Decydujesz, który skrypt widzą użytkownicy, utrzymujesz czyste kodowanie od pliku do transmisji i planujesz budżet tokenów dla tekstu bez spacji. Ten przewodnik omawia te trzy warstwy z kodem, który możesz uruchomić przeciwko endpointowi completions czatu już dziś.
Co łączysz
Usługa udostępnia POST /v1/chat/completions i GET /v1/models pod https://api.chinesellmapi.com/v1. Autoryzacja to klucz bearer, a jedynym id modelu jest uncensored. To API tylko tekstowe z jednym modelem, więc nie ma wyboru między modelami: Twoja praca lokalizacyjna odbywa się całkowicie w prompcie i w Twoim kodzie wokół niego.
Ograniczenia, które warto znać przed zaprojektowaniem czegokolwiek: okno kontekstu o pojemności 100 000 tokenów dzielone między prompt a completion, max_tokens domyślnie ustawione na 2048 z limitem 32 000, ciała zapytań do 8 MB i 300 zapytań na minutę na klucz. Strumieniowanie (stream: true) działa przez zdarzenia wysyłane przez serwer, a narzędzia w formacie wywoływania funkcji OpenAI są akceptowane.
Nowe konta otrzymują kredyt próbny $0,50 ważny przez siedem dni, bez podawania danych płatności; zarejestruj się e-mailem i hasłem, a klucz pojawi się natychmiast. FAQ dotyczący okresu próbnego omawia zasady szczegółowo.
Napisz prompty po chińsku i określ, który chiński
Prompty mieszane językowo to najczęstsza przyczyna driftu w zlokalizowanych funkcjach. Jeśli instrukcje są po angielsku, a treść po chińsku, odpowiedzi czasem wracają po angielsku lub w mieszanej formie. Niezawodnym wzorcem jest prompt systemowy napisany w języku docelowym, wskazujący trzy rzeczy: rolę, skrypt i słownictwo regionalne. Trzymaj tekst dostarczony przez użytkownika w osobnej wiadomości, aby nie został pomylony z instrukcjami.
Oto konfiguracja w uproszczonym chińskim. Zwróć uwagę, że prompt systemowy mówi modelowi, aby odpowiadał wyłącznie znakami uproszczonymi i unikał przypadkowego angielskiego, z wyjątkiem nazw własnych:
import os
from openai import OpenAI
client = OpenAI(
base_url="https://api.chinesellmapi.com/v1",
api_key=os.environ["API_KEY"],
)
SYSTEM_SC = (
"你是一名产品文案助手。始终使用简体中文回答,使用中国大陆常见的用词和标点,"
"不要夹杂繁体字或英文句子,专有名词除外。"
)
resp = client.chat.completions.create(
model="uncensored",
messages=[
{"role": "system", "content": SYSTEM_SC},
{"role": "user", "content": "为一款记账应用写三条应用商店的一句话简介。"},
],
max_tokens=300,
temperature=0.7,
)
print(resp.choices[0].message.content)
print(resp.usage)
Dwie nawyki szybko się opłacają. Po pierwsze, trzymaj prompty krótkie i konkretne: rola, format wyjścia, jedno lub dwa ograniczenia. Po drugie, umieść wymóg językowy w komunikacie systemowym zamiast powtarzać go w każdej wiadomości użytkownika, aby historia rozmowy go nie rozmywała.
Kontrola outputu uproszczony vs tradycyjny
Wybór skryptu to decyzja produktowa powiązana z lokalizacją użytkownika, a nie ustawienie modelu. Produkty nastawione na Chiny kontynentalne oczekują znaków uproszczonych; odbiorcy z Tajwanu i Hongkongu oczekują znaków tradycyjnych, z innym słownictwem (typowe przykłady to terminy programistyczne, sieciowe i bazodanowe). Praktycznym podejściem jest mapowanie tagu lokalizacji na prompt systemowy i jawne wskazanie wyboru w kodzie.
- zh-CN, zh-SG: Uproszczony, słownictwo kontynentalne, cyfry półszeryfowe, interpunkcja chińska pełnoszerokościowa.
- zh-TW: Tradycyjny, słownictw z Tajwanu, nawiasy ostre do cytatów są powszechne.
- zh-HK: Tradycyjny z hongkońskim słownictwem; dostarcz krótki słownik, jeśli Twój produkt ma ustalone terminy.
Wariant tradycyjny tej samej wiadomości wygląda tak; zmienia się tylko prompt systemowy:
import os
from openai import OpenAI
client = OpenAI(base_url="https://api.chinesellmapi.com/v1", api_key=os.environ["API_KEY"])
SYSTEM_TC = (
"你是一名產品文案助手。請一律使用繁體中文回答,採用臺灣常用的詞彙與全形標點,"
"例如「軟體」「網路」「資料庫」,不要混入簡體字。"
)
resp = client.chat.completions.create(
model="uncensored",
messages=[
{"role": "system", "content": SYSTEM_TC},
{"role": "user", "content": "請用兩句話說明什麼是雙重驗證。"},
],
max_tokens=200,
)
print(resp.choices[0].message.content)
Modele czasem wyciekają kilka znaków innego skryptu, zwłaszcza gdy wiadomość użytkownika jest w innym skrypcie. Dodaj tani post-check i zrestartuj raz z ostrzejszą instrukcją, jeśli wystąpi błąd. Do czegokolwiek poza próbą sprawdzenia uruchom output przez dedykowaną bibliotekę konwertera, taką jak OpenCC:
# A cheap guard: flag replies that contain characters that exist only in Simplified.
# The set below is a small sample, not a full list; use a converter such as OpenCC
# for production-grade checks.
SIMPLIFIED_ONLY = set("这个们说话时间书买卖东车门开关见觉")
def looks_simplified(text: str) -> bool:
return any(ch in SIMPLIFIED_ONLY for ch in text)
reply = "請用繁體中文回覆的範例文字"
print(looks_simplified(reply)) # False
UTF-8 od dysku do sieci i z powrotem
Większość błędów „zniekształconego chińskiego” to nie problemy modelu. Wynikają z domyślnego kodowania gdzieś w potoku: konsola Windows używająca legacy code page, CSV otwarte bez kodowania, proxy przepisujące content type. Ujawnij każdą granicę jawnie.
W Pythonie przekaż encoding="utf-8" do open, a jeśli budujesz JSON ręcznie, użyj ensure_ascii=False po czym .encode("utf-8"). Poniższy przykład robi to z zwykłym requests, co również pokazuje surowy kształt HTTP wywołania:
import json
import os
import requests
# 1) Always open files as UTF-8, never rely on the platform default encoding.
with open("notes_zh.txt", "r", encoding="utf-8") as f:
note = f.read()
payload = {
"model": "uncensored",
"messages": [{"role": "user", "content": "请把下面的笔记整理成三个要点:\n" + note}],
"max_tokens": 400,
}
# 2) requests encodes json= as UTF-8 for you. If you build the body by hand,
# keep Chinese readable and make the encoding explicit.
body = json.dumps(payload, ensure_ascii=False).encode("utf-8")
r = requests.post(
"https://api.chinesellmapi.com/v1/chat/completions",
headers={
"Authorization": "Bearer " + os.environ["API_KEY"],
"Content-Type": "application/json; charset=utf-8",
},
data=body,
timeout=60,
)
r.raise_for_status()
r.encoding = "utf-8"
print(r.json()["choices"][0]["message"]["content"])
W Node.js readFile zwraca Buffer, chyba że podasz encoding, a stringi szablonowe zawierające chiński są OK, o ile plik źródłowy jest zapisany jako UTF-8. Oficjalny SDK serializuje ciało za Ciebie:
import { readFile } from "node:fs/promises";
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://api.chinesellmapi.com/v1",
apiKey: process.env.API_KEY,
});
// Pass "utf8" explicitly; without it readFile returns a Buffer, not a string.
const note = await readFile("notes_zh.txt", "utf8");
const res = await client.chat.completions.create({
model: "uncensored",
messages: [{ role: "user", content: `请把下面的笔记整理成三个要点:\n${note}` }],
max_tokens: 400,
});
console.log(res.choices[0].message.content);
console.log(res.usage);
Dwa kolejne pułapki. Obcinanie stringów po długości bajtowej może uciąć znak na pół, więc zawsze dziel po znakach. A przy strumieniowaniu dekoduj strumień jako UTF-8 inkrementalnie, ponieważ wielobajtowy znak może być podzielony między chunki sieciowe; SDK to obsługują, ale ręczne parsery często nie.
Planowanie tokenów dla tekstu chińskiego
Chiński nie ma spacji, więc liczenie słów jest bezwartościowe do planowania. Jako założenie planistyczne, nie stała mierzona, traktuj jeden chiński znak jako około 1 do 2 tokenów i użyj 1,5, gdy potrzebujesz jednej liczby. Słowa łacińskie i cyfry osadzone w tekście to bliżej 1,3 tokena na słowo. Stosunek różni się w zależności od słownictwa, więc jedyną autorytatywną liczbą jest obiekt usage zwracany z każdą odpowiedzią.
Mała funkcja pomocnicza ułatwia oszacowanie promptu przed wysłaniem go i dostrajanie stosunków w oparciu o rzeczywiste użycie w czasie:
import re
CJK = re.compile(r"[㐀-鿿- -〿]")
def rough_tokens(text: str, per_cjk: float = 1.5, per_other_word: float = 1.3) -> int:
"""Planning estimate only. The 1.5 and 1.3 ratios are assumptions, not
measured values; compare against resp.usage and adjust them."""
cjk = len(CJK.findall(text))
others = len(re.findall(r"[A-Za-z0-9_]+", CJK.sub(" ", text)))
return round(cjk * per_cjk + others * per_other_word)
sample = "订单 A-1042 已发货,预计周三送达。"
print(rough_tokens(sample))
Przykład z założeniami: artykuł 2000 znaków przy 1,5 tokena na znak to około 3000 tokenów wejściowych. Podsumowanie 400 znaków to około 600 tokenów wyjściowych. Przy $0,25 za milion tokenów wejściowych i $1,00 za milion tokenów wyjściowych jedno wywołanie kosztuje około $0,00075 za wejście plus $0,0006 za wyjście, razem około $0,00135. Ponieważ kontekst jest ograniczony do 100 000 tokenów, to samo założenie oznacza, że prompt około 40 000 znaków zostawia miejsce na odpowiedź.
Kiedy musisz podać długie dokumenty, dziel na akapity lub nagłówki, nigdy w połowie zdania, i trzymaj max_tokens jawne. Ceny i limity są wymienione na stronie cennika.
Utrzymanie wieloetapowego czatu chińskiego w oknie
Funkcje czatu wysyłają ponownie całą historię przy każdym zapytaniu, więc koszt i kontekst rosną z każdą turą. Ponieważ okno ma 100 000 tokenów dzielonych między prompt a completion, długa rozmowa w końcu spowoduje błąd 400, jeśli nic nie zrobisz. Zdecyduj się na politykę przycinania wcześnie, zamiast reagować na błędy.
Prosta polityka to zachowanie promptu systemowego, usunięcie najstarszych tur, aż oszacowany prompt zmieści się w budżecie, i zarezerwowanie reszty na odpowiedź. Poniższy szkic ponownie używa estymatora z poprzedniego rozdziału:
MAX_PROMPT_TOKENS = 48_000 # leave headroom under the 100,000 window for the reply
def trim_history(messages, estimate):
# messages[0] is the system prompt and is always kept
system, rest = messages[0], messages[1:]
while rest and sum(estimate(m["content"]) for m in [system] + rest) > MAX_PROMPT_TOKENS:
rest.pop(0) # drop the oldest turn first
return [system] + rest
Dla produktów, gdzie wczesny kontekst ma znaczenie, takich jak bot nauczycielski lub asystent wsparcia, zastąp odrzucone tury krótką wiadnością podsumowania zamiast ich całkowitego odrzucenia. Poproś model o skompresowanie starych tur do kilku zdań w tym samym skrypcie co rozmowa, a następnie wstaw to podsumowanie tuż po promptzie systemowym. Kosztuje to jedno dodatkowe wywołanie od czasu do czasu i utrzymuje stabilność persony i faktów.
Pamiętaj też o rozsądnym ograniczeniu max_tokens dla czatu. Odpowiedzi w interfejsie messagingowym rzadko potrzebują więcej niż kilkuset tokenów, a ściślejszy limit sprawia, że opóźnienia i koszty są bardziej przewidywalne. Strumieniowanie odpowiedzi token po tokenie pomaga postrzeganej prędkości, szczególnie dla tekstu chińskiego, gdzie użytkownicy czytają krótkimi partiami.
Checklista przed uruchomieniem i kolejne kroki
- Zmapuj każdą lokalizację na prompt systemowy i ztestuj mapowanie jednostkowo.
- Ustaw kodowania jawnie przy odczycie plików, ciałach żądań i logach.
- Loguj
usagena funkcję i porównuj go z Twoim estymatorem co tydzień. - Obsługuj 402 (
no_credit), 429 i 503 (upstream_busy) inaczej: doładuj, zwolnij, ponów próbę po kilku sekundach. - Traktuj 403 (
content_blocked) jako ostateczną odpowiedź dla tego zapytania, a nie przypadek do ponowienia próby.
Jeśli Twoja aplikacja obejmuje potoki tłumaczeniowe, kontynuuj zgodnie z przewodnikiem po tłumaczeniu i lokalizacji; dla powieści serializowanych i czatu z postaciami zobacz przewodnik po powieściach internetowych. Pełna dokumentacja parametrów znajduje się w dokumentacji.
Pytania i odpowiedzi
Jak wymusić odpowiedzi wyłącznie w uproszczonym chińskim?
Wypisz to w chińskim systemowym prompcie, na przykład „zawsze odpowiadaj w uproszczonym chińskim słownictwem kontynentalnym”. Zachowaj tę instrukcję w komunikacie systemowym i dodaj weryfikację końcową, jeśli wynik musi być ścisły.
Czy mogę poprosić o tradycyjny chiński dla użytkowników z Tajwanu?
Tak. Użyj promptu systemowego napisanego znakami tradycyjnymi, który precyzuje pożądane słownictwo regionalne, i powiąż go z lokalizacją zh-TW w swoim kodzie.
Dlaczego w odpowiedziach widzę zniekształcone znaki chińskie?
Zawsze prawie zawsze jest to problem kodowania po stronie klienta. Czytaj pliki jako UTF-8, ustaw charset typu zawartości i upewnij się, że Twój terminal lub podgląd logów również używa UTF-8.
Ile tokenów zużywa tekst chiński?
Załóż przybliżony koszt 1,5 tokena na znak, a następnie sprawdź pole użycia w każdej odpowiedzi i skoryguj oszacowanie.
Twój klucz jest o jeden formularz stąd
Utwórz konto, skopiuj klucz, zmień bazowy URL. To cała konfiguracja.