W&B Sandboxes는 현재 비공개 프리뷰로, 초대를 받은 경우에만 사용할 수 있습니다. 등록을 요청하려면 support 또는 AISE에 문의하세요.
이 튜토리얼에서는 에이전트의 언어 모델로 OpenAI를 사용하며, 이를 위해 OpenAI API 키가 필요합니다.
사전 요구 사항
W&B Python SDK 설치
pip를 사용하면 됩니다:
pip install wandb
W&B에 로그인하고 인증하세요
wandb login CLI 명령을 실행한 다음, 안내에 따라 W&B 계정에 로그인하세요:
wandb login
Secret Manager에 API 키 저장
OPENAI_API_KEY로 W&B Secret Manager에 저장하세요. 샌드박스에서 시크릿을 사용하는 방법에 대한 자세한 내용은 Secrets를 참조하세요.
이렇게 하면 코드나 샌드박스 설정에 API 키를 하드코딩하지 않고도 샌드박스에서 API 키에 안전하게 액세스할 수 있습니다.
에이전트 코드 복사하기
OpenAI 에이전트 코드
OpenAI 에이전트 코드
다음 코드를 이 튜토리얼과 동일한 디렉토리에
demo.py 파일로 복사하여 붙여넣은 다음, 위의 코드 스니펫을 실행하여 샌드박스 환경에서 OpenAI 에이전트를 호출하는 방법을 확인하세요.demo.py
import json
import os
import urllib.request
import urllib.parse
from openai import OpenAI
api_key = os.getenv("OPENAI_API_KEY")
if not api_key:
raise ValueError("OPENAI_API_KEY environment variable not set")
client = OpenAI(api_key=api_key)
SYSTEM_PROMPT = """You are an expert weather forecaster, who speaks in puns.
You have access to two tools:
- get_weather_for_location: use this to get the weather for a specific location
- get_user_location: use this to get the user's location
If a user asks you for the weather, make sure you know the location. If you can tell from the question that they mean wherever they are, use the get_user_location tool to find their location.
"""
TOOLS = [
{
"type": "function",
"function": {
"name": "get_weather_for_location",
"description": "Get weather for a given location name.",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The location to get weather for.",
}
},
"required": ["location"],
},
},
},
{
"type": "function",
"function": {
"name": "get_user_location",
"description": "Retrieve the user's current location from application context.",
"parameters": {
"type": "object",
"properties": {},
"additionalProperties": False,
},
},
},
]
RESPONSE_FORMAT = {
"type": "json_schema",
"json_schema": {
"name": "weather_response",
"strict": True,
"schema": {
"type": "object",
"properties": {
"punny_response": {"type": "string"},
"weather_conditions": {"type": ["string", "null"]},
},
"required": ["punny_response", "weather_conditions"],
"additionalProperties": False,
},
},
}
_WMO_CODES = {
0: "clear sky", 1: "mainly clear", 2: "partly cloudy", 3: "overcast",
45: "foggy", 48: "depositing rime fog",
51: "light drizzle", 53: "moderate drizzle", 55: "dense drizzle",
61: "slight rain", 63: "moderate rain", 65: "heavy rain",
71: "slight snowfall", 73: "moderate snowfall", 75: "heavy snowfall",
80: "slight rain showers", 81: "moderate rain showers", 82: "violent rain showers",
95: "thunderstorm", 96: "thunderstorm with slight hail", 99: "thunderstorm with heavy hail",
}
def get_weather_for_location(location: str) -> str:
geo_url = "https://geocoding-api.open-meteo.com/v1/search?" + urllib.parse.urlencode(
{"name": location, "count": 1}
)
with urllib.request.urlopen(geo_url) as resp:
geo = json.loads(resp.read())
if not geo.get("results"):
return f"Could not find a location named '{location}'."
loc = geo["results"][0]
lat, lon = loc["latitude"], loc["longitude"]
name = loc.get("name", location)
weather_url = "https://api.open-meteo.com/v1/forecast?" + urllib.parse.urlencode({
"latitude": lat,
"longitude": lon,
"current": "temperature_2m,weather_code,wind_speed_10m",
"temperature_unit": "fahrenheit",
"wind_speed_unit": "mph",
})
with urllib.request.urlopen(weather_url) as resp:
weather = json.loads(resp.read())
cur = weather["current"]
condition = _WMO_CODES.get(cur["weather_code"], "unknown conditions")
temp = cur["temperature_2m"]
wind = cur["wind_speed_10m"]
return f"{name}: {condition}, {temp}°F, wind {wind} mph"
def get_user_location(user_id: str) -> str:
return "Miami" if user_id == "1" else "San Francisco"
TOOL_DISPATCH = {
"get_weather_for_location": lambda args, _ctx: get_weather_for_location(args["location"]),
"get_user_location": lambda _args, ctx: get_user_location(ctx["user_id"]),
}
def run_agent(messages: list[dict], context: dict) -> dict:
while True:
response = client.chat.completions.create(
model="gpt-4o",
temperature=0,
messages=messages,
tools=TOOLS,
response_format=RESPONSE_FORMAT,
)
message = response.choices[0].message
if message.tool_calls:
messages.append({
"role": "assistant",
"content": message.content,
"tool_calls": [
{
"id": tc.id,
"type": "function",
"function": {
"name": tc.function.name,
"arguments": tc.function.arguments,
},
}
for tc in message.tool_calls
],
})
for tool_call in message.tool_calls:
fn_name = tool_call.function.name
fn_args = json.loads(tool_call.function.arguments)
tool_fn = TOOL_DISPATCH.get(fn_name)
if tool_fn is None:
raise ValueError(f"Unknown tool: {fn_name}")
result = tool_fn(fn_args, context)
messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"content": result,
})
continue
messages.append({
"role": "assistant",
"content": message.content,
})
return json.loads(message.content)
# --- 에이전트 실행 ---
conversation: list[dict] = [{"role": "system", "content": SYSTEM_PROMPT}]
context = {"user_id": "1"}
# 첫 번째 턴
conversation.append({"role": "user", "content": "what is the weather outside?"})
result = run_agent(conversation, context)
print(result)
# {'punny_response': "Florida is still having a 'sun-derful' day! ...", 'weather_conditions': "It's always sunny in Florida!"}
# 두 번째 턴 (대화 이력 유지)
conversation.append({"role": "user", "content": "thank you!"})
result = run_agent(conversation, context)
print(json.dumps(result, indent=2))