IT ▾

Chinese LLM APIQuickstart

Ottieni la chiave API

Updated

Sviluppo di un'app in cinese: prompt, controllo degli script e UTF-8

Implementare una funzionalità in cinese è principalmente un problema di localizzazione, non di modellazione. Decidi quale script vedranno gli utenti, mantieni pulite le codifiche dal file alla rete e gestisci i token per un testo che non si divide negli spazi. Questa guida copre questi tre strati con codice che puoi eseguire oggi contro l'endpoint chat completions.

Cosa stai collegando

Il servizio espone POST /v1/chat/completions e GET /v1/models su https://api.chinesellmapi.com/v1. L'autenticazione richiede una chiave bearer e l'unico model id è uncensored. È un'API solo testo con un solo modello, quindi non c'è nulla tra cui scegliere: il tuo lavoro di localizzazione avviene interamente nel prompt e nel codice che lo circonda.

Limiti da conoscere prima di progettare: una finestra di contesto di 100.000 token condivisa tra prompt e completion, max_tokens con default 2.048 e un tetto di 32.000, corpi delle richieste fino a 8 MB e 300 richieste al minuto per chiave. Lo streaming (stream: true) funziona tramite server-sent events e sono accettati gli strumenti nel formato OpenAI function-calling.

I nuovi account ricevono un credito di prova di $0,50 valido per sette giorni, senza dettagli di pagamento; registrati con email e password e la chiave appare immediatamente. La FAQ sulla prova copre le regole nel dettaglio.

Scrivi prompt in cinese e specifica quale cinese

I prompt misti sono la fonte più comune di deriva nelle funzionalità localizzate. Se le istruzioni sono in inglese ma il contenuto è in cinese, le risposte a volte tornano in inglese o in un misto. Un pattern affidabile è un system prompt scritto nella lingua target, che indica tre cose: il ruolo, lo script e il vocabolario regionale. Mantieni il testo fornito dall'utente in un messaggio separato così che non venga confuso con le istruzioni.

Ecco una configurazione in cinese semplificato. Nota che il system prompt dice al modello di rispondere solo in caratteri semplificati ed evitare inglese casuale, con i nomi propri come eccezione:

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)

Due abitudini pagano rapidamente. Primo, mantieni i prompt brevi e concreti: un ruolo, un formato di output, uno o due vincoli. Secondo, inserisci il requisito linguistico nel messaggio di sistema invece di ripeterlo in ogni turno utente, così che la cronologia della conversazione non lo diluisca.

Controllo dell'output tra semplificato e tradizionale

La scelta dello script è una decisione di prodotto legata alla locale utente, non un'impostazione del modello. I prodotti orientati alla Cina continentale si aspettano caratteri semplificati; gli utenti di Taiwan e Hong Kong si aspettano il tradizionale, con vocabolari diversi (gli esempi soliti sono termini software, di rete e database). L'approccio pratico è mappare il tuo tag locale in un system prompt e rendere la scelta esplicita nel codice.

  • zh-CN, zh-SG: Semplificato, vocabolario continentale, cifre a larghezza mezza, punteggiatura cinese a larghezza piena.
  • zh-TW: Tradizionale, vocabolario taiwanese, sono comuni le virgolette angolari per le citazioni.
  • zh-HK: Tradizionale con terminologia di Hong Kong; fornisci un glossario breve se il tuo prodotto ha termini fissi.

La variante tradizionale della stessa chiamata appare così; cambia solo il system prompt:

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)

I modelli a volte perdono alcuni caratteri dello script alternativo, specialmente quando il messaggio utente è già nell'altro script. Aggiungi un controllo post-elaborazione economico e riprova una volta con un'istruzione più ferma se fallisce. Per qualsiasi cosa oltre a un controllo campione, passa l'output attraverso una libreria di conversione dedicata come 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 dal disco alla rete e ritorno

La maggior parte dei bug di cinese corrotto non sono problemi del modello. Derivano da una codifica predefinita da qualche parte nella pipeline: una console Windows che usa una code page legacy, un CSV aperto senza codifica, un proxy che riscrive il content type. Rendi esplicito ogni confine.

In Python, passa encoding="utf-8" a open e, se costruisci il JSON manualmente, usa ensure_ascii=False seguito da .encode("utf-8"). L'esempio qui sotto lo fa con requests, che mostra anche la forma HTTP grezza della chiamata:

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"])

In Node, readFile restituisce un Buffer a meno che tu non fornisci un'encoding, e le stringhe template contenenti cinese vanno bene purché il file sorgente stesso sia salvato in UTF-8. L'SDK ufficiale serializza il corpo per te:

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);

Altre due trappole. Tagliare le stringhe per lunghezza dei byte può tagliare un carattere a metà, quindi taglia sempre per caratteri. E quando fai streaming, decodifica lo stream come UTF-8 in modo incrementale, perché un carattere multi-byte potrebbe essere diviso tra chunk di rete; gli SDK gestiscono questo caso, ma i parser manuali spesso no.

