Kluczowe punkty
- ChatOpenAI działa niezmienione: ustaw base_url, api_key i model na
uncensored. - API obsługuje wywoływanie funkcji, więc bind_tools i gotowy agent działają poprawnie.
- Ogranicz liczbę iteracji pętli i zweryfikuj argumenty narzędzi; modele o otwartych wagach czasem je źle interpretują.
- Szanuj limit 8 równoległych zapytań przy pełnym kluczu, gdy uruchamiasz agenty równolegle.
Czego potrzebujesz przed rozpoczęciem
Potrzebujesz Pythona 3.10 lub nowszego, klucza API i kilku pakietów. Klucz uzyskasz na stronie klucza API: zarejestruj się przez Google lub e-mail i hasło, a następnie odbierz darmowy kredyt próbny w wysokości $0,50 jednym kliknięciem. Klucz próbny pozwala na 2 równoległe zapytania i 60 na minutę, co wystarczy do wszystkiego w tym artykule, jeśli uruchamiasz jednego agenta na raz.
pip install langchain-openai langchain-core langgraph
export API_KEY="paste-your-key-here"API udostępnia POST /v1/chat/completions oraz GET /v1/models. LangChain potrzebuje tylko tego pierwszego. Model to pojedynczy model o otwartych wagach, nastawiony na odpowiadanie bez odmów treści dla prawnego użytku dorosłych; jest uruchamiany przez niezależnego dostawcę i nie jest oficjalnym API żadnego dostawcy modeli. Dokumentacja zawiera listę nagłówków i limitów, jeśli chcesz mieć je pod ręką obok edytora.
Jak elementy mapują się na API
Warto wiedzieć, co LangChain wysyła w sieci. HumanMessage staje się wiadomością z rolą user. AIMessage staje się rolą assistant, a gdy zawiera wywołania narzędzi, pojawiają się one w wiadomości asystenta jako tablica tool_calls. ToolMessage staje się rolą tool z odpowiadającym identyfikatorem wywołania. Prompt systemowy jest pierwszy i ma rolę system.
Ta mapa ma znaczenie przy debugowaniu. Jeśli agent zachowuje się dziwnie, wydrukuj listę wiadomości przed każdym wywołaniem i czytaj ją jak transkrypcję. Zazwyczaj zlokalizujesz problem w ciągu minuty: pusty wynik narzędzia, ID wywołania, które nie pasuje, lub historia, która stała się znacznie dłuższa niż się spodziewałeś. Słowo agentic może sprawiać, że to brzmi jak magia, ale każdy krok to zwykłe zapytanie chat completion.
Krok 1: Podłącz ChatOpenAI
Cała integracja to trzy argumenty. LangChain buduje standardowe żądania w stylu OpenAI, więc serwer nie zauważy różnicy.
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)Jeśli wydrukują się trzy linie, połączenie działa. Jeśli otrzymasz 401, sprawdź klucz. Jeśli otrzymasz 404, sprawdź, czy URL kończy się na /v1 i nie ma dodatkowej ścieżki. max_retries to opcja klienta, która pomaga przy tymczasowych odpowiedziach 429 z nagłówkiem Retry-After: 5.
Strumieniowanie działa tak samo, jak w przypadku dowolnego modelu OpenAI: wywołaj llm.stream(...) i iteruj po wynikach. Ostatni chunk zawiera metryki użycia, więc możesz logować liczbę tokenów dla każdego wywołania.
Krok 2: Zdefiniuj narzędzia
Agent to pętla: model czyta rozmowę, albo odpowiada, albo prosi o narzędzie, twój kod uruchamia narzędzie, a wynik wraca do modelu. Poniższe narzędzia to zwykłe funkcje Pythona. Są celowo nudne, ponieważ celem jest zobaczenie mechaniki.
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]Docstring i podpowiedzi typów stają się opisem narzędzia i schematem, które widzi model. Pisz je tak, jakbyś wyjaśniał to koledze. Niejasny docstring to najczęstszy powód, dla którego agent wybiera złe narzędzie. Jeśli piszesz scenariusze do wideo, ten sam wzorzec skaluje się do narzędzi wyszukujących listy ujęć lub sprawdzających budżet długości — temat omówiony na stronie generatora scenariuszy Sora 2.
Krok 3: Uruchom pętlę agenta ręcznie
Gotowe pomocniki ukrywają pętlę. Napisanie jej raz samodzielnie ułatwia znalezienie każdego późniejszego błędu.
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)Trzy szczegóły mają znaczenie. Ograniczenie range(6) zapobiega nieskończonej pętli przy zagubionym modelu, a także ogranicza Twoje wydatki. tool_call_id musi pasować do wywołania, na które odpowiada. Model może też zażądać kilku narzędzi w jednej odpowiedzi, dlatego pętla wewnętrzna obsługuje listę.
Pod spodem zapytanie zawiera tablicę tools, a odpowiedź zawiera tool_calls, z wynikami zwracanymi jako wiadomości z rolą role: "tool". Możesz wymusić konkretne narzędzie za pomocą tool_choice, co LangChain udostępnia jako argument do bind_tools.
Krok 4: Użyj gotowego agenta LangGraph
Gdy ręczna pętla ma sens, gotowy agent oszczędza linie. Przyjmuje ten sam model i te same narzędzia.
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 i LangGraph zmieniają swoje API między wydaniami, a niektóre pomocniki zostały przemianowane lub przeniesione. Jeśli import się nie powiedzie, sprawdź aktualną dokumentację LangChain w poszukiwaniu odpowiedniego konstruktora agenta. Część połączenia, ChatOpenAI z bazowym URL, pozostaje bez zmian.
Wybór między pętlą a grafem
Napisana ręcznie pętla wystarczy dla agentów, którzy wybierają z kilku narzędzi i kończą. Jest łatwa do odczytania, łatwa do zalogowania i nie ma niespodzianek frameworka. Przenieś się do LangGraph, gdy potrzebujesz gałęzi zależnych od stanu: krok recenzji, który wysyła pracę z powrotem do kolejnej iteracji, zatwierdzenie człowieka przed uruchomieniem ryzykownego narzędzia lub kilka wyspecjalizowanych sub-agentów, które przekazują sobie wyniki.
Co wybierzesz, trzymaj każdy węzeł mały i daj mu jedno zadanie. Węzeł planowania, który wypisuje krótką listę numerowaną w JSON, węzeł wykonania, który uruchamia narzędzia, i węzeł pisania, który produkuje ostateczny tekst, są łatwiejsze do przetestowania niż jeden gigantyczny prompt. Pozwalają też użyć różnych temperatur: niskiej dla planowania i używania narzędzi, wyższej dla kroku pisania. Ponieważ każdy węzeł to normalne wywołanie ukończenia czatu, ten sam klucz, URL i nazwa modelu obsługują wszystkie z nich, a koszt to po prostu suma wywołań.
Jeszcze jeden nawyk: drukuj łączną liczbę tokenów. Agenty, które wyglądają tanio w demo, mogą wydać dziesięć razy więcej na chaotyczne, prawdziwe zadanie, a dane o użyciu w każdej odpowiedzi pokazują to przy pierwszym uruchomieniu, zanim zamieni się w niespodziankę na Twoim saldzie.
Pamięć, testowanie i wyjście strukturalne
Powyższa pętla zapomina o wszystkim po zakończeniu skryptu. Najprostszą pamięcią jest sama lista wiadomości: zachowaj ją między kolejnymi turami użytkownika, dodawaj każde nowe pytanie i przycinaj najstarsze wiadomości, gdy lista się wydłuży. W przypadku długich sesji zastąp stare wiadomości krótkim podsumowaniem wygenerowanym przez model. Ponieważ płatność naliczana jest za tokeny, podsumowanie o długości 500 tokenów jest lepsze niż 20 000 tokenów surowej historii pod względem kosztów i skupienia.
Testowanie agentów sprowadza się głównie do sprawdzania zachowań, które można zaobserwować. Ustaw temperaturę na 0 lub przekaż stały seed, który API przekazuje dalej, dzięki czemu uruchomienia są bardziej powtarzalne. Następnie napisz kilka pytań, w których wiesz, które narzędzie powinno zostać wywołane, i sprawdź nazwy narzędzi oraz argumenty w liście wiadomości, a nie dokładne sformułowanie odpowiedzi. Uruchamiaj je po każdej zmianie promptu lub opisu narzędzia. Zmiana docstringa może zmienić, które narzędzie wybierze model, a test to najtańszy sposób, by to zauważyć.
Loguj trzy rzeczy dla każdego uruchomienia: liczbę kroków, wywołania narzędzi z ich argumentami i użycie tokenów. Gdy uruchomienie się nie powiedzie, te trzy linie powiedzą Ci, czy model źle wybrał, czy narzędzie zawiodło, czy pętla wyczerpała kroki.
Wyjście strukturalne i tryb JSON
Agenci często muszą zwracać dane, a nie tekst. API obsługuje tryb JSON przez response_format: {"type":"json_object"}. W LangChain możesz o to poprosić za pomocą llm.bind(response_format={"type": "json_object"}). Powiedz modelowi w prompcie, że odpowiedź musi być obiektem JSON i wymień oczekiwane klucze, a następnie przeanalizuj ciąg i zweryfikuj go za pomocą Pydantic. Nie zakładaj, że krok parsowania zawsze się powiedzie; opakuj go w retry, który wyśle tekst błędu z powrotem do modelu raz.
Pułapki i jak je naprawić
- Złe argumenty narzędzi. Model o otwartych wagach czasem wysyła ciąg tam, gdzie zadeklarowałeś liczbę całkowitą. Zweryfikuj argumenty, zwróć krótki komunikat o błędzie z narzędzia i pozwól modelowi poprawić się w kolejnym kroku.
- Pętle nieskończone. Zawsze ograniczaj liczbę iteracji. Loguj każdy krok podczas rozwoju.
- Równoległe agenty. Pełny klucz pozwala na 8 równoległych zapytań. Jeśli uruchamiasz wsadowo, ustaw
config={"max_concurrency": 4}nallm.batch, aby zostawić margines bezpieczeństwa. Przekroczenie limitu zwraca 429 z kodemconcurrency; przekroczenie 300 zapytań na minutę zwracarate_limited. - Strumieniowanie plus narzędzia. Żądanie strumieniowe zajmuje slot konkurencji do końca strumienia, więc nie uruchamiaj nowych wywołań z wnętrza handlera strumienia na kluczu próbnym.
- Rosnąca historia. Każdy krok ponownie wysyła pełną listę wiadomości. Okno kontekstu ma 100 000 tokenów, ale płacisz za wejście przy każdym wywołaniu.
Ile kosztuje uruchomienie agenta
Weź skromnego agenta, który wykonuje 4 wywołania modelu, aby ukończyć zadanie, ze średnim promptem 3000 tokenów i 200 tokenami wyjściowymi na wywołanie. Wejście: 4 x 3000 = 12 000 tokenów, co daje 12 000 x $0,15 / 1 000 000 = $0,0018. Wyjście: 4 x 200 = 800 tokenów, co daje $0,0004. Jedno uruchomienie kosztuje $0,0022, więc 1000 uruchomień kosztuje $2,20. Kredyt próbny $0,50 pokrywa około 227 takich uruchomień. Nieudane lub odrzucone żądania nie są rozliczane, a kredyt nigdy nie wygasa. Zobacz cennik, aby poznać kwoty doładowań i bonusy. Ta strona przyjmuje tylko kryptowaluty, USDT na TRC20 lub USDC na Base.
