openai / openai/openai-java

Deserializing ResponseInputItem results in unknown state

Open
#584 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug spec
Dominant language
Kotlin
Stars
1.5k
Forks
264
Avg merge
9h 46m
Merged PRs (30d)
96

Description

Hey there! 👋

I'm working with the OpenAI Java SDK for a couple of days now and really like it. The general design of the library is fantastic and I'm having quite a lot fun working with it. Thanks! 👍

I stumbled upon an issue which I think is a bug. Let me first clarify about my goals: I'm using the Responses API part of the library to implement Chat-Bot like conversations. My requirement is to use ResponseCreateParams.builder().store(false) and instead serialize conversation state locally by myself.

Here's an example of what I do:

val jsonMapper = jsonMapper()
val inputItems: List<ResponseInputItem> = ...
val jsonData = jsonMapper.writeValueAsString(inputItems)
// store jsonData locally

// later:
val deserializedInputItems = jsonMapper.readValue(nativeData, object : TypeReference<MutableList<ResponseInputItem>>() {})
// attach new user message and continue conversation

This works pretty well. However I've noticed the following behavior:

When a ResponseInputItem from a ResponseInputItem.Message gets serialized and deserialized again, it's in an unknown state. The message field is null but the _json() field still holds the correct structured data from the original message.

Here's are a Kotlin Test to demonstrate the behavior:

❌ This test fails with v3.0.3

@Test
fun testSerializeInputItem() {
    // given
    val message = ResponseInputItem.Message.builder()
        .role(ResponseInputItem.Message.Role.USER)
        .addInputTextContent("Test")
        .build()
    val inputItem1 = ResponseInputItem.ofMessage(message)

    // when
    val jsonMapper = jsonMapper()
    val inputItemJson = jsonMapper.writeValueAsString(inputItem1)
    val inputItem2 = jsonMapper.readValue(inputItemJson, ResponseInputItem::class.java)

    // then
    Assertions.assertEquals(inputItem1, inputItem2)
}

Test fails:

Expected :ResponseInputItem{message=Message{content=[ResponseInputContent{inputText=ResponseInputText{text=Test, type=input_text, additionalProperties={}}}], role=user, status=, type=, additionalProperties={}}}
Actual   :ResponseInputItem{_unknown={content=[{text=Test, type=input_text}], role=user}}

I couldn't reproduce this issue with other types of ResponseInputItems, e.g. for ResponseOutputMessage the test succeeds:

🟢 This test succeeds with v3.0.3

@Test
fun testSerializeOutputItem() {
    val message = ResponseOutputMessage.builder()
        .id("my_id")
        .status(ResponseOutputMessage.Status.COMPLETED)
        .addContent(
            ResponseOutputText.builder()
                .text("Test")
                .annotations(emptyList())
                .build()
        )
        .build()
    val inputItem1 = ResponseInputItem.ofResponseOutputMessage(message)

    val jsonMapper = jsonMapper()
    val inputItemJson = jsonMapper.writeValueAsString(inputItem1)

    val inputItem2 = jsonMapper.readValue(inputItemJson, ResponseInputItem::class.java)
    Assertions.assertEquals(inputItem1, inputItem2)
}

Could you please clarify if this a bug? Or am I doing something wrong / unintended here?

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the ResponseInputItem.Message deserialization path and compare it with the ResponseOutputMessage path, using the supplied testSerializeInputItem reproduction. Confirm that serialized and deserialized ResponseInputItem.Message values compare equal without becoming unknown; the existing output-item test provides a working comparison case.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, kotlin
Domain
api
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.