IT ▾
Ottieni la chiave API

Uncensored VideoAPI Sora 2: utilizzo di testo senza censura per pipeline video

Tutorial sugli agenti AI con LangChain e API compatibile OpenAI

Questo tutorial LangChain collega LangChain a un endpoint compatibile OpenAI, associa due strumenti ed esegue un loop dell'agente che puoi leggere riga per riga. Ogni snippet usa lo stesso base URL e il nome del modello uncensored.

Aggiornato

Braccio robotico che cicla tra cubi degli strumenti in un loop, illustra un agente LangChain che chiama strumenti

Punti chiave

  • ChatOpenAI funziona invariato: imposta base_url, api_key e model su uncensored.
  • L'API supporta la chiamata di funzioni, quindi bind_tools e l'agente predefinito funzionano entrambi.
  • Limita le iterazioni del loop e valida gli argomenti degli strumenti; i modelli a pesi aperti a volte li sbagliano.
  • Rispetta 8 richieste concorrenti con una chiave completa quando esegui agenti in parallelo.

Cosa ti serve prima di iniziare

Ti servono Python 3.10 o superiore, una chiave API e alcuni pacchetti. La chiave si ottiene dalla pagina della chiave API: registrati con Google o con email e password, poi richiedi il credito di prova da $0,50 con un solo clic. La chiave di prova consente 2 richieste parallele e 60 al minuto, il che è sufficiente per tutto ciò che è trattato in questo articolo se esegui un agente alla volta.

pip install langchain-openai langchain-core langgraph
export API_KEY="paste-your-key-here"

L'API espone POST /v1/chat/completions e GET /v1/models. LangChain ha bisogno solo del primo. Il modello è un singolo modello a pesi aperti ottimizzato per rispondere senza rifiuti di contenuto per un uso adulto legale; è gestito da un provider indipendente e non è l'API ufficiale di alcun fornitore di modelli. La documentazione elenca le intestazioni e i limiti se li vuoi accanto al tuo editor.

Come i pezzi corrispondono all'API

È utile sapere cosa fa LangChain in rete. Un HumanMessage diventa un messaggio con ruolo user. Un AIMessage diventa assistant, e quando trasporta chiamate di strumenti, queste appaiono nel messaggio dell'assistente come un array tool_calls. Un ToolMessage diventa ruolo tool con l'ID della chiamata corrispondente. Il prompt di sistema va per primo come ruolo system.

Questa mappatura è importante per il debug. Se un agente si comporta in modo strano, stampa l'elenco dei messaggi prima di ogni chiamata e leggilo come una trascrizione. Di solito individui il problema entro un minuto: un risultato dello strumento vuoto, un ID di chiamata che non corrisponde o una cronologia cresciuta molto più del previsto. La parola agentic può far sembrare tutto magia, ma ogni passaggio è una normale richiesta di completamento chat.

Passo 1: Connetti ChatOpenAI

L'intera integrazione richiede tre argomenti. LangChain genera richieste standard in stile OpenAI, quindi il server non è in grado di notare la differenza.

import os
from langchain_openai import ChatOpenAI

llm = ChatOpenAI(
    model="uncensored",
    base_url="https://api.uncensoredvideo.cc/v1",
    api_key=os.environ["API_KEY"],
    temperature=0.7,
    max_retries=2,
)

print(llm.invoke("Name three beats of a heist scene, one line each.").content)

Se questo stampa tre righe, il collegamento funziona. Se ottieni un 401, controlla la chiave. Se ottieni un 404, controlla che l'URL termini con /v1 e non abbia percorsi extra. max_retries è un'opzione client e aiuta con le risposte 429 temporanee che trasportano Retry-After: 5.

Lo streaming funziona nello stesso modo in cui lo useresti con qualsiasi modello OpenAI: chiama llm.stream(...) ed esegui l'iterazione. L'ultimo chunk trasporta l'utilizzo, quindi puoi registrare i conteggi dei token per ogni chiamata.

Passo 2: Definisci gli strumenti

Un agente è un loop: il modello legge la conversazione, o risponde o chiede uno strumento, il tuo codice esegue lo strumento e il risultato torna al modello. Gli strumenti qui sotto sono semplici funzioni Python. Sono volutamente noiosi, perché l'obiettivo è vedere la meccanica.

from langchain_core.tools import tool

@tool
def word_count(text: str) -> int:
    """Count the words in a piece of text."""
    return len(text.split())

@tool
def spoken_minutes(words: int, words_per_minute: int = 150) -> float:
    """Estimate how many minutes a script takes to read aloud."""
    return round(words / words_per_minute, 2)

