주석 기반 도구

·3분 읽기

원문: Koog Documentation — annotation-based-tools 이 글은 Koog 공식 문서의 annotation-based-tools 페이지를 한국어로 옮긴 번역본입니다. 문서 구조와 링크 의미를 유지하되, MkDocs 전용 UI 문법은 블로그에서 읽기 좋도록 정리했습니다.

주석 기반 도구

주석 기반 도구는 Kotlin과 Java 모두에서 LLM(대형 언어 모델)용 도구로 함수와 메서드를 노출하는 선언적 방법을 제공합니다. 주석을 사용하면 모든 기능이나 방법을 LLM이 이해하고 사용할 수 있는 도구로 변환할 수 있습니다.

이 접근 방식은 도구 설명을 수동으로 구현하지 않고 Kotlin 또는 Java의 LLM에 기존 기능을 노출해야 할 때 유용합니다.

참고 주석 기반 도구는 JVM 전용이며 다른 플랫폼에서는 사용할 수 없습니다. 다중 플랫폼 지원을 위해서는 class-based tool API을 사용하세요.

주요 주석

프로젝트에서 주석 기반 도구를 사용하려면 다음 주요 주석을 이해해야 합니다.

주석 설명
@Tool LLM에 도구로 공개되어야 하는 기능을 표시합니다.
@LLMDescription 도구와 해당 구성 요소에 대한 설명 정보를 제공합니다.

@Tool 주석

@Tool 주석은 LLM에 도구로 노출되어야 하는 함수(Kotlin) 또는 메서드(Java)를 표시하는 데 사용됩니다. @Tool 주석이 달린 함수와 메소드는 ToolSet 인터페이스를 구현하는 객체로부터 리플렉션을 통해 수집됩니다. 자세한 내용은 Implement the ToolSet interface을 참조하세요.

정의

1@Target(AnnotationTarget.FUNCTION)2public annotation class Tool(val customName: String = "")

매개변수

이름 필수의 설명
customName 아니요 도구의 사용자 정의 이름을 지정합니다. 제공되지 않으면 함수 이름이 사용됩니다.

용법

함수나 메서드를 도구로 표시하려면 ToolSet 인터페이스를 구현하는 클래스의 이 함수나 메서드에 @Tool 주석을 적용하세요.

코틀린

