diff --git a/src/StructuredOutputs.jl b/src/StructuredOutputs.jl index c2e6921..1ac8650 100644 --- a/src/StructuredOutputs.jl +++ b/src/StructuredOutputs.jl @@ -3,6 +3,7 @@ module StructuredOutputs using JSON3, StructTypes using REPL # needed for Docs.doc in _getdoc +include("json3_issue272.jl") # workaround to an issue with JSON3.jl include("enum_replacement.jl") # `OneOf` as a replacement for `Enum` include("logprobs.jl") # correlate logprobs of tokens with items in struct include("schema.jl") # generate a JSON schema from a Julia type diff --git a/src/json3_issue272.jl b/src/json3_issue272.jl new file mode 100644 index 0000000..e95c52e --- /dev/null +++ b/src/json3_issue272.jl @@ -0,0 +1,15 @@ +""" +Wrapper type used for a workaround to https://github.com/quinnj/JSON3.jl/issues/272 +until that issue is resolved. +""" +struct Workaround272{T} <: AbstractString + str::T +end + +JSON3.read_json_str(s::Workaround272) = s.str + +""" +Parse a JSON string using `JSON3.read`, without first trying to interpret it as a filename. +""" +parse_json(s::AbstractString) = JSON3.read(Workaround272(s)) +parse_json(s::AbstractString, t) = JSON3.read(Workaround272(s), t) diff --git a/src/openAI.jl b/src/openAI.jl index ba1ba71..0da714a 100644 --- a/src/openAI.jl +++ b/src/openAI.jl @@ -61,7 +61,7 @@ function _get_choice(T, c) c.finish_reason == "length" && error("JSON output not complete due to length limit.") c.finish_reason == "content_filter" && error("JSON output not complete due to content filter.") hasproperty(c.message, :refusal) && !isnothing(c.message.refusal) && error("Refused with message: ", c.message.refusal) - o = JSON3.read(c.message.content, T) + o = parse_json(c.message.content, T) if hasproperty(c, :logprobs) find_logprobs!(o, c.logprobs.content) else diff --git a/test/runtests.jl b/test/runtests.jl index 88726db..8f21f47 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,5 +1,5 @@ using StructuredOutputs -using StructuredOutputs: system, assistant, user, get_choice, response_format +using StructuredOutputs: system, assistant, user, get_choice, response_format, parse_json using Test using JSON3 using JSONSchema @@ -64,7 +64,7 @@ end # For now it is better to use Union than absstract type... o15b = FooOrBar[Foo(42, "Hi"), Bar(Foo(0, "bye"), nothing)] - @test_throws ArgumentError JSON3.read(JSON3.write(o15b), typeof(o15b)) + @test_throws ArgumentError parse_json(JSON3.write(o15b), typeof(o15b)) noS = Schema(JSON3.write(StructuredOutputs.schema(typeof((invalid=true,))))) @@ -78,11 +78,11 @@ end #println("Object:") #println(jo) S = Schema(js) - pjo = JSON3.read(jo) # Object in JSON3.Object form + pjo = parse_json(jo) # Object in JSON3.Object form @test validate(S, pjo) === nothing @test validate(noS, pjo) !== nothing #r = StructTypes.constructfrom(t, pjo) # Object restored into type t. - r = JSON3.read(jo, t) # skip StructTypes + r = parse_json(jo, t) # skip StructTypes @test typeof(r) == t @test r == o end