KO ▾
API 키 받기

Uncensored VideoSora 2 API: 비디오 파이프라인에서 무검열 텍스트 사용

OpenAI 호환 API를 사용한 LangChain 에이전트 AI 튜토리얼

이 LangChain 에이전트 AI 튜토리얼은 LangChain을 OpenAI 호환 엔드포인트에 연결하고, 두 개의 도구를 바인딩하며, 줄별로 읽을 수 있는 에이전트 루프를 실행합니다. 모든 코드 스니펫은 동일한 Base URL과 uncensored 모델 이름을 사용합니다.

업데이트됨

루프 내에서 도구 큐 사이를 순환하는 로봇 팔, LangChain 에이전트가 도구를 호출하는 것을 보여줍니다

주요 포인트

  • ChatOpenAI는 변경되지 않고 작동합니다: base_url, api_key 및 모델을 uncensored로 설정합니다.
  • API는 함수 호출을 지원하므로, bind_tools와 사전 구축된 에이전트 모두 작동합니다.
  • 루프 반복 횟수를 제한하고 도구 인수를 검증합니다. 오픈 웨이트 모델은 때때로 이를 잘못 처리합니다.
  • 에이전트를 병렬로 실행할 때 전체 키의 동시 요청 8개를 준수하십시오.

시작하기 전에 필요한 항목

Python 3.10 이상, API 키, 그리고 몇 가지 패키지가 필요합니다. 키는 API 키 페이지에서 발급받습니다: Google 또는 이메일과 비밀번호로 로그인하고, 한 번의 클릭으로 $0.50 무료 체험 크레딧을 받습니다. 체험 키는 동시 요청 2개와 분당 60개의 요청을 허용하며, 이는 에이전트를 하나만 실행할 때 이 문서의 모든 작업에 충분합니다.

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

API는 POST /v1/chat/completions과 GET /v1/models을 제공합니다. LangChain에는 첫 번째 엔드포인트만 필요합니다. 이 모델은 콘텐츠 거부 없이 합법적인 성인 사용을 위해 응답하도록 조정된 단일 오픈 웨이트 모델입니다. 독립적인 제공업체에서 운영하며, 어떤 모델 벤더의 공식 API도 아닙니다. 편집기 옆에 필요하시다면 문서에서 헤더와 제한 사항을 확인하세요.

구성 요소가 API에 매핑되는 방법

LangChain이 네트워크에서 수행하는 작업을 아는 것이 도움이 됩니다. HumanMessage는 role이 user인 메시지로 변환됩니다. AIMessage는 assistant로 변환되며, 도구 호출을 포함할 경우 어시스턴트 메시지에 tool_calls 배열로 나타납니다. ToolMessage는 일치하는 호출 ID와 함께 role이 tool로 변환됩니다. 시스템 프롬프트는 role이 system로 가장 먼저 전달됩니다.

이 매핑은 디버깅에 중요합니다. 에이전트가 이상하게 동작하는 경우 각 호출 전에 메시지 목록을 출력하고 기록처럼 읽으십시오. 일반적으로 1분 이내에 문제를 찾을 수 있습니다: 빈 도구 결과, 일치하지 않는 호출 ID 또는 예상보다 훨씬 길어진 이력. 에이전트라는 단어는 이를 마법처럼 들리게 할 수 있지만, 모든 단계는 일반적인 chat completion 요청입니다.

1단계: ChatOpenAI 연결

전체 통합은 세 가지 인수로 구성됩니다. LangChain은 표준 OpenAI 스타일 요청을 생성하므로 서버는 차이를 알 수 없습니다.

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)

이 코드가 세 줄을 출력하면 연결이 정상적으로 작동합니다. 401 오류가 발생하면 키를 확인하십시오. 404 오류가 발생하면 URL이 /v1로 끝나고 추가 경로가 없는지 확인하십시오. max_retries은 클라이언트 옵션이며, Retry-After: 5 헤더와 함께 일시적인 429 응답을 처리하는 데 도움이 됩니다.

스트리밍은 다른 OpenAI 모델을 사용할 때와 동일한 방식으로 작동합니다: llm.stream(...)를 호출하고 반복합니다. 마지막 청크에는 사용량 정보가 포함되어 있으므로 호출당 토큰 수를 기록할 수 있습니다.

2단계: 도구 정의

