@@ -10,26 +10,43 @@ import com.google.gson.stream.JsonReader
1010import com.google.gson.stream.JsonToken
1111import com.google.gson.stream.JsonWriter
1212
13+ /* *
14+ * A Gson TypeAdapter for serializing and deserializing the `ChatChoiceChunk`
15+ * data class to and from JSON. This adapter handles the `delta` field of the
16+ * `ChatChoiceChunk` class, which can be either a string or an object.
17+ */
1318class ChatChoiceChunkAdapter : TypeAdapter <ChatChoiceChunk ?>() {
1419
20+ /* *
21+ * Serializes a `ChatChoiceChunk` object to JSON.
22+ * If the provided value is null, it is serialized to a JSON null value.
23+ *
24+ * @param writer The JsonWriter to which the value should be written.
25+ * @param value The value to be serialized.
26+ */
1527 override fun write (writer : JsonWriter , value : ChatChoiceChunk ? ) {
16- if (value == null ) {
28+ writer.beginObject()
29+ writer.name(" index" ).value(value!! .index)
30+ writer.name(" message" ).jsonValue(GsonBuilder ().create().toJson(value.message))
31+ writer.name(" delta" ).value(value.delta)
32+ writer.name(" finish_reason" )
33+
34+ // in general, it is bad practice to save a message in progress (but yes... you can do it)
35+ if (value.finishReason == null ) {
1736 writer.nullValue()
1837 } else {
19- writer.beginObject()
20- writer.name(" index" ).value(value.index)
21- writer.name(" message" ).jsonValue(GsonBuilder ().create().toJson(value.message))
22- writer.name(" delta" ).value(value.delta)
23- writer.name(" finish_reason" )
24- if (value.finishReason == null ) {
25- writer.nullValue()
26- } else {
27- writer.value(value.finishReason!! .name.lowercase())
28- }
29- writer.endObject()
38+ writer.value(value.finishReason!! .name.lowercase())
3039 }
40+ writer.endObject()
3141 }
3242
43+ /* *
44+ * Deserializes a JSON string to a `ChatChoiceChunk` object.
45+ *
46+ * @param reader The JsonReader from which the value should be read.
47+ * @return The deserialized `ChatChoiceChunk` object, or null if the JSON value is null.
48+ * @throws IllegalArgumentException if the provided string cannot be parsed to a valid `ChatChoiceChunk` object.
49+ */
3350 override fun read (reader : JsonReader ): ChatChoiceChunk ? {
3451 var index: Int = - 1
3552 var message: ChatMessage ? = null
@@ -47,6 +64,8 @@ class ChatChoiceChunkAdapter : TypeAdapter<ChatChoiceChunk?>() {
4764 }
4865 }
4966 " delta" -> {
67+ // delta -> map when returned from OpenAI (we can ignore it since we use #update(json)).
68+ // delta -> string when we store it as json.
5069 when (reader.peek()) {
5170 JsonToken .BEGIN_OBJECT -> reader.skipValue()
5271 else -> delta = reader.nextString()
@@ -63,6 +82,9 @@ class ChatChoiceChunkAdapter : TypeAdapter<ChatChoiceChunk?>() {
6382 }
6483 reader.endObject()
6584
85+ // when message == null, that means that a message has not been
86+ // provided yet. This means it is the first json message from OpenAI.
87+ // In this case, ChatUser is always assistant.
6688 return ChatChoiceChunk (index, message ? : ChatMessage (ChatUser .ASSISTANT , " " ), delta ? : " " , finishReason)
6789 }
6890}
0 commit comments