(위 이미지를 클릭하면 이 강의의 영상을 볼 수 있습니다)
도구는 AI 에이전트가 더 넓은 범위의 기능을 수행할 수 있도록 해준다는 점에서 흥미롭습니다. 에이전트가 수행할 수 있는 동작이 제한된 상태에서 도구를 추가하면, 에이전트는 훨씬 더 다양한 동작을 수행할 수 있게 됩니다. 이 장에서는 AI 에이전트가 특정 도구를 사용하여 목표를 달성하는 방법을 설명하는 도구 사용 디자인 패턴에 대해 살펴보겠습니다.
이 강의에서는 다음 질문에 답을 찾고자 합니다:
이 강의를 완료한 후, 여러분은 다음을 할 수 있게 됩니다:
도구 사용 디자인 패턴은 LLM이 외부 도구와 상호작용하여 특정 목표를 달성할 수 있도록 하는 데 중점을 둡니다. 도구는 에이전트가 동작을 수행하기 위해 실행할 수 있는 코드입니다. 도구는 계산기와 같은 간단한 함수일 수도 있고, 주식 가격 조회나 날씨 예보와 같은 서드파티 서비스에 대한 API 호출일 수도 있습니다. AI 에이전트의 맥락에서 도구는 모델이 생성한 함수 호출에 따라 에이전트가 실행하도록 설계됩니다.
AI 에이전트는 도구를 활용하여 복잡한 작업을 완료하거나, 정보를 검색하거나, 결정을 내릴 수 있습니다. 도구 사용 디자인 패턴은 데이터베이스, 웹 서비스, 코드 해석기와 같은 외부 시스템과의 동적 상호작용이 필요한 시나리오에서 자주 사용됩니다. 이 능력은 다음과 같은 다양한 사용 사례에서 유용합니다:
이 구성 요소들은 AI 에이전트가 다양한 작업을 수행할 수 있도록 합니다. 도구 사용 디자인 패턴을 구현하는 데 필요한 주요 요소를 살펴보겠습니다:
다음으로, 함수/도구 호출에 대해 자세히 살펴보겠습니다.
함수 호출은 대형 언어 모델(LLM)이 도구와 상호작용할 수 있도록 하는 주요 방법입니다. ‘함수’와 ‘도구’는 종종 서로 바꿔 사용되는데, 이는 ‘함수’(재사용 가능한 코드 블록)가 에이전트가 작업을 수행하는 데 사용하는 ‘도구’이기 때문입니다. 함수 코드를 호출하려면, LLM은 사용자의 요청을 함수 설명과 비교해야 합니다. 이를 위해 사용 가능한 모든 함수의 설명이 포함된 스키마가 LLM에 전송됩니다. LLM은 작업에 가장 적합한 함수를 선택한 후, 함수 이름과 인수를 반환합니다. 선택된 함수가 호출되고, 그 응답이 LLM에 다시 전송되며, LLM은 이 정보를 사용하여 사용자 요청에 응답합니다.
개발자가 에이전트를 위한 함수 호출을 구현하려면 다음이 필요합니다:
도시의 현재 시간을 가져오는 예제를 사용해 보겠습니다:
함수 호출을 지원하는 LLM 초기화:
모든 모델이 함수 호출을 지원하는 것은 아니므로, 사용하는 LLM이 이를 지원하는지 확인하는 것이 중요합니다. Azure OpenAI는 함수 호출을 지원합니다. Azure OpenAI 클라이언트를 초기화하는 것으로 시작할 수 있습니다.
# Initialize the Azure OpenAI client
client = AzureOpenAI(
azure_endpoint = os.getenv("AZURE_OPENAI_ENDPOINT"),
api_key=os.getenv("AZURE_OPENAI_API_KEY"),
api_version="2024-05-01-preview"
)
함수 스키마 생성:
다음으로, 함수 이름, 함수가 수행하는 작업에 대한 설명, 함수 매개변수의 이름과 설명이 포함된 JSON 스키마를 정의합니다. 그런 다음 이 스키마를 이전에 생성한 클라이언트와 함께 사용자의 요청과 함께 전달합니다. 중요한 점은 도구 호출이 반환된다는 것이며, 질문에 대한 최종 답변이 반환되는 것이 아닙니다. 앞서 언급했듯이, LLM은 작업에 선택된 함수의 이름과 전달될 인수를 반환합니다.
# Function description for the model to read
tools = [
{
"type": "function",
"function": {
"name": "get_current_time",
"description": "Get the current time in a given location",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The city name, e.g. San Francisco",
},
},
"required": ["location"],
},
}
}
]
# Initial user message
messages = [{"role": "user", "content": "What's the current time in San Francisco"}]
# First API call: Ask the model to use the function
response = client.chat.completions.create(
model=deployment_name,
messages=messages,
tools=tools,
tool_choice="auto",
)
# Process the model's response
response_message = response.choices[0].message
messages.append(response_message)
print("Model's response:")
print(response_message)
Model's response:
ChatCompletionMessage(content=None, role='assistant', function_call=None, tool_calls=[ChatCompletionMessageToolCall(id='call_pOsKdUlqvdyttYB67MOj434b', function=Function(arguments='{"location":"San Francisco"}', name='get_current_time'), type='function')])
작업을 수행하는 데 필요한 함수 코드:
이제 LLM이 실행해야 할 함수를 선택했으므로, 작업을 수행하는 코드를 구현하고 실행해야 합니다. Python에서 현재 시간을 가져오는 코드를 구현할 수 있습니다. 또한, response_message에서 함수 이름과 인수를 추출하여 최종 결과를 얻는 코드를 작성해야 합니다.
def get_current_time(location):
"""Get the current time for a given location"""
print(f"get_current_time called with location: {location}")
location_lower = location.lower()
for key, timezone in TIMEZONE_DATA.items():
if key in location_lower:
print(f"Timezone found for {key}")
current_time = datetime.now(ZoneInfo(timezone)).strftime("%I:%M %p")
return json.dumps({
"location": location,
"current_time": current_time
})
print(f"No timezone data found for {location_lower}")
return json.dumps({"location": location, "current_time": "unknown"})
# Handle function calls
if response_message.tool_calls:
for tool_call in response_message.tool_calls:
if tool_call.function.name == "get_current_time":
function_args = json.loads(tool_call.function.arguments)
time_response = get_current_time(
location=function_args.get("location")
)
messages.append({
"tool_call_id": tool_call.id,
"role": "tool",
"name": "get_current_time",
"content": time_response,
})
else:
print("No tool calls were made by the model.")
# Second API call: Get the final response from the model
final_response = client.chat.completions.create(
model=deployment_name,
messages=messages,
)
return final_response.choices[0].message.content
get_current_time called with location: San Francisco
Timezone found for san francisco
The current time in San Francisco is 09:24 AM.
함수 호출은 대부분의 에이전트 도구 사용 설계의 핵심이며, 이를 처음부터 구현하는 것은 때로는 어려울 수 있습니다.
Lesson 2에서 배운 것처럼, 에이전트 프레임워크는 도구 사용을 구현하기 위한 사전 구축된 구성 요소를 제공합니다.
다양한 에이전트 프레임워크를 사용하여 도구 사용 디자인 패턴을 구현하는 방법에 대한 예제를 살펴보겠습니다:
Semantic Kernel은 대형 언어 모델(LLM)을 사용하는 .NET, Python, Java 개발자를 위한 오픈 소스 AI 프레임워크입니다. 이 프레임워크는 함수 호출을 사용하는 과정을 단순화하며, 함수와 매개변수를 모델에 자동으로 설명하는 직렬화 과정을 통해 이를 수행합니다. 또한, 모델과 코드 간의 상호작용을 자동으로 처리합니다. Semantic Kernel과 같은 에이전트 프레임워크를 사용하면 파일 검색 및 코드 해석기와 같은 사전 구축된 도구에 액세스할 수도 있습니다.
다음 다이어그램은 Semantic Kernel에서 함수 호출 과정을 보여줍니다:
Semantic Kernel에서는 함수/도구를 플러그인이라고 부릅니다. 앞서 본 get_current_time
함수를 플러그인으로 변환하려면, 이를 클래스와 함수로 변환하면 됩니다. 또한, 함수 설명을 입력으로 받는 kernel_function
데코레이터를 가져올 수 있습니다. 그런 다음 GetCurrentTimePlugin과 함께 커널을 생성하면, 커널이 함수와 매개변수를 자동으로 직렬화하여 LLM에 보낼 스키마를 생성합니다.
from semantic_kernel.functions import kernel_function
class GetCurrentTimePlugin:
async def __init__(self, location):
self.location = location
@kernel_function(
description="Get the current time for a given location"
)
def get_current_time(location: str = ""):
...
from semantic_kernel import Kernel
# Create the kernel
kernel = Kernel()
# Create the plugin
get_current_time_plugin = GetCurrentTimePlugin(location)
# Add the plugin to the kernel
kernel.add_plugin(get_current_time_plugin)
Azure AI Agent Service는 개발자가 기본 컴퓨팅 및 스토리지 리소스를 관리하지 않고도 고품질의 확장 가능한 AI 에이전트를 안전하게 구축, 배포, 확장할 수 있도록 설계된 최신 에이전트 프레임워크입니다. 이 서비스는 엔터프라이즈 애플리케이션에 특히 유용하며, 완전 관리형 서비스로 엔터프라이즈급 보안을 제공합니다.
LLM API를 직접 사용하는 것과 비교했을 때, Azure AI Agent Service는 다음과 같은 이점을 제공합니다:
Azure AI Agent Service에서 사용할 수 있는 도구는 두 가지 범주로 나뉩니다:
Agent Service를 사용하면 이러한 도구를 toolset
으로 함께 사용할 수 있습니다. 또한, 특정 대화의 메시지 기록을 추적하는 threads
를 활용합니다.
Contoso라는 회사의 영업 담당자라고 가정해 보겠습니다. 영업 데이터를 분석할 수 있는 대화형 에이전트를 개발하고자 합니다.
다음 이미지는 Azure AI Agent Service를 사용하여 영업 데이터를 분석하는 방법을 보여줍니다:
이 서비스에서 도구를 사용하려면 클라이언트를 생성하고 도구 또는 도구 세트를 정의할 수 있습니다. 이를 실제로 구현하려면 다음 Python 코드를 사용할 수 있습니다. LLM은 도구 세트를 살펴보고, 사용자가 생성한 함수 fetch_sales_data_using_sqlite_query
를 사용할지, 사전 구축된 코드 해석기를 사용할지를 사용자 요청에 따라 결정합니다.
import os
from azure.ai.projects import AIProjectClient
from azure.identity import DefaultAzureCredential
from fetch_sales_data_functions import fetch_sales_data_using_sqlite_query # fetch_sales_data_using_sqlite_query function which can be found in a fetch_sales_data_functions.py file.
from azure.ai.projects.models import ToolSet, FunctionTool, CodeInterpreterTool
project_client = AIProjectClient.from_connection_string(
credential=DefaultAzureCredential(),
conn_str=os.environ["PROJECT_CONNECTION_STRING"],
)
# Initialize function calling agent with the fetch_sales_data_using_sqlite_query function and adding it to the toolset
fetch_data_function = FunctionTool(fetch_sales_data_using_sqlite_query)
toolset = ToolSet()
toolset.add(fetch_data_function)
# Initialize Code Interpreter tool and adding it to the toolset.
code_interpreter = code_interpreter = CodeInterpreterTool()
toolset = ToolSet()
toolset.add(code_interpreter)
agent = project_client.agents.create_agent(
model="gpt-4o-mini", name="my-agent", instructions="You are helpful agent",
toolset=toolset
)
LLM이 동적으로 생성한 SQL과 관련된 일반적인 우려 사항은 보안, 특히 SQL 삽입 또는 데이터베이스 삭제나 변조와 같은 악의적인 동작의 위험입니다. 이러한 우려는 타당하지만, 데이터베이스 액세스 권한을 적절히 구성함으로써 효과적으로 완화할 수 있습니다. 대부분의 데이터베이스에서는 데이터베이스를 읽기 전용으로 구성하는 것이 포함됩니다. PostgreSQL이나 Azure SQL과 같은 데이터베이스 서비스의 경우, 앱에 읽기 전용(SELECT) 역할을 할당해야 합니다.
앱을 안전한 환경에서 실행하면 보호 수준이 더욱 향상됩니다. 엔터프라이즈 시나리오에서는 데이터가 일반적으로 운영 시스템에서 읽기 전용 데이터베이스나 데이터 웨어하우스로 추출 및 변환됩니다. 이 데이터베이스는 사용자 친화적인 스키마를 갖추고 있으며, 데이터가 안전하고 성능과 접근성이 최적화되며, 앱이 제한된 읽기 전용 액세스를 갖도록 보장합니다.
Azure AI Foundry Discord에 가입하여 다른 학습자들과 만나고, 오피스 아워에 참석하며 AI Agents 관련 질문에 대한 답변을 받아보세요.
면책 조항:
이 문서는 AI 번역 서비스 Co-op Translator를 사용하여 번역되었습니다. 정확성을 위해 최선을 다하고 있지만, 자동 번역에는 오류나 부정확성이 포함될 수 있습니다. 원본 문서를 해당 언어로 작성된 상태에서 권위 있는 자료로 간주해야 합니다. 중요한 정보의 경우, 전문적인 인간 번역을 권장합니다. 이 번역을 사용함으로써 발생하는 오해나 잘못된 해석에 대해 책임을 지지 않습니다.