1// Package openai provides an implementation of the fantasy AI SDK for OpenAI's language models.
2package openai
3
4import (
5 "encoding/json"
6
7 "charm.land/fantasy"
8 "github.com/openai/openai-go/v2"
9)
10
11// ReasoningEffort represents the reasoning effort level for OpenAI models.
12type ReasoningEffort string
13
14const (
15 // ReasoningEffortMinimal represents minimal reasoning effort.
16 ReasoningEffortMinimal ReasoningEffort = "minimal"
17 // ReasoningEffortLow represents low reasoning effort.
18 ReasoningEffortLow ReasoningEffort = "low"
19 // ReasoningEffortMedium represents medium reasoning effort.
20 ReasoningEffortMedium ReasoningEffort = "medium"
21 // ReasoningEffortHigh represents high reasoning effort.
22 ReasoningEffortHigh ReasoningEffort = "high"
23)
24
25// Global type identifiers for OpenAI-specific provider data.
26const (
27 TypeProviderOptions = Name + ".options"
28 TypeProviderFileOptions = Name + ".file_options"
29 TypeProviderMetadata = Name + ".metadata"
30)
31
32// ProviderMetadata represents additional metadata from OpenAI provider.
33type ProviderMetadata struct {
34 Logprobs []openai.ChatCompletionTokenLogprob `json:"logprobs"`
35 AcceptedPredictionTokens int64 `json:"accepted_prediction_tokens"`
36 RejectedPredictionTokens int64 `json:"rejected_prediction_tokens"`
37}
38
39// Options implements the ProviderOptions interface.
40func (*ProviderMetadata) Options() {}
41
42// MarshalJSON implements custom JSON marshaling with type info for ProviderMetadata.
43func (m ProviderMetadata) MarshalJSON() ([]byte, error) {
44 type plain ProviderMetadata
45 raw, err := json.Marshal(plain(m))
46 if err != nil {
47 return nil, err
48 }
49 return json.Marshal(struct {
50 Type string `json:"type"`
51 Data json.RawMessage `json:"data"`
52 }{
53 Type: TypeProviderMetadata,
54 Data: raw,
55 })
56}
57
58// UnmarshalJSON implements custom JSON unmarshaling with type info for ProviderMetadata.
59func (m *ProviderMetadata) UnmarshalJSON(data []byte) error {
60 type plain ProviderMetadata
61 var pm plain
62 err := json.Unmarshal(data, &pm)
63 if err != nil {
64 return err
65 }
66 *m = ProviderMetadata(pm)
67 return nil
68}
69
70// ProviderOptions represents additional options for OpenAI provider.
71type ProviderOptions struct {
72 LogitBias map[string]int64 `json:"logit_bias"`
73 LogProbs *bool `json:"log_probs"`
74 TopLogProbs *int64 `json:"top_log_probs"`
75 ParallelToolCalls *bool `json:"parallel_tool_calls"`
76 User *string `json:"user"`
77 ReasoningEffort *ReasoningEffort `json:"reasoning_effort"`
78 MaxCompletionTokens *int64 `json:"max_completion_tokens"`
79 TextVerbosity *string `json:"text_verbosity"`
80 Prediction map[string]any `json:"prediction"`
81 Store *bool `json:"store"`
82 Metadata map[string]any `json:"metadata"`
83 PromptCacheKey *string `json:"prompt_cache_key"`
84 SafetyIdentifier *string `json:"safety_identifier"`
85 ServiceTier *string `json:"service_tier"`
86 StructuredOutputs *bool `json:"structured_outputs"`
87}
88
89// Options implements the ProviderOptions interface.
90func (*ProviderOptions) Options() {}
91
92// MarshalJSON implements custom JSON marshaling with type info for ProviderOptions.
93func (o ProviderOptions) MarshalJSON() ([]byte, error) {
94 type plain ProviderOptions
95 raw, err := json.Marshal(plain(o))
96 if err != nil {
97 return nil, err
98 }
99 return json.Marshal(struct {
100 Type string `json:"type"`
101 Data json.RawMessage `json:"data"`
102 }{
103 Type: TypeProviderOptions,
104 Data: raw,
105 })
106}
107
108// UnmarshalJSON implements custom JSON unmarshaling with type info for ProviderOptions.
109func (o *ProviderOptions) UnmarshalJSON(data []byte) error {
110 type plain ProviderOptions
111 var oo plain
112 err := json.Unmarshal(data, &oo)
113 if err != nil {
114 return err
115 }
116 *o = ProviderOptions(oo)
117 return nil
118}
119
120// ProviderFileOptions represents file options for OpenAI provider.
121type ProviderFileOptions struct {
122 ImageDetail string `json:"image_detail"`
123}
124
125// Options implements the ProviderOptions interface.
126func (*ProviderFileOptions) Options() {}
127
128// MarshalJSON implements custom JSON marshaling with type info for ProviderFileOptions.
129func (o ProviderFileOptions) MarshalJSON() ([]byte, error) {
130 type plain ProviderFileOptions
131 raw, err := json.Marshal(plain(o))
132 if err != nil {
133 return nil, err
134 }
135 return json.Marshal(struct {
136 Type string `json:"type"`
137 Data json.RawMessage `json:"data"`
138 }{
139 Type: TypeProviderFileOptions,
140 Data: raw,
141 })
142}
143
144// UnmarshalJSON implements custom JSON unmarshaling with type info for ProviderFileOptions.
145func (o *ProviderFileOptions) UnmarshalJSON(data []byte) error {
146 type plain ProviderFileOptions
147 var of plain
148 err := json.Unmarshal(data, &of)
149 if err != nil {
150 return err
151 }
152 *o = ProviderFileOptions(of)
153 return nil
154}
155
156// ReasoningEffortOption creates a pointer to a ReasoningEffort value.
157func ReasoningEffortOption(e ReasoningEffort) *ReasoningEffort {
158 return &e
159}
160
161// NewProviderOptions creates new provider options for OpenAI.
162func NewProviderOptions(opts *ProviderOptions) fantasy.ProviderOptions {
163 return fantasy.ProviderOptions{
164 Name: opts,
165 }
166}
167
168// NewProviderFileOptions creates new file options for OpenAI.
169func NewProviderFileOptions(opts *ProviderFileOptions) fantasy.ProviderOptions {
170 return fantasy.ProviderOptions{
171 Name: opts,
172 }
173}
174
175// ParseOptions parses provider options from a map.
176func ParseOptions(data map[string]any) (*ProviderOptions, error) {
177 var options ProviderOptions
178 if err := fantasy.ParseOptions(data, &options); err != nil {
179 return nil, err
180 }
181 return &options, nil
182}
183
184// Register OpenAI provider-specific types with the global registry.
185func init() {
186 fantasy.RegisterProviderType(TypeProviderOptions, func(data []byte) (fantasy.ProviderOptionsData, error) {
187 var v ProviderOptions
188 if err := json.Unmarshal(data, &v); err != nil {
189 return nil, err
190 }
191 return &v, nil
192 })
193 fantasy.RegisterProviderType(TypeProviderFileOptions, func(data []byte) (fantasy.ProviderOptionsData, error) {
194 var v ProviderFileOptions
195 if err := json.Unmarshal(data, &v); err != nil {
196 return nil, err
197 }
198 return &v, nil
199 })
200 fantasy.RegisterProviderType(TypeProviderMetadata, func(data []byte) (fantasy.ProviderOptionsData, error) {
201 var v ProviderMetadata
202 if err := json.Unmarshal(data, &v); err != nil {
203 return nil, err
204 }
205 return &v, nil
206 })
207}