에이전트는 루프입니다: 모델이 대화를 읽고, 답변하거나 도구 요청을 하며, 코드가 도구를 실행하고, 결과가 모델로 다시 전송됩니다. 아래 도구는 일반 Python 함수입니다. 메커니즘을 볼 수 있도록 의도적으로 지루하게 작성되었습니다.

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과 타입 힌트는 모델이 보는 도구 설명과 스키마가 됩니다. 동료에게 업무를 설명하는 것처럼 작성하세요. 모호한 docstring은 에이전트가 잘못된 도구를 선택하는 가장 흔한 이유입니다. 비디오용 스크립트를 작성한다면, 이 패턴은 촬영 목록을 조회하거나 길이 예산을 확인하는 도구로 확장할 수 있습니다. 이 주제는 Sora 2 스크립트 생성기 페이지에서 다룹니다.

3단계: 에이전트 루프를 수동으로 실행

사전 구축된 도우미는 루프를 숨깁니다. 직접 작성하면 이후의 모든 버그를 쉽게 찾을 수 있습니다.

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)

세 가지 세부 사항이 중요합니다. range(6) 제한은 혼란스러운 모델이 무한 루프에 빠지는 것을 방지하고 지출도 제한합니다. tool_call_id는 답변하는 호출과 일치해야 합니다. 그리고 모델은 한 번의 응답으로 여러 도구를 요청할 수 있으므로 내부 루프가 목록을 처리합니다.

내부적으로 요청에는 tools 배열이 포함되고 응답에는 tool_calls이 포함되며, 결과는 role: "tool" 메시지로 반환됩니다. tool_choice로 특정 도구를 강제할 수 있으며, 이는 LangChain에서 bind_tools에 인수로 노출됩니다.

4단계: 사전 구축된 LangGraph 에이전트 사용

수동 루프가 이해되면 사전 구축된 에이전트가 줄을 절약합니다. 동일한 모델과 동일한 도구를 사용합니다.

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과 LangGraph는 릴리스 간에 API를 변경하며, 일부 도우미 함수는 이름이 변경되거나 이동되었습니다. 가져오기 오류가 발생하면 현재 LangChain 문서에서 해당 에이전트 생성자를 확인하십시오. Base URL을 사용하는 ChatOpenAI 연결 부분은 동일하게 유지됩니다.

루프와 그래프 간 선택

수동으로 작성된 루프는 몇 가지 도구에서 선택하고 중지하는 에이전트에 충분합니다. 읽기 쉽고 로깅하기 쉬우며 프레임워크 놀라움이 없습니다. 상태에 따라 분기가 필요한 경우 LangGraph로 이동하십시오: 작업을 다시 전달하기 위한 검토 단계, 위험한 도구 실행 전의 인간 승인 또는 결과를 서로 전달하는 여러 전문 하위 에이전트.

무엇을 선택하든 각 노드를 작게 유지하고 하나의 작업을 수행하십시오. JSON 형식의 짧은 번호 목록을 출력하는 계획 노드, 도구를 실행하는 실행 노드 및 최종 텍스트를 생성하는 작성 노드는 하나의 거대한 프롬프트보다 테스트하기 쉽습니다. 또한 다른 온도를 사용할 수 있습니다: 계획 및 도구 사용에는 낮게, 작성 단계에는 높게. 모든 노드가 일반적인 chat completion 호출이므로 동일한 키, URL 및 모델 이름이 모두에 제공되며 비용은 호출의 합계입니다.

마지막 습관: 실행 중인 토큰 총계를 출력하십시오. 데모에서는 저렴해 보이는 에이전트도 지저분한 실제 작업에서 10배 더 많은 토큰을 소모할 수 있으며, 모든 응답의 사용량 수치는 첫 번째 실행에서 이를 바로 보여주므로 잔액에서 뜻밖의 금액으로 드러나기 전에 알 수 있습니다.

메모리, 테스트 및 구조화된 출력

위의 루프는 스크립트가 종료될 때 모든 것을 잊어버립니다. 가장 간단한 메모리는 메시지 목록 자체입니다: 사용자 턴 사이에 목록을 유지하고, 새 질문을 각각 추가하며, 길어지면 가장 오래된 메시지를 잘라내십시오. 긴 세션의 경우, 모델이 작성한 짧은 요약을 사용하여 오래된 메시지를 대체하십시오. 입력은 토큰당 요금이 부과되므로, 500 토큰의 요약본은 비용과 집중도 측면에서 20,000 토큰의 원본 이력보다 우수합니다.

에이전트 테스트는 주로 관찰 가능한 동작을 확인하는 것입니다. 온도를 0으로 설정하거나 API가 전달하는 고정 seed를 전달하여 실행의 재현성을 높입니다. 그런 다음 어떤 도구를 호출해야 하는지 알고 있는 질문 몇 개를 작성하고, 답변의 정확한 표현이 아닌 메시지 목록의 도구 이름과 인수를 확인하세요. 프롬프트나 도구 설명을 변경할 때마다 이를 실행하세요. docstring을 변경하면 모델이 선택하는 도구가 바뀔 수 있으며, 테스트는 이를 알아차리는 가장 저렴한 방법입니다.

모든 실행에 대해 세 가지 항목을 기록하십시오: 단계 수, 도구 호출 및 인수, 토큰 사용량. 실행이 실패할 경우, 이 세 줄은 모델이 잘못 선택했는지, 도구가 실패했는지, 또는 루프가 단계 부족으로 종료되었는지 알려줍니다.

구조화된 출력 및 JSON 모드

에이전트는 종종 텍스트가 아닌 데이터를 반환해야 합니다. API는 response_format: {"type":"json_object"}을 통해 JSON 모드를 지원합니다. LangChain에서는 llm.bind(response_format={"type": "json_object"})로 요청할 수 있습니다. 프롬프트에서 답변이 JSON 객체여야 하며 예상하는 키의 이름을 지정하라고 모델에 지시한 다음, 문자열을 구문 분석하고 Pydantic으로 검증하십시오. 구문 분석 단계가 항상 성공한다고 신뢰하지 마십시오. 오류 텍스트를 모델에 한 번 다시 보내는 재시도로 감싸십시오.

주의할 점 및 해결 방법

  • 잘못된 도구 인수. 오픈 웨이트 모델은 때때로 정수여야 할 곳에 문자열을 전송합니다. 인수를 검증하고, 도구에서 짧은 오류 메시지를 반환한 후, 모델이 다음 단계에서 스스로 수정하도록 하십시오.
  • 무한 루프. 항상 반복 횟수를 제한하십시오. 개발 중에는 각 단계를 로그에 기록하십시오.
  • 병렬 에이전트. 전체 키는 최대 8개의 동시 요청을 허용합니다. 일괄 처리를 실행하는 경우 llm.batch에 config={"max_concurrency": 4}을 설정하여 여유 공간을 확보하십시오. 제한을 초과하면 코드 concurrency로 429가 반환되고, 분당 300개 요청을 초과하면 rate_limited이 반환됩니다.
  • 스트리밍 및 도구. 스트리밍된 요청은 스트림이 끝날 때까지 동시성 슬롯을 유지하므로 체험 키의 스트림 핸들러 내에서 새 호출을 시작하지 마십시오.
  • 증가하는 대화 이력. 각 단계에서 전체 메시지 목록이 다시 전송됩니다. 컨텍스트 창은 100,000 토큰이지만, 각 호출마다 입력 토큰에 대해 요금이 부과됩니다.

에이전트 실행 비용

작업을 완료하기 위해 4번의 모델 호출을 수행하는 적당한 에이전트를 가정해 봅시다. 평균 프롬프트는 3,000 토큰이며, 호출당 출력 토큰은 200개입니다. 입력: 4 x 3,000 = 12,000 토큰, 이는 12,000 x $0.15 / 1,000,000 = $0.0018입니다. 출력: 4 x 200 = 800 토큰, 이는 $0.0004입니다. 한 번의 실행 비용은 $0.0022이므로, 1,000번의 실행 비용은 $2.20입니다. $0.50 무료 체험 크레딧은 약 227번의 실행을 커버합니다. 실패하거나 거부된 요청에는 요금이 부과되지 않으며, 크레딧은 만료되지 않습니다. 가격 정책에서 충전 금액과 보너스를 확인하십시오. 이 사이트는 암호화폐만 받으며, TRC20 네트워크의 USDT 또는 Base 네트워크의 USDC를 사용합니다.

질문과 답변

LangChain에 이 API를 위한 특별한 통합이 필요합니까?

아니요. langchain-openai의 ChatOpenAI 클래스는 base_url을 허용하므로, API를 가리키고 모델 uncensored을 사용하십시오. 커스텀 래퍼가 필요하지 않습니다.

API는 에이전트를 위한 도구 호출을 지원합니까?

예. 도구와 tool_choice를 허용하고, tool_calls를 반환하며(스트리밍 시에도), role tool 메시지를 통해 결과를 다시 받습니다.

에이전트가 429 오류로 종료되는 이유는 무엇입니까?

요청 속도 제한이나 동시 요청 제한에 도달했습니다. 전체 키는 분당 300회, 최대 8개의 동시 요청을 허용합니다. max_concurrency를 낮추거나 Retry-After 기간이 끝날 때까지 기다리세요.

단순 루프 대신 LangGraph를 사용할 수 있나요?

네. LangGraph의 사전 구축된 에이전트는 동일한 ChatOpenAI 객체와 동일한 도구 목록을 사용하므로 연결 코드가 변경되지 않습니다.

키는 양식 하나만 작성하면 받을 수 있습니다

계정을 생성하고 키를 복사한 후 Base URL을 변경하세요. 설정은 이것으로 끝입니다.

API 키 받기