사용법
TypeSafe Python SDK를 사용하는 방법과 패턴을 다룹니다.
System One API 호출하기
import asyncio
from typesafe_sdk import AsyncTypeSafeClient, Choice, Noul, Score
async def main() -> None:
async with AsyncTypeSafeClient() as client:
result = await client.system_one(
"I was charged twice. Please help ASAP.",
{
"billing": Noul(instructions="Is this about billing?"),
"tone": Choice(
instructions="What is the tone?",
criteria={"calm": None, "angry": None},
),
"urgency": Score(
instructions="How urgent is this?",
criteria=["low", "medium", "high"],
),
},
)
print(
result.nouls["billing"].noul,
result.choices["tone"].choice,
result.scores["urgency"].score,
)
asyncio.run(main())from typesafe_sdk import Choice, Noul, Score, TypeSafeClient
client = TypeSafeClient()
state = "I was charged twice. Please help ASAP."
questions = {
"billing": Noul(instructions="Is this about billing?"),
"tone": Choice(
instructions="What is the tone?", criteria={"calm": None, "angry": None}
),
"urgency": Score(
instructions="How urgent is this?", criteria=["low", "medium", "high"]
),
}
result = client.system_one(state, questions)
print(
result.nouls["billing"].noul,
result.choices["tone"].choice,
result.scores["urgency"].score,
)타입이 지정된 system_one 응답
system_one에 응답 모델을 제공하면 응답을 더 타입 안전하게 사용할 수 있습니다:
import asyncio
from typesafe_sdk import AsyncTypeSafeClient, Noul, NoulAnswer, SystemOneResponse
class BillingResponse(SystemOneResponse):
billing: NoulAnswer
async def main() -> None:
async with AsyncTypeSafeClient() as client:
result = await client.system_one(
"I was charged twice.",
{"billing": Noul(instructions="Is this about billing?")},
response_model=BillingResponse,
)
assert 0 <= result.billing.noul <= 1
assert result.billing == result.nouls["billing"]
print(result.request_id)
asyncio.run(main())from typesafe_sdk import Noul, NoulAnswer, SystemOneResponse, TypeSafeClient
class BillingResponse(SystemOneResponse):
billing: NoulAnswer
with TypeSafeClient() as client:
result = client.system_one(
"I was charged twice.",
{"billing": Noul(instructions="Is this about billing?")},
response_model=BillingResponse,
)
assert 0 <= result.billing.noul <= 1
assert result.billing == result.nouls["billing"]
print(result.request_id)사용자 정의 응답 타입
SystemOneResponse를 상속하지 않고 완전히 새로운 응답 모델을 정의할 수도 있습니다:
import asyncio
from pydantic import BaseModel
from typesafe_sdk import AsyncTypeSafeClient, Noul, NoulAnswer
class BillingAnswers(BaseModel):
billing: NoulAnswer
class BillingResponse(BaseModel):
answers: BillingAnswers
async def main() -> None:
async with AsyncTypeSafeClient() as client:
result = await client.system_one(
"I was charged twice.",
{"billing": Noul(instructions="Is this about billing?")},
response_model=BillingResponse,
)
assert 0 <= result.answers.billing.noul <= 1
asyncio.run(main())from pydantic import BaseModel
from typesafe_sdk import Noul, NoulAnswer, TypeSafeClient
class BillingAnswers(BaseModel):
billing: NoulAnswer
class BillingResponse(BaseModel):
answers: BillingAnswers
result = TypeSafeClient().system_one(
"I was charged twice.",
{"billing": Noul(instructions="Is this about billing?")},
response_model=BillingResponse,
)
assert 0 <= result.answers.billing.noul <= 1모델 선택
사용 가능한 모델을 확인합니다:
import asyncio
from typesafe_sdk import AsyncTypeSafeClient
async def main() -> None:
async with AsyncTypeSafeClient() as client:
print(await client.models.list())
asyncio.run(main())from typesafe_sdk import TypeSafeClient
print(TypeSafeClient().models.list())클라이언트를 생성할 때 모델을 선택합니다:
client = AsyncTypeSafeClient(model="jev")client = TypeSafeClient(model="jev")자세한 내용은 Models 리소스 레퍼런스를 참조하십시오.
기본 URL 구성
다른 API url과 함께 SDK를 사용하려면 클라이언트에 base_url을 설정하거나 TYPESAFE_BASE_URL 환경 변수를 설정하십시오. 이 경우 대체 API가 TypeSafe OpenAPI 스펙을 따라야 합니다.
예를 들어 API 키와 모델 ID를 사용하여 AI 게이트웨이를 통해 연결합니다.
OpenRouter API 키와 OpenRouter 모델 ID를 사용합니다:
import asyncio
import os
from typesafe_sdk import AsyncTypeSafeClient, Noul
async def main() -> None:
async with AsyncTypeSafeClient(
api_key=os.environ["OPENROUTER_API_KEY"],
base_url="https://openrouter.ai/api",
model="~typesafe/jev-latest",
) as client:
result = await client.system_one(
"I was charged twice.",
{"billing": Noul(instructions="Is this about billing?")},
)
print(result.nouls["billing"].noul)
asyncio.run(main())import os
from typesafe_sdk import Noul, TypeSafeClient
with TypeSafeClient(
api_key=os.environ["OPENROUTER_API_KEY"],
base_url="https://openrouter.ai/api",
model="~typesafe/jev-latest",
) as client:
result = client.system_one(
"I was charged twice.",
{"billing": Noul(instructions="Is this about billing?")},
)
print(result.nouls["billing"].noul)Vercel의 TypeSafe 호환 API를 SDK와 함께 사용할 수 있습니다:
import asyncio
import os
from typesafe_sdk import AsyncTypeSafeClient, Noul
async def main() -> None:
async with AsyncTypeSafeClient(
api_key=os.environ["AI_GATEWAY_API_KEY"],
base_url="https://ai-gateway.vercel.sh/typesafe",
model="typesafe-ai/jev",
) as client:
result = await client.system_one(
"I was charged twice.",
{"billing": Noul(instructions="Is this about billing?")},
)
print(result.nouls["billing"].noul)
asyncio.run(main())import os
from typesafe_sdk import Noul, TypeSafeClient
with TypeSafeClient(
api_key=os.environ["AI_GATEWAY_API_KEY"],
base_url="https://ai-gateway.vercel.sh/typesafe",
model="typesafe-ai/jev",
) as client:
result = client.system_one(
"I was charged twice.",
{"billing": Noul(instructions="Is this about billing?")},
)
print(result.nouls["billing"].noul)Pydantic AI Gateway API 키를 사용합니다:
import asyncio
import os
from typesafe_sdk import AsyncTypeSafeClient, Noul
async def main() -> None:
async with AsyncTypeSafeClient(
api_key=os.environ["PYDANTIC_AI_GATEWAY_API_KEY"],
base_url="https://gateway-us.pydantic.dev/proxy/typesafe",
model="jev-latest",
) as client:
result = await client.system_one(
"I was charged twice.",
{"billing": Noul(instructions="Is this about billing?")},
)
print(result.nouls["billing"].noul)
asyncio.run(main())import os
from typesafe_sdk import Noul, TypeSafeClient
with TypeSafeClient(
api_key=os.environ["PYDANTIC_AI_GATEWAY_API_KEY"],
base_url="https://gateway-us.pydantic.dev/proxy/typesafe",
model="jev-latest",
) as client:
result = client.system_one(
"I was charged twice.",
{"billing": Noul(instructions="Is this about billing?")},
)
print(result.nouls["billing"].noul)HTTP/2
import httpx2
from typesafe_sdk import AsyncTypeSafeClient
client = AsyncTypeSafeClient(http_client=httpx2.AsyncClient(http2=True))import httpx2
from typesafe_sdk import TypeSafeClient
client = TypeSafeClient(http_client=httpx2.Client(http2=True))재시도
RetryPolicy를 클라이언트나 호출별로 retry에 전달하여 사용자 정의할 수 있습니다. 유효하지 않은 API 키는 요청이나 재시도 전에, 클라이언트 생성 중에 TypeSafeError를 발생시킵니다.
클라이언트에서:
from typesafe_sdk import AsyncTypeSafeClient, RetryPolicy
client = AsyncTypeSafeClient(
retry=RetryPolicy(max_retries=3, backoff_max=0.2, timeout=1.0)
)from typesafe_sdk import RetryPolicy, TypeSafeClient
client = TypeSafeClient(retry=RetryPolicy(max_retries=3, backoff_max=0.2, timeout=1.0))호출별로:
import asyncio
from typesafe_sdk import AsyncTypeSafeClient, RetryPolicy
async def main() -> None:
async with AsyncTypeSafeClient() as client:
await client.system_one(
state,
questions,
retry=RetryPolicy(max_retries=3, backoff_max=0.2, timeout=1.0),
)
asyncio.run(main())from typesafe_sdk import RetryPolicy
client.system_one(
state, questions, retry=RetryPolicy(max_retries=3, backoff_max=0.2, timeout=1.0)
)오류 처리
SDK가 발생시키는 예외를 처리합니다:
import asyncio
from typesafe_sdk import AsyncTypeSafeClient, TypeSafeAPIError
async def main() -> None:
async with AsyncTypeSafeClient() as client:
try:
await client.system_one(state, questions)
except TypeSafeAPIError as error:
print(error.status, error.request_id)
asyncio.run(main())from typesafe_sdk import TypeSafeAPIError
try:
client.system_one(state, questions)
except TypeSafeAPIError as error:
print(error.status, error.request_id)로깅
SDK는 typesafe_sdk 로거에 기록합니다. 표준 로깅 가이드에 따라 구성하십시오:
import logging
logging.getLogger("typesafe_sdk").setLevel(logging.DEBUG)
또는 SDK를 가져오기 전에 TYPESAFE_LOG_LEVEL을 debug, info, warning, error, off 중 하나로 설정하십시오.
info는 요청마다 요약 한 줄을 기록하고, debug는 요청과 응답의 헤더와 본문도 기록합니다. 비밀 헤더 — authorization, API 키, 쿠키, 그리고 이름에 token이나 secret이 들어간 모든 헤더 — 는 로그 출력에서 가려집니다. 요청과 응답 본문은 가려지지 않습니다.
환경 변수
SDK는 다음 환경 변수를 읽어 사용합니다:
| 변수 | 설정 대상 | 기본값 |
|---|---|---|
TYPESAFE_API_KEY |
API 키(필수) | — |
TYPESAFE_BASE_URL |
API 루트 URL | https://api.typesafe.ai |
TYPESAFE_DEFAULT_MODEL |
기본 모델 | jev-latest |
TYPESAFE_LOG_LEVEL |
typesafe_sdk 로거 수준, 가져올 때 한 번 적용 |
설정 안 됨 |
SDK 기본값은 상수 레퍼런스를 참조하십시오.
api_key나 TYPESAFE_API_KEY로 전달된 API 키는 키 파일의 줄바꿈을 포함하여 앞뒤 공백이 제거됩니다. 빈 키, 내부 공백, 제어 문자, 비ASCII 문자는 요청을 보내기 전에 거부됩니다. 명시적으로 빈 키는 환경으로 폴백하지 않습니다.
전방 호환성
SDK는 TypeSafe API가 발전해도 계속 동작하므로, SDK 릴리스가 정식 지원을 추가하기 전에 새로운 API 기능을 먼저 도입할 수 있습니다.
추가 요청 필드
extra_body로 추가 API 요청 필드를 보냅니다. 아래의 beam_width 필드는 예시일 뿐이며, API가 지원하는 필드만 보내십시오.
import asyncio
from typesafe_sdk import AsyncTypeSafeClient, Noul
async def main() -> None:
async with AsyncTypeSafeClient() as client:
await client.system_one(
"I was charged twice.",
{"billing": Noul(instructions="About billing?")},
extra_body={"beam_width": 4},
)
asyncio.run(main())from typesafe_sdk import Noul, TypeSafeClient
with TypeSafeClient() as client:
client.system_one(
"I was charged twice.",
{"billing": Noul(instructions="About billing?")},
extra_body={"beam_width": 4},
)원시 질문 딕셔너리
import asyncio
from typesafe_sdk import AsyncTypeSafeClient
async def main() -> None:
async with AsyncTypeSafeClient() as client:
await client.system_one(
"I was charged twice.",
{
"billing": {
"type": "noul",
"instructions": "About billing?",
"weight": 2,
}
},
)
asyncio.run(main())from typesafe_sdk import TypeSafeClient
with TypeSafeClient() as client:
client.system_one(
"I was charged twice.",
{"billing": {"type": "noul", "instructions": "About billing?", "weight": 2}},
)알 수 없는 답변 종류
SDK는 인식하지 못한 답변 종류를 경고로 기록하고 건너뜁니다. raw_http_response를 사용하면 그런 답변을 포함한 전체 API 응답을 검사할 수 있습니다:
import asyncio
from typesafe_sdk import AsyncTypeSafeClient, Noul
async def main() -> None:
async with AsyncTypeSafeClient() as client:
result = await client.system_one(
"I was charged twice.",
{"billing": Noul(instructions="Is this about billing?")},
)
print(result.raw_http_response.json()["answers"])
asyncio.run(main())from typesafe_sdk import Noul, TypeSafeClient
result = TypeSafeClient().system_one(
"I was charged twice.",
{"billing": Noul(instructions="Is this about billing?")},
)
raw_answers = result.raw_http_response.json()["answers"]알 수 없는 응답 필드
인식된 응답에 있는 알 수 없는 추가 필드는 무시됩니다.