먼저 밝힙니다. 저는 APIGOTO 팀에서 일합니다. APIGOTO는 OpenAI 호환 API 게이트웨이이고, OpenAI·Anthropic·Google과는 관계없는 독립 서비스입니다. 아래 방법은 vLLM, Ollama 같은 다른 OpenAI 호환 서버에도 그대로 쓸 수 있습니다.
1. 연결 확인
export APIGOTO_API_KEY=...
curl https://api.china-aiapi.com/v1/models -H "Authorization: Bearer $APIGOTO_API_KEY"
JSON 모델 목록이 나오면 주소와 키는 정상입니다. 여기서 정확한 모델 ID를 복사해 둡니다(아래 MODEL_ID_*).
2. SDK에서 바꿀 곳은 두 줄
import os
from openai import OpenAI
client = OpenAI(base_url="https://api.china-aiapi.com/v1",
api_key=os.environ["APIGOTO_API_KEY"])
코드를 고치기 싫다면 OPENAI_BASE_URL, OPENAI_API_KEY 환경변수만 설정해도 SDK가 읽습니다.
3. 같은 프롬프트로 여러 모델 비교
import os, time
from openai import OpenAI
client = OpenAI(base_url="https://api.china-aiapi.com/v1",
api_key=os.environ["APIGOTO_API_KEY"],
max_retries=0, timeout=60)
MODELS = ["MODEL_ID_A", "MODEL_ID_B", "MODEL_ID_C"] # /models 결과에서 복사
PROMPT = "PyTorch에서 model.eval()과 torch.no_grad()의 차이를 세 문장으로 설명해 주세요."
for m in MODELS:
t0 = time.perf_counter()
try:
r = client.chat.completions.create(
model=m, temperature=0, max_tokens=300,
messages=[{"role": "user", "content": PROMPT}])
except Exception as e:
print(f"[{m}] 실패: {e}")
continue
dt = time.perf_counter() - t0
u = r.usage
print(f"=== {m} | {dt:.2f}s | in={getattr(u,'prompt_tokens','-')} out={getattr(u,'completion_tokens','-')}")
print(r.choices[0].message.content.strip(), "\n")
설계 메모:
- 코드 비교에는
max_retries=0을 씁니다. SDK 재시도가 시간 측정에 섞이지 않게 하려는 것입니다. - 게이트웨이 쪽에서도 업스트림 실패 시 다른 경로로 재시도합니다(최대 3회). 한 모델만 유난히 느리면 요청 로그에서 재시도가 있었는지 먼저 확인하세요.
- 한 번 돌린 결과는 벤치마크가 아닙니다. 여러 번 반복해서 중앙값을 보세요.
temperature=0이어도 매번 같은 출력이 나오지는 않을 수 있습니다.
4. 문제 해결
- 404:
base_url은/v1까지만 씁니다./chat/completions를 붙이면 경로가 중복됩니다. model not found: ID는 대소문자와 접미사까지/models결과와 같아야 합니다.- 401: 키 앞뒤 공백, 또는 다른 서비스의 키를 넣은 경우.
max_tokens관련 오류: 일부 모델은max_completion_tokens를 요구합니다.usage가 비어 있음: 업스트림에 따라 다릅니다. 위 스크립트는 비스트리밍 기준입니다.
제가 쓴 게이트웨이는 base_url 하나로 여러 모델 계열을 부르고, 요청별 로그를 남기며, 종량제와 BYOK를 지원합니다: www.china-aiapi.com
여러 모델을 비교할 때 어떤 프롬프트 세트를 쓰시는지 궁금합니다. 한국어 평가용으로 괜찮은 게 있으면 공유 부탁드립니다.