packages feed

openai 2.4.0 → 2.5.0

raw patch · 7 files changed

+80/−59 lines, 7 files

Files

CHANGELOG.md view
@@ -1,3 +1,7 @@+2.5.0:++- **BREAKING (streaming imports):** move chat-completion streaming payload types (`ChatCompletionChunk`, `ChunkChoice`, `Delta`, `ChatCompletionStreamEvent`) from `OpenAI.V1.Chat.Completions` to `OpenAI.V1.Chat.Completions.Stream` to avoid selector ambiguity on `choices`/`usage` in non-streaming imports.+ 2.4.0:  - Add Structured Outputs support to the Responses API (`TextConfig`, `TextFormat`, `TextFormat_JSON_Schema`).
examples/chat-completions-stream-example/Main.hs view
@@ -12,6 +12,7 @@ import qualified Data.Text.IO as TIO import qualified OpenAI.V1 as V1 import qualified OpenAI.V1.Chat.Completions as Chat+import qualified OpenAI.V1.Chat.Completions.Stream as ChatStream  main :: IO () main = do@@ -23,10 +24,10 @@     let onEvent (Left err) = hPutStrLn stderr ("stream error: " <> T.unpack err)         onEvent (Right chunk) = case chunk of             -- Print content deltas as they arrive-            Chat.ChatCompletionChunk{ Chat.choices = cs } ->+            ChatStream.ChatCompletionChunk{ ChatStream.choices = cs } ->                 mapM_ printChoice cs               where-                printChoice Chat.ChunkChoice{ Chat.delta = d } = case Chat.delta_content d of+                printChoice ChatStream.ChunkChoice{ ChatStream.delta = d } = case ChatStream.delta_content d of                     Just content -> TIO.putStr content >> hFlush stdout                     Nothing -> pure () 
openai.cabal view
@@ -1,6 +1,6 @@ cabal-version:      2.4 name:               openai-version:            2.4.0+version:            2.5.0 synopsis:           Servant bindings to OpenAI description:        This package provides comprehensive and type-safe bindings                     to OpenAI, providing both a Servant interface and@@ -53,6 +53,7 @@                         OpenAI.V1.AutoOr                         OpenAI.V1.Batches                         OpenAI.V1.Chat.Completions+                        OpenAI.V1.Chat.Completions.Stream                         OpenAI.V1.ChatKit                         OpenAI.V1.ChunkingStrategy                         OpenAI.V1.DeletionStatus
src/OpenAI/V1.hs view
@@ -134,6 +134,7 @@ import qualified OpenAI.V1.Audio as Audio import qualified OpenAI.V1.Batches as Batches import qualified OpenAI.V1.Chat.Completions as Chat.Completions+import qualified OpenAI.V1.Chat.Completions.Stream as Chat.Completions.Stream import qualified OpenAI.V1.ChatKit as ChatKit import qualified OpenAI.V1.Embeddings as Embeddings import qualified OpenAI.V1.Files as Files@@ -362,7 +363,7 @@      createChatCompletionStreamTyped         :: CreateChatCompletion-        -> (Either Text Chat.Completions.ChatCompletionStreamEvent -> IO ())+        -> (Either Text Chat.Completions.Stream.ChatCompletionStreamEvent -> IO ())         -> IO ()     createChatCompletionStreamTyped req onEvent =         createChatCompletionStream req $ \ev -> case ev of@@ -531,7 +532,7 @@         -> IO ()     , createChatCompletionStreamTyped         :: CreateChatCompletion-        -> (Either Text Chat.Completions.ChatCompletionStreamEvent -> IO ())+        -> (Either Text Chat.Completions.Stream.ChatCompletionStreamEvent -> IO ())         -> IO ()     , createResponse :: CreateResponse -> IO ResponseObject     , createResponseStream
src/OpenAI/V1/Chat/Completions.hs view
@@ -1,6 +1,7 @@ -- | @\/v1\/chat\/completions@ ----- Streaming is not implemented here;+-- Streaming payload types are available in+-- "OpenAI.V1.Chat.Completions.Stream". module OpenAI.V1.Chat.Completions     ( -- * Main types       CreateChatCompletion(..)@@ -10,11 +11,6 @@     , Message(..)     , messageToContent     , Content(..)-      -- * Streaming types-    , ChatCompletionChunk(..)-    , ChunkChoice(..)-    , Delta(..)-    , ChatCompletionStreamEvent       -- * Stream options     , ChatCompletionStreamOptions(..)     , _ChatCompletionStreamOptions@@ -429,50 +425,6 @@     , usage :: Usage CompletionTokensDetails PromptTokensDetails     } deriving stock (Generic, Show)       deriving anyclass (FromJSON, ToJSON)---- | Delta message content for streaming-data Delta = Delta-    { delta_content :: Maybe Text-    , delta_refusal :: Maybe Text-    , delta_role :: Maybe Text-    , delta_tool_calls :: Maybe (Vector ToolCall)-    } deriving stock (Generic, Show)--deltaOptions :: Options-deltaOptions = aesonOptions-    { fieldLabelModifier = stripPrefix "delta_"-    }--instance FromJSON Delta where-    parseJSON = genericParseJSON deltaOptions--instance ToJSON Delta where-    toJSON = genericToJSON deltaOptions---- | A streaming choice chunk-data ChunkChoice = ChunkChoice-    { delta :: Delta-    , finish_reason :: Maybe Text-    , index :: Natural-    , logprobs :: Maybe LogProbs-    } deriving stock (Generic, Show)-      deriving anyclass (FromJSON, ToJSON)---- | Chat completion chunk (streaming response)-data ChatCompletionChunk = ChatCompletionChunk-    { id :: Text-    , choices :: Vector ChunkChoice-    , created :: POSIXTime-    , model :: Model-    , service_tier :: Maybe ServiceTier-    , system_fingerprint :: Maybe Text-    , object :: Text-    , usage :: Maybe (Usage CompletionTokensDetails PromptTokensDetails)-    } deriving stock (Generic, Show)-      deriving anyclass (FromJSON, ToJSON)---- | Type alias for streaming events (currently just chunks)-type ChatCompletionStreamEvent = ChatCompletionChunk  -- | Servant API type API =
+ src/OpenAI/V1/Chat/Completions/Stream.hs view
@@ -0,0 +1,62 @@+-- | Streaming payload types for @/v1/chat/completions@.+module OpenAI.V1.Chat.Completions.Stream+    ( ChatCompletionChunk(..)+    , ChunkChoice(..)+    , Delta(..)+    , ChatCompletionStreamEvent+    ) where++import OpenAI.Prelude+import OpenAI.V1.Chat.Completions (LogProbs, ServiceTier)+import OpenAI.V1.Models (Model)+import OpenAI.V1.ToolCall (ToolCall)+import OpenAI.V1.Usage+    ( CompletionTokensDetails+    , PromptTokensDetails+    , Usage+    )+import Prelude hiding (id)++-- | Delta message content for streaming+data Delta = Delta+    { delta_content :: Maybe Text+    , delta_refusal :: Maybe Text+    , delta_role :: Maybe Text+    , delta_tool_calls :: Maybe (Vector ToolCall)+    } deriving stock (Generic, Show)++deltaOptions :: Options+deltaOptions = aesonOptions+    { fieldLabelModifier = stripPrefix "delta_"+    }++instance FromJSON Delta where+    parseJSON = genericParseJSON deltaOptions++instance ToJSON Delta where+    toJSON = genericToJSON deltaOptions++-- | A streaming choice chunk+data ChunkChoice = ChunkChoice+    { delta :: Delta+    , finish_reason :: Maybe Text+    , index :: Natural+    , logprobs :: Maybe LogProbs+    } deriving stock (Generic, Show)+      deriving anyclass (FromJSON, ToJSON)++-- | Chat completion chunk (streaming response)+data ChatCompletionChunk = ChatCompletionChunk+    { id :: Text+    , choices :: Vector ChunkChoice+    , created :: POSIXTime+    , model :: Model+    , service_tier :: Maybe ServiceTier+    , system_fingerprint :: Maybe Text+    , object :: Text+    , usage :: Maybe (Usage CompletionTokensDetails PromptTokensDetails)+    } deriving stock (Generic, Show)+      deriving anyclass (FromJSON, ToJSON)++-- | Type alias for streaming events (currently just chunks)+type ChatCompletionStreamEvent = ChatCompletionChunk
tasty/Main.hs view
@@ -17,7 +17,7 @@ import OpenAI.V1.Audio.Translations (CreateTranslation(..)) import OpenAI.V1.AutoOr (AutoOr(..)) import OpenAI.V1.Batches (BatchObject(..), CreateBatch(..))-import OpenAI.V1.Chat.Completions (CreateChatCompletion(..), Modality(..), ChatCompletionChunk(..), ChunkChoice(..), delta_content)+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(..))@@ -60,6 +60,7 @@ import qualified Network.HTTP.Client.TLS as TLS import qualified OpenAI.V1 as V1 import qualified OpenAI.V1.Chat.Completions as Completions+import qualified OpenAI.V1.Chat.Completions.Stream as ChatStream import qualified OpenAI.V1.Files as Files import qualified OpenAI.V1.FineTuning.Jobs as Jobs import qualified OpenAI.V1.Images.ResponseFormat as ResponseFormat@@ -356,10 +357,10 @@                let onEvent (Left _err) = Concurrent.putMVar done ()                   onEvent (Right ev) = case ev of-                    ChatCompletionChunk{ choices = cs } ->+                    ChatStream.ChatCompletionChunk{ ChatStream.choices = cs } ->                         mapM_ accChoice cs                       where-                        accChoice ChunkChoice{ delta = d } = case delta_content d of+                        accChoice ChatStream.ChunkChoice{ ChatStream.delta = d } = case ChatStream.delta_content d of                             Just content -> IORef.modifyIORef' acc (<> content)                             Nothing -> Concurrent.putMVar done () @@ -1203,7 +1204,6 @@                fineTuningTest,                batchesTest,                uploadsTest,-               createImageMinimalTest,                createImageMaximalTest,                createImageEditMinimalTest,                createImageEditMaximalTest,