{"id":1960,"date":"2025-06-27T15:08:30","date_gmt":"2025-06-27T13:08:30","guid":{"rendered":"https:\/\/www.loicmathieu.fr\/wordpress\/?p=1960"},"modified":"2025-06-27T15:22:32","modified_gmt":"2025-06-27T13:22:32","slug":"creer-un-chatbot-avec-google-gemini-vertex-ai-et-quarkus","status":"publish","type":"post","link":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/informatique\/creer-un-chatbot-avec-google-gemini-vertex-ai-et-quarkus\/","title":{"rendered":"Cr\u00e9er un chatbot avec Google Gemini Vertex AI et Quarkus"},"content":{"rendered":"<p>J&rsquo;ai r\u00e9cemment cr\u00e9\u00e9 une extension Quarkus qui permet d&rsquo;acc\u00e9der \u00e0 <a href=\"https:\/\/docs.quarkiverse.io\/quarkus-google-cloud-services\/main\/vertexai.html\" rel=\"noopener\" target=\"_blank\">Google Vertex AI<\/a>.\nDans cet article, je vais utiliser cette extension pour cr\u00e9er un chatbot.<\/p>\n<p>La premi\u00e8re \u00e9tape consiste \u00e0 cr\u00e9er un projet Quarkus contenant les extensions <strong>REST<\/strong> et <strong>Google Cloud Vertex AI<\/strong>.<\/p>\n<p>Voici les extensions \u00e0 ajouter \u00e0 votre fichier de d\u00e9pendances :<\/p>\n<pre>\n\n  io.quarkiverse.googlecloudservices\n  quarkus-google-cloud-vertex-ai\n\n\n  io.quarkus\n  quarkus-resteasy-reactive\n\n<\/pre>\n<p>Ou plus simplement, voici un lien qui va vous permettre de cr\u00e9er un projet depuis <a href=\"https:\/\/code.quarkus.io\/?g=fr.loicmathieu.quarkus&amp;a=quarkus-vertexai-example&amp;e=io.quarkiverse.googlecloudservices%3Aquarkus-google-cloud-vertex-ai&amp;extension-search=vertex\" rel=\"noopener\" target=\"_blank\">code.quarkus.io<\/a>.<\/p>\n<p>L&rsquo;extension permet d&rsquo;injecter un objet <code>VertexAI<\/code> dans une application Quarkus pour acc\u00e9der au service Google Cloud Vertex AI. Ce service permet d&rsquo;utiliser le mod\u00e8le d&rsquo;AI g\u00e9n\u00e9rative <strong>Gemini<\/strong> dans un projet Google Cloud.<\/p>\n<p>Nous allons utiliser cette extension dans un endpoint REST pour coder un chatbot. Comme je n&rsquo;aime pas trop d\u00e9velopper des UI, je vais utiliser cURL pour appeler le chatbot.<\/p>\n<p>Voici le code de d\u00e9part pour un chatbot :<\/p>\n<pre>\npackage fr.loicmathieu.quarkus.vertexai;\n\n\/\/ [...] imports omitted for brevity\n\n\/\/ 1. Standard REST endpoint available on \/chat\n@Path(\"\/chat\")\npublic class VertexAIResource {\n    \/\/ 2. System message tellin the LLM it is a chatbot\n    private static final String SYSTEM_INSTRUCTION = \"\"\"\n        You are a chatbot named Lo\u00efc. \n        Don't pretend you know everything but be helpful with a touch of humour.\"\"\";\n\n    private GenerativeModel model;\n\n    \/\/ 3. Injection of the provided VertexAI object\n    @Inject\n    VertexAI vertexAI;\n\n    \/\/ 4. Init the model with Gemini 2.5 Flash\n    @PostConstruct\n    void initModel() {\n        this.model =  new GenerativeModel(\"gemini-2.5-flash\", vertexAI)\n            .withSystemInstruction(ContentMaker.fromString(SYSTEM_INSTRUCTION));\n    }\n\n    \/\/ 5. Generate a chat response on each call to \/chat\n    @GET\n    public String chat(@QueryParam(\"message\") String message) throws IOException {\n        var response = model.generateContent(message);\n\n        \/\/ For simplicity: we only take the first part of the first candidate\n        return response.getCandidatesList().getFirst()\n            .getContent().getPartsList().getFirst().getText() + \"\\n\";\n    }\n}\n<\/pre>\n<ol><li>Endpoint REST utilisant le standard JAX-RS disponible au path <code>\/chat<\/code> de l&rsquo;application.<\/li>\n\n<li>Message syst\u00e8me permettant de dire au mod\u00e8le qu&rsquo;il est un chatbot et lui demandant de r\u00e9pondre avec une touche d&rsquo;humour.<\/li>\n\n<li>Injection du service <code>VertexAI<\/code>, ce service est fourni par l&rsquo;extension Quarkus Google Cloud VertexAI.<\/li>\n\n<li>Initialisation du mod\u00e8le au post-construct du endpoint REST. On utilise ici <strong>Gemini Flash 2.5<\/strong> car Gemini Flash est un mod\u00e8le qui allie performance et ma\u00eetrise de co\u00fbt ce que l&rsquo;on veut pour un chatbot qui doit r\u00e9pondre rapidement et ne n\u00e9cessite pas de <em>raisonnement<\/em> trop complexe.<\/li>\n\n<li>\u00c0 chaque appel du endpoint, on va appeler le mod\u00e8le et retourner la premi\u00e8re r\u00e9ponse g\u00e9n\u00e9r\u00e9e. Une application cas r\u00e9el impl\u00e9menterait certainement quelque chose de plus pouss\u00e9.<\/li>\n<\/ol>\n<p>Pour d\u00e9marrer l&rsquo;application en mode dev, vous pouvez utiliser le CLI Quarkus : <code>quarkus dev<\/code>, l&rsquo;application est alors disponible sur le port 8080.<\/p>\n<p>Pour appeler le chatbot, j&rsquo;utilise le cURL suivant : <code>curl -G localhost:8080\/chat --data-urlencode &quot;message=A message?&quot;<\/code>. Pour ceux qui ne connaissent pas, en utilisant <code>-G<\/code> je force cURL a fait un GET, il va alors passer les donn\u00e9es en tant que query-string dans l&rsquo;URL. Cela permet d&rsquo;\u00e9viter tout probl\u00e8me d&rsquo;encodage des espaces en utilisant <code>--data-urlencode<\/code>.<\/p>\n<p>Voici un exemple de conversation :<\/p>\n<img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/loicmathieu.fr\/wordpress\/wp-content\/uploads\/Capture-decran-du-2025-06-27-14-22-26-1024x376.png?resize=640%2C235&#038;ssl=1\" alt=\"\" width=\"640\" height=\"235\" class=\"alignnone size-large wp-image-1963\" srcset=\"https:\/\/i0.wp.com\/www.loicmathieu.fr\/wordpress\/wp-content\/uploads\/Capture-decran-du-2025-06-27-14-22-26.png?resize=1024%2C376&amp;ssl=1 1024w, https:\/\/i0.wp.com\/www.loicmathieu.fr\/wordpress\/wp-content\/uploads\/Capture-decran-du-2025-06-27-14-22-26.png?resize=300%2C110&amp;ssl=1 300w, https:\/\/i0.wp.com\/www.loicmathieu.fr\/wordpress\/wp-content\/uploads\/Capture-decran-du-2025-06-27-14-22-26.png?resize=768%2C282&amp;ssl=1 768w, https:\/\/i0.wp.com\/www.loicmathieu.fr\/wordpress\/wp-content\/uploads\/Capture-decran-du-2025-06-27-14-22-26.png?resize=1536%2C565&amp;ssl=1 1536w, https:\/\/i0.wp.com\/www.loicmathieu.fr\/wordpress\/wp-content\/uploads\/Capture-decran-du-2025-06-27-14-22-26.png?resize=604%2C222&amp;ssl=1 604w, https:\/\/i0.wp.com\/www.loicmathieu.fr\/wordpress\/wp-content\/uploads\/Capture-decran-du-2025-06-27-14-22-26.png?w=1885&amp;ssl=1 1885w, https:\/\/i0.wp.com\/www.loicmathieu.fr\/wordpress\/wp-content\/uploads\/Capture-decran-du-2025-06-27-14-22-26.png?w=1280&amp;ssl=1 1280w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/>\n<p>Comme vous le voyez, tout se passe bien jusqu&rsquo;\u00e0 ce que je lui demande quel est mon nom ! M\u00eame si je viens de lui dire, il ne le connait pas, car il n&rsquo;a pas de m\u00e9moire.<\/p>\n<p>Nous allons ajouter une m\u00e9moire au chatbot pour pouvoir avoir une vraie conversation avec lui.<\/p>\n<pre>\npackage fr.loicmathieu.quarkus.vertexai;\n\n\/\/ [...] Imports omitted for brevity\n\n\/\/ 1. Standard REST endpoint available on \/chat\n@Path(\"\/chat\")\npublic class VertexAIResource {\n    \/\/ 2. System message tellin the LLM it is a chatbot\n    private static final String SYSTEM_INSTRUCTION = \"\"\"\n        You are a chatbot named Lo\u00efc. \n        Don't pretend you know everything but be helpful with a touch of humour.\"\"\";\n\n    private GenerativeModel model;\n    private ChatSession chatSession;\n\n    \/\/ 3. Injection of the provided VertexAI object\n    @Inject\n    VertexAI vertexAI;\n\n    \/\/ 4. Init the model with Gemini 2.5 Flash\n    @PostConstruct\n    void initModel() {\n        this.model =  new GenerativeModel(\"gemini-2.5-flash\", vertexAI)\n            .withSystemInstruction(ContentMaker.fromString(SYSTEM_INSTRUCTION));\n\n        \/\/ For simplicity: we use a single chat session.\n        \/\/ On real use cases, we should use one per user\n        this.chatSession = this.model.startChat();\n    }\n\n    \/\/ 5. Generate a chat response on each call to \/chat\n    @GET\n    public String chat(@QueryParam(\"message\") String message) throws IOException {\n        var response = chatSession.sendMessage(message);\n\n        \/\/ For simplicity: we only take the first part of the first candidate\n        return response.getCandidatesList().getFirst()\n            .getContent().getPartsList().getFirst().getText() + \"\\n\";\n    }\n}\n<\/pre>\n<p>Avec une m\u00e9moire, le chatbot fonctionne beaucoup mieux !<\/p>\n<img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/loicmathieu.fr\/wordpress\/wp-content\/uploads\/Capture-decran-du-2025-06-27-14-32-15-1024x376.png?resize=640%2C235&#038;ssl=1\" alt=\"\" width=\"640\" height=\"235\" class=\"alignnone size-large wp-image-1965\" srcset=\"https:\/\/i0.wp.com\/www.loicmathieu.fr\/wordpress\/wp-content\/uploads\/Capture-decran-du-2025-06-27-14-32-15.png?resize=1024%2C376&amp;ssl=1 1024w, https:\/\/i0.wp.com\/www.loicmathieu.fr\/wordpress\/wp-content\/uploads\/Capture-decran-du-2025-06-27-14-32-15.png?resize=300%2C110&amp;ssl=1 300w, https:\/\/i0.wp.com\/www.loicmathieu.fr\/wordpress\/wp-content\/uploads\/Capture-decran-du-2025-06-27-14-32-15.png?resize=768%2C282&amp;ssl=1 768w, https:\/\/i0.wp.com\/www.loicmathieu.fr\/wordpress\/wp-content\/uploads\/Capture-decran-du-2025-06-27-14-32-15.png?resize=1536%2C565&amp;ssl=1 1536w, https:\/\/i0.wp.com\/www.loicmathieu.fr\/wordpress\/wp-content\/uploads\/Capture-decran-du-2025-06-27-14-32-15.png?resize=604%2C222&amp;ssl=1 604w, https:\/\/i0.wp.com\/www.loicmathieu.fr\/wordpress\/wp-content\/uploads\/Capture-decran-du-2025-06-27-14-32-15.png?w=1885&amp;ssl=1 1885w, https:\/\/i0.wp.com\/www.loicmathieu.fr\/wordpress\/wp-content\/uploads\/Capture-decran-du-2025-06-27-14-32-15.png?w=1280&amp;ssl=1 1280w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/>\n<p>Ici, j&rsquo;ai utilis\u00e9 une m\u00e9moire de chat unique pour toute l&rsquo;application, stock\u00e9e en m\u00e9moire (RAM). En cas r\u00e9el, il faudra bien s\u00fbr utiliser une m\u00e9moire par utilisateur (ou session) de chat, id\u00e9alement stock\u00e9e de mani\u00e8re persistante.<\/p>\n<p>Ce sera tout pour aujourd&rsquo;hui, nous avons d\u00e9couvert comment cr\u00e9er un chatbot en Quarkus avec Google VertexAI et le mod\u00e8le Gemini.\nGoogle VertexAI supporte de nombreuses autres fonctionnalit\u00e9s : RAG, multimodal completion, tools, &#8230; Vous trouverez plus d&rsquo;information dans sa <a href=\"https:\/\/cloud.google.com\/vertex-ai\/docs\" rel=\"noopener\" target=\"_blank\">documentation<\/a>.<\/p>\n<p>Vous pouvez retrouver le code du projet sur GitHub : <a href=\"https:\/\/github.com\/loicmathieu\/quarkus-vertexai-example\" rel=\"noopener\" target=\"_blank\">quarkus-vertexai-example<\/a>.<\/p>\n<p>Merci \u00e0 Google d&rsquo;avoir fourni des cr\u00e9dits Google Cloud pour \u00e9crire cet article.<\/p>","protected":false},"excerpt":{"rendered":"<p>J&rsquo;ai r\u00e9cemment cr\u00e9\u00e9 une extension Quarkus qui permet d&rsquo;acc\u00e9der \u00e0 Google Vertex AI. Dans cet article, je vais utiliser cette extension pour cr\u00e9er un chatbot. La premi\u00e8re \u00e9tape consiste \u00e0 cr\u00e9er un projet Quarkus contenant les extensions REST et Google Cloud Vertex AI. Voici les extensions \u00e0 ajouter \u00e0 votre fichier de d\u00e9pendances : io.quarkiverse.googlecloudservices quarkus-google-cloud-vertex-ai io.quarkus quarkus-resteasy-reactive Ou plus simplement, voici un lien qui va vous permettre de cr\u00e9er un projet depuis code.quarkus.io. L&rsquo;extension permet d&rsquo;injecter un objet VertexAI&#8230;<p class=\"read-more\"><a class=\"btn btn-default\" href=\"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/informatique\/creer-un-chatbot-avec-google-gemini-vertex-ai-et-quarkus\/\">Lire la suite<span class=\"screen-reader-text\"> Lire la suite<\/span><\/a><\/p><\/p>","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"activitypub_content_warning":"","activitypub_content_visibility":"","activitypub_max_image_attachments":4,"activitypub_interaction_policy_quote":"anyone","activitypub_status":"","footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[9],"tags":[227,225,228,109,11,167,226],"class_list":["post-1960","post","type-post","status-publish","format-standard","hentry","category-informatique","tag-ai","tag-gemini","tag-genai","tag-google","tag-java","tag-quarkus","tag-vertexai"],"aioseo_notices":[],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_likes_enabled":true,"jetpack-related-posts":[{"id":1005,"url":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/informatique\/quarkus-et-testcontainers\/","url_meta":{"origin":1960,"position":0},"title":"Quarkus et Testcontainers","author":"admin","date":"lundi 17 f\u00e9vrier 2020","format":false,"excerpt":"Si vous ne connaissait pas Quarkus, voici un article d'introduction : Zoom sur Quarkus. Quarkus offre un support des Tests Unitaires (TU) avec JUnit 5 via l'annotation @QuarkusTest, la documentation du support des TU de Quarkus peut \u00eatre trouv\u00e9 ici. Voici un exemple de TU tir\u00e9 du Quickstart Hibernate ORM\u2026","rel":"","context":"Dans &quot;informatique&quot;","block_context":{"text":"informatique","link":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/category\/informatique\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1353,"url":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/informatique\/quarkus-tip-comment-ne-pas-creer-une-extension-quarkus\/","url_meta":{"origin":1960,"position":1},"title":"Quarkus Tip : Comment NE PAS cr\u00e9er une extension Quarkus","author":"admin","date":"mardi 16 novembre 2021","format":false,"excerpt":"Quand on d\u00e9veloppe une application compos\u00e9e de plusieurs composants, il est fr\u00e9quent de vouloir partager du code dans une librairie externe, par exemple via un JAR externe int\u00e9gr\u00e9 comme une d\u00e9pendance de vos composants. Quarkus est un framework d'extension, chaque extension qu'il propose permet d'int\u00e9grer une technologie (client BDD, framework\u2026","rel":"","context":"Dans &quot;informatique&quot;","block_context":{"text":"informatique","link":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/category\/informatique\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1560,"url":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/informatique\/quarkus-tip-tester-une-fonction-google-cloud\/","url_meta":{"origin":1960,"position":2},"title":"Quarkus Tip : Tester une fonction Google Cloud","author":"admin","date":"jeudi 29 d\u00e9cembre 2022","format":false,"excerpt":"J'ai r\u00e9cemment contribu\u00e9 une PR \u00e0 Quarkus qui contient un framework de test pour les fonctions Google Cloud. Quarkus supporte la cr\u00e9ation de fonction Google Cloud de trois mani\u00e8res diff\u00e9rentes : En utilisant l'API de Google Cloud. En utilisant une extension HTTP de Quarkus : RESTEasy, Reactive routes, Servlet, Spring\u2026","rel":"","context":"Dans &quot;informatique&quot;","block_context":{"text":"informatique","link":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/category\/informatique\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1345,"url":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/informatique\/quarkus-et-les-google-cloud-functions\/","url_meta":{"origin":1960,"position":3},"title":"Quarkus et les  Google Cloud Functions","author":"admin","date":"mardi  2 novembre 2021","format":false,"excerpt":"Quarkus est un framework de d\u00e9veloppement de microservice pens\u00e9 pour le cloud et les conteneurs. Il est pens\u00e9 pour avoir une utilisation m\u00e9moire r\u00e9duite et un temps de d\u00e9marrage le plus court possible. Il se base principalement sur des standards (Jakarta EE, Eclipse MicroProfile, \u2026) et permet l'utilisation de librairies\u2026","rel":"","context":"Dans &quot;informatique&quot;","block_context":{"text":"informatique","link":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/category\/informatique\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":2089,"url":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/informatique\/deployer-une-application-quarkus-dans-cloud-run\/","url_meta":{"origin":1960,"position":4},"title":"D\u00e9ployer une application Quarkus dans Cloud Run","author":"admin","date":"mardi 30 d\u00e9cembre 2025","format":false,"excerpt":"Quarkus est un framework de d\u00e9veloppement de microservice pens\u00e9 pour le cloud et les conteneurs. Il est pens\u00e9 pour avoir une utilisation m\u00e9moire r\u00e9duite et un temps de d\u00e9marrage le plus court possible. Il se base principalement sur des standards (Jakarta EE, Eclipse MicroProfile, \u2026) et permet l\u2019utilisation de librairies\u2026","rel":"","context":"Dans &quot;informatique&quot;","block_context":{"text":"informatique","link":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/category\/informatique\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1068,"url":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/informatique\/j-ai-teste-java-google-cloud-functions-aplha\/","url_meta":{"origin":1960,"position":5},"title":"J&rsquo;ai test\u00e9 Java Google Cloud Functions Alpha","author":"admin","date":"mercredi  6 mai 2020","format":false,"excerpt":"J'ai test\u00e9 les Java Google Cloud Functions en Alpha. Jusqu'ici, les Cloud Functions de Google n'\u00e9taient impl\u00e9mentables qu'en NodeJs, Go ou Python. Mais Google est en train de pr\u00e9parer l'ouverture d'un runtime Java (8 et 11), que j'ai pu tester en alpha release priv\u00e9e (pour s'inscrire, c'est ici). Apr\u00e8s inscription\u2026","rel":"","context":"Dans &quot;informatique&quot;","block_context":{"text":"informatique","link":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/category\/informatique\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]}],"_links":{"self":[{"href":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/wp-json\/wp\/v2\/posts\/1960","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/wp-json\/wp\/v2\/comments?post=1960"}],"version-history":[{"count":12,"href":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/wp-json\/wp\/v2\/posts\/1960\/revisions"}],"predecessor-version":[{"id":1975,"href":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/wp-json\/wp\/v2\/posts\/1960\/revisions\/1975"}],"wp:attachment":[{"href":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/wp-json\/wp\/v2\/media?parent=1960"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/wp-json\/wp\/v2\/categories?post=1960"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.loicmathieu.fr\/wordpress\/fr\/wp-json\/wp\/v2\/tags?post=1960"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}