openai 2.5.3 → 2.5.4
raw patch · 4 files changed
+79/−43 lines, 4 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ OpenAI.V1.Chat.Completions: ReasoningEffort_None :: ReasoningEffort
Files
- CHANGELOG.md +4/−0
- openai.cabal +3/−1
- src/OpenAI/V1/Chat/Completions.hs +2/−1
- tasty/Main.hs +70/−41
CHANGELOG.md view
@@ -1,3 +1,7 @@+2.5.4:++- Add `ReasoningEffort_None` support to chat completions, serialized as `"none"`.+ 2.5.3: - Fix streaming Responses and chat-completions requests so caller-injected headers added via `ClientEnv.middleware` are preserved on the wire.
openai.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.4 name: openai-version: 2.5.3+version: 2.5.4 synopsis: Servant bindings to OpenAI description: This package provides comprehensive and type-safe bindings to OpenAI, providing both a Servant interface and@@ -117,8 +117,10 @@ , aeson , http-client , http-client-tls+ , http-types , openai , servant-client+ , servant-client-core , tasty , tasty-hunit , text
src/OpenAI/V1/Chat/Completions.hs view
@@ -215,7 +215,8 @@ -- | Constrains effort on reasoning for reasoning models data ReasoningEffort- = ReasoningEffort_Minimal+ = ReasoningEffort_None+ | ReasoningEffort_Minimal | ReasoningEffort_Low | ReasoningEffort_Medium | ReasoningEffort_High
tasty/Main.hs view
@@ -1,34 +1,42 @@-{-# LANGUAGE BlockArguments, DuplicateRecordFields, NamedFieldPuns #-}-{-# LANGUAGE OverloadedLists, OverloadedStrings, RecordWildCards #-}-{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE BlockArguments #-}+{-# LANGUAGE DuplicateRecordFields #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE OverloadedLists #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE ScopedTypeVariables #-} {-# OPTIONS_GHC -Wno-orphans #-} module Main where -import Data.Aeson ((.=))+import Control.Exception (SomeException, catch)+import Data.Aeson ((.=)) import qualified Data.Aeson as Aeson import qualified Data.Aeson.KeyMap as KeyMap-import Control.Exception (SomeException, catch)-import Data.Foldable (toList)-import Data.Maybe (isJust, listToMaybe)-import OpenAI.V1 (Methods(..))-import OpenAI.V1.Audio.Speech (CreateSpeech(..), Voice(..), _CreateSpeech)-import OpenAI.V1.Audio.Transcriptions (CreateTranscription(..))-import OpenAI.V1.Audio.Translations (CreateTranslation(..))-import OpenAI.V1.AutoOr (AutoOr(..))-import OpenAI.V1.Batches (BatchObject(..), CreateBatch(..))-import OpenAI.V1.Chat.Completions (CreateChatCompletion(..), Modality(..))-import OpenAI.V1.Embeddings (CreateEmbeddings(..), EncodingFormat(..))-import OpenAI.V1.Files (FileObject(..), Order(..), UploadFile(..))-import OpenAI.V1.Images.Edits (CreateImageEdit(..))-import OpenAI.V1.Images.Generations (CreateImage(..), Quality(..), Style(..))-import OpenAI.V1.Images.Variations (CreateImageVariation(..))-import OpenAI.V1.Message (Message(..))-import OpenAI.V1.Moderations (CreateModeration(..))-import OpenAI.V1.Threads.Messages (MessageObject(..), ModifyMessage(..))-import OpenAI.V1.Tool (CodeInterpreterContainer(..), Tool(..), ToolChoice(..))-import OpenAI.V1.ToolCall (ToolCall(..))-import Prelude hiding (id)+import Data.Foldable (toList)+import Data.Maybe (isJust, listToMaybe)+import OpenAI.V1 (Methods(..))+import OpenAI.V1.Audio.Speech+ (CreateSpeech(..), Voice(..), _CreateSpeech)+import OpenAI.V1.Audio.Transcriptions (CreateTranscription(..))+import OpenAI.V1.Audio.Translations (CreateTranslation(..))+import OpenAI.V1.AutoOr (AutoOr(..))+import OpenAI.V1.Batches (BatchObject(..), CreateBatch(..))+import OpenAI.V1.Chat.Completions+ (CreateChatCompletion(..), Modality(..))+import OpenAI.V1.Embeddings (CreateEmbeddings(..), EncodingFormat(..))+import OpenAI.V1.Files (FileObject(..), Order(..), UploadFile(..))+import OpenAI.V1.Images.Edits (CreateImageEdit(..))+import OpenAI.V1.Images.Generations (CreateImage(..))+import OpenAI.V1.Images.Variations (CreateImageVariation(..))+import OpenAI.V1.Message (Message(..))+import OpenAI.V1.Moderations (CreateModeration(..))+import OpenAI.V1.Threads.Messages+ (MessageObject(..), ModifyMessage(..))+import OpenAI.V1.Tool+ (CodeInterpreterContainer(..), Tool(..), ToolChoice(..))+import OpenAI.V1.ToolCall (ToolCall(..))+import Prelude hiding (id) import OpenAI.V1.Assistants (AssistantObject(..), CreateAssistant(..), ModifyAssistant(..))@@ -58,6 +66,7 @@ import qualified Data.Text.Encoding as Text.Encoding import qualified Network.HTTP.Client as HTTP.Client import qualified Network.HTTP.Client.TLS as TLS+import qualified Network.HTTP.Types.Status as HTTP.Status import qualified OpenAI.V1 as V1 import qualified OpenAI.V1.Chat.Completions as Completions import qualified OpenAI.V1.Chat.Completions.Stream as ChatStream@@ -68,6 +77,7 @@ import qualified OpenAI.V1.Tool as Tool import qualified OpenAI.V1.ToolCall as ToolCall import qualified Servant.Client as Client+import qualified Servant.Client.Core.Response as Client.Response import qualified System.Environment as Environment import qualified Test.Tasty as Tasty import qualified Test.Tasty.HUnit as HUnit@@ -94,6 +104,16 @@ let ttsModel = "tts-1" let Methods {..} = V1.makeMethods clientEnv (Text.pack key) Nothing Nothing + let createImageVariationWhenAvailable request =+ (createImageVariation request >> return ())+ `catch` \(clientError :: Client.ClientError) ->+ case clientError of+ -- DALL-E 2 variations are not enabled for every project.+ Client.FailureResponse _ response+ | Client.Response.responseStatusCode response == HTTP.Status.status404 ->+ return ()+ _ -> HUnit.assertFailure (show clientError)+ -- Test each format to make sure we're handling each possible content type -- correctly let speechTest format =@@ -371,8 +391,8 @@ HUnit.assertBool "Expected non-empty streamed text" (not (Text.null text)) return ()- + let embeddingsTest = do HUnit.testCase "Create embedding" do _ <-@@ -516,18 +536,18 @@ return () - let createImageMaximalTest = do- HUnit.testCase "Create image - maximal" do+ let createImageConfiguredTest = do+ HUnit.testCase "Create image - configured" do _ <- createImage CreateImage { prompt = "A baby panda",- model = Just "dall-e-3",+ model = Just "gpt-image-1", n = Just 1,- quality = Just Standard,- response_format = Just ResponseFormat.URL,+ quality = Nothing,+ response_format = Nothing, size = Just "1024x1024",- style = Just Vivid,+ style = Nothing, user = Just user } @@ -541,7 +561,7 @@ { image = "tasty/data/v1/images/image.png", prompt = "The panda should be greener", mask = Nothing,- model = Nothing,+ model = Just "gpt-image-1", n = Nothing, size = Nothing, response_format = Nothing,@@ -558,10 +578,10 @@ { image = "tasty/data/v1/images/image.png", prompt = "The panda should be greener", mask = Nothing,- model = Just "dall-e-2",+ model = Just "gpt-image-1", n = Just 1, size = Just "1024x1024",- response_format = Just ResponseFormat.URL,+ response_format = Nothing, user = Just user } @@ -570,7 +590,7 @@ let createImageVariationMinimalTest = do HUnit.testCase "Create image variation - minimal" do _ <-- createImageVariation+ createImageVariationWhenAvailable CreateImageVariation { image = "tasty/data/v1/images/image.png", model = Nothing,@@ -585,7 +605,7 @@ let createImageVariationMaximalTest = do HUnit.testCase "Create image variation - maximal" do _ <-- createImageVariation+ createImageVariationWhenAvailable CreateImageVariation { image = "tasty/data/v1/images/image.png", model = Just "dall-e-2",@@ -810,6 +830,13 @@ let vectorStoreFilesTest = do HUnit.testCase "Vector store file and batch operations" do+ FileObject {id = seedFileId} <-+ uploadFile+ UploadFile+ { file = "tasty/data/v1/vector_stores/index.html",+ purpose = Files.Assistants+ }+ FileObject {id = fileId} <- uploadFile UploadFile@@ -820,7 +847,7 @@ VectorStoreObject {id = vectorStoreId} <- createVectorStore CreateVectorStore- { file_ids = [],+ { file_ids = [seedFileId], name = Nothing, expires_after = Nothing, chunking_strategy = Nothing,@@ -870,14 +897,14 @@ metadata = Nothing } - _ <- cancelVectorStoreFileBatch vectorStoreId batchId- _ <- deleteVectorStoreFile vectorStoreId vectorStoreFileId _ <- deleteVectorStore vectorStoreId _ <- deleteFile fileId + _ <- deleteFile seedFileId+ return () Left _ -> do -- If batch creation fails (likely due to size limit), still test other operations@@ -904,6 +931,8 @@ _ <- deleteFile fileId + _ <- deleteFile seedFileId+ return () let responsesMinimalTest =@@ -1221,7 +1250,7 @@ fineTuningTest, batchesTest, uploadsTest,- createImageMaximalTest,+ createImageConfiguredTest, createImageEditMinimalTest, createImageEditMaximalTest, createImageVariationMinimalTest,