Cosa significa la frase
Le persone usano "LLM locale API OpenAI" per due cose correlate. La prima è un modello linguistico che esegui tu stesso, su un laptop o un server domestico, che ascolta su una porta locale e parla il formato chat OpenAI. La seconda è l'abitudine di scrivere la tua app contro quel formato in modo che il modello sottostante possa essere scambiato.
Il formato è un contratto semplice. La tua app invia un corpo JSON con un nome model e un elenco di messages, ciascuno con un ruolo di system, user o assistant. Il server risponde con un oggetto JSON contenente il messaggio generato, o con uno streaming di piccoli chunk se richiedi lo streaming. Gli SDK ufficiali per Python e JavaScript avvolgono questo, e ti permettono di sovrascrivere l'URL di base, che è il trucco principale.
Molti strumenti locali espongono questo contratto. Ollama, LM Studio, il server llama.cpp e vLLM offrono ciascuno un percorso in stile OpenAI. Anche i servizi ospitati lo fanno, motivo per cui le stesse venti righe di codice client possono parlare con entrambi. L'endpoint di questo sito è di tipo ospitato. Accetta POST /v1/chat/completions e GET /v1/models, ed è raggiungibile a https://api.onekeyllmapi.com/v1.
Locale versus ospitato a colpo d'occhio
Nessuno dei due è migliore in generale. Scambiano il controllo per lo sforzo. La tabella si attiene alle differenze che valgono per la categoria, non per un prodotto specifico.
| Domanda | Runner locale | API ospitata in stile OpenAI |
|---|---|---|
| Dove vanno i prompt | Restano sulla tua macchina | Connessione al provider tramite HTTPS |
| Hardware | Fornisci GPU o CPU e memoria | Nessuno da parte tua |
| Dimensioni del modello | Limitato dalla tua memoria | Qualunque cosa serva il provider |
| Modello di costo | Hardware e alimentazione | Per token, da credito prepagato qui |
| Disponibilità | Finché la tua macchina è accesa | Server sempre attivo, limiti condivisi |
| Configurazione | Installa, scarica i pesi, ottimizza | Crea una chiave, imposta l'URL di base |
Se i tuoi dati non devono mai lasciare una macchina che controlli, la soluzione locale vince e quella ospitata è lo strumento sbagliato. Se hai bisogno di un modello più grande di quello che il tuo hardware supporta, o di un bot che rimanga raggiungibile da molti posti, la soluzione ospitata vince. Una configurazione comune mantiene entrambi e sceglie in base al compito.
Passaggio di un client da locale a ospitato
Se il tuo codice parla già con un runner locale, il passaggio richiede tre valori. Tutto il resto, incluso come costruisci i messaggi e leggi i frammenti in streaming, resta uguale.
- URL di base. Usa
https://api.onekeyllmapi.com/v1invece del tuo indirizzo locale. - Chiave API. I server locali spesso ignorano la chiave. Uno ospitato la richiede come
Authorization: Bearer <key>, e l'SDK la invia per te. - ID del modello. I nomi locali sono quelli che hai scaricato. Qui l'ID è
uncensored.
Un approccio ordinato per mantenere questa flessibilità è leggere tutti e tre i valori dalle variabili d'ambiente, così un unico file funziona in entrambi gli ambienti.
import os
from openai import OpenAI
client = OpenAI(
base_url=os.environ.get("LLM_BASE_URL", "https://api.onekeyllmapi.com/v1"),
api_key=os.environ.get("LLM_API_KEY", "YOUR_KEY"),
)
MODEL = os.environ.get("LLM_MODEL", "uncensored")
models = client.models.list()
print([m.id for m in models.data])
resp = client.chat.completions.create(
model=MODEL,
messages=[
{"role": "system", "content": "Answer in two sentences."},
{"role": "user", "content": "Why do OpenAI-style endpoints make switching models easy?"},
],
temperature=0.5,
)
print(resp.choices[0].message.content)
La stessa chiamata da riga di comando, utile per un test rapido:
curl https://api.onekeyllmapi.com/v1/chat/completions \
-H "Authorization: Bearer YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"model": "uncensored", "messages": [{"role": "user", "content": "ping"}], "max_tokens": 20}'
Con Node, la struttura è identica:
import OpenAI from "openai";
const client = new OpenAI({
baseURL: process.env.LLM_BASE_URL ?? "https://api.onekeyllmapi.com/v1",
apiKey: process.env.LLM_API_KEY,
});
const res = await client.chat.completions.create({
model: process.env.LLM_MODEL ?? "uncensored",
messages: [{ role: "user", content: "Name three uses for JSON mode." }],
});
console.log(res.choices[0].message.content);
Cosa fa e cosa non copre la compatibilità OpenAI
Compatibile significa che il formato di rete corrisponde. Non promette che ogni funzione offerta dal servizio originale sia presente. Prima di migrare un'app reale, verifica ciascuna di queste contro il target.
Cosa supporta questa API
- Completazioni chat su
POST /v1/chat/completionse un elenco dei modelli suGET /v1/models. - Streaming su eventi inviati dal server con
stream: true, con l'utilizzo riportato alla fine dello streaming. - Chiamata di strumenti tramite
toolsetool_choice, streamingtool_calls, e risultati inviati come messaggirole: "tool". - Modalità JSON tramite
response_format: {"type": "json_object"}. - Parametri di campionamento: temperature, top_p, stop, seed e i parametri di penalità vengono inoltrati.
Cosa non fa
- Nessuna generazione di immagini, audio o video. È solo testo.
- Nessun endpoint embedding e nessun fine-tuning. Se la tua app costruisce un indice vettoriale, hai bisogno di una fonte di embedding separata.
- Solo un modello. Il modello è un modello a pesi aperti gestito da un provider indipendente. Non è l'API ufficiale di nessun grande fornitore e non è un router tra fornitori, quindi non puoi scegliere tra famiglie di modelli modificando l'ID.
I runner locali a volte differiscono nel modo opposto: un server locale può offrire un percorso embedding o permetterti di caricare diversi modelli, e la dimensione del contesto è quella che configuri. Leggi la documentazione del target per ciascuno e tieni un breve elenco delle funzionalità che la tua app usa davvero. La documentazione di avvio rapido mostra i campi della richiesta in dettaglio.
Contesto, limiti e differenze di costo
Tre numeri cambiano quando lasci un server locale. Il primo è la finestra. La lunghezza del contesto di un runner locale è un'impostazione legata alla tua memoria. Qui è fissa a 100.000 token, condivisa dal prompt e dal completamento, e max_tokens è opzionale. Il secondo è la concorrenza. La tua macchina può essere accodata quanto vuoi, ma una chiave completa qui permette 8 richieste parallele e 300 al minuto, e una chiave di prova 2 e 60. Il terzo è il conto.
L'uso ospitato costa $0,15 per 1M token di input e $0,50 per 1M token di output, pagamento a consumo da credito prepagato. Esegui un lavoro giornaliero come esempio: un summarizer elabora 400 documenti al giorno, ciascuno con 3.000 token in input e 300 token in output. L'input è 400 x 3.000 = 1.200.000 token, che costano 1,2 x $0,15 = $0,18. L'output è 400 x 300 = 120.000 token, che costano 0,12 x $0,50 = $0,06. Il totale giornaliero è $0,24, e un mese di 30 giorni è $7,20. Confrontalo con il costo di tenere una GPU accesa e della scheda stessa prima di decidere.
Quando superi un limite, l'API risponde con HTTP 429 con il codice rate_limited o concurrency. Per sovraccarico breve aggiunge Retry-After: 5. Mantieni la logica di retry che attende e riprova. Le richieste che falliscono o vengono rifiutate non vengono addebitate. Il credito non scade mai, quindi un mese inattivo non costa nulla.
Una richiesta in streaming mantiene il suo slot di concorrenza fino alla fine dello streaming, quindi chiudi gli streaming che smetti di leggere. Le ricariche iniziano da $20; i tier e i bonus sono nella pagina dei prezzi.
Debug quando l'interruttore si comporta male
La maggior parte delle migrazioni fallite dipende da un numero limitato di cause. Procedi controllandole in questo ordine.
- Errori 404 o di connessione. All'URL base manca probabilmente il suffisso
/v1, oppure è presente un percorso extra. Usalo esattamente comehttps://api.onekeyllmapi.com/v1. - Errori di autenticazione. La chiave manca o è inviata con l'header sbagliato. Il formato è
Authorization: Bearer <key>. Gli utenti di SDK devono verificare che la variabile d'ambiente sia stata effettivamente caricata. - Modello non trovato. Il vecchio nome del modello locale è ancora nella tua configurazione. Chiama
GET /v1/modelse usa l'ID che elenca, ovverouncensored. - Errore 429 sotto carico. Hai superato 8 richieste parallele o 300 al minuto con una chiave completa. Aggiungi una coda o un semaforo.
- Un parametro sembra ignorato. Verifica che sia uno dei campi passati elencati sopra e confronta il comportamento con un
seedfisso e una temperatura bassa.
Ogni risposta include un header X-Request-Id. Registralo accanto al tuo ID di richiesta così da poter tracciare una risposta scadente in seguito. Se gestisci traffico in produzione e vuoi misurare la qualità nel tempo, l'articolo del sito LLM Observability: Myths vs Facts è una buona lettura successiva. Gli header di risposta X-Balance-USD, X-RateLimit-Limit-Requests e X-RateLimit-Limit-Concurrency valgono anche la pena di essere catturati.
Provalo senza impegno
Il modo più economico per testare se il tuo codice si porta in modo pulito è eseguirlo una volta. Crea un account con Google o email e password, poi richiedi il credito di prova da $0,50 dalla pagina della chiave. Richiede un solo clic, non richiede una carta, è limitato a uno per persona e resta valido per 7 giorni. Ottieni la tua chiave alla pagina della chiave API, imposta le tre variabili d'ambiente sopra e esegui la tua suite di test esistente.
Se i test passano e l'utilizzo rientra nel tuo budget, ricarica da $20, con carta (Visa, Mastercard, Apple Pay, Google Pay) o cripto (USDT su TRC20, USDC su Base). I prompt non sono usati per l'addestramento. Il modello è ottimizzato per rispondere senza rifiuti di contenuto per uso adulto legale, con un'unica regola fissa: nessun contenuto sessuale che coinvolga minorenni.
