lancecarlson/openai.cr

[bug] Compilation failure when parameter hash contains non-strings

Opened this issue · 0 comments

Environment:

  • Affected Crystal Versions: (probably not relevant)
    • Crystal 1.7.3 [d61a01e18] (2023-03-07)
    • Crystal 1.10.1 [c6f3552f5] (2023-10-13)
  • Affected openai.cr versions:
    • Latest main branch (commit bdbd3df)
    • Note: the same code was compiling with success when using older versions of the openai.cr library (before introduction of function calls).

Reproduction Steps:

  • Implemented the openai.cr library within a Crystal-lang project.
  • Supplied the following hash of parameters to the openai.chat method :
{
  "temperature" => 0.8,
  "presence_penalty" => 1.0,
  "frequency_penalty" => 1.0,
  "max_tokens" => 384
}

Expected Behavior:

The expected behavior is a successful compilation of the project with the provided parameter hash in the method call, without triggering any errors.

Actual Behavior:

Encountered a compilation error concerning the handling of the parameters hash:

In src/requests/generic_request.cr:11:23

 11 | result = openai.chat(
                      ^---
Error: instantiating 'OpenAI::Client#chat(String, Array(NamedTuple(role: String, content: String)), Hash(String, Float64 | Int32 | Nil))'

In lib/openai/src/client.cr:18:67

 18 | if parameters["functions"]?.nil? || parameters["functions"].empty?
                                                                  ^-----
Error: undefined method 'empty?' for Float64 (compile-time type is (Array(NamedTuple(role: String, content: String)) | Float64 | Int32 | String | Nil))

Insights/Fixes:

The issue appears to arise from a method (empty?) being incorrectly applied to a Float64 object as part of a parameters hash (where only strings where expected?) during the compilation process, resulting in a type mismatch error.

Proposed patch

diff --git a/src/client.cr b/src/client.cr
index 616a04e..86b0e9f 100644
--- a/src/client.cr
+++ b/src/client.cr
@@ -15,7 +15,8 @@ module OpenAI
       parameters = prepare_chat_parameters(model, messages, options)
       path = "/chat/completions"
 
-      if parameters["functions"]?.nil? || parameters["functions"].empty?
+      parameters_function = parameters["functions"]?
+      if parameters_function.nil? || (parameters_function.is_a?(String) && parameters_function.empty?)
         ChatResponse.from_json(post(path: path, parameters: parameters))
       else
         ChatFunctionResponse.from_json(post(path: path, parameters: parameters))