tools = [word_count, spoken_minutes]

Il docstring e gli hint di tipo diventano la descrizione e lo schema dello strumento che vede il modello. Scrivili come se stessi spiegando a un collega. Un docstring vago è la ragione più comune per cui un agente sceglie lo strumento sbagliato. Se scrivi script per video, lo stesso pattern si estende a strumenti che cercano liste di riprese o verificano un budget di lunghezza, un argomento trattato nella pagina del generatore di script Sora 2.

Passo 3: Esegui il ciclo dell'agente manualmente

Le utility predefinite nascondono il ciclo. Scriverlo una volta da solo rende ogni bug successivo più facile da trovare.

from langchain_core.messages import HumanMessage, ToolMessage

by_name = {t.name: t for t in tools}
llm_tools = llm.bind_tools(tools)

messages = [HumanMessage(
    "Here is a draft: 'The vault door hums. Nina counts to three, "
    "then cuts the power.' How many words is it, and how long is it read aloud?"
)]

for step in range(6):
    ai = llm_tools.invoke(messages)
    messages.append(ai)
    if not ai.tool_calls:
        break
    for call in ai.tool_calls:
        result = by_name[call["name"]].invoke(call["args"])
        messages.append(ToolMessage(content=str(result), tool_call_id=call["id"]))

print(messages[-1].content)

Tre dettagli sono importanti. Il limite range(6) impedisce a un modello confuso di andare in loop all'infinito, e limita anche la tua spesa. Il tool_call_id deve corrispondere alla chiamata a cui risponde. E il modello può richiedere diversi strumenti in una sola risposta, motivo per cui il ciclo interno gestisce un elenco.

Sotto il cofano, la richiesta trasporta un array tools e la risposta trasporta tool_calls, con risultati restituiti come messaggi con role: "tool". Puoi forzare uno strumento specifico con tool_choice, che LangChain espone come argomento a bind_tools.

Passo 4: Usa l'agente LangGraph predefinito

Una volta che il loop manuale ha senso, l'agente predefinito fa risparmiare righe. Usa lo stesso modello e gli stessi strumenti.

import os
from langchain_openai import ChatOpenAI
from langgraph.prebuilt import create_react_agent

llm = ChatOpenAI(
    model="uncensored",
    base_url="https://api.uncensoredvideo.cc/v1",
    api_key=os.environ["API_KEY"],
)

agent = create_react_agent(llm, tools)
out = agent.invoke({"messages": [("user", "How long is a 450 word script read aloud?")]})
print(out["messages"][-1].content)

LangChain e LangGraph cambiano le loro API tra le release, e alcune utility sono state rinominate o spostate. Se un'istruzione import fallisce, controlla la documentazione corrente di LangChain per il costruttore di agente equivalente. La parte di connessione, ChatOpenAI con un URL di base, rimane la stessa.

Scegliere tra un loop e un grafo

Il ciclo scritto a mano è sufficiente per gli agenti che scelgono tra pochi strumenti e si fermano. È facile da leggere, facile da registrare e non ha sorprese del framework. Passa a LangGraph quando hai bisogno di rami che dipendono dallo stato: un passaggio di revisione che rimanda il lavoro per un'altra passata, un'approvazione umana prima che uno strumento rischioso venga eseguito, o diversi sotto-agenti specializzati che passano i risultati tra loro.

Qualunque cosa tu scelga, mantieni ogni nodo piccolo e dagli un solo lavoro. Un nodo di pianificazione che produce un breve elenco numerato in JSON, un nodo di esecuzione che esegue strumenti e un nodo di scrittura che produce il testo finale sono più facili da testare rispetto a un singolo prompt gigante. Ti permettono anche di usare temperature diverse: bassa per la pianificazione e l'uso di strumenti, più alta per il passaggio di scrittura. Poiché ogni nodo è una normale chiamata di completamento chat, la stessa chiave, URL e nome del modello li servono tutti, e il costo è semplicemente la somma delle chiamate.

Un'ultima abitudine: stampa il totale dei token in esecuzione. Gli agenti che sembrano economici in una demo possono spendere dieci volte di più in un compito reale disordinato, e i dati di utilizzo su ogni risposta lo rendono visibile alla prima esecuzione, prima che si trasformi in una sorpresa sul tuo saldo.

Memoria, test e output strutturato

Il ciclo sopra dimentica tutto quando lo script termina. La memoria più semplice è l'elenco dei messaggi stesso: tienilo tra i turni dell'utente, aggiungi ogni nuova domanda e taglia i messaggi più vecchi quando diventa lungo. Per sessioni lunghe, sostituisci i messaggi vecchi con un breve riassunto scritto dal modello. Poiché l'input viene fatturato per token, un riassunto da 500 token batte 20.000 token di storico grezzo sia in termini di costo che di concentrazione.

