직렬화
원문: Koog Documentation — serialization 이 글은 Koog 공식 문서의 serialization 페이지를 한국어로 옮긴 번역본입니다. 문서 구조와 링크 의미를 유지하되, MkDocs 전용 UI 문법은 블로그에서 읽기 좋도록 정리했습니다.
직렬화
소개
Koog는 라이브러리에 구애받지 않는 얇은 직렬화 계층을 사용하여 도구 인수 및 결과를 JSON으로 변환합니다. 이 레이어는 에이전트 런타임과 기본 직렬화 라이브러리 사이에 위치하므로 라이브러리를 교체할 수 있습니다. 도구나 에이전트 코드를 변경하지 않고.
도구 외에도 직렬화 계층은 지속성과 같은 에이전트 기능에서 직렬화 및 노드 입력 및 출력을 역직렬화합니다.
기본적으로 Koog는 KotlinxSerializer(kotlinx-serialization 지원)을 사용합니다.
JVM에서는 JacksonSerializer(jackson-databind 지원)으로 전환할 수도 있습니다.
JSONSerializer 인터페이스
JSONSerializer은 serialization-core에 있는 핵심 추상화입니다.
인터페이스에는 네 가지 기본 방법(문자열 및 JSONElement 모두에 대한 인코딩/디코딩)이 있습니다.
JSONElement과 문자열 간 변환을 위한 두 가지 편리한 방법도 있습니다.
encodeToString/decodeFromString— JSON 문자열과 입력된 값을 직렬화합니다.encodeToJSONElement/decodeFromJSONElement—JSONElement트리에서 입력된 값을 직렬화합니다.encodeJSONElementToString/decodeJSONElementFromString—JSONElement와 해당 문자열 형식 간에 변환합니다.
다음 예에서는 모든 주요 작업을 보여줍니다.
코틀린
1@Serializable2data class User(val name: String, val age: Int)34val serializer: JSONSerializer = KotlinxSerializer()56// Encode a data class to a JSON string7val json: String = serializer.encodeToString(User("Alice", 30), typeToken<User>())89// Decode a JSON string back to a data class10val user: User = serializer.decodeFromString(json, typeToken<User>())1112// Encode to a JSONElement tree13val element: JSONElement = serializer.encodeToJSONElement(user, typeToken<User>())1415// Decode from a JSONElement tree16val userFromElement: User = serializer.decodeFromJSONElement(element, typeToken<User>())1718// Convert between JSONElement and a raw JSON string19val jsonString = """{"key": "value"}"""20val jsonElement: JSONElement = serializer.decodeJSONElementFromString(jsonString)21val backToString: String = serializer.encodeJSONElementToString(jsonElement)자바
1// Jackson-serializable class2record User(3 @JsonProperty("name") String name,4 @JsonProperty("age") int age5) {}67var serializer = new JacksonSerializer();89// Encode a data class to a JSON string10String json = serializer.encodeToString(new User("Alice", 30), TypeToken.of(User.class));1112// Decode a JSON string back to a data class13User user = serializer.decodeFromString(json, TypeToken.of(User.class));1415// Encode to a JSONElement tree16JSONElement element = serializer.encodeToJSONElement(user, TypeToken.of(User.class));1718// Decode from a JSONElement tree19User userFromElement = serializer.decodeFromJSONElement(element, TypeToken.of(User.class));2021// Convert between JSONElement and a raw JSON string22String jsonString = "{\"key\": \"value\"}";23JSONElement jsonElement = serializer.decodeJSONElementFromString(jsonString);24String backToString = serializer.encodeJSONElementToString(jsonElement);유형 토큰
TypeToken은 Koog가 런타임에 유형 정보를 전달하는 방법입니다.
코틀린
1data class MyClass(val value: String)23// Inline reified — preferred in Kotlin4val tokenReified = typeToken<MyClass>()56// From a KClass (when no reified type parameter is available)7val tokenKClass = typeToken(MyClass::class)89// Generic type — preserves type arguments at runtime10val tokenGeneric = typeToken<List<String>>()자바
1record MyClass(2 String value3) {}45// Simple class6TypeToken tokenClass = TypeToken.of(MyClass.class);78// Generic type — use TypeCapture to preserve type arguments9TypeToken tokenGeneric = TypeToken.of(new TypeCapture<List<String>>() {});JSONElement — 라이브러리에 구애받지 않는 JSON 트리
JSONElement은 JSON 데이터에 대한 중립 중간 표현입니다.
직렬 변환기, 도구 및 에이전트 내부가 특정 JSON 유형에 의존하지 않도록 존재합니다.
도서관.
계층
1JSONElement2├── JSONObject – key-value pairs (entries: Map<String, JSONElement>)3├── JSONArray – ordered list (elements: List<JSONElement>)4└── JSONPrimitive5 ├── JSONLiteral – string, number, or boolean6 └── JSONNull – JSON null singleton라이브러리 유형 간 변환
각 직렬화 통합은 JSONElement과 JSONElement 사이를 변환할 수 있는 확장 기능을 제공합니다.
라이브러리 자체의 동적 JSON 유형입니다. 이는 이미 JsonElement, JsonNode 등이 있고
전체 인코딩/디코딩 주기를 거치지 않고 Koog에(또는 그 반대로) 전달하려고 합니다.
지원되는 각 라이브러리에 대한 예가 아래에 제공됩니다.
요소 작성 및 읽기
코틀린
1val obj = JSONObject(2 mapOf(3 "name" to JSONPrimitive("Alice"),4 "age" to JSONPrimitive(30),5 "active" to JSONPrimitive(true),6 )7)89val arr = JSONArray(listOf(JSONPrimitive(1), JSONPrimitive(2), JSONPrimitive(3)))1011// Reading values from an object12val nameContent: String = (obj.entries["name"] as JSONPrimitive).content // "Alice"13val age: Int? = (obj.entries["age"] as JSONPrimitive).intOrNull // 30자바
1JSONObject obj = new JSONObject(2 Map.of(3 "name", JSONPrimitive.of("Alice"),4 "age", JSONPrimitive.of(30),5 "active", JSONPrimitive.of(true)6 )7);89JSONArray arr = new JSONArray(List.of(JSONPrimitive.of(1), JSONPrimitive.of(2), JSONPrimitive.of(3)));1011// Reading values from an object12String nameContent = ((JSONPrimitive) obj.getEntries().get("name")).getContent(); // "Alice"13Integer age = ((JSONPrimitive) obj.getEntries().get("age")).getIntOrNull(); // 30지원되는 직렬 변환기
KotlinxSerializer(기본값)
- 모듈:
ai.koog:serialization-core(ai.koog:agents-core에 전이적으로 포함됨) - 지원: kotlinx-serialization
코틀린
1// Default instance — uses Json.Default2val defaultSerializer = KotlinxSerializer()34// Custom Json configuration5val customSerializer = KotlinxSerializer(6 json = Json {7 ignoreUnknownKeys = true8 prettyPrint = true9 }10)Koog의 JSONElement과 kotlinx-serialization의 JsonElement 간에 변환할 수도 있습니다.
코틀린
1val koogJson: JSONElement = JSONObject(2 mapOf(3 "key" to JSONPrimitive("value")4 )5)67// Convert to kotlinx-serialization dynamic JSON instance8val kotlinxJson: JsonElement = koogJson.toKotlinxJsonElement()910// Convert to Koog dynamic JSON instance11val koogJsonConverted: JSONElement = kotlinxJson.toKoogJSONElement()JacksonSerializer(JVM에만 해당)
- 모듈:
ai.koog:serialization-jackson(별도의 종속성) - 지원: jackson-databind
build.gradle.kts에 종속성을 추가합니다.
1dependencies {2 implementation("ai.koog:serialization-jackson:<version>")3}그런 다음 직렬 변환기를 만듭니다.
코틀린
1// Default instance — uses a fresh ObjectMapper with JSONElementModule pre-registered2val defaultSerializer = JacksonSerializer()34// Custom ObjectMapper configuration5val customSerializer = JacksonSerializer(6 objectMapper = ObjectMapper().apply {7 configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)8 }9)자바
1// Default instance — uses a fresh ObjectMapper with JSONElementModule pre-registered2var defaultSerializer = new JacksonSerializer();34// Custom ObjectMapper configuration5ObjectMapper objectMapper = new ObjectMapper();6objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);7var customSerializer = new JacksonSerializer(objectMapper);참고
JacksonSerializer은ObjectMapper에JSONElementModule을 자동으로 등록합니다.JSONElement유형의 적절한 직렬화/역직렬화.
Koog의 JSONElement과 Jackson의 JsonNode 간에 변환할 수도 있습니다.
코틀린
1val koogJson: JSONElement = JSONObject(2 mapOf(3 "key" to JSONPrimitive("value")4 )5)67// Convert to Jackson dynamic JSON instance8val jacksonJson: JsonNode = koogJson.toJacksonJsonNode()910// Convert to Koog dynamic JSON instance11val koogJsonConverted: JSONElement = jacksonJson.toKoogJSONElement()자바
1JSONElement koogJson = new JSONObject(2 Map.of(3 "key", JSONPrimitive.of("value")4 )5);67// Convert to Jackson dynamic JSON instance8JsonNode jacksonJson = JacksonJSONElementMappers.toJacksonJsonNode(koogJson);910// Convert to Koog dynamic JSON instance11JSONElement koogJsonConverted = JacksonJSONElementMappers.toKoogJSONElement(jacksonJson);AIAgentConfig에서 직렬 변환기 구성
코틀린
AIAgentConfig을 생성할 때 serializer 매개변수를 전달합니다.
생략하면 KotlinxSerializer이 사용됩니다.
1val agentConfig = AIAgentConfig(2 prompt = prompt("assistant") {3 system("You are a helpful assistant.")4 },5 model = OpenAIModels.Chat.GPT4o,6 maxAgentIterations = 10,7 serializer = JacksonSerializer()8)자바
AIAgentConfig을 생성할 때 serializer 매개변수를 전달합니다.
생략하면 JacksonSerializer이 사용됩니다.
1var agentConfig = AIAgentConfig.builder()2 .model(OpenAIModels.Chat.GPT4o)3 .prompt(4 Prompt.builder("assistant")5 .system("You are a helpful assistant")6 .build()7 )8 .maxAgentIterations(10)9 .serializer(new JacksonSerializer())10 .build();도구가 직렬 변환기와 상호 작용하는 방법
에이전트 런타임은 각 Tool 인스턴스에서 다음 메서드를 자동으로 호출합니다.
일반적인 사용법에서는 직접 호출할 필요가 없습니다.
decodeArgs(rawArgs, serializer)(JSON → TArgs) — LLM의 원시 JSON 인수를 도구의 형식화된 인수 클래스로 역직렬화합니다.encodeArgs(args, serializer)(TArgs → JSON) — 입력된 인수를 JSON으로 다시 직렬화합니다(특정 에이전트 기능에서 사용됨).decodeResult(rawResult, serializer)(JSON → TResult) — 저장된 JSON 결과를 역직렬화합니다.encodeResult(result, serializer)(TResult → JSON) — 도구의 결과를 JSON으로 직렬화합니다.encodeResultToString(result, serializer)(TResult → String) — 도구 결과를 LLM으로 전송된 문자열로 직렬화합니다. 기본적으로encodeResult에 위임합니다. LLM의 결과 형식을 사용자 정의하기 위해 재정의될 수 있습니다.
이러한 메서드는 Tool의 open이므로 사용자 정의 직렬화 동작이 필요한 경우 이를 재정의할 수 있습니다.
특정 도구.
기능이 직렬 변환기를 사용하는 방법
직렬화 계층은 도구에만 국한되지 않고 특정 에이전트 기능도 이에 의존합니다.
예를 들어 지속성은 생성 시 노드 입력 및 출력을 직렬화 및 역직렬화하기 위해 AIAgentConfig에 구성된 JSONSerializer을 사용합니다.
체크포인트 및 에이전트 상태 복원. 이는 지속형 노드를 통해 흐르는 모든 유형이 다음과 같아야 함을 의미합니다.
구성된 JSONSerializer에 의해 직렬화 가능합니다.
체크포인트 생성 및 복원에 대한 자세한 내용은 Agent Persistence을 참조하세요.