Gestione dei token per il testo cinese

Il cinese non ha spazi, quindi i conteggi di parole sono inutili per il budgeting. Come ipotesi di pianificazione, non una costante misurata, tratta un carattere cinese come circa 1-2 token e usa 1,5 quando ti serve un numero unico. Le parole latine e le cifre incorporate nel testo sono vicine a 1,3 token per parola. Il rapporto varia con il vocabolario, quindi l'unica figura autorevole è l'oggetto usage restituito con ogni risposta.

Un piccolo helper rende facile stimare un prompt prima di inviarlo e regolare i rapporti contro l'uso reale nel tempo:

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))

Esempio pratico, con ipotesi dichiarate: un articolo di 2.000 caratteri a 1,5 token per carattere è circa 3.000 token di input. Un riassunto di 400 caratteri è circa 600 token di output. A $0,25 per milione di token di input e $1,00 per milione di token di output, una chiamata costa circa $0,00075 per l'input più $0,0006 per l'output, circa $0,00135 in totale. Poiché il contesto è limitato a 100.000 token, la stessa ipotesi significa che un prompt di circa 40.000 caratteri lascia spazio per una risposta.

Quando devi alimentare documenti lunghi, frammenta per paragrafo o intestazione, mai a metà frase, e mantieni max_tokens esplicito. Prezzi e limiti sono elencati nella pagina dei prezzi.

Mantenere la chat cinese multi-turno dentro la finestra

Le funzionalità chat reinviano l'intera cronologia su ogni richiesta, quindi costo e contesto crescono con ogni turno. Poiché la finestra è di 100.000 token condivisi tra prompt e completion, una conversazione lunga alla fine innescherà un 400 se non fai nulla. Decidi una politica di trimming presto piuttosto che reagire agli errori.

Una politica semplice è mantenere il system prompt, rimuovere i turni più vecchi fino a quando il prompt stimato si adatta a un budget, e riservare il resto per la risposta. Lo sketch qui sotto riutilizza il stimatore della sezione precedente:

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

Per prodotti dove il contesto iniziale è importante, come un bot tutor o un assistente di supporto, sostituisci i turni rimossi con un messaggio di riassunto breve invece di scartarli completamente. Chiedi al modello di comprimere i turni vecchi in poche parole nella stessa script della conversazione, poi inserisci quel riassunto subito dopo il system prompt. Costa una chiamata extra ogni tanto e mantiene stabile la persona e i fatti.

Ricorda anche di limitare max_tokens in modo sensato per la chat. Le risposte in un'interfaccia di messaggistica raramente hanno bisogno di più di poche centinaia di token e un limite più stretto rende sia la latenza che il costo più prevedibili. Lo streaming della risposta token per token aiuta la velocità percepita, in particolare per il testo cinese dove gli utenti leggono a brevi raffiche.

Checklist pre-lancio e prossimi passi

  1. Mappa ogni locale a un system prompt e testa l'unità della mappatura.
  2. Imposta le codifiche esplicitamente nelle letture dei file, nei corpi delle richieste e nei log.
  3. Registra usage per funzionalità e confrontalo con il tuo stimatore settimanalmente.
  4. Gestisci 402 (no_credit), 429 e 503 (upstream_busy) in modo diverso: ricarica, rallenta, riprova dopo qualche secondo.
  5. Tratta il 403 (content_blocked) come una risposta finale per quella richiesta, non come un caso di ritentativa.

Se la tua app prevede pipeline di traduzione, continua con la guida alla traduzione e localizzazione; per la narrativa serializzata e la chat con personaggi, consulta la guida alla narrativa web. Il riferimento completo dei parametri è nella documentazione.

Domande e risposte

Come faccio a far tornare le risposte solo in cinese semplificato?

Specificalo in un prompt di sistema, ad esempio "rispondi sempre in cinese semplificato con il vocabolario della Cina continentale". Mantieni questa istruzione nel messaggio di sistema e aggiungi un controllo finale se l'output deve essere rigoroso.

Posso richiedere il cinese tradizionale per gli utenti taiwanesi?

Sì. Usa un prompt di sistema scritto in caratteri tradizionali che indichi il vocabolario regionale desiderato e mappalo dalla locale zh-TW nel tuo codice.

Perché vedo caratteri cinesi corrotti nel mio output?

Quasi sempre un problema di codifica lato client. Leggi i file come UTF-8, imposta il charset del content type e assicurati che anche il tuo terminale o visualizzatore di log usi UTF-8.

Quanti token utilizza il testo cinese?

Pianifica con circa 1,5 token per carattere come approssimazione, poi controlla il campo usage in ogni risposta e regola la tua stima.

La tua chiave è a un modulo di distanza

Crea un account, copia la chiave, modifica l'URL di base. È tutta qui la configurazione.

Ottieni la chiave API