Created
May 11, 2026 10:20
-
-
Save pagetronic/1b92d2c079773b3305b6d2bd834d0e32 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
| package com.agroneo; | |
| import com.google.genai.Client; | |
| import com.google.genai.errors.ClientException; | |
| import com.google.genai.types.*; | |
| import live.page.hubd.system.db.Db; | |
| import live.page.hubd.system.json.Json; | |
| import live.page.hubd.system.utils.Fx; | |
| import live.page.hubd.system.utils.ai.models.Gemini; | |
| import org.apache.commons.io.FileUtils; | |
| import java.io.File; | |
| import java.io.IOException; | |
| import java.nio.charset.StandardCharsets; | |
| import java.util.*; | |
| import java.util.concurrent.TimeUnit; | |
| public class GenerateGarden { | |
| public static void main(String[] args) { | |
| image("z-001-1-2"); | |
| //update("Ajoute 3 Events", "z-001-1-2"); | |
| Fx.log("done"); | |
| } | |
| private static void init() { | |
| List<Content> contents = new ArrayList<>(); | |
| contents.add(Content.builder().role("user").parts(Part.fromText("Commençons par 3 catégories à la racines qui contienne jusqu'à 20 déscendants sur 4 niveaux.")).build()); | |
| Json data = generate(contents); | |
| java.io.File result = new java.io.File("/data/repo/PageBack/Utils/res/result.json"); | |
| try { | |
| FileUtils.write(result, data.toString(false), StandardCharsets.UTF_8); | |
| } catch (IOException e) { | |
| throw new RuntimeException(e); | |
| } | |
| contents.add(Content.builder().role("assistant").parts(Part.fromText(data.toString(true))).build()); | |
| } | |
| private static void update(String what, String where) { | |
| try { | |
| java.io.File result = new java.io.File("/data/repo/PageBack/Utils/res/result.json"); | |
| String histo = FileUtils.readFileToString(result, StandardCharsets.UTF_8); | |
| List<Content> contents = new ArrayList<>(); | |
| contents.add(Content.builder().role("assistant").parts(Part.fromText(histo)).build()); | |
| contents.add(Content.builder().role("user").parts(Part.fromText("Pour l'éléments \"" + where + ", " + | |
| "donne moi en réponse uniquement les nouveaux children pout cet élément: {\"id\": \"" + where + "\",\"children\": [\n..." + what + "...\n]")).build()); | |
| Json data = generate(contents); | |
| Json root = new Json(histo); | |
| if (where.equals(data.getId()) && injectChildren(root, data)) { | |
| FileUtils.write(result, root.toString(false), StandardCharsets.UTF_8); | |
| } else { | |
| Fx.log("Element not found: " + where); | |
| Fx.log(data); | |
| } | |
| } catch (IOException e) { | |
| throw new RuntimeException(e); | |
| } | |
| } | |
| private static Json generate(List<Content> contents) { | |
| String instruction = "Output ONLY a valid JSON object. No explanations, no markdown, no code fences, no comments.\n" + | |
| "Current date : " + Fx.dateFormater().format(new Date()) + | |
| "Translate the Json in the language code ISO-639-1 provided by the user using the \"context\" entry to contextualize the translation.\n" + | |
| "Responds only in the language specified by user." + | |
| "Example of output format: \n" + | |
| new Json(Fx.getResource("/res/garden.json")).toString(false); | |
| instruction += """ | |
| \s | |
| Je veux générer des éléments afin de remplir une interface de test pour un logiciel de gestion agricole, suivi des cultures et du bétail. | |
| Les types sont : Zones, Cultures, Events. Les Zones peuvent contenir Zones, Cultures, Events. Cultures peuvent contenir Cultures, Events. Events peut contenir des Events. | |
| Zones sont des zones, des plate-bandes de plantation, des batiments, des champs, des jardins.. | |
| Cultures sont ce qui est planté ou les animaux élevés.. | |
| Events sont les évènements comme l'arrosage, les maladies, la nouritures, les apports d'engrais.. Les Events contenu dans un Events sont les déclinaisons du parent. | |
| Change les dates pour avoir une cohérence de date comme si c'était réel. | |
| Génère un ID unique pour chaque éléments | |
| Je veux une réponse en Français. | |
| \s"""; | |
| try (Client client = Client.builder().apiKey(Gemini.apiKey).build()) { | |
| GenerateContentConfig config = GenerateContentConfig.builder() | |
| .responseModalities("TEXT") | |
| .responseMimeType("application/json") | |
| .systemInstruction(Content.fromParts(Part.fromText(instruction))) | |
| .build(); | |
| GenerateContentResponse response = client.models.generateContent( | |
| Gemini.Model.geminiFlashLatest.getKey(), contents, config); | |
| Part part = response.parts().get(0); | |
| if (part.text().isPresent()) { | |
| String raw = part.text().get().replaceAll("```(json)?\\s*|\\s*```", "").trim(); | |
| int start = raw.indexOf('{'); | |
| int end = raw.lastIndexOf('}'); | |
| if (start >= 0 && end > start) { | |
| raw = raw.substring(start, end + 1); | |
| } | |
| try { | |
| return new Json(raw); | |
| } catch (Exception e) { | |
| Fx.log(part.text().get()); | |
| throw new Exception(e); | |
| } | |
| } | |
| } catch (ClientException e) { | |
| Fx.log(e.getMessage()); | |
| try { | |
| Thread.sleep(TimeUnit.SECONDS.toMillis(60)); | |
| } catch (InterruptedException ignore) { | |
| } | |
| Fx.log("Retry "); | |
| return generate(contents); | |
| } catch (Exception e) { | |
| Fx.log(e.getMessage()); | |
| } | |
| return null; | |
| } | |
| private static File image(String id) { | |
| try { | |
| File file = new File("/data/repo/PageBack/Utils/res/images/" + id + "/", Db.getKey() + ".png"); | |
| file.getParentFile().mkdirs(); | |
| java.io.File result = new java.io.File("/data/repo/PageBack/Utils/res/result.json"); | |
| Json data = new Json(FileUtils.readFileToString(result, StandardCharsets.UTF_8)); | |
| String instruction = """ | |
| \s | |
| Je veux générer des éléments afin de remplir une interface de test pour un logiciel de gestion agricole, suivi des cultures et du bétail. | |
| Zones sont des zones, des plate-bandes de plantation, des batiments, des champs, des jardins.. | |
| Cultures sont ce qui est planté ou les animaux élevés.. | |
| Events sont les évènements comme l'arrosage, les maladies, la nouritures, les apports d'engrais.. Les Events contenu dans un Events sont les déclinaisons du parent. | |
| Génère des images de style réel, représentant des photos prises pour illustrer l'élément indiqué. | |
| \s"""; | |
| instruction += "\n\nLes données: " + data.toString(false); | |
| try (Client client = Client.builder().apiKey(Gemini.apiKey).build()) { | |
| GenerateContentConfig config = GenerateContentConfig.builder() | |
| .responseModalities("TEXT", "IMAGE") | |
| .imageConfig(ImageConfig.builder() | |
| .aspectRatio(new Random().nextBoolean() ? "16:9" : "9:16") | |
| .imageSize("1K") | |
| .build()) | |
| .systemInstruction(Content.fromParts( | |
| Part.fromText(instruction) | |
| )) | |
| .build(); | |
| GenerateContentResponse response = client.models.generateContent( | |
| Gemini.Model.geminiNanoBanana.getKey(), | |
| Content.fromParts( | |
| Part.fromText("Génère une photo pour l'élément avec l'ID : \"" + id + "\"") | |
| ), | |
| config); | |
| for (Part part : response.parts()) { | |
| if (part.text().isPresent()) { | |
| Fx.log(part.text().get()); | |
| } | |
| if (part.inlineData().isPresent()) { | |
| Blob blob = part.inlineData().get(); | |
| if (blob.data().isPresent()) { | |
| byte[] databytes = blob.data().get(); | |
| FileUtils.writeByteArrayToFile(file, databytes); | |
| return file; | |
| } | |
| } | |
| } | |
| } catch (IOException e) { | |
| Fx.debug(e); | |
| } | |
| } catch (IOException e) { | |
| throw new RuntimeException(e); | |
| } | |
| return null; | |
| } | |
| private static boolean injectChildren(Json node, Json update) { | |
| String nodeId = node.getId(); | |
| if (nodeId != null && nodeId.equals(update.getId())) { | |
| List<Json> newChildren = update.getListJson("children"); | |
| if (newChildren != null) { | |
| List<Json> existing = node.getListJson("children"); | |
| List<Json> merged = existing != null ? new ArrayList<>(existing) : new ArrayList<>(); | |
| for (Json newChild : newChildren) { | |
| boolean duplicate = merged.stream() | |
| .anyMatch(c -> newChild.getId() != null && newChild.getId().equals(c.getId())); | |
| if (!duplicate) { | |
| merged.add(newChild); | |
| } | |
| } | |
| merged.sort(Comparator.comparing( | |
| c -> c.getString("date", ""), | |
| Comparator.nullsLast(Comparator.naturalOrder()) | |
| )); | |
| node.put("children", merged); | |
| } | |
| return true; | |
| } | |
| List<Json> children = node.getListJson("children"); | |
| if (children != null) { | |
| for (Json child : children) { | |
| if (injectChildren(child, update)) { | |
| return true; | |
| } | |
| } | |
| } | |
| return false; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment