KO ▾
API 키 받기

LangChain + LLM: 무검열 API 연결

LangChain은 ChatOpenAI 클래스를 통해 모든 OpenAI 호환 엔드포인트와 통신합니다. base URL, 키 및 모델 ID를 설정하면 체인과 에이전트가 이 API에서 실행됩니다.

업데이트됨

중앙의 빛나는 허브에 연결된 체인으로 구성된 블록, 하나의 API를 호출하는 LangChain 파이프라인을 나타냄

주요 포인트

  1. base_url을 API로 설정하고 model을 uncensored로 설정하여 ChatOpenAI를 사용하세요.
  2. 체인, 스트리밍, 도구 호출 및 JSON 출력은 모두 표준 채팅 완료 경로를 통해 처리됩니다.
  3. 429 오류를 피하려면 전체 키에서는 배치 동시성을 8로, 체험 키에서는 2로 제한하세요.
  4. 이것은 라우터가 아닌 단일 호스팅 모델이므로 벤더별 모델 전환은 불가능합니다.

간단한 설정

보통 langchain + llm 질문은 타사 엔드포인트에 특별한 통합이 필요한지 여부입니다. 필요 없습니다. LangChain의 OpenAI 채팅 래퍼는 사용자 지정 base URL을 허용하며, 이 API는 OpenAI 채팅 완료 형식을 따르므로 표준 클래스가 작동합니다. 패키지를 설치하고 세 가지 값을 전달하면 어떤 체인에도 바로 넣을 수 있는 채팅 모델 객체를 얻습니다.

pip install -U langchain-openai langchain-core
from langchain_openai import ChatOpenAI

llm = ChatOpenAI(
    model="uncensored",
    base_url="https://api.nsfwllmrouter.com/v1",
    api_key="YOUR_API_KEY",
    temperature=0.7,
)

print(llm.invoke("Give me one sentence about LangChain.").content)

API 키 페이지에서 키를 가져오세요. 신규 사용자는 가입 후 한 번의 클릭으로 $0.50의 무료 체험 크레딧을 받을 수 있으며, 이는 이 기사의 모든 내용을 여러 번 실행하기에 충분합니다. 모델 ID는 항상 uncensored이며, 요청은 POST /v1/chat/completions로 전송됩니다.

사이트 이름에 대한 참고: 도메인에 "router"라는 단어가 포함되어 있지만, 이는 벤더 간 라우터가 아닌 독립적인 공급자가 운영하는 단일 오픈 웨이트 모델이며, 어느 벤더의 공식 API도 아닙니다. 여기서는 모델 간 선택이 없습니다. 코드에서 하나의 모델을 지정하면 해당 모델이 응답합니다.

키를 소스에서 분리하세요

키를 하드 코딩하면 첫 테스트에는 작동하지만 파일을 커밋하는 순간 문제가 됩니다. 대신 환경 변수에서 읽으세요. LangChain이 감싸는 OpenAI 클라이언트 라이브러리는 기본적으로 OPENAI_API_KEY 및 OPENAI_BASE_URL을 찾으므로 셸에서 설정하면 모델 생성 시 인수를 더 적게 전달할 수 있습니다.

export OPENAI_API_KEY="YOUR_API_KEY"
export OPENAI_BASE_URL="https://api.nsfwllmrouter.com/v1"
import os
from langchain_openai import ChatOpenAI

llm = ChatOpenAI(
    model="uncensored",
    base_url=os.environ.get("OPENAI_BASE_URL", "https://api.nsfwllmrouter.com/v1"),
    api_key=os.environ["OPENAI_API_KEY"],
)

위와 같이 base URL을 명시적으로 전달하는 것에는 한 가지 이점이 있습니다. 같은 머신에서 다른 프로젝트가 실제 OpenAI 서비스를 사용하고 동일한 환경 변수에 의존하는 경우, 명시적 인수가 두 가지가 충돌하는 것을 방지합니다.

프롬프트 템플릿이 있는 첫 번째 체인

대부분의 실제 작업은 프롬프트 템플릿, 모델 및 파이프 연산자로 연결된 출력 파서를 사용합니다. 이는 LangChain 표현 언어 스타일이며 사용자 정의 엔드포인트에 특별한 것이 필요하지 않습니다.

from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_openai import ChatOpenAI

llm = ChatOpenAI(
    model="uncensored",
    base_url="https://api.nsfwllmrouter.com/v1",
    api_key="YOUR_API_KEY",
)

prompt = ChatPromptTemplate.from_messages([
    ("system", "You write short story openings in the style the user asks for."),
    ("human", "Genre: {genre}\nSetting: {setting}\nWrite three sentences."),
])

chain = prompt | llm | StrOutputParser()
print(chain.invoke({"genre": "noir mystery", "setting": "a rainy harbor town"}))

이 모델은 합법적인 성인 사용에 대해 콘텐츠 거부가 없으며, 이는 체인이 더 신중한 모델이 거부할 수 있는 소설, 역할극 장면 또는 컴패니언 대화를 생성할 때 중요합니다. 유일한 고정 규칙은 미성년자가 관련된 성 콘텐츠는 절대 생성되지 않는다는 것입니다. 제품에 더 엄격한 규칙이 있는 경우 이를 기반으로 자체 입력 검증을 구축하세요.

스트리밍 및 사용량

API는 stream: true를 사용한 서버 전송 이벤트를 통한 스트리밍을 지원하며, 사용량은 스트림 끝에 보고됩니다. LangChain에서는 .stream()을 호출하고 청크를 반복합니다.

from langchain_openai import ChatOpenAI

llm = ChatOpenAI(
    model="uncensored",
    base_url="https://api.nsfwllmrouter.com/v1",
    api_key="YOUR_API_KEY",
)

for chunk in llm.stream("Write a four-line poem about debugging at night."):
    print(chunk.content, end="", flush=True)

주의할 점 하나: 스트리밍 요청은 스트림이 끝날 때까지 동시성 슬롯 중 하나를 차지합니다. UI가 스트림을 열지만 사용자가 닫지 않고 떠난 경우 해당 슬롯은 계속 사용 중입니다. 전체 키에서는 8개의 동시 요청이 가능하므로, 몇몇 방치된 스트림이 새로운 요청을 차단할 수 있습니다. 클라이언트가 연결을 끊을 때 반복자를 취소하세요.

함수 호출 및 에이전트

도구 호출이 지원됩니다: tools를 전달하고 선택적으로 tool_choice을 설정하면, 모델은 tool_calls로 응답합니다(스트리밍 가능). 이후 role: "tool" 메시지로 결과를 다시 전송합니다. LangChain에서는 bind_tools가 와이어 형식을 처리합니다.

from langchain_core.tools import tool
from langchain_openai import ChatOpenAI

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

llm = ChatOpenAI(
    model="uncensored",
    base_url="https://api.nsfwllmrouter.com/v1",
    api_key="YOUR_API_KEY",
)
llm_with_tools = llm.bind_tools([word_count])

msg = llm_with_tools.invoke("How many words are in: the quick brown fox?")
for call in msg.tool_calls:
    print(call["name"], call["args"], word_count.invoke(call["args"]))

전체 에이전트 루프의 경우 LangChain의 에이전트 도우미 또는 LangGraph가 이 주기를 자동으로 실행합니다: 모델 호출, 요청된 도구 실행, 도구 메시지 추가, 다시 호출. 도구 사용은 표준 OpenAI 형식을 따르므로 호환되는 엔드포인트에 대해 작성하는 코드와 동일하게 작동합니다. 모든 오픈 웨이트 모델과 마찬가지로 특정 도구 스키마를 테스트하세요. 인수는 간단하게, 설명은 짧게, 도구 목록은 작게 유지하세요. 긴 목록은 약한 모델이 잘못된 도구를 선택할 여지를 줍니다.

JSON 모드를 사용한 구조화된 출력

JSON 모드는 response_format: {"type": "json_object"}을 통해 제공됩니다. LangChain에서는 모델 인수로 전달하고 결과를 직접 구문 분석하여 검증 및 재시도에 대한 제어권을 가질 수 있습니다.

import json
from langchain_openai import ChatOpenAI

llm = ChatOpenAI(
    model="uncensored",
    base_url="https://api.nsfwllmrouter.com/v1",
    api_key="YOUR_API_KEY",
    model_kwargs={"response_format": {"type": "json_object"}},
)

msg = llm.invoke(
    "Return a JSON object with keys title and tags (a list of three strings) "
    "for an article about hiking."
)
data = json.loads(msg.content)
print(data["title"], data["tags"])

프롬프트에 "JSON"이라는 단어를 사용하고 원하는 키를 설명하세요. JSON 모드는 출력을 유효한 JSON으로 만듭니다. 하지만 정확한 스키마를 보장하지는 않으므로 구문 분석 후 키를 확인하고 실패 시 재시도하세요. 실패한 요청에는 요금이 부과되지 않으므로 잘못된 출력에 대한 재시도 루프는 비용이 거의 들지 않습니다.

동시성, 재시도 및 속도 제한

LangChain은 .batch()로 작업을 병렬로 분산하기 쉽게 만들어주며, 대부분의 사용자가 여기서 첫 번째 속도 제한에 부딪힙니다. 전체 키는 8개의 동시 요청과 분당 300개 요청을 허용합니다. 체험 키는 2개의 동시 요청과 분당 60개 요청을 허용합니다. 초과하면 API는 HTTP 429를 반환합니다. 분당 요청 수를 초과하면 오류 코드는 rate_limited이고, 동시 요청이 너무 많으면 concurrency입니다. 일시적 과부하 시에도 Retry-After: 5 헤더와 함께 429가 반환됩니다.

배치 동시성을 직접 설정하고 클라이언트가 백오프로 재시도하도록 하세요:

from langchain_openai import ChatOpenAI

llm = ChatOpenAI(
    model="uncensored",
    base_url="https://api.nsfwllmrouter.com/v1",
    api_key="YOUR_API_KEY",
    max_retries=4,
    timeout=120,
)