1class MyToolSet : ToolSet {2    @Tool3    fun myTool(): String {4        // Tool implementation5        return "Result"6    }78    @Tool(customName = "customToolName")9    fun anotherTool(): String {10        // Tool implementation11        return "Result"12    }13}

자바

1public class MyToolSet implements ToolSet {2    @Tool3    public String myTool() {4        // Tool implementation5        return "Result";6    }78    @Tool(customName = "customToolName")9    public String anotherTool() {10        // Tool implementation11        return "Result";12    }13}

@LLMDescription 주석

@LLMDescription 주석은 코드 요소(클래스, 함수, 메서드, 매개변수 등)에 대한 설명 정보를 LLM에 제공합니다. 이는 LLM이 이러한 요소의 목적과 사용법을 이해하는 데 도움이 됩니다.

정의

1@Target(2    AnnotationTarget.PROPERTY,3    AnnotationTarget.CLASS,4    AnnotationTarget.TYPE,5    AnnotationTarget.VALUE_PARAMETER,6    AnnotationTarget.FUNCTION7)8public annotation class LLMDescription(val description: String)

매개변수

이름 필수의 설명
description 주석이 달린 요소를 설명하는 문자열입니다.

용법

@LLMDescription 주석은 다양한 수준에서 적용될 수 있습니다. 예를 들어:

  • 기능 수준:

코틀린

1@Tool2@LLMDescription("Performs a specific operation and returns the result")3fun myTool(): String {4    // Function implementation5    return "Result"6}

자바

1@Tool2@LLMDescription(description = "Performs a specific operation and returns the result")3public String myTool() {4    // Function implementation5    return "Result";6}
  • 매개변수 수준:

코틀린

1@Tool2@LLMDescription("Processes input data")3fun processTool(4    @LLMDescription("The input data to process")5    input: String,67    @LLMDescription("Optional configuration parameters")8    config: String = ""9): String {10    // Function implementation11    return "Processed: $input with config: $config"12}

자바

1@Tool2@LLMDescription(description = "Processes input data")3public String processTool(4        @LLMDescription(description = "The input data to process") String input,5        @LLMDescription(description = "Optional configuration parameters") String config6) {7    // Function implementation8    return "Processed: " + input + " with config: " + config;9}

도구 만들기

1. ToolSet 인터페이스 구현

ToolSet 인터페이스를 구현하는 클래스를 만듭니다. 이 인터페이스는 클래스를 도구의 컨테이너로 표시합니다.

코틀린

1class MyFirstToolSet : ToolSet {2    // Tools will go here3}

자바

1public class MyFirstToolSet implements ToolSet {2    // Tools will go here3}

2. 도구 기능 추가

클래스에 함수나 메서드를 추가하고 @Tool 주석을 달아 도구로 노출합니다.

코틀린

1class MyFirstToolSet : ToolSet {2    @Tool3    fun getWeather(location: String): String {4        // In a real implementation, you would call a weather API5        return "The weather in $location is sunny and 72°F"6    }7}

자바

1public class MyFirstToolSet implements ToolSet {2    @Tool3    public String getWeather(String location) {4        // In a real implementation, you would call a weather API5        return "The weather in " + location + " is sunny and 72°F";6    }7}

3. 설명 추가

@LLMDescription 주석을 추가하여 LLM에 대한 컨텍스트를 제공합니다.

코틀린

1@LLMDescription("Tools for getting weather information")2class MyFirstToolSet : ToolSet {3    @Tool4    @LLMDescription("Get the current weather for a location")5    fun getWeather(6        @LLMDescription("The city and state/country")7        location: String8    ): String {9        // In a real implementation, you would call a weather API10        return "The weather in $location is sunny and 72°F"11    }12}

자바

1@LLMDescription(description = "Tools for getting weather information")2public class MyFirstToolSet implements ToolSet {3    @Tool4    @LLMDescription(description = "Get the current weather for a location")5    public String getWeather(6            @LLMDescription(description = "The city and state/country") String location7    ) {8        // In a real implementation, you would call a weather API9        return "The weather in " + location + " is sunny and 72°F";10    }11}

4. 에이전트와 함께 도구를 사용하세요

이제 에이전트와 함께 도구를 사용할 수 있습니다.

코틀린

1fun main() {2    runBlocking {3        // Create your tool set4        val weatherTools = MyFirstToolSet()56        // Create an agent with your tools78        val agent = AIAgent(9            promptExecutor = simpleOpenAIExecutor(apiToken),10            systemPrompt = "Provide weather information for a given location.",11            llmModel = OpenAIModels.Chat.GPT4o,12            toolRegistry = ToolRegistry {13                tools(weatherTools)14            }15        )1617        // The agent can now use your weather tools18        agent.run("What's the weather like in New York?")19    }20}

자바

1String apiToken = System.getenv("OPENAI_API_KEY");23// Create your tool set4 MyFirstToolSet weatherTools = new MyFirstToolSet();56ToolRegistry toolRegistry = ToolRegistry.builder()7    .tools(weatherTools)8    .build();910// Create an agent with your tools11AIAgent<String, String> agent = AIAgent.builder()12    .promptExecutor(simpleOpenAIExecutor(System.getenv("OPENAI_API_KEY")))13    .systemPrompt("Provide weather information for a given location.")14    .llmModel(OpenAIModels.Chat.GPT4o)15    .toolRegistry(toolRegistry)16    .build();1718// The agent can now use your weather tools19String result = agent.run("What's the weather like in New York?");20System.out.println(result);

사용 예

다음은 도구 주석의 실제 예입니다.

기본 예: 스위치 컨트롤러

이 예에서는 스위치를 제어하기 위한 간단한 도구 세트를 보여줍니다.

코틀린

1@LLMDescription("Tools for controlling a switch")2class SwitchTools(val switch: Switch) : ToolSet {3    @Tool4    @LLMDescription("Switches the state of the switch")5    fun switch(6        @LLMDescription("The state to set (true for on, false for off)")7        state: Boolean8    ): String {9        switch.switch(state)10        return "Switched to ${if (state) "on" else "off"}"11    }1213    @Tool14    @LLMDescription("Returns the current state of the switch")15    fun switchState(): String {16        return "Switch is ${if (switch.isOn()) "on" else "off"}"17    }18}

자바

1public class Switch {2    private boolean state;34    public Switch(boolean state) {5        this.state = state;6    }78    // "switch" is a reserved keyword in Java, so we use a different method name9    public void setState(boolean state) {10        this.state = state;11    }1213    public boolean isOn() {14        return state;15    }16}1718@LLMDescription(description = "Tools for controlling a switch")19public class SwitchTools implements ToolSet {20    private final Switch sw;2122    public SwitchTools(Switch sw) {23        this.sw = sw;24    }2526    @Tool27    @LLMDescription(description = "Switches the state of the switch")28    public String switchStateTo(29            @LLMDescription(description = "The state to set (true for on, false for off)") boolean state30    ) {31        sw.setState(state);32        return "Switched to " + (state ? "on" : "off");33    }3435    @Tool36    @LLMDescription(description = "Returns the current state of the switch")37    public String switchState() {38        return "Switch is " + (sw.isOn() ? "on" : "off");39    }40}

LLM이 스위치를 제어해야 하는 경우 제공된 설명에서 다음 정보를 이해할 수 있습니다.

  • 도구의 목적과 기능.
  • 도구 사용에 필요한 매개변수입니다.
  • 각 매개변수에 허용되는 값입니다.
  • 실행 시 예상되는 반환 값입니다.

고급 예: 진단 도구

이 예에서는 장치 진단을 위한 보다 복잡한 도구 세트를 보여줍니다.

코틀린

1@LLMDescription("Tools for performing diagnostics and troubleshooting on devices")2class DiagnosticToolSet : ToolSet {3    @Tool4    @LLMDescription("Run diagnostic on a device to check its status and identify any issues")5    fun runDiagnostic(6        @LLMDescription("The ID of the device to diagnose")7        deviceId: String,89        @LLMDescription("Additional information for the diagnostic (optional)")10        additionalInfo: String = ""11    ): String {12        // Implementation13        return "Diagnostic results for device $deviceId"14    }1516    @Tool17    @LLMDescription("Analyze an error code to determine its meaning and possible solutions")18    fun analyzeError(19        @LLMDescription("The error code to analyze (e.g., 'E1001')")20        errorCode: String21    ): String {22        // Implementation23        return "Analysis of error code $errorCode"24    }25}

자바

1@LLMDescription(description = "Tools for performing diagnostics and troubleshooting on devices")2public class DiagnosticToolSet implements ToolSet {3    // Convenience overload (not exposed as a tool)4    public String runDiagnostic(String deviceId) {5        return runDiagnostic(deviceId, "");6    }78    @Tool9    @LLMDescription(description = "Run diagnostic on a device to check its status and identify any issues")10    public String runDiagnostic(11            @LLMDescription(description = "The ID of the device to diagnose") String deviceId,12            @LLMDescription(description = "Additional information for the diagnostic (optional)") String additionalInfo13    ) {14        // Implementation15        return "Diagnostic results for device " + deviceId;16    }1718    @Tool19    @LLMDescription(description = "Analyze an error code to determine its meaning and possible solutions")20    public String analyzeError(21            @LLMDescription(description = "The error code to analyze (e.g., 'E1001')") String errorCode22    ) {23        // Implementation24        return "Analysis of error code " + errorCode;25    }26}

모범 사례

  • 명확한 설명 제공: 도구, 매개변수 및 반환 값의 목적과 동작을 설명하는 명확하고 간결한 설명을 작성하세요.
  • 모든 매개변수 설명: LLM이 각 매개변수의 용도를 이해할 수 있도록 모든 매개변수에 @LLMDescription를 추가하세요.
  • 일관된 이름 지정 사용: 도구 및 매개변수에 대해 일관된 이름 지정 규칙을 사용하여 보다 직관적으로 만듭니다.
  • 그룹 관련 도구: 동일한 ToolSet 구현에서 관련 도구를 그룹화하고 클래스 수준 설명을 제공합니다.
  • 유익한 결과 반환: 도구 반환 값이 작업 결과에 대한 명확한 정보를 제공하는지 확인하세요.
  • 순조롭게 오류 처리: 도구에 오류 처리를 포함하고 유익한 오류 메시지를 반환합니다.
  • 기본값 문서화: 매개변수에 기본값(Kotlin) 또는 오버로드(자바)가 있는 경우 이를 설명에 기록하세요.
  • 도구에 집중하세요: 각 도구는 너무 많은 작업을 수행하기보다는 구체적이고 잘 정의된 작업을 수행해야 합니다.

일반적인 문제 해결

도구 주석 작업 시 몇 가지 일반적인 문제가 발생할 수 있습니다.

도구가 인식되지 않습니다

상담원이 도구를 인식하지 못하는 경우 다음을 확인하세요.

  • 귀하의 클래스는 ToolSet 인터페이스를 구현합니다.
  • 모든 도구 기능 또는 방법에는 @Tool이라는 주석이 붙어 있습니다.
  • 도구 함수 또는 메서드에는 적절한 반환 유형이 있습니다(단순화를 위해 String 권장).
  • 귀하의 도구가 에이전트에 올바르게 등록되었습니다.

불분명한 도구 설명

LLM이 도구를 올바르게 사용하지 않거나 도구의 목적을 잘못 이해하는 경우 다음을 시도해 보십시오.

  • 가능하면 기본 매개변수 유형을 사용하십시오(Kotlin의 경우 String, Boolean, Int 또는 Java의 경우 String, boolean, int).
  • 매개변수 설명에 예상되는 형식을 명확하게 설명하세요.
  • 복합 유형의 경우 특정 형식의 String 매개변수 사용을 고려하고 도구에서 이를 구문 분석하세요.
  • 매개변수 설명에 유효한 입력의 예를 포함하세요.
  • Java는 기본 매개변수를 지원하지 않습니다. 대신 메소드 오버로딩을 사용하세요.

매개변수 유형 문제

LLM이 잘못된 매개변수 유형을 제공하는 경우 다음을 시도해 보십시오.

  • 가능하면 간단한 매개변수 유형을 사용하십시오(String, Boolean, Int).
  • 매개변수 설명에 예상되는 형식을 명확하게 설명하세요.
  • 복합 유형의 경우 특정 형식의 String 매개변수 사용을 고려하고 도구에서 이를 구문 분석하세요.
  • 매개변수 설명에 유효한 입력의 예를 포함하세요.

성능 문제

도구로 인해 성능 문제가 발생하는 경우 다음을 시도해 보십시오.

  • 도구 구현을 가볍게 유지하세요.
  • 리소스 집약적인 작업의 경우 비동기 처리 구현을 고려하세요.
  • 적절한 경우 결과를 캐시합니다.
  • 병목 현상을 식별하기 위한 로그 도구 사용.