@@ -9,51 +9,73 @@ import kotlinx.serialization.descriptors.buildClassSerialDescriptor
9
9
import kotlinx.serialization.descriptors.element
10
10
import kotlinx.serialization.encoding.Decoder
11
11
import kotlinx.serialization.encoding.Encoder
12
- import kotlinx.serialization.json.JsonElement
13
12
import kotlinx.serialization.json.JsonObject
13
+ import kotlinx.serialization.json.JsonObjectBuilder
14
14
import kotlinx.serialization.json.JsonPrimitive
15
+ import kotlinx.serialization.json.booleanOrNull
16
+ import kotlinx.serialization.json.contentOrNull
17
+ import kotlinx.serialization.json.jsonObject
15
18
import kotlinx.serialization.json.jsonPrimitive
16
19
17
20
/* *
18
- * string: auto is the default value
21
+ * Represents the format of the response from the assistant.
19
22
*
20
- * object: An object describing the expected output of the model. If json_object only function type tools are allowed to be passed to the Run.
21
- * If text, the model can return text or any value needed.
22
- * type: string Must be one of text or json_object.
23
+ * @property type The type of the response format.
24
+ * @property jsonSchema The JSON schema associated with the response format, if type is "json_schema" otherwise null.
23
25
*/
24
26
@BetaOpenAI
25
27
@Serializable(with = AssistantResponseFormat .ResponseFormatSerializer ::class )
26
28
public data class AssistantResponseFormat (
27
- val format : String? = null ,
28
- val objectType : AssistantResponseType ? = null ,
29
+ val type : String ,
30
+ val jsonSchema : JsonSchema ? = null
29
31
) {
32
+
33
+ /* *
34
+ * Represents a JSON schema.
35
+ *
36
+ * @property name The name of the schema.
37
+ * @property description The description of the schema.
38
+ * @property schema The actual JSON schema.
39
+ * @property strict Indicates if the schema is strict.
40
+ */
30
41
@Serializable
31
- public data class AssistantResponseType (
32
- val type : String
42
+ public data class JsonSchema (
43
+ val name : String ,
44
+ val description : String? = null ,
45
+ val schema : JsonObject ,
46
+ val strict : Boolean? = null
33
47
)
34
48
35
49
public companion object {
36
- public val AUTO : AssistantResponseFormat = AssistantResponseFormat (format = " auto" )
37
- public val TEXT : AssistantResponseFormat = AssistantResponseFormat (objectType = AssistantResponseType (type = " text" ))
38
- public val JSON_OBJECT : AssistantResponseFormat = AssistantResponseFormat (objectType = AssistantResponseType (type = " json_object" ))
50
+ public val AUTO : AssistantResponseFormat = AssistantResponseFormat (" auto" )
51
+ public val TEXT : AssistantResponseFormat = AssistantResponseFormat (" text" )
52
+ public val JSON_OBJECT : AssistantResponseFormat = AssistantResponseFormat (" json_object" )
53
+
54
+ /* *
55
+ * Creates an instance of `AssistantResponseFormat` with type `json_schema`.
56
+ *
57
+ * @param name The name of the schema.
58
+ * @param description The description of the schema.
59
+ * @param schema The actual JSON schema.
60
+ * @param strict Indicates if the schema is strict.
61
+ * @return An instance of `AssistantResponseFormat` with the specified JSON schema.
62
+ */
63
+ public fun JSON_SCHEMA (
64
+ name : String ,
65
+ description : String? = null,
66
+ schema : JsonObject ,
67
+ strict : Boolean? = null
68
+ ): AssistantResponseFormat = AssistantResponseFormat (
69
+ " json_schema" ,
70
+ JsonSchema (name, description, schema, strict)
71
+ )
39
72
}
40
73
74
+
41
75
public object ResponseFormatSerializer : KSerializer<AssistantResponseFormat> {
42
76
override val descriptor: SerialDescriptor = buildClassSerialDescriptor(" AssistantResponseFormat" ) {
43
- element<String >(" format" , isOptional = true )
44
- element<AssistantResponseType >(" type" , isOptional = true )
45
- }
46
-
47
- override fun serialize (encoder : Encoder , value : AssistantResponseFormat ) {
48
- val jsonEncoder = encoder as ? kotlinx.serialization.json.JsonEncoder
49
- ? : throw SerializationException (" This class can be saved only by Json" )
50
-
51
- if (value.format != null ) {
52
- jsonEncoder.encodeJsonElement(JsonPrimitive (value.format))
53
- } else if (value.objectType != null ) {
54
- val jsonElement: JsonElement = JsonObject (mapOf (" type" to JsonPrimitive (value.objectType.type)))
55
- jsonEncoder.encodeJsonElement(jsonElement)
56
- }
77
+ element<String >(" type" )
78
+ element<JsonSchema >(" json_schema" , isOptional = true ) // Only for "json_schema" type
57
79
}
58
80
59
81
override fun deserialize (decoder : Decoder ): AssistantResponseFormat {
@@ -63,14 +85,63 @@ public data class AssistantResponseFormat(
63
85
val jsonElement = jsonDecoder.decodeJsonElement()
64
86
return when {
65
87
jsonElement is JsonPrimitive && jsonElement.isString -> {
66
- AssistantResponseFormat (format = jsonElement.content)
88
+ AssistantResponseFormat (type = jsonElement.content)
67
89
}
68
90
jsonElement is JsonObject && " type" in jsonElement -> {
69
91
val type = jsonElement[" type" ]!! .jsonPrimitive.content
70
- AssistantResponseFormat (objectType = AssistantResponseType (type))
92
+ when (type) {
93
+ " json_schema" -> {
94
+ val schemaObject = jsonElement[" json_schema" ]?.jsonObject
95
+ val name = schemaObject?.get(" name" )?.jsonPrimitive?.content ? : " "
96
+ val description = schemaObject?.get(" description" )?.jsonPrimitive?.contentOrNull
97
+ val schema = schemaObject?.get(" schema" )?.jsonObject ? : JsonObject (emptyMap())
98
+ val strict = schemaObject?.get(" strict" )?.jsonPrimitive?.booleanOrNull
99
+ AssistantResponseFormat (
100
+ type = " json_schema" ,
101
+ jsonSchema = JsonSchema (name = name, description = description, schema = schema, strict = strict)
102
+ )
103
+ }
104
+ " json_object" -> AssistantResponseFormat (type = " json_object" )
105
+ " auto" -> AssistantResponseFormat (type = " auto" )
106
+ " text" -> AssistantResponseFormat (type = " text" )
107
+ else -> throw SerializationException (" Unknown response format type: $type " )
108
+ }
71
109
}
72
110
else -> throw SerializationException (" Unknown response format: $jsonElement " )
73
111
}
74
112
}
113
+
114
+ override fun serialize (encoder : Encoder , value : AssistantResponseFormat ) {
115
+ val jsonEncoder = encoder as ? kotlinx.serialization.json.JsonEncoder
116
+ ? : throw SerializationException (" This class can be saved only by Json" )
117
+
118
+ val jsonElement = when (value.type) {
119
+ " json_schema" -> {
120
+ JsonObject (
121
+ mapOf (
122
+ " type" to JsonPrimitive (" json_schema" ),
123
+ " json_schema" to JsonObject (
124
+ mapOf (
125
+ " name" to JsonPrimitive (value.jsonSchema?.name ? : " " ),
126
+ " description" to JsonPrimitive (value.jsonSchema?.description ? : " " ),
127
+ " schema" to (value.jsonSchema?.schema ? : JsonObject (emptyMap())),
128
+ " strict" to JsonPrimitive (value.jsonSchema?.strict ? : false )
129
+ )
130
+ )
131
+ )
132
+ )
133
+ }
134
+ " json_object" -> JsonObject (mapOf (" type" to JsonPrimitive (" json_object" )))
135
+ " auto" -> JsonPrimitive (" auto" )
136
+ " text" -> JsonObject (mapOf (" type" to JsonPrimitive (" text" )))
137
+ else -> throw SerializationException (" Unsupported response format type: ${value.type} " )
138
+ }
139
+ jsonEncoder.encodeJsonElement(jsonElement)
140
+ }
141
+
75
142
}
76
143
}
144
+
145
+ public fun JsonObject.Companion.buildJsonObject (block : JsonObjectBuilder .() -> Unit ): JsonObject {
146
+ return kotlinx.serialization.json.buildJsonObject(block)
147
+ }
0 commit comments