-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
884ab3d
commit 3321b6e
Showing
11 changed files
with
283 additions
and
4 deletions.
There are no files selected for viewing
14 changes: 14 additions & 0 deletions
14
src/main/java/ch/akop/homesystem/config/properties/OpenAIProperties.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package ch.akop.homesystem.config.properties; | ||
|
||
import ch.akop.homesystem.openai.ImageRequest; | ||
import lombok.Value; | ||
import org.springframework.boot.context.properties.ConfigurationProperties; | ||
import org.springframework.boot.context.properties.ConstructorBinding; | ||
|
||
@Value | ||
@ConstructorBinding | ||
@ConfigurationProperties(prefix = "home-automation.openai") | ||
public class OpenAIProperties { | ||
String apiKey; | ||
ImageRequest.Size size; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package ch.akop.homesystem.openai; | ||
|
||
import com.fasterxml.jackson.annotation.JsonProperty; | ||
import com.fasterxml.jackson.annotation.JsonValue; | ||
import lombok.Data; | ||
import lombok.Getter; | ||
import lombok.RequiredArgsConstructor; | ||
|
||
@Data | ||
public class ImageRequest { | ||
private String prompt; | ||
private int n; | ||
private Size size; | ||
|
||
@JsonProperty("response_format") | ||
private ResponseFormat responseFormat; | ||
|
||
@RequiredArgsConstructor | ||
public enum Size { | ||
SMALL("256x256"), | ||
MEDIUM("512x512"), | ||
BIG("1024x1024"); | ||
|
||
@Getter | ||
@JsonValue | ||
private final String text; | ||
} | ||
|
||
@RequiredArgsConstructor | ||
public enum ResponseFormat { | ||
URL("url"), | ||
B64_JSON("b64_json"); | ||
|
||
@Getter | ||
@JsonValue | ||
private final String text; | ||
|
||
} | ||
} |
56 changes: 56 additions & 0 deletions
56
src/main/java/ch/akop/homesystem/openai/OpenAIService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
package ch.akop.homesystem.openai; | ||
|
||
import ch.akop.homesystem.config.properties.OpenAIProperties; | ||
import lombok.RequiredArgsConstructor; | ||
import lombok.SneakyThrows; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.springframework.http.MediaType; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.web.reactive.function.BodyInserters; | ||
import org.springframework.web.reactive.function.client.WebClient; | ||
import reactor.core.publisher.Mono; | ||
|
||
import javax.annotation.PostConstruct; | ||
import java.util.Base64; | ||
|
||
import static ch.akop.homesystem.openai.ImageRequest.ResponseFormat.B64_JSON; | ||
|
||
@Slf4j | ||
@Service | ||
@RequiredArgsConstructor | ||
public class OpenAIService { | ||
|
||
private final OpenAIProperties openAIProperties; | ||
private WebClient apiWebClient; | ||
|
||
|
||
@PostConstruct | ||
protected void initializeWebClients() { | ||
apiWebClient = WebClient.builder() | ||
.baseUrl("https://api.openai.com/v1/") | ||
.defaultHeaders(header -> header.setBearerAuth(openAIProperties.getApiKey())) | ||
.codecs(codecs -> codecs.defaultCodecs().maxInMemorySize(1024 * 1024 * 10)) | ||
.build(); | ||
} | ||
|
||
@SneakyThrows | ||
public Mono<byte[]> requestImage(String text) { | ||
var requestBody = new ImageRequest() | ||
.setResponseFormat(B64_JSON) | ||
.setN(1) | ||
.setSize(openAIProperties.getSize()) | ||
.setPrompt(text); | ||
|
||
log.info("Request a {} open-ai image for: {}", requestBody.getSize(), text); | ||
|
||
return apiWebClient.post() | ||
.uri("images/generations") | ||
.body(BodyInserters.fromValue(requestBody)) | ||
.headers(header -> header.setContentType(MediaType.APPLICATION_JSON)) | ||
.retrieve() | ||
.bodyToMono(Response.class) | ||
.map(response -> response.getData().get(0).getB64_json()) | ||
.map(b64 -> Base64.getDecoder().decode(b64)); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package ch.akop.homesystem.openai; | ||
|
||
import lombok.Data; | ||
|
||
import java.util.List; | ||
|
||
@Data | ||
public class Response { | ||
|
||
private List<ResponseData> data; | ||
|
||
@Data | ||
public static class ResponseData { | ||
private String url; | ||
private String b64_json; | ||
} | ||
|
||
} |
26 changes: 26 additions & 0 deletions
26
src/main/java/ch/akop/homesystem/persistence/model/ImageOfOpenAI.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package ch.akop.homesystem.persistence.model; | ||
|
||
import lombok.Getter; | ||
import lombok.NonNull; | ||
import lombok.Setter; | ||
|
||
import javax.persistence.*; | ||
import java.time.LocalDateTime; | ||
|
||
@Entity | ||
@Table(name = "openai_images") | ||
@Getter | ||
@Setter | ||
public class ImageOfOpenAI { | ||
|
||
@Id | ||
private LocalDateTime created = LocalDateTime.now(); | ||
|
||
@Column(nullable = false) | ||
@NonNull | ||
private String prompt; | ||
|
||
@Lob | ||
private byte[] image; | ||
|
||
} |
12 changes: 12 additions & 0 deletions
12
src/main/java/ch/akop/homesystem/persistence/repository/OpenAIImageRepository.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package ch.akop.homesystem.persistence.repository; | ||
|
||
import ch.akop.homesystem.persistence.model.ImageOfOpenAI; | ||
import org.springframework.data.jpa.repository.JpaRepository; | ||
import org.springframework.stereotype.Repository; | ||
|
||
import java.time.LocalDateTime; | ||
|
||
@Repository | ||
public interface OpenAIImageRepository extends JpaRepository<ImageOfOpenAI, LocalDateTime> { | ||
|
||
} |
7 changes: 7 additions & 0 deletions
7
src/main/java/ch/akop/homesystem/services/ImageCreatorService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package ch.akop.homesystem.services; | ||
|
||
public interface ImageCreatorService { | ||
|
||
void generateAndSendDailyImage(); | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
87 changes: 87 additions & 0 deletions
87
src/main/java/ch/akop/homesystem/services/impl/ImageCreatorServiceImpl.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
package ch.akop.homesystem.services.impl; | ||
|
||
import ch.akop.homesystem.openai.OpenAIService; | ||
import ch.akop.homesystem.persistence.model.ImageOfOpenAI; | ||
import ch.akop.homesystem.persistence.repository.OpenAIImageRepository; | ||
import ch.akop.homesystem.services.ImageCreatorService; | ||
import ch.akop.homesystem.services.MessageService; | ||
import ch.akop.homesystem.services.WeatherService; | ||
import ch.akop.weathercloud.Weather; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.stereotype.Service; | ||
|
||
import java.util.List; | ||
|
||
import static ch.akop.weathercloud.rain.RainUnit.MILLIMETER_PER_HOUR; | ||
import static ch.akop.weathercloud.temperature.TemperatureUnit.DEGREE; | ||
|
||
@Service | ||
@RequiredArgsConstructor | ||
public class ImageCreatorServiceImpl implements ImageCreatorService { | ||
|
||
private final OpenAIService imageService; | ||
private final OpenAIImageRepository imageRepository; | ||
private final MessageService messageService; | ||
private final WeatherService weatherService; | ||
|
||
|
||
@Override | ||
public void generateAndSendDailyImage() { | ||
var prompt = generatePrompt(); | ||
imageService.requestImage(prompt) | ||
.subscribe(image -> { | ||
messageService.sendImageToMainChannel(image, prompt); | ||
imageRepository.save(new ImageOfOpenAI().setPrompt(prompt).setImage(image)); | ||
}); | ||
} | ||
|
||
private String generatePrompt() { | ||
var atTheBeginning = List.of("A swiss house in the mountains with a lake", | ||
"A train passing wonderful mountains", | ||
"A blue Ford Kuga MK 2 on the highway"); | ||
|
||
var inTheMiddle = weatherService.getWeather() | ||
.take(1) | ||
.map(this::extractTextFromWeather) | ||
.blockingFirst(); | ||
|
||
var atTheEnd = List.of("as an oil painting", | ||
"as a stained glass window", | ||
"as an abstract pencil and watercolor drawing", | ||
"in digital art", | ||
"as a realistic photograph", | ||
"as a 3D render", | ||
"in Van Gogh style"); | ||
|
||
return "%s %s %s".formatted(atTheBeginning, inTheMiddle, atTheEnd); | ||
} | ||
|
||
private String extractTextFromWeather(Weather weather) { | ||
|
||
var isRaining = weather.getRain().isBiggerThan(0, MILLIMETER_PER_HOUR); | ||
var isCold = weather.getOuterTemperatur().isSmallerThan(5, DEGREE); | ||
var isWarm = weather.getOuterTemperatur().isBiggerThan(15, DEGREE); | ||
|
||
if (isRaining && isCold) { | ||
return "on cold and rainy day"; | ||
} | ||
|
||
if (isRaining && isWarm) { | ||
return "on a summer rainy day"; | ||
} | ||
|
||
if (isRaining) { | ||
return "on a rainy day"; | ||
} | ||
|
||
if (isCold) { | ||
return "in the winter"; | ||
} | ||
|
||
if (isWarm) { | ||
return "in the summer"; | ||
} | ||
|
||
return ""; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters