{"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\/informatique\/creer-un-chatbot-avec-google-gemini-vertex-ai-et-quarkus\/","title":{"rendered":"Creating a chatbot with Google Gemini Vertex AI and Quarkus"},"content":{"rendered":"<p>I recently created a Quarkus extension that provides access to <a href=\"https:\/\/docs.quarkiverse.io\/quarkus-google-cloud-services\/main\/vertexai.html\" rel=\"noopener\" target=\"_blank\">Google Vertex AI<\/a>.\nIn this article, I&#8217;m going to use this extension to create a chatbot.<\/p>\n<p>The first step is to create a Quarkus project containing the <strong>REST<\/strong> and <strong>Google Cloud Vertex AI<\/strong> extensions.<\/p>\n<p>Here are the extensions to add to your dependency file:<\/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>Or more simply, here is a link that will allow you to create a project from <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>The extension allows you to inject a <code>VertexAI<\/code> object into a Quarkus application to access the Google Cloud Vertex AI service. This service enables the <strong>Gemini<\/strong> generative AI model to be used in a Google Cloud project.<\/p>\n<p>We&#8217;re going to use this extension in a REST endpoint to code a chatbot. As I don&#8217;t really like developing UIs, I&#8217;m going to use cURL to call the chatbot.<\/p>\n<p>Here is the starting code for a chatbot with VertexAI:<\/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>REST endpoint using the JAX-RS standard available from the <code>\/chat<\/code> path of the application.<\/li>\n\n<li>System message telling the model it&#8217;s a chatbot and asking it to respond with a touch of humor.<\/li>\n\n<li>Injection of the <code>VertexAI<\/code> service, provided by the Quarkus Google Cloud VertexAI extension.<\/li>\n\n<li>Model initialization at the REST endpoint post-construct. We&#8217;re using <strong>Gemini Flash 2.5<\/strong> here, because Gemini Flash is a model that combines performance and cost control, which is what we want for a chatbot that needs to respond quickly and doesn&#8217;t require overly complex <em>reasoning<\/em>.<\/li>\n\n<li>Each time the endpoint is called, the model is called and the first response generated is returned. A real-life application would certainly implement something more advanced.<\/li>\n<\/ol>\n<p>To start the application in dev mode, you can use the Quarkus CLI: <code>quarkus dev<\/code>, the application is then available on port 8080.<\/p>\n<p>To call the chatbot, I use the following cURL: <code>curl -G localhost:8080\/chat --data-urlencode &quot;message=A message?&quot;<\/code>. For those who don&#8217;t know thsi trick, by using <code>-G<\/code> I force cURL to do a GET, it will then pass the data as a query-string in the URL. This avoids any space-encoding problems by using <code>--data-urlencode<\/code>.<\/p>\n<p>Here&#8217;s a sample 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.png?resize=640%2C235&#038;ssl=1\" alt=\"\" width=\"640\" height=\"235\" class=\"alignnone size-large wp-image-1963\" srcset=\"https:\/\/i0.wp.com\/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\/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\/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\/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\/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\/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\/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>As you can see, everything&#8217;s going fine until I ask it what my name is! Even though I&#8217;ve just told it, it doesn&#8217;t know it, because it has no memory.<\/p>\n<p>We&#8217;re going to add a memory to the chatbot so that we can have a real conversation with it.<\/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>With a memory, the chatbot works much better!<\/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.png?resize=640%2C235&#038;ssl=1\" alt=\"\" width=\"640\" height=\"235\" class=\"alignnone size-large wp-image-1965\" srcset=\"https:\/\/i0.wp.com\/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\/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\/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\/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\/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\/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\/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>Here, I&#8217;ve used a single chat memory for the whole application, stored in memory (RAM). In the real world, of course, you&#8217;ll need to use one memory per chat user (or session), ideally stored persistently.<\/p>\n<p>That&#8217;s all for today, we&#8217;ve discovered how to create a chatbot in Quarkus with Google VertexAI and the Gemini model.\nGoogle VertexAI supports many other features: RAG, multimodal completion, tools, &#8230; You&#8217;ll find more information in its <a href=\"https:\/\/cloud.google.com\/vertex-ai\/docs\" rel=\"noopener\" target=\"_blank\">documentation<\/a>.<\/p>\n<p>You can find the project code on GitHub: <a href=\"https:\/\/github.com\/loicmathieu\/quarkus-vertexai-example\" rel=\"noopener\" target=\"_blank\">quarkus-vertexai-example<\/a>.<\/p>\n<p>Thanks to Google for providing Google Cloud credits to write this article.<\/p>","protected":false},"excerpt":{"rendered":"<p>I recently created a Quarkus extension that provides access to Google Vertex AI. In this article, I&#8217;m going to use this extension to create a chatbot. The first step is to create a Quarkus project containing the REST and Google Cloud Vertex AI extensions. Here are the extensions to add to your dependency file: io.quarkiverse.googlecloudservices quarkus-google-cloud-vertex-ai io.quarkus quarkus-resteasy-reactive Or more simply, here is a link that will allow you to create a project from code.quarkus.io. The extension allows you to&#8230;<p class=\"read-more\"><a class=\"btn btn-default\" href=\"https:\/\/www.loicmathieu.fr\/wordpress\/informatique\/creer-un-chatbot-avec-google-gemini-vertex-ai-et-quarkus\/\"> Read More<span class=\"screen-reader-text\">  Read More<\/span><\/a><\/p><\/p>","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_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},"jetpack_post_was_ever_published":false},"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\/informatique\/quarkus-et-testcontainers\/","url_meta":{"origin":1960,"position":0},"title":"Quarkus and Testcontainers","author":"admin","date":"Monday February 17th, 2020","format":false,"excerpt":"If you did not know Quarkus, here is an introductory article: Zoom sur Quarkus (french). Quarkus offers Unit Test (TU) support with JUnit 5 via the @QuarkusTest annotation, documentation for Quarkus TU support can be found here. Here is an example of a TU from the Hibernate ORM Quickstart :\u2026","rel":"","context":"In &quot;informatique&quot;","block_context":{"text":"informatique","link":"https:\/\/www.loicmathieu.fr\/wordpress\/category\/informatique\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1353,"url":"https:\/\/www.loicmathieu.fr\/wordpress\/informatique\/quarkus-tip-comment-ne-pas-creer-une-extension-quarkus\/","url_meta":{"origin":1960,"position":1},"title":"Quarkus Tip: How NOT to create a Quarkus extension","author":"admin","date":"Tuesday November 16th, 2021","format":false,"excerpt":"When you develop an application composed of several components, it is frequent to want to share some code in an external library, for example via an external JAR integrated as a dependency of your components. Quarkus is an extension framework, each extension it offers allows to integrate a technology (BDD\u2026","rel":"","context":"In &quot;informatique&quot;","block_context":{"text":"informatique","link":"https:\/\/www.loicmathieu.fr\/wordpress\/category\/informatique\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1560,"url":"https:\/\/www.loicmathieu.fr\/wordpress\/informatique\/quarkus-tip-tester-une-fonction-google-cloud\/","url_meta":{"origin":1960,"position":2},"title":"Quarkus Tip: Testing a Google Cloud function","author":"admin","date":"Thursday December 29th, 2022","format":false,"excerpt":"I recently contributed a PR to Quarkus that contains a testing framework for Google Cloud functions. Quarkus supports creating Google Cloud functions three different ways: Using the Google Cloud API. Using a Quarkus HTTP extension: RESTEasy, Reactive routes, Servlet, Spring Web. Using Funqy, the cloud provider agnostic Quarkus function API.\u2026","rel":"","context":"In &quot;informatique&quot;","block_context":{"text":"informatique","link":"https:\/\/www.loicmathieu.fr\/wordpress\/category\/informatique\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1345,"url":"https:\/\/www.loicmathieu.fr\/wordpress\/informatique\/quarkus-et-les-google-cloud-functions\/","url_meta":{"origin":1960,"position":3},"title":"Quarkus and  the Google Cloud Functions","author":"admin","date":"Tuesday November  2nd, 2021","format":false,"excerpt":"Quarkus is a microservice framework designed for the cloud and the containers. It is designed to have a reduced memory usage and the shortest possible startup time. It is mainly based on standards (Jakarta EE, Eclipse MicroProfile, ...) and allows the use of mature and widespread Java libraries via its\u2026","rel":"","context":"In &quot;informatique&quot;","block_context":{"text":"informatique","link":"https:\/\/www.loicmathieu.fr\/wordpress\/category\/informatique\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":2089,"url":"https:\/\/www.loicmathieu.fr\/wordpress\/informatique\/deploy-a-quarkus-application-in-cloud-run\/","url_meta":{"origin":1960,"position":4},"title":"Deploy a Quarkus application in Cloud Run","author":"admin","date":"Tuesday December 30th, 2025","format":false,"excerpt":"Quarkus is a microservice development framework designed for the cloud and containers. It is designed to have reduced memory usage and the shortest possible startup time. It is mainly based on standards (Jakarta EE, Eclipse MicroProfile, etc.) and allows the use of mature and widely used Java libraries via its\u2026","rel":"","context":"In &quot;informatique&quot;","block_context":{"text":"informatique","link":"https:\/\/www.loicmathieu.fr\/wordpress\/category\/informatique\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1068,"url":"https:\/\/www.loicmathieu.fr\/wordpress\/informatique\/j-ai-teste-java-google-cloud-functions-aplha\/","url_meta":{"origin":1960,"position":5},"title":"(Fran\u00e7ais) J&#8217;ai test\u00e9 Java Google Cloud Functions Alpha","author":"admin","date":"Wednesday May  6th, 2020","format":false,"excerpt":"Sorry, this entry is only available in Fran\u00e7ais.","rel":"","context":"In &quot;informatique&quot;","block_context":{"text":"informatique","link":"https:\/\/www.loicmathieu.fr\/wordpress\/category\/informatique\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]}],"_links":{"self":[{"href":"https:\/\/www.loicmathieu.fr\/wordpress\/wp-json\/wp\/v2\/posts\/1960","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.loicmathieu.fr\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.loicmathieu.fr\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.loicmathieu.fr\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.loicmathieu.fr\/wordpress\/wp-json\/wp\/v2\/comments?post=1960"}],"version-history":[{"count":12,"href":"https:\/\/www.loicmathieu.fr\/wordpress\/wp-json\/wp\/v2\/posts\/1960\/revisions"}],"predecessor-version":[{"id":1975,"href":"https:\/\/www.loicmathieu.fr\/wordpress\/wp-json\/wp\/v2\/posts\/1960\/revisions\/1975"}],"wp:attachment":[{"href":"https:\/\/www.loicmathieu.fr\/wordpress\/wp-json\/wp\/v2\/media?parent=1960"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.loicmathieu.fr\/wordpress\/wp-json\/wp\/v2\/categories?post=1960"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.loicmathieu.fr\/wordpress\/wp-json\/wp\/v2\/tags?post=1960"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}