지원 및 미지원 항목
| 항목 | 상태 | 참고 |
|---|---|---|
| 채팅 완료 | 예 | POST /v1/chat/completions |
| 응답 | 예 | POST /v1/responses |
| 스트리밍 (SSE) | 예 | stream: true, 끝에 사용량 정보 포함 |
| 함수 호출 | 예 | tools, tool_choice, 스트리밍된 tool_calls, 결과를 role: "tool" 형식으로 반환 |
| JSON 모드 | 예 | response_format: {"type":"json_object"} |
| 샘플링 제어 | 예 | temperature, top_p, stop, seed, 페널티 |
| 이미지, 오디오, 비디오 | 아니요 | 텍스트 전용 |
| 임베딩, 파인튜닝 | 아니요 | 제공되지 않음 |
이 모델은 ID가 uncensored인 독립 제공업체가 운영하는 오픈 웨이트 텍스트 모델입니다. 합법적인 성인 사용자에게 콘텐츠 거부 없이 응답하며, OpenAI 또는 기타 벤더의 공식 API가 아닙니다. 아래 모든 예제는 베이스 URL https://api.chatgptunfiltered.com/v1를 사용합니다.
이 목록에 없는 항목은 문서에서 달리 명시될 때까지 사용 불가로 간주해야 합니다. 여기에는 아래에 보이는 함수 호출과는 다른 벤더별 호스팅 도구가 포함됩니다.
스트리밍
stream: true를 설정하고 청크를 반복합니다. 텍스트 조각이 도착할 때마다 출력하고 마지막 청크에서 사용량을 확인합니다.
from openai import OpenAI
client = OpenAI(
base_url="https://api.chatgptunfiltered.com/v1",
api_key="YOUR_KEY",
)
stream = client.chat.completions.create(
model="uncensored",
messages=[{"role": "user", "content": "Write a four-line poem about a night train."}],
stream=True,
)
for chunk in stream:
if chunk.choices and chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="", flush=True)
if chunk.usage:
print("\nusage:", chunk.usage)
두 가지 기억할 점입니다. 첫째, 스트리밍 요청은 스트림이 끝날 때까지 동시 요청 슬롯을 점유하므로, 중단된 스트림은 슬롯을 계속 차지합니다. 사용자가 떠날 때 스트림을 닫습니다. 둘째, 마지막 청크에는 사용량 데이터가 포함될 수 있지만 텍스트는 없을 수 있으므로, 위의 예시처럼 choices에 접근할 때 주의합니다.
웹 앱에서는 청크를 도착하는 대로 브라우저로 전달합니다. 예를 들어 자체 SSE 라우트를 통해 전달하고, 페이지가 각 텍스트 조각을 메시지에 추가하도록 합니다. 스트림이 종료된 후 서버에서 사용량 계산을 수행합니다. 마지막 청크에서 요청 비용을 확인할 수 있습니다.
도구 호출, 전체 과정
함수를 선언하고 모델이 해당 함수를 요청하도록 한 후, 직접 실행하여 결과를 role: "tool"로 다시 전송합니다.
import json
tools = [{
"type": "function",
"function": {
"name": "get_order_status",
"description": "Look up the status of an order by its ID.",
"parameters": {
"type": "object",
"properties": {"order_id": {"type": "string"}},
"required": ["order_id"],
},
},
}]
def get_order_status(order_id):
return {"order_id": order_id, "status": "shipped"}
messages = [{"role": "user", "content": "Where is order A-1042?"}]
r = client.chat.completions.create(
model="uncensored", messages=messages, tools=tools, tool_choice="auto"
)
msg = r.choices[0].message
if msg.tool_calls:
messages.append(msg.model_dump(exclude_none=True))
for call in msg.tool_calls:
args = json.loads(call.function.arguments)
result = get_order_status(**args)
messages.append({
"role": "tool",
"tool_call_id": call.id,
"content": json.dumps(result),
})
final = client.chat.completions.create(model="uncensored", messages=messages, tools=tools)
print(final.choices[0].message.content)
else:
print(msg.content)
모델이 함수를 호출할지 여부를 결정합니다. tool_choice를 사용하여 이를 조정할 수 있습니다. 함수 자체는 서버가 아닌 귀하의 코드에서 실행되므로, 함수가 접근할 수 있는 데이터를 귀하가 제어합니다. 모델이 잘못된 형식의 인수를 보내거나 누락된 필드를 보낼 수 있으므로, 실행 전에 인수를 검증합니다.
도구 호출 스트리밍
stream: true를 tools와 함께 사용하면 호출이 여러 조각으로 도착합니다. 함수 이름이 먼저 오고, 인수는 index로 연결해야 하는 조각으로 도착합니다.
calls = {}
stream = client.chat.completions.create(
model="uncensored",
messages=[{"role": "user", "content": "Where is order A-1042?"}],
tools=tools,
stream=True,
)
for chunk in stream:
if not chunk.choices:
continue
for tc in chunk.choices[0].delta.tool_calls or []:
slot = calls.setdefault(tc.index, {"id": "", "name": "", "args": ""})
if tc.id:
slot["id"] = tc.id
if tc.function and tc.function.name:
slot["name"] = tc.function.name
if tc.function and tc.function.arguments:
slot["args"] += tc.function.arguments
for slot in calls.values():
print(slot["name"], json.loads(slot["args"]))
스트리밍이 끝날 때까지 args를 구문 분석하지 마세요. 부분적으로 수신된 문자열은 유효한 JSON이 아닙니다. 이후 함수를 실행하고 비스트리밍 예제와 정확히 동일한 방식으로 결과를 다시 보내세요.
JSON 모드
구조화된 응답의 경우 JSON 모드를 활성화하고 프롬프트에 원하는 형상을 설명하세요.
r = client.chat.completions.create(
model="uncensored",
temperature=0.2,
response_format={"type": "json_object"},
messages=[
{"role": "system", "content": "Reply with JSON only: {\"mood\": string, \"intensity\": integer from 1 to 5}."},
{"role": "user", "content": "Rate this line: The door slammed and nobody spoke for an hour."},
],
)
try:
data = json.loads(r.choices[0].message.content)
except json.JSONDecodeError:
data = None # retry once, or fall back
print(data)
JSON 모드는 유효한 JSON일 가능성을 크게 높이지만 스키마를 강제하지는 않습니다. 키와 형식을 직접 확인하고 재시도 경로를 유지하세요. 추출에는 낮은 temperature가 도움이 됩니다. temperature, top_p, stop, seed 및 페널티와 같은 샘플링 설정이 전달됩니다.
유용한 패턴은 JSON 모드를 명확한 오류 메시지를 반환하는 작은 검증 함수와 결합하는 것입니다. 그런 다음 해당 메시지를 단일 재시도로 모델에 피드백하세요: "마지막 응답에 intensity 키가 누락되었습니다. 유효한 JSON으로 다시 응답하세요." 모델은 보통 두 번째 시도에서 스스로 수정하며, 추가 요청 비용은 1센트의 일부에 불과입니다.
스트리밍 중 오류 처리
스트리밍은 일반 요청이 아닌 방식으로 실패합니다: 텍스트의 절반 이후에 연결이 끊어질 수 있습니다. 이에 대비하세요.
import time
from openai import RateLimitError, APIConnectionError
def stream_reply(messages):
for attempt in range(3):
parts = []
try:
stream = client.chat.completions.create(
model="uncensored", messages=messages, stream=True
)
for chunk in stream:
if chunk.choices and chunk.choices[0].delta.content:
parts.append(chunk.choices[0].delta.content)
return "".join(parts)
except RateLimitError:
time.sleep(5)
except APIConnectionError:
time.sleep(1)
raise RuntimeError("stream failed after retries")
여기서 429는 한도 초과 또는 일시적 과부하를 의미하며, API가 보내는 Retry-After: 5에 맞춰 5초 동안 대기하는 것이 올바른 조치입니다. 스트림이 중간에 끊기면 부분적인 답변을 받게 됩니다. 이를 버리고 재시도할지, 아니면 유지하고 모델에 계속하도록 요청할지 결정합니다. 채팅 UI의 경우 버리고 재시도하는 것이 일반적으로 사용자에게 덜 혼란스럽습니다.
계획할 한도 및 비용
- 속도 제한: 전체 키 기준 분당 300개 요청, 체험 키 기준 분당 60개 요청.
- 동시 요청: 전체 키 기준 8개, 체험 키 기준 2개. 모든 열린 스트림이 포함됨을 기억하세요.
- 크기: 요청 본문 최대 8 MB; 토큰 100,000개의 컨텍스트 창, 프롬프트 및 완성 포함.
- 429 처리: 코드
rate_limited및concurrency은 한도를 초과했음을 의미합니다. 일시적 과부하는Retry-After: 5와 함께 429를 반환합니다.
비용 예시: 두 개의 요청이 포함된 함수 호출 교환. 첫 번째 요청은 입력 1,200 토큰, 출력 80 토큰, 두 번째 요청은 입력 1,400 토큰, 출력 150 토큰입니다. 입력 비용은 2,600 x $0.15 / 1M = $0.00039입니다. 출력 비용은 230 x $0.50 / 1M = $0.000115입니다. 총 비용은 $0.000505입니다. 실패하거나 거부된 요청에는 요금이 부과되지 않습니다. 속도는 가격 책정 페이지를 참조하세요. 전체 메서드 목록은 문서에 있습니다. API 키 페이지에서 $0.50 체험 크레딧으로 시작하세요. 모델 배경 지식은 무검열 ChatGPT 모델 이해하기를 참조하세요. 모든 모드에서 다음 한도가 적용됩니다: 미성년자가 관련된 성적 콘텐츠는 금지됩니다.
출시 전 체크리스트
- 도구 인수는 try 블록에서
json.loads로 구문 분석되며, 실행 전에 예상 키와 형식과 비교됩니다. - 노출된 함수는 익명 사용자에게 허용할 수 있는 작업만 수행할 수 있습니다. 호출 시기는 모델이 결정하며 귀하가 결정하지 않습니다.
- JSON 응답은 검증되며, 실패 시 재시도가 한 번 허용됩니다.
- 스트림은 사용자가 페이지를 떠날 때 닫히므로 동시 요청 슬롯을 점유하지 않습니다.
- 코드 내 동시 요청 한도는 키의 한도보다 작거나 같아야 합니다. 전체 키의 경우 8입니다.
X-Request-Id의 요청 ID가 기록됩니다.- 키는 서버에 저장되며 재생성할 수 있으며, 이전 키는 즉시 작동하지 않게 됩니다.
서비스는 텍스트 전용이므로 이미지나 임베딩이 필요한 기능은 다른 제공업체에서 제공해야 합니다.
