16
16
17
17
package org .springframework .ai .openai ;
18
18
19
+ import java .time .Duration ;
20
+ import java .util .List ;
21
+
19
22
import org .slf4j .Logger ;
20
23
import org .slf4j .LoggerFactory ;
21
- import org .springframework .ai .image .*;
24
+
25
+ import org .springframework .ai .image .Image ;
26
+ import org .springframework .ai .image .ImageClient ;
27
+ import org .springframework .ai .image .ImageGeneration ;
28
+ import org .springframework .ai .image .ImageOptions ;
29
+ import org .springframework .ai .image .ImagePrompt ;
30
+ import org .springframework .ai .image .ImageResponse ;
31
+ import org .springframework .ai .image .ImageResponseMetadata ;
22
32
import org .springframework .ai .model .ModelOptionsUtils ;
23
- import org .springframework .ai .openai .api .*;
33
+ import org .springframework .ai .openai .api .OpenAiApi ;
34
+ import org .springframework .ai .openai .api .OpenAiImageApi ;
24
35
import org .springframework .ai .openai .metadata .OpenAiImageGenerationMetadata ;
25
36
import org .springframework .ai .openai .metadata .OpenAiImageResponseMetadata ;
26
37
import org .springframework .http .ResponseEntity ;
30
41
import org .springframework .retry .support .RetryTemplate ;
31
42
import org .springframework .util .Assert ;
32
43
33
- import java .time .Duration ;
34
- import java .util .List ;
35
-
44
+ /**
45
+ * OpenAiImageClient is a class that implements the ImageClient interface. It provides a
46
+ * client for calling the OpenAI image generation API.
47
+ *
48
+ * @author Mark Pollack
49
+ * @author Christian Tzolov
50
+ * @since 0.8.0
51
+ */
36
52
public class OpenAiImageClient implements ImageClient {
37
53
38
54
private final Logger logger = LoggerFactory .getLogger (getClass ());
39
55
40
- private OpenAiImageOptions options ;
56
+ private OpenAiImageOptions defaultOptions ;
41
57
42
58
private final OpenAiImageApi openAiImageApi ;
43
59
@@ -58,45 +74,40 @@ public OpenAiImageClient(OpenAiImageApi openAiImageApi) {
58
74
this .openAiImageApi = openAiImageApi ;
59
75
}
60
76
61
- public OpenAiImageOptions getOptions () {
62
- return options ;
77
+ public OpenAiImageOptions getDefaultOptions () {
78
+ return this .defaultOptions ;
79
+ }
80
+
81
+ public OpenAiImageClient withDefaultOptions (OpenAiImageOptions defaultOptions ) {
82
+ this .defaultOptions = defaultOptions ;
83
+ return this ;
63
84
}
64
85
65
86
@ Override
66
87
public ImageResponse call (ImagePrompt imagePrompt ) {
67
88
return this .retryTemplate .execute (ctx -> {
68
- ImageOptions runtimeOptions = imagePrompt .getOptions ();
69
- OpenAiImageOptions imageOptionsToUse = updateImageOptions (imagePrompt .getOptions ());
70
-
71
- // Merge the runtime options passed via the prompt with the
72
- // StabilityAiImageClient
73
- // options configured via Autoconfiguration.
74
- // Runtime options overwrite StabilityAiImageClient options
75
- OpenAiImageOptions optionsToUse = ModelOptionsUtils .merge (runtimeOptions , this .options ,
76
- OpenAiImageOptionsImpl .class );
77
-
78
- // Copy the org.springframework.ai.model derived ImagePrompt and ImageOptions
79
- // data
80
- // types to the data types used in OpenAiImageApi
89
+
81
90
String instructions = imagePrompt .getInstructions ().get (0 ).getText ();
82
- String size ;
83
- if (imageOptionsToUse .getWidth () != null && imageOptionsToUse .getHeight () != null ) {
84
- size = imageOptionsToUse .getWidth () + "x" + imageOptionsToUse .getHeight ();
91
+
92
+ OpenAiImageApi .OpenAiImageRequest imageRequest = new OpenAiImageApi .OpenAiImageRequest (instructions ,
93
+ OpenAiImageApi .DEFAULT_IMAGE_MODEL );
94
+
95
+ if (this .defaultOptions != null ) {
96
+ imageRequest = ModelOptionsUtils .merge (this .defaultOptions , imageRequest ,
97
+ OpenAiImageApi .OpenAiImageRequest .class );
85
98
}
86
- else {
87
- size = null ;
99
+
100
+ if (imagePrompt .getOptions () != null ) {
101
+ imageRequest = ModelOptionsUtils .merge (toOpenAiImageOptions (imagePrompt .getOptions ()), imageRequest ,
102
+ OpenAiImageApi .OpenAiImageRequest .class );
88
103
}
89
- OpenAiImageApi .OpenAiImageRequest openAiImageRequest = new OpenAiImageApi .OpenAiImageRequest (instructions ,
90
- imageOptionsToUse .getModel (), imageOptionsToUse .getN (), imageOptionsToUse .getQuality (), size ,
91
- imageOptionsToUse .getResponseFormat (), imageOptionsToUse .getStyle (), imageOptionsToUse .getUser ());
92
104
93
105
// Make the request
94
106
ResponseEntity <OpenAiImageApi .OpenAiImageResponse > imageResponseEntity = this .openAiImageApi
95
- .createImage (openAiImageRequest );
107
+ .createImage (imageRequest );
96
108
97
109
// Convert to org.springframework.ai.model derived ImageResponse data type
98
- return convertResponse (imageResponseEntity , openAiImageRequest );
99
-
110
+ return convertResponse (imageResponseEntity , imageRequest );
100
111
});
101
112
}
102
113
@@ -117,8 +128,13 @@ private ImageResponse convertResponse(ResponseEntity<OpenAiImageApi.OpenAiImageR
117
128
return new ImageResponse (imageGenerationList , openAiImageResponseMetadata );
118
129
}
119
130
120
- private OpenAiImageOptions updateImageOptions (ImageOptions runtimeImageOptions ) {
121
- OpenAiImageOptionsBuilder openAiImageOptionsBuilder = OpenAiImageOptionsBuilder .builder ();
131
+ /**
132
+ * Convert the {@link ImageOptions} into {@link OpenAiImageOptions}.
133
+ * @param defaultOptions the image options to use.
134
+ * @return the converted {@link OpenAiImageOptions}.
135
+ */
136
+ private OpenAiImageOptions toOpenAiImageOptions (ImageOptions runtimeImageOptions ) {
137
+ OpenAiImageOptions .Builder openAiImageOptionsBuilder = OpenAiImageOptions .builder ();
122
138
if (runtimeImageOptions != null ) {
123
139
// Handle portable image options
124
140
if (runtimeImageOptions .getN () != null ) {
@@ -150,8 +166,7 @@ private OpenAiImageOptions updateImageOptions(ImageOptions runtimeImageOptions)
150
166
}
151
167
}
152
168
}
153
- OpenAiImageOptions updatedOpenAiImageOptions = openAiImageOptionsBuilder .build ();
154
- return updatedOpenAiImageOptions ;
169
+ return openAiImageOptionsBuilder .build ();
155
170
}
156
171
157
172
}
0 commit comments