사전 정의된 노드 및 구성 요소

·3분 읽기

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

사전 정의된 노드 및 구성 요소

노드는 Koog 프레임워크에서 에이전트 워크플로의 기본 구성 요소입니다. 각 노드는 워크플로의 특정 작업이나 변환을 나타내며, 실행 흐름을 정의하기 위해 에지를 사용해 연결될 수 있습니다.

일반적으로 노드를 사용하면 복잡한 논리를 쉽게 통합할 수 있는 재사용 가능한 구성 요소로 캡슐화할 수 있습니다. 상담사 워크플로가 다릅니다. 이 가이드는 에이전트에서 사용할 수 있는 기존 노드를 안내합니다. 전략.

각 노드는 기본적으로 특정 유형의 입력을 받아 특정 유형의 출력을 반환하는 함수(Kotlin) 또는 작업(Java)입니다.

1graph LR2    in:::hidden3    out:::hidden4    5    subgraph node ["Node"]6        execute(Do stuff)7    end8    9    in --Input--> execute --Output--> out1011    classDef hidden display: none;

다음은 문자열을 입력으로 예상하고 문자열 길이(정수)를 출력으로 반환하는 노드를 정의하는 방법입니다.

코틀린

1val nodeLength by node<String, Int> { input ->2    input.length3}

자바

1var nodeLength = AIAgentNode.builder("nodeLength")2    .withInput(String.class)3    .withOutput(Integer.class)4    .withAction((input, ctx) -> input.length())5    .build();

자세한 내용은 node()(Kotlin) 또는 Java용 AIAgentNode.builder()을 참조하세요.

유틸리티 노드

통과 노드

아무것도 하지 않고 입력을 출력으로 반환하는 간단한 통과 노드입니다. 자세한 내용은 nodeDoNothing(Kotlin) 또는 AIAgentNode.doNothing()(Java)을 참조하세요.

1graph LR2    in:::hidden3    out:::hidden4    5    subgraph node ["Pass-through node"]6        execute(Do nothing)7    end8    9    in ---|T| execute --T--> out1011    classDef hidden display: none;

이 노드는 다음과 같은 목적으로 사용할 수 있습니다.

  • 그래프에 자리 표시자 노드를 만듭니다.
  • 데이터를 수정하지 않고 연결점을 만듭니다.

예는 다음과 같습니다.

코틀린

1val passthrough by nodeDoNothing<String>("passthrough")23edge(nodeStart forwardTo passthrough)4edge(passthrough forwardTo nodeFinish)

자바

1var passthrough = AIAgentNode.doNothing(String.class);23strategy.edge(strategy.nodeStart, passthrough);4strategy.edge(passthrough, strategy.nodeFinish);

LLM 노드

신속한 준비 노드

제공된 프롬프트 빌더를 사용하여 LLM 프롬프트에 메시지를 추가하는 노드입니다. 이는 실제 LLM 요청을 하기 전에 대화 컨텍스트를 수정하는 데 유용합니다. 자세한 내용은 nodeAppendPrompt(Kotlin) 또는 AIAgentNode.appendPrompt()(Java)을 참조하세요.

1graph LR2    in:::hidden3    out:::hidden4    5    subgraph node ["Prompt preparation node"]6        execute(Append prompt)7    end8    9    in ---|T| execute --T--> out1011    classDef hidden display: none;

이 노드는 다음과 같은 목적으로 사용할 수 있습니다.

  • 프롬프트에 시스템 지침을 추가합니다.
  • 대화에 사용자 메시지를 삽입합니다.
  • 후속 LLM 요청에 대한 컨텍스트를 준비합니다.

예는 다음과 같습니다.

코틀린

