ex_openai icon indicating copy to clipboard operation
ex_openai copied to clipboard

Can't parse new OpenAI OpenAPI spec

Open nallwhy opened this issue 2 years ago • 4 comments

https://github.com/openai/openai-openapi/blob/master/openapi.yaml

== Compilation error in file lib/ex_openai.ex ==
** (FunctionClauseError) no function clause matching in ExOpenAI.Codegen.parse_component_schema/1    
    
    The following arguments were given to ExOpenAI.Codegen.parse_component_schema/1:
    
        # 1
        %{"oneOf" => [%{"$ref" => "#/components/schemas/ChatCompletionRequestMessageContentPartText"}, %{"$ref" => "#/components/schemas/ChatCompletionRequestMessageContentPartImage"}], "x-oaiExpandable" => true}
    
    lib/ex_openai/codegen.ex:394: ExOpenAI.Codegen.parse_component_schema/1
    lib/ex_openai/codegen.ex:625: anonymous fn/2 in ExOpenAI.Codegen.get_documentation/0
    (stdlib 5.0.2) maps.erl:416: :maps.fold_1/4
    lib/ex_openai/codegen.ex:624: ExOpenAI.Codegen.get_documentation/0
    lib/ex_openai.ex:31: (file)

nallwhy avatar Nov 07 '23 13:11 nallwhy

Looks like they changed the format slightly, there’s now a OneOf type for 2 different components 😅

Need to add handling for that

dvcrn avatar Nov 07 '23 22:11 dvcrn

Culprit:

    ChatCompletionRequestMessageContentPart:
      oneOf:
        - $ref: "#/components/schemas/ChatCompletionRequestMessageContentPartText"
        - $ref: "#/components/schemas/ChatCompletionRequestMessageContentPartImage"
      x-oaiExpandable: true

and

    ChatCompletionRequestMessage:
      oneOf:
        - $ref: "#/components/schemas/ChatCompletionRequestSystemMessage"
        - $ref: "#/components/schemas/ChatCompletionRequestUserMessage"
        - $ref: "#/components/schemas/ChatCompletionRequestAssistantMessage"
        - $ref: "#/components/schemas/ChatCompletionRequestToolMessage"
        - $ref: "#/components/schemas/ChatCompletionRequestFunctionMessage"
      x-oaiExpandable: true

So this is a component that can be oneOf many different components. Need to figure out a good way to represent those

dvcrn avatar Nov 08 '23 02:11 dvcrn

Hrrmmm so the issue here is that those new components aren't representable as structs in Elixir. Previously each of those had properties so it was easy. What we could do is, represent them as empty structs (%{}), but then use the @type to map them to the others, like this:

iex(3)> t ExOpenAI.Components.ChatCompletionRequestMessage
@type t() ::
        ExOpenAI.Components.ChatCompletionRequestFunctionMessage.t()
        | ExOpenAI.Components.ChatCompletionRequestToolMessage.t()
        | ExOpenAI.Components.ChatCompletionRequestAssistantMessage.t()
        | ExOpenAI.Components.ChatCompletionRequestUserMessage.t()
        | ExOpenAI.Components.ChatCompletionRequestSystemMessage.t()

Then when a function references them, it would do ExOpenAI.Components.ChatCompletionRequestMessage.t() which maps to the others

dvcrn avatar Nov 11 '23 01:11 dvcrn

Done, please give latest HEAD a try. It changes component handling a bit so I don't want to release it immediately, need to test a bit

dvcrn avatar Nov 11 '23 03:11 dvcrn