Tutoriale
Come chiamare kimi-k3.1-pro tramite l'API HiAPI: curl, Python e richieste eseguibili direttamente
Una guida pratica all'integrazione, che copre endpoint, parametri della richiesta, streaming, tool calling e risoluzione dei problemi
In questa pagina
Perché chiamare kimi-k3.1-pro tramite un'API aggregata
Ogni integrazione di un modello porta con sé lo stesso costo nascosto: il primo giorno è divertente, il secondo mese è manutenzione. Quando colleghi kimi-k3.1-pro direttamente alla tua applicazione, erediti anche lo schema di autenticazione, la semantica degli errori, il modello delle quote e il ritmo di rilascio di quel fornitore. Per un prototipo con un solo modello va bene. Ma appena vuoi un secondo modello, un secondo ambiente, o un percorso di fallback quando un endpoint ha problemi, diventa attrito.
Un'API aggregata riduce queste differenze a un unico contratto. HiAPI espone kimi-k3.1-pro con una forma di richiesta compatibile con OpenAI, il che significa che il codice client che scrivi qui non è usa e getta. Cambiando l'identificatore del modello, la stessa struttura di richiesta può essere riutilizzata con altri modelli sulla piattaforma—stessi header, stesso array di messaggi, stesso wrapper di streaming.
Nello specifico di kimi-k3.1-pro, questo ha tre implicazioni pratiche:
- Un'unica superficie di credenziali. Gestisci una sola API Key e un solo URL di base, invece di un insieme crescente di account dei fornitori.
- Payload prevedibili. Gli schemi di richiesta e risposta restano stabili tra i modelli, quindi il tuo livello di parsing, retry e logging va scritto una volta sola.
- Costi di migrazione bassi. Se in futuro un tipo di carico è più adatto a un altro modello, la modifica è una stringa nel payload, non una riscrittura del livello di trasporto.
Il resto di questa guida è l'integrazione stessa: anatomia della richiesta, chiamate curl pronte da copiare, il client Python equivalente, poi le due funzionalità che di solito causano più problemi in produzione—streaming e tool calling—e infine una checklist per la risoluzione dei problemi.
Cosa ti serve prima di iniziare
- Una API Key di HiAPI, conservata dove il tuo progetto archivia i segreti.
- L'URL di base dell'API del tuo account, dalla console HiAPI. Tutti gli esempi sotto usano
https://api.hiapi.ai/v1come URL di base segnaposto; prima di andare in produzione verifica l'host reale nella console. - La stringa dell'identificatore del modello kimi-k3.1-pro—copiala esattamente dalla lista dei modelli della console, perché l'identificatore è sensibile alle maiuscole.
curlper il primo test, e Python 3.9+ con la libreriarequestsper l'esempio del client.
Forma della richiesta: endpoint, header e parametri del modello
Ogni chiamata di chat segue la stessa anatomia. Una volta capita ogni parte, non dovrai più eseguire il debug campo per campo.
Endpoint
Le completion di chat si trovano su un unico percorso sotto l'URL di base:
POST {BASE_URL}/chat/completions
Questo è l'unico endpoint necessario per tutti gli esempi di questa guida. Streaming e tool calling non sono endpoint separati—sono opzioni nello stesso corpo della richiesta.
Header
Solo due header contano davvero:
Authorization: Bearer $HIAPI_API_KEY
Content-Type: application/json
La chiave va nell'header Authorization, con il prefisso Bearer. Non metterla nell'URL, nei parametri di query o nel corpo della richiesta—tutte e tre le pratiche la fanno trapelare nei log e nei report degli errori. Imposta esplicitamente Content-Type; alcuni client HTTP non lo deducono per te.
I campi del corpo della richiesta che contano davvero
Un corpo di richiesta minimo ha quattro campi significativi:
model— l'identificatore di kimi-k3.1-pro. Obbligatorio. È il campo che si sbaglia più facilmente al primo tentativo, perché deve corrispondere esattamente.messages— un array ordinato di oggetti, ciascuno conrole(system,useroassistant) econtent. Obbligatorio e non vuoto. L'ordine è la cronologia della conversazione; il modello vede esattamente questo array, nient'altro.stream— booleano, predefinitofalse. Setrue, la risposta arriva come server-sent event invece che come un unico corpo JSON. C'è una sezione dedicata più sotto.temperature— controllo opzionale del campionamento. Valori più bassi producono output più deterministici; valori più alti più variazione. Scegli un valore una volta per caso d'uso e non toccarlo, non regolarlo a ogni richiesta.
Campi opzionali che puoi aggiungere man mano che l'integrazione matura:
max_tokens— limite superiore alla lunghezza generata. Utile come barriera per costi e latenza. Nota che limita l'output, non l'input.tools— array di definizioni di strumenti, descritto in dettaglio più avanti.tool_choice— controlla se e come il modello chiama gli strumenti che fornisci.stop— una o più sequenze che terminano la generazione.
La risposta che dovresti aspettarti
Una risposta non in streaming restituisce un oggetto JSON il cui array choices contiene almeno una voce. In quella voce troverai un oggetto message con role e content, più un finish_reason che ti dice perché la generazione si è fermata. Ramifica sempre in base a finish_reason, non assumere che il contenuto sia completo—una risposta troncata ha comunque contenuto, solo non è la risposta completa.
Scrivi il parser su questa struttura, non su una risposta serializzata in stringa. Così sopravviverà a qualunque cambio di modello tu faccia sulla piattaforma.
Una richiesta curl eseguibile
Inizia da qui. Se restituisce una risposta valida, la tua chiave, l'URL di base e l'identificatore del modello sono corretti, e qualsiasi problema successivo sarà nel codice, non nelle credenziali.
curl -sS "$HIAPI_BASE_URL/chat/completions" \
-H "Authorization: Bearer $HIAPI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "kimi-k3.1-pro",
"messages": [
{"role": "system", "content": "Sei un assistente tecnico conciso."},
{"role": "user", "content": "Spiega in due frasi cos'è una chiave di idempotenza."}
],
"temperature": 0.3,
"max_tokens": 256
}'
Spiegazione dei campi
-sSmantiene curl silenzioso sul progresso, ma espone comunque gli errori. Senza la secondaS, una richiesta fallita potrebbe uscire silenziosamente, sprecando un giro di debug.- Le variabili d'ambiente evitano che la chiave finisca nella cronologia della shell o nel buffer di scorrimento del terminale. Esporta
HIAPI_BASE_URLeHIAPI_API_KEYnel tuo profilo della shell o in un.envcaricato. - Corpo della richiesta tra apici singoli è corretto per una shell POSIX, finché il payload non contiene apici singoli. Appena servono apici singoli, sposta il corpo in un file e passalo con
-d @body.json—così eviti una classe di bug di quoting che sembrano errori di formato JSON. - Il messaggio
systemè opzionale, ma vale la pena includerlo. È il posto più comodo per fissare tono e formato dell'output. max_tokensin questo esempio è volutamente conservativo. Limita sia la latenza che il costo dello smoke test.
Interpretare il risultato
Una chiamata riuscita restituisce HTTP 200 e un corpo JSON. Prima di procedere conferma tre cose:
choicesè un array non vuoto.choices[0].message.contentcontiene una risposta reale.choices[0].finish_reasonè un valore di completamento normale, non un troncamento per lunghezza.
Se il corpo della risposta è un oggetto di errore, salta alla sezione sulla risoluzione dei problemi—il messaggio di errore di solito indica il campo specifico che ha causato il problema.
Consiglio per la riproducibilità
Salva quella chiamata curl come script shell nel repository. Un singolo comando che esegue uno smoke test sull'API live è il modo più rapido per distinguere "la mia integrazione è rotta" da "il mio account o la mia chiave sono cambiati". Eseguilo ogni volta che qualcosa sembra sbagliato.
La stessa richiesta scritta in Python
La versione Python dovrebbe sembrare noiosa—è esattamente l'obiettivo. Tutte le decisioni interessanti (identificatore del modello, URL di base, timeout) dovrebbero stare nella configurazione, non sparse nei vari punti di chiamata.
import os
import requests
BASE_URL = os.environ["HIAPI_BASE_URL"].rstrip("/")
API_KEY = os.environ["HIAPI_API_KEY"]
MODEL = os.environ.get("HIAPI_MODEL", "kimi-k3.1-pro")
HEADERS = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
}
def chat(messages, temperature=0.3, max_tokens=512, timeout=60):
payload = {
"model": MODEL,
"messages": messages,
"temperature": temperature,
"max_tokens": max_tokens,
}
resp = requests.post(
f"{BASE_URL}/chat/completions",
headers=HEADERS,
json=payload,
timeout=timeout,
)
resp.raise_for_status()
data = resp.json()
choice = data["choices"][0]
return choice["message"]["content"], choice.get("finish_reason")
if __name__ == "__main__":
text, reason = chat([
{"role": "system", "content": "Sei un assistente tecnico conciso."},
{"role": "user", "content": "Spiega in due frasi cos'è una chiave di idempotenza."},
])
print(reason)
print(text)
Perché è organizzato così
- Usa
json=invece didata=— la libreriarequestsserializza il dizionario e imposta il content type per te. La serializzazione manuale introduce facilmente errori di escaping. - Sempre
timeout=60— non impostare un timeout è la causa più comune di processi worker che restano appesi finché il gestore non li uccide. Ogni chiamata di rete in un servizio dovrebbe avere un timeout. raise_for_status()prima del parsing — converte i fallimenti a livello HTTP in eccezioni nel punto di chiamata, invece di lasciare che corpi di risposta malformati scorrano a valle.MODELdall'ambiente — quando cambi modello, l'identificatore del modello è l'unica cosa che cambia. Averlo nella configurazione significa che il cambio è una variabile di deploy, non una modifica al codice.- Restituisce
finish_reason— chi chiama ha quasi sempre bisogno di sapere se la risposta è stata troncata.
Mantienilo riutilizzabile tra i modelli
La firma di chat(messages, ...) non espone volutamente nulla di specifico al modello. Se in futuro instradi carichi più economici verso altri modelli, o passi un parametro esplicito di override del modello, o costruisci un secondo oggetto client con un MODEL diverso. Trasporto, header, policy di retry e gestione degli errori restano invariati.
Nota sui retry
Non fare retry ciechi dentro chat(). Fai retry al livello che sa se l'operazione può essere ripetuta in sicurezza—le completion fallite di solito sono sicure, ma le richieste che hanno già modificato lo stato a valle non lo sono. Fai retry solo su fallimenti transitori di trasporto e risposte di rate limit, e solo con backoff esponenziale con tetto massimo.
Consumare lo streaming senza rompere il client
Lo streaming è la differenza tra una UI di chat che sembra immediata e dieci secondi di schermo bianco. Introduce anche la maggior parte dei bug di integrazione, perché la risposta non è più un singolo documento JSON.
Come abilitarlo
Aggiungi "stream": true al corpo della richiesta. Il resto della richiesta resta invariato.
with requests.post(
f"{BASE_URL}/chat/completions",
headers=HEADERS,
json={"model": MODEL, "messages": messages, "stream": True},
stream=True,
timeout=120,
) as resp:
resp.raise_for_status()
for line in resp.iter_lines(decode_unicode=True):
if not line or not line.startswith("data:"):
continue
chunk = line[len("data:"):].strip()
if chunk == "[DONE]":
break
# Analizza chunk come JSON e leggi choices[0].delta.content
Cosa arriva effettivamente
Il corpo della risposta è una serie di server-sent event. Ogni evento è una riga data: che trasporta un piccolo oggetto JSON. Dentro choices[0] c'è un oggetto delta invece di un oggetto message—il delta di solito contiene un frammento di content, ma può anche non contenerne nulla. Lo stream termina con la riga sentinella data: [DONE].
Quattro regole coprono quasi tutti gli errori:
- Accumula, non sostituire. Ogni delta è un frammento. Accoda
delta.contenta un buffer; la risposta completa è la concatenazione in ordine di ogni frammento. - Salta i delta vuoti. Il primo e l'ultimo evento spesso non contengono content. Evita di accodare
None. - Tratta
[DONE]come terminatore, non come dato. Ferma la lettura lì; ciò che segue non fa parte della risposta. - Leggi
finish_reasondall'ultimo evento che lo trasporta. In modalità streaming, lo stato di completamento compare in un delta successivo, non in un campo di primo livello.
Trappole che vale la pena nominare
- Dimenticare
stream=Truenella chiamata client. Riceverai l'intero stream come un unico corpo bufferizzato, il che vanifica lo scopo e sembra una richiesta non in streaming molto lenta. - Timeout impostati come per il non streaming. Gli stream di generazioni lunghe durano più di una richiesta breve. Dai al percorso di streaming un timeout di lettura più permissivo, e considera un timer di inattività che interrompa se non arriva nessun byte per un intervallo scelto.
- Parsing riga per riga senza controllare il prefisso. Non ogni riga è un dato. Le righe vuote separano gli eventi; ignorale.
- Assumere che il delta abbia la chiave
content. Lo streaming di tool calling inserisce altre chiavi nei delta. Leggi sempre in modo difensivo. - Dimenticare il consumatore lato client. Un server che scrive lo stream in un buffer e lo emette solo alla fine è tecnicamente streaming, ma in pratica no. Assicurati che il downstream renderizzi i frammenti man mano che arrivano.
Quando non usare lo streaming
Attività batch, riepiloghi in background e qualsiasi cosa il cui output sia consumato da un programma invece che mostrato a un umano, di solito sono più semplici senza streaming. Una risposta non in streaming richiede un solo parsing, è più facile da loggare e più facile da validare secondo uno schema. Usa lo streaming dove la latenza è visibile all'utente; non farlo per impostazione predefinita.
Aggiungere tool calling al flusso
Il tool calling permette al modello di chiedere al tuo codice di eseguire un'azione, invece di inventare una risposta. Il protocollo è una conversazione in due turni: dichiari gli strumenti, il modello può rispondere con una richiesta di chiamata, tu la esegui, poi rimandi indietro il risultato.
Dichiarare gli strumenti
Aggiungi l'array tools alla richiesta. Ogni voce racchiude la descrizione di una funzione:
{
"model": "kimi-k3.1-pro",
"messages": [{"role": "user", "content": "Che tempo fa a Lisbona?"}],
"tools": [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Restituisce il meteo attuale della città indicata.",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string", "description": "Nome della città"}
},
"required": ["city"]
}
}
}
],
"tool_choice": "auto"
}
La description sulla funzione e su ciascun parametro non è decorazione—è l'unica guida che il modello ha per decidere quando e come chiamare lo strumento. Scrivila come scriveresti le istruzioni per un nuovo collega.
Il ciclo di risposta
- Invia la richiesta.
- Se
choices[0].finish_reasonindica una chiamata a strumento, leggichoices[0].message.tool_calls. Ogni voce haid, ilnamedella funzione earguments—una stringa codificata in JSON, non un oggetto. Analizzala. - Esegui la funzione nel tuo codice. Valida i parametri prima di fare qualsiasi cosa con essi; il modello può generare payload plausibili ma con campi mancanti o tipi errati.
- Accoda il messaggio dell'assistente—incluse le sue
tool_calls—al tuo arraymessages. - Accoda un nuovo messaggio con ruolo
tool, con iltool_call_idcorrispondente e il risultato comecontent. - Invia di nuovo la richiesta. Il modello ora usa l'output dello strumento per comporre la risposta finale.
Il passo 4 è quello che tutti saltano, ed è esattamente quello che si rompe. Se rimandi indietro solo il risultato dello strumento senza il turno di tool call dell'assistente, la conversazione ha un riferimento pendente e il modello non ha traccia di aver chiesto nulla.
Gestire più chiamate
Una risposta può contenere più chiamate a strumenti nello stesso turno. Eseguile una per una e restituisci un messaggio tool per ciascuna chiamata, ciascuno con il proprio tool_call_id. Non unirli.
Controllare le chiamate
tool_choice è la tua leva di policy: auto lascia decidere al modello, richiedere uno strumento specifico ne forza una chiamata, disabilitare gli strumenti gli dice di rispondere direttamente. Mantieni un budget—se uno strumento continua a fallire e il modello continua a riprovare, il ciclo degli strumenti può durare molto. Limita il numero di iterazioni nel tuo ciclo e, al raggiungimento del limite, restituisci un messaggio chiaro invece di lasciare che la richiesta continui a consumarsi.
Trattare l'output degli strumenti come non attendibile
Il modello legge i risultati degli strumenti come testo. Mantienili piccoli, strutturati, privi di istruzioni, e valida i parametri dalla tua parte. Uno strumento che restituisce testo illimitato è sia un problema di costo che un rischio di correttezza.
Risolvere gli errori comuni
La maggior parte dei fallimenti di integrazione ricade in cinque categorie. Segui questa checklist prima di modificare i prompt.
1. Autenticazione e autorizzazione
- Sintomo: stato HTTP nell'intervallo 401/403.
- Controlla: la chiave esiste, non ha spazi prima o dopo quando incollata, e ha esattamente il prefisso
Bearer. - Controlla: l'URL di base corrisponde a quello mostrato nella console HiAPI—un host obsoleto o incollato male produce errori di autenticazione confusi.
- Correggi: riesporta la variabile d'ambiente, poi riesegui lo smoke test curl, prima di toccare il codice.
2. Payload malformati
- Sintomo: errore di validazione della richiesta che nomina un campo, o corpo della risposta non analizzabile.
- Controlla: il corpo della richiesta è JSON valido. Se costruito a mano, validalo con un rapido
json.tool; se costruito dal codice, assicurati che il dizionario non sia stato accidentalmente annidato un livello di troppo. - Controlla:
messagesnon è vuoto e ogni voce haroleecontent. - Controlla: i valori di
roleprovengono dall'insieme supportato. Un errore di ortografia comerole: "human"in alcuni client è un errore silenzioso invece che evidente. - Controlla: le voci di
toolshannotype: "function"e un oggettofunctionannidato. Le definizioni appiattite sono l'errore di tool calling più comune.
3. Identificatore del modello
- Sintomo: errore di tipo non trovato, o avviso che il modello non è disponibile per il tuo account.
- Controlla: l'identificatore è copiato esattamente dalla console. Maiuscole e separatori contano.
- Controlla: il modello è abilitato per la tua chiave. Anche con un identificatore valido, un modello che il tuo account non può chiamare fallirà comunque.
4. Limiti di contesto e lunghezza
- Sintomo: errore che la richiesta supera il contesto massimo, o risposta che termina con un
finish_reasonlegato alla lunghezza. - Controlla: la somma del tuo system prompt, della cronologia dei messaggi e di ogni definizione di strumento. Gli schemi degli strumenti contano nel budget e si dimenticano facilmente.
- Correggi: riduci la cronologia, riassumi i turni precedenti o suddividi il compito. Per il troncamento dell'output, se il carico richiede davvero di più, aumenta
max_tokens; altrimenti mantienilo limitato.
5. Rate limit e timeout
- Sintomo: stato di rate limit sotto carico, o timeout di lettura del client.
- Controlla: se i retry partono senza alcun backoff. Un ciclo di retry stretto trasforma un rate limit temporaneo in uno persistente.
- Correggi: rispetta il segnale di rate limit indicato dalla risposta, usa backoff esponenziale con tetto massimo e jitter, e controlla la concorrenza per chiave. Per i timeout, controlla prima il valore di timeout del client—un limite client più breve del tempo di generazione del modello produce esattamente questo sintomo.
Disciplina generale di debug
Registra quattro cose per ogni fallimento: stato HTTP, corpo della risposta, identificatore del modello e se stream era impostato. Questi quattro elementi spiegano la stragrande maggioranza degli incidenti. E mantieni aggiornato lo smoke test curl—quando passa e la tua applicazione fallisce, sai che il problema è nel codice, non nelle credenziali.
Leggere i messaggi di errore
Il livello di aggregazione di solito dice chiaramente quale campo ha causato il rifiuto. Resisti all'impulso di riscrivere il prompt. Leggi il messaggio, correggi il campo indicato, riprova una volta. Se lo stesso errore persiste, prima di approfondire verifica la richiesta con lo smoke test.
Prima di andare in produzione: checklist di produzione
Il divario tra "funziona nel mio terminale" e "funziona in produzione" è soprattutto una checklist che nessuno ha scritto. Eccone una che vale la pena copiare.
Configurazione e segreti
- La API key è conservata in un gestore di segreti, mai nel controllo del codice sorgente e mai in un URL o in una riga di log. Verifica che il tuo client HTTP non possa stampare l'header
Authorizationa livello di debug. - L'URL di base e l'identificatore del modello sono configurazione, non costanti sparse nel codice. Verifica l'URL di base con la console.
- Ruota le chiavi secondo un piano, e dopo l'uscita di qualsiasi membro del team. Il tuo codice client dovrebbe raccogliere la chiave ruotata senza modifiche.
Igiene delle richieste
- Ogni chiamata in uscita ha un timeout esplicito; il percorso di streaming ha un timeout più permissivo più regole di interruzione per inattività.
- Ogni percorso di chiamata imposta
max_tokens. La generazione illimitata è fatturazione illimitata. - Le impostazioni di campionamento sono fissate per caso d'uso e documentate, così i risultati sono riproducibili quando serve il debug.
Gestione delle risposte
- Il tuo parser ramifica in base a
finish_reasone tratta il troncamento come un risultato distinto, non come una risposta completa. - L'accumulo in streaming è testato sia su risposte brevi che lunghe, comprese quelle che terminano in anticipo.
- I parametri del tool calling sono validati prima dell'uso, e il turno di tool call dell'assistente è sempre riportato nell'array dei messaggi.
- Il ciclo degli strumenti ha un limite di iterazioni e un messaggio di fallimento chiaro.
Comportamento in caso di fallimento
- I retry sono limitati, usano backoff esponenziale con tetto massimo e jitter, e si applicano solo a operazioni ripetibili in sicurezza.
- Le risposte di rate limit sono rispettate, non martellate.
- I fallimenti registrano stato, corpo della risposta, identificatore del modello e flag stream—questi quattro campi sono ciò che risolve davvero gli incidenti.
- Lo smoke test curl viene eseguito in CI o secondo un piano, così vieni a sapere di cambi di credenziali o di modello dalla dashboard, non dai clienti.
Costi e capacità
- Sai come viene fatturato l'uso—la piattaforma fattura in base ai token elaborati, quindi contano sia i prompt lunghi che le generazioni lunghe. Controlla le tariffe attuali nel pannello prezzi della console.
- Sai quale tipo di carico è il maggiore consumatore, e se richiede il modello completo o uno più leggero.
- Hai un percorso di degradazione: se una chiamata fallisce ripetutamente, l'applicazione degrada in modo visibile invece di restare appesa silenziosamente.
L'ultima domanda
Chiediti: qualcuno che non ha scritto questa integrazione può osservarla. Se uno sviluppatore del tuo team sa leggere lo smoke test, i campi dei log degli errori e la configurazione, e capisce come diagnosticare un fallimento, hai finito. Se no, la checklist non è completa.
Con una chiamata curl eseguibile, un client Python riutilizzabile e questa checklist, kimi-k3.1-pro è davvero integrato, non solo connesso.
Articoli correlati
Vedi tutti gli articoli →-
Tutoriale
API ElevenLabs Music su HiAPI: generare musica con curl, Python e ricette di prompt
Un tutorial pratico per chiamare elevenlabs/music-v2.5 tramite HiAPI, con ricette di prompt pronte da copiare per stile, mood e durata
-
Tutoriale
Come usare gpt-image-2.5-sunburst/image-to-image tramite l'API HiAPI: curl e Python
Richieste eseguibili per sviluppatori, flusso di caricamento dell'immagine di riferimento e risoluzione degli errori
-
Tutoriale
Come usare gemini-omni-1.2-flash tramite l'API HiAPI: curl e Python