inputs = [f"Summarize idea number {i} in one line." for i in range(40)]
results = llm.batch(inputs, config={"max_concurrency": 6})
print(len(results))

전체 키에서 6으로 유지하면 같은 계정의 다른 요청을 위한 여유 공간이 생깁니다. 체험 키에서는 2를 사용하세요. 여전히 concurrency 오류가 발생하면 완료되지 않은 스트림을 찾아보세요. 각 스트림은 슬롯을 차지합니다. 각 응답에는 X-Request-Id이 포함되어 있으며, 이는 지원팀에 문의할 때 인용해야 할 값입니다. 또한 X-Balance-USD은 남은 크레딧을 보여줍니다.

웹 앱을 위한 비동기 호출

웹 서버 내부에서는 일반적으로 블로킹 호출을 원하지 않습니다. 모든 LangChain 채팅 모델에는 ainvoke, astream, abatch와 같은 비동기 메서드가 있으며, 이 엔드포인트에서는 동기식 버전과 동일하게 작동합니다.

import asyncio
from langchain_openai import ChatOpenAI

llm = ChatOpenAI(
    model="uncensored",
    base_url="https://api.nsfwllmrouter.com/v1",
    api_key="YOUR_API_KEY",
)

async def main():
    async for chunk in llm.astream("Describe a quiet harbor at dawn in two sentences."):
        print(chunk.content, end="", flush=True)

asyncio.run(main())

비동기 서비스에서는 세마포어를 사용하여 키에 맞는 크기로 실행 중인 호출 수를 관리하세요. 예를 들어 전체 키의 경우 8로 설정합니다. 이렇게 하면 앱의 한 엔드포인트가 모든 슬롯을 채워 다른 요청이 굶주리는 것을 방지할 수 있습니다. 호출 주변에서 예외를 캐치하고, X-Request-Id 헤더가 있으면 로그를 남기며, 스택 트레이스 대신 짧은 재시도 메시지를 사용자에게 표시하세요.

디버깅 팁: 체인이 이상하게 동작하는 경우 모델이 받는 정확한 메시지를 출력하세요. 프롬프트 템플릿은 때로 불필요한 공백을 삽입하거나 변수를 누락시킬 수 있으며, 모델은 전달된 내용에만 응답할 수 있습니다. LangChain의 verbose 및 debug 스위치 또는 이미 사용하는 경우 LangSmith 추적을 사용하면 최종 메시지 목록을 확인할 수 있습니다.

컨텍스트 창이 체인에 미치는 영향

프롬프트와 출력을 합쳐 컨텍스트 창은 100,000 토큰이며, max_tokens은 선택 사항입니다. 이는 여러 문서를 하나의 프롬프트에 넣는 검색 체인이나 긴 대화 내역을 유지하는 대화 메모리에 충분히 큰 크기입니다. 또한 매 턴마다 잘라내지 않고 전체 내역을 다시 보내면 비용이 많이 들 수 있을 정도로 큽니다.

간단한 계산입니다. 12,000 입력 토큰을 보내고 800을 받는 검색 단계는 0.012 x $0.15 + 0.0008 x $0.50 = $0.0018 + $0.0004 = $0.0022가 듭니다. 이를 1,000번 실행하면 $2.20이 발생합니다. 가격은 입력 토큰 100만 개당 $0.15, 출력 토큰 100만 개당 $0.50이며 구독료가 없으므로 체인이 실제로 사용하는 것만 지불하면 됩니다. 가격 책정 페이지에는 충전 옵션이, 빠른 시작 문서에는 지원되는 모든 매개변수 목록이 있습니다. 프롬프트는 학습에 사용되지 않습니다.

질문과 답변

이 엔드포인트에 특별한 LangChain 패키지가 필요한가요?

아니요. langchain-openai 패키지만 있으면 됩니다. base URL, 키 및 모델 ID uncensored를 ChatOpenAI에 전달하세요.

LangGraph 및 에이전트와 호환되나요?

네, 표준 OpenAI 채팅 및 도구 호출 형식을 사용하는 한 가능합니다. 도구 호출, 스트리밍된 tool_calls 및 역할: 도구 결과가 지원됩니다.

체인 내에서 모델을 전환할 수 있나요?

아니요. uncensored라는 하나의 모델만 있으며, 이 서비스는 벤더 간 라우터가 아닙니다. 다른 단계에 다른 공급자가 필요한 경우 별도의 LangChain 모델 객체를 사용하세요.

429 오류는 어떻게 처리해야 합니까?

배치 동시성을 낮추고, Retry-After 헤더가 있을 경우 이를 준수하며, 완료된 스트림을 닫으세요. 전체 키는 분당 300개 요청과 8개의 동시 요청을 허용합니다.

벡터 저장소에 임베딩이 제공되나요?

아니요. API는 텍스트 전용이며 임베딩 엔드포인트가 없으므로 검색을 위해 별도의 임베딩 소스가 필요합니다.

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

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

API 키 받기