Testare gli agenti consiste principalmente nel verificare il comportamento che puoi osservare. Imposta la temperatura a 0 o passa un seed fisso, che l'API inoltra, quindi le esecuzioni sono più ripetibili. Poi scrivi una manciata di domande in cui sai quale strumento dovrebbe essere chiamato, e verifica i nomi degli strumenti e gli argomenti nell'elenco dei messaggi, non il testo esatto della risposta. Esegui questi test dopo ogni modifica a un prompt o a una descrizione di uno strumento. Modificare un docstring può cambiare quale strumento sceglie il modello, e un test è il modo più economico per accorgersene.

Registra tre cose per ogni esecuzione: il numero di passaggi, le chiamate di strumenti con i loro argomenti e l'utilizzo dei token. Quando un'esecuzione va male, quelle tre righe ti dicono se il modello ha scelto male, se uno strumento è fallito o se il loop ha esaurito i passaggi.

Output strutturato e modalità JSON

Gli agenti spesso hanno bisogno di restituire dati, non prosa. L'API supporta la modalità JSON tramite response_format: {"type":"json_object"}. In LangChain puoi richiederlo con llm.bind(response_format={"type": "json_object"}). Dì al modello nel prompt che la risposta deve essere un oggetto JSON e nomina le chiavi che ti aspetti, poi analizza la stringa e validala con Pydantic. Non fidarti che il passaggio di analisi abbia sempre successo; avvolgilo in un tentativo di nuovo invio che invia il testo di errore al modello una volta.

Punti critici e come risolverli

  • Argomenti di strumento scadenti. Un modello a pesi aperti a volte invia una stringa dove hai dichiarato un intero. Convalida gli argomenti, restituisci un breve messaggio di errore dallo strumento e lascia che il modello si corregga nel passaggio successivo.
  • Loop incontrollati. Limita sempre le iterazioni. Registra ogni passaggio mentre sviluppi.
  • Agenti paralleli. Una chiave completa permette 8 richieste concorrenti. Se esegui un batch, imposta config={"max_concurrency": 4} su llm.batch per lasciare margine. Superare il limite restituisce 429 con il codice concurrency; superare 300 richieste al minuto restituisce rate_limited.
  • Streaming più strumenti. Una richiesta in streaming mantiene il suo slot di concorrenza fino alla fine dello stream, quindi non avviare nuove chiamate da un gestore di stream su una chiave di prova.
  • Cronologia in crescita. Ogni passaggio rispedisce l'elenco completo dei messaggi. La finestra di contesto è di 100.000 token, ma paghi per l'input su ogni chiamata.

Quanto costa un'esecuzione dell'agente

Prendi un agente modesto che fa 4 chiamate al modello per completare un compito, con un prompt medio di 3.000 token e 200 token di output per chiamata. Input: 4 x 3.000 = 12.000 token, che è 12.000 x $0,15 / 1.000.000 = $0,0018. Output: 4 x 200 = 800 token, che è $0,0004. Un'esecuzione costa $0,0022, quindi 1.000 esecuzioni costano $2,20. Il credito di prova da $0,50 copre circa 227 di queste esecuzioni. Le richieste fallite o rifiutate non vengono addebitate e il credito non scade mai. Vedi prezzi per gli importi di ricarica e i bonus. Questo sito accetta solo cripto, USDT su TRC20 o USDC su Base.

Domande e risposte

LangChain ha bisogno di un'integrazione speciale per questa API?

No. La classe ChatOpenAI di langchain-openai accetta un base_url, quindi puntala all'API e usa il modello uncensored. Non serve un wrapper personalizzato.

L'API supporta la chiamata di strumenti per gli agenti?

Sì. Accetta strumenti e tool_choice, restituisce tool_calls (anche in streaming) e accetta i risultati come messaggi con role tool.

Perché il mio agente si ferma con un errore 429?

Hai raggiunto il limite di richieste o quello di concorrenza. Una chiave completa permette 8 richieste concorrenti e 300 al minuto. Riduci max_concurrency o attendi il periodo Retry-After.

Posso usare LangGraph invece del ciclo semplice?

Sì. L'agente predefinito di LangGraph utilizza lo stesso oggetto ChatOpenAI e la stessa lista di strumenti, quindi il codice di connessione non cambia.

La tua chiave è a un modulo di distanza

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

Ottieni la chiave API