1val firstNode by node<Input, Output> {2    // Transform input to output3}45val secondNode by node<Output, Output> {6    // Transform output to output7}89// Node will get the value of type Output as input from the previous node and path through it to the next node10val setupContext by nodeAppendPrompt<Output>("setupContext") {11    system("You are a helpful assistant specialized in Kotlin programming.")12    user("I need help with Kotlin coroutines.")13}1415edge(firstNode forwardTo setupContext)16edge(setupContext forwardTo secondNode)

자바

1var firstNode = AIAgentNode.builder()2    .withInput(Input.class)3    .withOutput(Output.class)4    .withAction((input, ctx) -> {5        // Transform input to output6        return input;7    })8    .build();910var secondNode = AIAgentNode.builder()11    .withInput(Output.class)12    .withOutput(Output.class)13    .withAction((output, ctx) -> {14        // Transform output to output15        return output;16    })17    .build();1819var setupContext = AIAgentNode.builder()20    .withInput(Output.class)21    .appendPrompt(prompt -> {22        prompt.system("You are a helpful assistant specialized in Kotlin programming.");23        prompt.user("I need help with Kotlin coroutines.");24    });2526strategy.edge(firstNode, setupContext);27strategy.edge(setupContext, secondNode);

도구 전용 노드

LLM 프롬프트에 사용자 메시지를 추가하고 LLM이 도구만 호출할 수 있는 응답을 받는 노드입니다. 자세한 내용은 nodeLLMSendMessageOnlyCallingTools(Kotlin) 또는 AIAgentNode.llmSendMessageOnlyCallingTools()(Java)을 참조하세요.

1graph LR2    in:::hidden3    out:::hidden4    5    subgraph node ["Tool-only node"]6        execute(Request LLM expecting only tool calls)7    end8    9    in --String--> execute --Message.Response--> out1011    classDef hidden display: none;

강제 단일 도구 사용 노드

LLM 프롬프트에 사용자 메시지를 추가하고 LLM이 특정 도구를 사용하도록 하는 노드입니다. 자세한 내용은 nodeLLMSendMessageForceOneTool(Kotlin) 또는 AIAgentNode.llmSendMessageForceOneTool()(Java)을 참조하세요.

1graph LR2    in:::hidden3    out:::hidden4    5    subgraph node ["Forced single tool use node"]6        execute(Request LLM expecting a specific tool call)7    end8    9    in --String--> execute --Message.Response--> out1011    classDef hidden display: none;

LLM 요청 노드

LLM 프롬프트에 사용자 메시지를 추가하고 선택적 도구 사용에 대한 응답을 받는 노드입니다. 노드 구성에 따라 다음이 결정됩니다. 메시지 처리 중에는 도구 호출이 허용됩니다. 자세한 내용은 nodeLLMRequest(Kotlin) 또는 AIAgentNode.llmRequest()(Java)을 참조하세요.

1graph LR2    in:::hidden3    out:::hidden4    5    subgraph node ["LLM request node"]6        execute(Request LLM)7    end8    9    in --String--> execute --Message.Response--> out1011    classDef hidden display: none;

이 노드는 다음과 같은 목적으로 사용할 수 있습니다.

  • 현재 프롬프트에 대한 LLM 응답을 생성하여 LLM이 도구 호출을 생성하도록 허용할지 여부를 제어합니다.

예는 다음과 같습니다.

코틀린

1val requestLLM by nodeLLMRequest("requestLLM", allowToolCalls = true)2edge(getUserQuestion forwardTo requestLLM)

자바

1var requestLLM = AIAgentNode.llmRequest(true, "requestLLM");23strategy.edge(getUserQuestion, requestLLM);

구조화된 응답이 있는 LLM 요청 노드

LLM 프롬프트에 사용자 메시지를 추가하고 오류 수정 기능을 통해 LLM에 구조화된 데이터를 요청하는 노드입니다. 자세한 내용은 nodeLLMRequestStructured(Kotlin) 또는 AIAgentNode.llmRequestStructured()(Java)을 참조하세요.

1graph LR2    in:::hidden3    out:::hidden4    5    subgraph node ["LLM request node, structured response"]6        execute(Request LLM structured)7    end8    9    in --String--> execute -- "Result&lt;StructuredResponse&gt;" --> out1011    classDef hidden display: none;

스트리밍 응답이 있는 LLM 요청 노드

LLM 프롬프트에 사용자 메시지를 추가하고 스트림 데이터 변환 여부에 관계없이 LLM 응답을 스트리밍하는 노드입니다. 자세한 내용은 nodeLLMRequestStreaming(Kotlin) 또는 AIAgentNode.llmRequestStreaming()(Java)을 참조하세요.

1graph LR2    in:::hidden3    out:::hidden4    5    subgraph node ["LLM request node, streaming response"]6        execute(Request LLM streaming)7    end8    9    in --String--> execute --Flow--> out1011    classDef hidden display: none;

다중 응답이 있는 LLM 요청 노드

LLM 프롬프트에 사용자 메시지를 추가하고 도구 호출이 활성화된 여러 LLM 응답을 받는 노드입니다. 자세한 내용은 nodeLLMRequestMultiple(Kotlin) 또는 AIAgentNode.llmRequestMultiple()(Java)을 참조하세요.

1graph LR2    in:::hidden3    out:::hidden4    5    subgraph node ["LLM request node, multiple responses"]6        execute(Request LLM expecting multiple responses)7    end8    9    in --String--> execute -- "List&lt;Message.Response&gt;" --> out1011    classDef hidden display: none;

이 노드는 다음과 같은 목적으로 사용할 수 있습니다.

  • 여러 도구 호출이 필요한 복잡한 쿼리를 처리합니다.
  • 여러 도구 호출을 생성합니다.
  • 여러 병렬 작업이 필요한 워크플로를 구현합니다.

예는 다음과 같습니다.

코틀린

1val requestLLMMultipleTools by nodeLLMRequestMultiple()2edge(getComplexUserQuestion forwardTo requestLLMMultipleTools)

자바

1var requestLLMMultipleTools = AIAgentNode.llmRequestMultiple("requestLLMMultipleTools");23strategy.edge(getComplexUserQuestion, requestLLMMultipleTools);

히스토리 압축 노드

현재 LLM 프롬프트(메시지 기록)를 요약으로 압축하여 메시지를 간결한 요약(TL;DR)으로 바꾸는 노드입니다. 이는 토큰 사용량을 줄이기 위해 기록을 압축하여 긴 대화를 관리하는 데 유용합니다. 자세한 내용은 nodeLLMCompressHistory(Kotlin) 또는 AIAgentNode.llmCompressHistory()(Java)을 참조하세요.

1graph LR2    in:::hidden3    out:::hidden4    5    subgraph node ["History compression node"]6        execute(Compress current prompt)7    end8    9    in ---|T| execute --T--> out1011    classDef hidden display: none;

기록 압축에 대해 자세히 알아보려면 History compression을 참조하세요.

이 노드는 다음과 같은 목적으로 사용할 수 있습니다.

  • 긴 대화를 관리하여 토큰 사용량을 줄이세요.
  • 맥락을 유지하기 위해 대화 기록을 요약합니다.
  • 장기 실행 에이전트에서 메모리 관리를 구현합니다.

예는 다음과 같습니다.

코틀린

1val compressHistory by nodeLLMCompressHistory<String>(2    "compressHistory",3    strategy = HistoryCompressionStrategy.FromLastNMessages(10),4    preserveMemory = true5)6edge(generateHugeHistory forwardTo compressHistory)

자바

1var compressHistory = AIAgentNode.llmCompressHistory("compressHistory")2    .withInput(String.class)3    .build();45strategy.edge(generateHugeHistory, compressHistory);

도구 노드

도구 실행 노드

단일 도구 호출을 실행하고 그 결과를 반환하는 노드입니다. 이 노드는 LLM의 도구 호출을 처리하는 데 사용됩니다. 자세한 내용은 nodeExecuteTool(Kotlin) 또는 AIAgentNode.executeTool()(Java)을 참조하세요.

1graph LR2    in:::hidden3    out:::hidden4    5    subgraph node ["Tool execution node"]6        execute(Execute tool call)7    end8    9    in --Message.Tool.Call--> execute --ReceivedToolResult--> out1011    classDef hidden display: none;

이 노드는 다음과 같은 목적으로 사용할 수 있습니다.

  • LLM이 요청한 도구를 실행합니다.
  • LLM 결정에 따라 특정 조치를 처리합니다.
  • 외부 기능을 상담원 워크플로에 통합합니다.

예는 다음과 같습니다.

코틀린

1val requestLLM by nodeLLMRequest()2val executeTool by nodeExecuteTool()3edge(requestLLM forwardTo executeTool onToolCall { true })

자바

1var requestLLM = AIAgentNode.llmRequest(true, "requestLLM");2var executeTool = AIAgentNode.executeTool("executeTool");34strategy.edge(AIAgentEdge.builder()5    .from(requestLLM)6    .to(executeTool)7    .onIsInstance(Message.Tool.Call.class)8    .build());

도구 결과 후속 노드

프롬프트에 도구 결과를 추가하고 LLM 응답을 요청하는 노드입니다. 자세한 내용은 nodeLLMSendToolResult(Kotlin) 또는 AIAgentNode.llmSendToolResult()(Java)을 참조하세요.

1graph LR2    in:::hidden3    out:::hidden4    5    subgraph node ["Tool result follow-up node"]6        execute(Request LLM)7    end8    9    in --ReceivedToolResult--> execute --Message.Response--> out1011    classDef hidden display: none;

이 노드는 다음과 같은 목적으로 사용할 수 있습니다.

  • 도구 실행 결과를 처리합니다.
  • 도구 출력을 기반으로 응답을 생성합니다.
  • 도구 실행 후 대화를 계속하세요.

예는 다음과 같습니다.

코틀린

1val executeTool by nodeExecuteTool()2val sendToolResultToLLM by nodeLLMSendToolResult()3edge(executeTool forwardTo sendToolResultToLLM)

자바

1var executeTool = AIAgentNode.executeTool("executeTool");2var sendToolResultToLLM = AIAgentNode.llmSendToolResult("sendToolResultToLLM");34strategy.edge(executeTool, sendToolResultToLLM);

다중 도구 실행 노드

여러 도구 호출을 실행하는 노드입니다. 이러한 호출은 선택적으로 병렬로 실행될 수 있습니다. 자세한 내용은 nodeExecuteMultipleTools(Kotlin) 또는 AIAgentNode.executeMultipleTools()(Java)을 참조하세요.

1graph LR2    in:::hidden3    out:::hidden4    5    subgraph node ["Multi-tool execution node"]6        execute(Execute multiple tool calls)7    end8    9    in -- "List&lt;Message.Tool.Call&gt;" --> execute -- "List&lt;ReceivedToolResult&gt;" --> out1011    classDef hidden display: none;

이 노드는 다음과 같은 목적으로 사용할 수 있습니다.

  • 여러 도구를 동시에 실행합니다.
  • 여러 도구 실행이 필요한 복잡한 워크플로를 처리합니다.
  • 도구 호출을 일괄 처리하여 성능을 최적화합니다.

예는 다음과 같습니다.

코틀린

1val requestLLMMultipleTools by nodeLLMRequestMultiple()2val executeMultipleTools by nodeExecuteMultipleTools()3edge(requestLLMMultipleTools forwardTo executeMultipleTools onMultipleToolCalls { true })

자바

1var requestLLMMultipleTools = AIAgentNode.llmRequestMultiple("requestLLMMultipleTools");2var executeMultipleTools = AIAgentNode.executeMultipleTools(false, "executeMultipleTools");34// Extract tool calls from the list of responses5strategy.edge(AIAgentEdge.builder()6    .from(requestLLMMultipleTools)7    .to(executeMultipleTools)8    .onCondition(responses -> responses.stream()9        .anyMatch(msg -> msg instanceof Message.Tool.Call))10    .transformed(responses -> responses.stream()11        .filter(msg -> msg instanceof Message.Tool.Call)12        .map(msg -> (Message.Tool.Call) msg)13        .toList())14    .build());

다중 도구 결과 후속 노드

여러 도구 결과를 프롬프트에 추가하고 여러 LLM 응답을 받는 노드입니다. 자세한 내용은 nodeLLMSendMultipleToolResults(Kotlin) 또는 AIAgentNode.llmSendMultipleToolResults()(Java)을 참조하세요.

1graph LR2    in:::hidden3    out:::hidden4    5    subgraph node ["Multiple tool result follow-up node"]6        execute(Request LLM expecting multiple responses)7    end8    9    in -- "List&lt;ReceivedToolResult&gt;" --> execute -- "List&lt;Message.Response&gt;" --> out1011    classDef hidden display: none;

이 노드는 다음과 같은 목적으로 사용할 수 있습니다.

  • 여러 도구 실행의 결과를 처리합니다.
  • 여러 도구 호출을 생성합니다.
  • 여러 병렬 작업으로 복잡한 워크플로를 구현합니다.

예는 다음과 같습니다.

코틀린

1val executeMultipleTools by nodeExecuteMultipleTools()2val sendMultipleToolResultsToLLM by nodeLLMSendMultipleToolResults()3edge(executeMultipleTools forwardTo sendMultipleToolResultsToLLM)

자바

1var executeMultipleTools = AIAgentNode.executeMultipleTools(false, "executeMultipleTools");2var sendMultipleToolResultsToLLM = AIAgentNode.llmSendMultipleToolResults("sendMultipleToolResultsToLLM");34strategy.edge(executeMultipleTools, sendMultipleToolResultsToLLM);

노드 출력 변환

프레임워크는 Kotlin에서 다음을 생성할 수 있는 transform 확장 기능을 제공합니다. 출력에 변환을 적용하는 변환된 노드 버전입니다. Java에서는 다음을 달성합니다. 명시적인 변환을 사용하여 중간 노드를 생성해도 동일한 결과를 얻을 수 있습니다. 이것은 유용하다 노드의 출력을 보존하면서 다른 유형이나 형식으로 변환해야 하는 경우 원래 노드의 기능.

1graph LR2    in:::hidden3    out:::hidden4    5    subgraph nodeWithTransform [transformed node]6        subgraph node ["node"]7            execute(Do stuff)8        end9        transform10    end11    12    in --Input--> execute --> transform --Output--> out1314    classDef hidden display: none;

노드 변환

Kotlin에서 transform() 함수는 원래 노드를 래핑하고 출력에 변환 함수를 적용하는 새로운 AIAgentNodeDelegate을 생성합니다. Java에서는 AIAgentNode.builder() 및 명시적 유형 매개변수를 사용하여 변환 논리로 노드를 수동으로 구성해야 합니다.

코틀린

1inline fun <reified T> AIAgentNodeDelegate<Input, Output>.transform(2    noinline transformation: suspend (Output) -> T3): AIAgentNodeDelegate<Input, T>

자바

1// In Java, you need to manually compose nodes2// with transformation logic using AIAgentNode.builder() and explicit type parameters.3// See the examples below for the Java approach to node transformations.

사용자 정의 노드 변환

사용자 정의 노드의 출력을 다른 데이터 유형으로 변환합니다.

코틀린

1val textNode by nodeDoNothing<String>("textNode").transform<Int> { text ->2    text.split(" ").filter { it.isNotBlank() }.size3}45edge(nodeStart forwardTo textNode)6edge(textNode forwardTo nodeFinish)

자바

1var textNode = AIAgentNode.builder("textNode")2    .withInput(String.class)3    .withOutput(Integer.class)4    .withAction((text, ctx) -> {5        String[] words = text.split(" ");6        int count = 0;7        for (String word : words) {8            if (!word.isBlank()) {9                count++;10            }11        }12        return count;13    })14    .build();1516strategy.edge(strategy.nodeStart, textNode);17strategy.edge(textNode, strategy.nodeFinish);

내장 노드 변환

nodeLLMRequest(Kotlin) 또는 AIAgentNode.llmRequest()(Java)과 같은 내장 노드의 출력을 변환합니다.

코틀린

1val lengthNode by nodeLLMRequest("llmRequest").transform<Int> { assistantMessage ->2    assistantMessage.content.length3}45edge(nodeStart forwardTo lengthNode)6edge(lengthNode forwardTo nodeFinish)

자바

1var llmRequest = AIAgentNode.llmRequest(true, "llmRequest");2var lengthNode = AIAgentNode.builder("lengthNode")3    .withInput(Message.Response.class)4    .withOutput(Integer.class)5    .withAction((assistantMessage, ctx) -> {6        if (assistantMessage instanceof Message.Assistant) {7            return ((Message.Assistant) assistantMessage).getContent().length();8        }9        return 0;10    })11    .build();1213strategy.edge(strategy.nodeStart, llmRequest);14strategy.edge(llmRequest, lengthNode);15strategy.edge(lengthNode, strategy.nodeFinish);

사전 정의된 하위 그래프

프레임워크는 일반적으로 사용되는 패턴과 워크플로우를 캡슐화하는 사전 정의된 하위 그래프를 제공합니다. 이러한 하위 그래프는 기본 노드 및 에지 생성을 자동으로 처리하여 복잡한 에이전트 전략 개발을 단순화합니다. API는 Kotlin과 Java 간에 일관됩니다. Kotlin은 DSL 기능을 사용하고 Java는 빌더 메소드를 사용합니다.

사전 정의된 하위 그래프를 사용하면 다양한 인기 파이프라인을 구현할 수 있습니다. 예는 다음과 같습니다.

  1. 데이터를 준비합니다.
  2. 작업을 실행합니다.
  3. 작업 결과를 검증합니다. 결과가 잘못된 경우 피드백 메시지와 함께 2단계로 돌아가서 조정하세요.

작업 실행 하위 그래프

제공된 도구를 사용하여 특정 작업을 수행하고 구조화된 결과를 반환하는 하위 그래프입니다. 다중 응답 LLM 상호 작용(어시스턴트는 도구 호출과 인터리브된 여러 응답을 생성할 수 있음)을 지원하고 도구 호출이 실행되는 방법을 제어할 수 있습니다. Kotlin에서는 subgraphWithTask()을 사용하고 Java에서는 AIAgentSubgraph.builder().withTask()을 사용합니다.

이 하위 그래프를 다음과 같은 목적으로 사용할 수 있습니다.

  • 더 큰 작업 흐름 내에서 특정 작업을 처리하는 특수 구성 요소를 만듭니다.
  • 명확한 입력 및 출력 인터페이스로 복잡한 논리를 캡슐화합니다.
  • 작업별 도구, 모델 및 프롬프트를 구성합니다.
  • 자동 압축으로 대화 기록을 관리하세요.
  • 구조화된 에이전트 워크플로 및 작업 실행 파이프라인을 개발합니다.
  • 여러 보조 응답 및 도구 호출이 포함된 흐름을 포함하여 LLM 작업 실행에서 구조화된 결과를 생성합니다.

API를 사용하면 선택적 매개변수를 사용하여 실행을 미세 조정할 수 있습니다.

  • runMode: 작업 중에 도구 호출이 실행되는 방식을 제어합니다(기본적으로 순차적). 기본 모델/실행기에서 지원하는 경우 다양한 도구 실행 전략 간에 전환하려면 이를 사용합니다.
  • assistantResponseRepeatMax: 작업을 완료할 수 없다고 결론을 내리기 전에 허용되는 보조 응답 수를 제한합니다(제공되지 않은 경우 기본값은 안전한 내부 제한입니다).

하위 그래프에 작업을 텍스트로 제공하고, 필요한 경우 LLM을 구성하고, 필요한 도구를 제공하면 하위 그래프가 작업을 처리하고 해결합니다. 예는 다음과 같습니다.

코틀린

1val processQuery by subgraphWithTask<String, String>(2    tools = listOf(searchTool, calculatorTool, weatherTool),3    llmModel = OpenAIModels.Chat.GPT4o,4    runMode = ToolCalls.SEQUENTIAL,5    assistantResponseRepeatMax = 3,6) { userQuery ->7    """8    You are a helpful assistant that can answer questions about various topics.9    Please help with the following query:10    $userQuery11    """12}

자바

1var processQuery = AIAgentSubgraph.builder("processQuery")2    .limitedTools(List.of(searchTool, calculatorTool, weatherTool))3    .withInput(String.class)4    .withOutput(String.class)5    .withTask(userQuery ->6        "You are a helpful assistant that can answer questions about various topics.\n" +7        "Please help with the following query:\n" +8        userQuery)9    .runMode(ToolCalls.SEQUENTIAL)10    .assistantResponseRepeatMax(3)11    .build();

검증이 포함된 작업 실행 하위 그래프

작업이 올바르게 수행되었는지 확인하고 발생한 문제에 대한 세부 정보를 제공하는 subgraphWithTask의 특수 버전입니다. 이 하위 그래프는 검증 또는 품질 확인이 필요한 작업 흐름에 유용합니다. Kotlin에서는 subgraphWithVerification()을 사용하고 Java에서는 AIAgentSubgraph.builder().withVerification()를 사용합니다.

이 하위 그래프를 다음과 같은 목적으로 사용할 수 있습니다.

  • 작업 실행의 정확성을 확인합니다.
  • 귀하의 작업 흐름에 품질 관리 프로세스를 구현하십시오.
  • 자체 검증 구성 요소를 만듭니다.
  • 성공/실패 상태와 상세한 피드백을 통해 구조화된 검증 결과를 생성합니다.

하위 그래프는 LLM이 작업 흐름이 끝날 때 확인 도구를 호출하여 작업이 성공적으로 완료되었는지 확인하도록 합니다. 이 검증이 마지막 단계로 수행되도록 보장하고 작업이 성공적으로 완료되었는지 여부를 나타내는 CriticResult을 반환하고 자세한 피드백을 제공합니다. 예는 다음과 같습니다.

코틀린

1val verifyCode by subgraphWithVerification<String>(2    tools = listOf(runTestsTool, analyzeTool, readFileTool),3    llmModel = AnthropicModels.Opus_4_6,4    runMode = ToolCalls.SEQUENTIAL,5    assistantResponseRepeatMax = 3,6) { codeToVerify ->7    """8    You are a code reviewer. Please verify that the following code meets all requirements:9    1. It compiles without errors10    2. All tests pass11    3. It follows the project's coding standards1213    Code to verify:14    $codeToVerify15    """16}

자바

1var verifyCode = AIAgentSubgraph.builder("verifyCode")2    .limitedTools(List.of(runTestsTool, analyzeTool, readFileTool))3    .withInput(String.class)4    .withVerification(codeToVerify ->5        "You are a code reviewer. Please verify that the following code meets all requirements:\n" +6        "1. It compiles without errors\n" +7        "2. All tests pass\n" +8        "3. It follows the project's coding standards\n\n" +9        "Code to verify:\n" +10        codeToVerify)11    .runMode(ToolCalls.SEQUENTIAL)12    .assistantResponseRepeatMax(3)13    .build();

사전 정의된 전략 및 일반적인 전략 패턴

Koog는 다양한 노드를 결합하는 사전 정의된 전략을 제공합니다. 노드는 작업 흐름을 정의하기 위해 모서리를 사용하여 연결되며, 각 모서리를 따라갈 시기를 지정하는 조건이 있습니다.

필요한 경우 이러한 전략을 상담원 워크플로에 통합할 수 있습니다.

단일 실행 전략

단일 실행 전략은 에이전트가 입력을 한 번 처리하고 결과를 반환합니다.

복잡한 논리가 필요하지 않은 간단한 프로세스를 실행해야 할 때 이 전략을 사용할 수 있습니다.

코틀린

1public fun singleRunStrategy(): AIAgentGraphStrategy<String, String> = strategy("single_run") {2    val nodeCallLLM by nodeLLMRequest("sendInput")3    val nodeExecuteTool by nodeExecuteTool("nodeExecuteTool")4    val nodeSendToolResult by nodeLLMSendToolResult("nodeSendToolResult")56    edge(nodeStart forwardTo nodeCallLLM)7    edge(nodeCallLLM forwardTo nodeExecuteTool onToolCall { true })8    edge(nodeCallLLM forwardTo nodeFinish onAssistantMessage { true })9    edge(nodeExecuteTool forwardTo nodeSendToolResult)10    edge(nodeSendToolResult forwardTo nodeFinish onAssistantMessage { true })11    edge(nodeSendToolResult forwardTo nodeExecuteTool onToolCall { true })12}

자바

1public static AIAgentGraphStrategy<String, String> singleRunStrategy() {2    var strategy = AIAgentGraphStrategy.builder("single_run")3        .withInput(String.class)4        .withOutput(String.class);56    var nodeCallLLM = AIAgentNode.llmRequest(true, "sendInput");7    var nodeExecuteTool = AIAgentNode.executeTool("nodeExecuteTool");8    var nodeSendToolResult = AIAgentNode.llmSendToolResult("nodeSendToolResult");910    strategy.edge(strategy.nodeStart, nodeCallLLM);1112    strategy.edge(AIAgentEdge.builder()13        .from(nodeCallLLM)14        .to(nodeExecuteTool)15        .onIsInstance(Message.Tool.Call.class)16        .build());1718    strategy.edge(AIAgentEdge.builder()19        .from(nodeCallLLM)20        .to(strategy.nodeFinish)21        .onIsInstance(Message.Assistant.class)22        .transformed(Message.Assistant::getContent)23        .build());2425    strategy.edge(nodeExecuteTool, nodeSendToolResult);2627    strategy.edge(AIAgentEdge.builder()28        .from(nodeSendToolResult)29        .to(strategy.nodeFinish)30        .onIsInstance(Message.Assistant.class)31        .transformed(Message.Assistant::getContent)32        .build());3334    strategy.edge(AIAgentEdge.builder()35        .from(nodeSendToolResult)36        .to(nodeExecuteTool)37        .onIsInstance(Message.Tool.Call.class)38        .build());3940    return strategy.build();41}

도구 기반 전략

도구 기반 전략은 특정 작업을 수행하기 위해 도구에 크게 의존하는 워크플로를 위해 설계되었습니다. 일반적으로 LLM 결정을 기반으로 도구를 실행하고 결과를 처리합니다.

코틀린

1fun toolBasedStrategy(name: String, toolRegistry: ToolRegistry): AIAgentGraphStrategy<String, String> {2    return strategy(name) {3        val nodeSendInput by nodeLLMRequest()4        val nodeExecuteTool by nodeExecuteTool()5        val nodeSendToolResult by nodeLLMSendToolResult()67        // Define the flow of the agent8        edge(nodeStart forwardTo nodeSendInput)910        // If the LLM responds with a message, finish11        edge(12            (nodeSendInput forwardTo nodeFinish)13                    onAssistantMessage { true }14        )1516        // If the LLM calls a tool, execute it17        edge(18            (nodeSendInput forwardTo nodeExecuteTool)19                    onToolCall { true }20        )2122        // Send the tool result back to the LLM23        edge(nodeExecuteTool forwardTo nodeSendToolResult)2425        // If the LLM calls another tool, execute it26        edge(27            (nodeSendToolResult forwardTo nodeExecuteTool)28                    onToolCall { true }29        )3031        // If the LLM responds with a message, finish32        edge(33            (nodeSendToolResult forwardTo nodeFinish)34                    onAssistantMessage { true }35        )36    }37}

자바

1public static AIAgentGraphStrategy<String, String> toolBasedStrategy(String name, ToolRegistry toolRegistry) {2    var strategy = AIAgentGraphStrategy.builder(name)3        .withInput(String.class)4        .withOutput(String.class);56    var nodeSendInput = AIAgentNode.llmRequest(true, "nodeSendInput");7    var nodeExecuteTool = AIAgentNode.executeTool("nodeExecuteTool");8    var nodeSendToolResult = AIAgentNode.llmSendToolResult("nodeSendToolResult");910    // Define the flow of the agent11    strategy.edge(strategy.nodeStart, nodeSendInput);1213    // If the LLM responds with a message, finish14    strategy.edge(AIAgentEdge.builder()15        .from(nodeSendInput)16        .to(strategy.nodeFinish)17        .onIsInstance(Message.Assistant.class)18        .transformed(Message.Assistant::getContent)19        .build());2021    // If the LLM calls a tool, execute it22    strategy.edge(AIAgentEdge.builder()23        .from(nodeSendInput)24        .to(nodeExecuteTool)25        .onIsInstance(Message.Tool.Call.class)26        .build());2728    // Send the tool result back to the LLM29    strategy.edge(nodeExecuteTool, nodeSendToolResult);3031    // If the LLM calls another tool, execute it32    strategy.edge(AIAgentEdge.builder()33        .from(nodeSendToolResult)34        .to(nodeExecuteTool)35        .onIsInstance(Message.Tool.Call.class)36        .build());3738    // If the LLM responds with a message, finish39    strategy.edge(AIAgentEdge.builder()40        .from(nodeSendToolResult)41        .to(strategy.nodeFinish)42        .onIsInstance(Message.Assistant.class)43        .transformed(Message.Assistant::getContent)44        .build());4546    return strategy.build();47}

스트리밍 데이터 전략

스트리밍 데이터 전략은 LLM의 스트리밍 데이터를 처리하기 위해 설계되었습니다. 일반적으로 요청합니다. 데이터를 스트리밍하고 처리하며 잠재적으로 처리된 데이터로 도구를 호출합니다.

코틀린

1val agentStrategy = strategy<String, List<Book>>("library-assistant") {2    // Describe the node containing the output stream parsing3    val getMdOutput by node<String, List<Book>> { booksDescription ->4        val books = mutableListOf<Book>()5        val mdDefinition = markdownBookDefinition()67        llm.writeSession {8            appendPrompt { user(booksDescription) }9            // Initiate the response stream in the form of the definition `mdDefinition`10            val markdownStream = requestLLMStreaming(mdDefinition)11            // Call the parser with the result of the response stream and perform actions with the result12            parseMarkdownStreamToBooks(markdownStream).collect { book ->13                books.add(book)14                println("Parsed Book: ${book.title} by ${book.author}")15            }16        }1718        books19    }20    // Describe the agent's graph making sure the node is accessible21    edge(nodeStart forwardTo getMdOutput)22    edge(getMdOutput forwardTo nodeFinish)23}

자바

1var strategy = AIAgentGraphStrategy.builder()2    .withInput(String.class)3    .withOutput(List.class);45var getMdOutput = AIAgentNode.builder()6    .withInput(String.class)7    .<List<Book>>withOutput(TypeToken.of(new TypeCapture<List<Book>>() {}))8    .withAction((booksDescription, ctx) -> {9        var books = new ArrayList<Book>();10        StructureDefinition mdDefinition = markdownBookDefinition();1112        ctx.getLlm().writeSession(session -> {13            session.appendPrompt(prompt -> {14                prompt.user(booksDescription);15            });1617            // Initiate the response stream in the form of the definition `mdDefinition`18            var markdownStream = session.requestLLMStreaming(mdDefinition);19            // Call the parser with the result of the response stream and perform actions with the result20            parseMarkdownStreamToBooks(markdownStream).subscribe(new Flow.Subscriber<>() {21                @Override22                public void onSubscribe(Flow.Subscription subscription) {23                }2425                @Override26                public void onNext(Book book) {27                    books.add(book);28                    System.out.println("Parsed Book: " + book.getTitle() + " by " + book.getAuthor());29                }3031                @Override32                public void onError(Throwable throwable) {33                }3435                @Override36                public void onComplete() {37                }38            });3940            return null;41        });4243        return books;44    })45    .build();4647strategy.edge(strategy.nodeStart, getMdOutput);48strategy.edge(getMdOutput, strategy.nodeFinish);