This is an automated email from the ASF dual-hosted git repository.
paulk pushed a commit to branch asf-site
in repository https://gitbox.apache.org/repos/asf/groovy-website.git
The following commit(s) were added to refs/heads/asf-site by this push:
new 7949909 initial draft
7949909 is described below
commit 794990944d032ebc597b0e609cae975d0348b53c
Author: Paul King <[email protected]>
AuthorDate: Tue Oct 14 20:13:55 2025 +1000
initial draft
---
site/src/site/blog/groovy-ai.adoc | 366 ++++++++++++++++++++++++++++++++++++++
1 file changed, 366 insertions(+)
diff --git a/site/src/site/blog/groovy-ai.adoc
b/site/src/site/blog/groovy-ai.adoc
new file mode 100644
index 0000000..bd8233d
--- /dev/null
+++ b/site/src/site/blog/groovy-ai.adoc
@@ -0,0 +1,366 @@
+= Exploring AI with Groovy&trade
+Paul King <paulk-asert|PMC_Member>
+:revdate: 2025-10-14T19:27:25+00:00
+:keywords: groovy, ai, ollama4j, langchain4j, spring-ai, embabel
+:description: A tour of using Groovy with modern AI libraries including
ollama4j, LangChain4j, Spring AI, and Embabel.
+:draft: true
+
+In this post, we’ll look at several ways to integrate Groovy with AI tools,
including `ollama4j`, `langchain4j`, `Spring AI`, and `Embabel`.
+We'll use a simple chat example, perhaps similar to what you might have done
yourself when trying out your favourite LLM.
+We'll ask for activities to do while on vacation.
+To make the examples as accessible as possible, we'll use Ollama's open-source
models,
+which can be run locally. The libraries we use here can also connect to remote
models and services.
+The examples mostly use the `mistral:7b` model, which you'll need to download
to run the examples
+unchanged, but feel free to try other models and see what results you get.
+We also used Groovy 5 and JDK 25, but the examples should work on other Groovy
and Java versions.
+
+== Using ollama4j
+
+https://github.com/ollama/ollama4j[_Ollama4j_] provides a client for
interacting with local or remote https://ollama.com/[Ollama] models.
+
+We first create an instance of the `Ollama` class.
+We set a generous timeout to allow for longer-running models.
+While not strictly necessary, we can call the `ping` method to verify that the
Ollama server is reachable.
+
+[source,groovy]
+----
+var ollama = new Ollama(requestTimeoutSeconds: 300)
+println "Found ollama: ${ollama.ping()}"
+----
+
+Which gives this output:
+
+----
+Found ollama: true
+----
+
+Now we can send our prompt to the model:
+
+[source,groovy]
+----
+var prompt = 'What are 4 interesting things to do while I am on vacation in
Caloundra?'
+var builder = OllamaChatRequestBuilder.builder()
+ .withModel('mistral:7b')
+
+var request = builder
+ .withMessage(OllamaChatMessageRole.USER, prompt)
+ .build()
+
+var result = ollama.chat(request, null)
+println "Four things:\n$result.responseModel.message.response"
+----
+
+It will respond with something like:
+
+----
+Four things:
+ 1. Visit the beautiful beaches: Caloundra is famous for its stunning beaches,
including Kings Beach, Moffat Beach, and Bulcock Beach. Spend your days soaking
up the sun, swimming, or surfing.
+
+2. Explore the UnderWater World SeaLife Aquarium: This marine attraction
offers a unique opportunity to interact with various sea creatures. You can
even have a close encounter with sharks and turtles!
+
+3. Visit the Glastonbury Estate: For those who love history, this beautiful
estate is worth a visit. It was built in the 1920s and features a variety of
artifacts and memorabilia from World War I and II.
+
+4. Take a day trip to the Australia Zoo: Made famous by the Crocodile Hunter,
Steve Irwin, the Australia Zoo is just a short drive from Caloundra. It's home
to a wide variety of Australian wildlife, including kangaroos, koalas, and
crocodiles. Don't miss the daily wildlife shows!
+----
+
+We can continue the conversation by including the previous chat history in the
next request:
+
+[source,groovy]
+----
+var prompt2 = 'If I had half a day and can only go to one, which would you
recommend?'
+request = builder
+ .withMessages(result.chatHistory)
+ .withMessage(OllamaChatMessageRole.USER, prompt2)
+ .build()
+
+result = ollama.chat(request, null)
+println "Best thing:\n$result.responseModel.message.response"
+----
+
+The output might be:
+
+----
+Best thing:
+ If you only have half a day and can choose just one activity, I would
recommend visiting the beautiful Kings Beach in Caloundra. It offers a lovely
stretch of sandy beach, perfect for swimming, sunbathing, or simply taking a
leisurely stroll along the shoreline. The beach also has various amenities like
picnic areas, BBQ facilities, and a playground for children. Plus, it provides
stunning views of the Pacific Ocean and the Glass House Mountains in the
distance. It's the perfect place t [...]
+----
+
+== Using LangChain4j
+
+https://github.com/langchain4j/langchain4j[_LangChain4j_] brings LangChain’s
composable AI approach to the JVM.
+Here’s the same initial prompt using its `OllamaChatModel` interface:
+
+[source,groovy]
+----
+var chatModel = OllamaChatModel.builder()
+ .baseUrl("http://localhost:11434")
+ .timeout(Duration.ofMinutes(5))
+ .modelName("mistral:7b")
+ .build()
+
+String prompt = 'What are 4 interesting things to do while I am on vacation in
Caloundra?'
+println "Response: " + chatModel.chat(prompt)
+----
+
+The output might look something like:
+
+----
+Response:
+ 1. Visit the beautiful beaches: Caloundra is known for its stunning beaches,
with Kings Beach and Moffat Beach being some of the most popular ones. You can
spend your days sunbathing, swimming, or surfing.
+
+2. Explore the underwater world: Take a trip to the UnderWater World Sea Life
Mooloolaba, an aquarium that houses a variety of marine life including sharks,
turtles, and seahorses. It's a great way to learn about and appreciate the
ocean's wonders.
+
+3. Visit the Glastonbury Estate: This historic homestead offers a glimpse into
Australia's past. The estate features beautiful gardens, a tea room, and often
hosts various events throughout the year.
+
+4. Take a day trip to the Glass House Mountains: Just a short drive from
Caloundra, these iconic volcanic plugs offer breathtaking views and hiking
trails for all levels of fitness. You can also visit the Kondalilla National
Park for waterfalls and rainforest walks.
+----
+
+== Using Spring AI
+
+https://docs.spring.io/spring-ai/reference/[_Spring AI_] provides first-class
integration with the Spring ecosystem.
+In Groovy, this makes it simple to embed AI capabilities into a Spring Boot
app.
+
+[source,groovy]
+----
+@SpringBootApplication
+void main() {
+ try(var context = SpringApplication.run(Holiday)) {
+ var chatClient = context.getBean(ChatClient.Builder).build()
+ var response = chatClient
+ .prompt("What are some interesting things to do while I am on
vacation in Caloundra?")
+ .call()
+ println "Response:\n" + response.content()
+ }
+}
+----
+
+The output might look something like:
+
+----
+Response:
+ Caloundra, located on the Sunshine Coast of Australia, offers a variety of
activities that cater to different interests. Here are some suggestions for an
enjoyable vacation:
+
+1. Beaches: Caloundry has several beautiful beaches, including Kings Beach,
Moffat Beach, and Bulcock Beach. You can swim, sunbathe, surf, or just enjoy
the stunning views.
+
+2. Visit the Underwater World SEA LIFE Mooloolaba: This aquarium is home to a
diverse range of marine life, including sharks, turtles, and seahorses. It's a
great place for both children and adults to learn about and interact with
marine creatures.
+
+3. Explore the Glass House Mountains: These are a series of 12 granite peaks
that offer stunning views of the surrounding area. You can hike, picnic, or
simply enjoy the panoramic vistas.
+
+4. Visit the Eumundi Markets: Open on Saturdays and Wednesdays, these markets
feature over 600 stalls selling art, crafts, produce, and food. It's a great
place to pick up unique souvenirs and sample local delicacies.
+
+5. Go for a scenic flight: For a truly unforgettable experience, consider
taking a scenic flight over the Sunshine Coast. You'll get breathtaking views
of the coastline, hinterland, and the Glass House Mountains.
+
+6. Visit Australia Zoo: Made famous by the Crocodile Hunter, Steve Irwin, this
zoo is home to a wide variety of Australian wildlife. It's a great place for
families and animal lovers.
+
+7. Enjoy local cuisine: Caloundra has a vibrant food scene with numerous
restaurants offering everything from fresh seafood to international cuisines.
Be sure to try some local favorites like Barramundi, Moreton Bay bugs, and
mangoes.
+
+8. Visit the Powerboat Park: If you're a fan of powerboats, this park is a
must-visit. It features a museum dedicated to the history of powerboating in
Australia.
+
+9. Relax at a day spa: After a day of exploring, treat yourself to a relaxing
massage or beauty treatment at one of Caloundra's many day spas.
+
+10. Go fishing: Whether you prefer deep-sea fishing or casting a line from the
shore, Caloundra offers numerous opportunities for anglers. You can even hire a
charter boat if you don't have your own equipment.
+----
+
+Spring AI also supports structured outputs — where responses are deserialized
into domain objects.
+
+Let's create a small domain model for describing activities and lists of
activities (itineraries).
+
+[source,groovy]
+----
+@ToString(includePackage = false)
+record Activity(String activity, String location, String day, String time) {
+}
+
+record Itinerary(List<Activity> itinerary) {
+}
+----
+
+These simple records let the AI models return structured data that Groovy can
manipulate easily.
+With our domain records defined, our earlier example can be tweaked as follows:
+
+[source,groovy]
+----
+@SpringBootApplication
+void main() {
+ try(var context = SpringApplication.run(Holiday)) {
+ var chatClient = context.getBean(ChatClient.Builder).build()
+ var response = chatClient
+ .prompt("What are some interesting things to do while I am on
vacation in Caloundra?")
+ .call()
+ .entity(Itinerary)
+ println "Response:\n" + response.itinerary.join('\n')
+ }
+}
+----
+
+The output might look something like:
+
+----
+Response:
+Activity(Visit Kings Beach, Caloundra, Day 1, Morning)
+Activity(Explore Bulcock Beach, Caloundra, Day 1, Afternoon)
+Activity(Sunset at Moffat Headland, Caloundra, Day 1, Evening)
+Activity(Visit the Australian Zoo, Beerwah, Day 2, Whole Day)
+Activity(Relax at Shelly Beach, Caloundra, Day 3, Morning)
+Activity(Explore Pumicestone Passage by boat tour, Caloundra, Day 3, Afternoon)
+----
+
+== Using Embabel
+
+https://github.com/vaadin/embabel[_Embabel_] is a newer JVM library that
provides agent orchestration and LLM integration through a declarative approach.
+
+A simple text-generation example:
+
+[source,groovy]
+----
+@SpringBootApplication
+@EnableAgents(loggingTheme = LoggingThemes.STAR_WARS)
+void main() {
+ try(var context = SpringApplication.run(Holiday)) {
+ println context.getBean(OperationContext)
+ .ai()
+ .withDefaultLlm()
+ .generateText('What are some interesting things to do while I am
on vacation in Caloundra?')
+ }
+}
+----
+
+The output might look something like:
+
+----
+Caloundra, located on the Sunshine Coast in Queensland, Australia, offers a
variety of activities for tourists. Here are some suggestions for an enjoyable
vacation:
+
+1. Visit the beautiful beaches: Caloundra has several beautiful beaches, such
as Kings Beach, Shelly Beach, and Moffat Beach, where you can swim, sunbathe,
or surf.
+
+2. Explore the Coastal Walk: Take a leisurely stroll along the Coastal Walk,
which offers stunning views of the ocean, coastal cliffs, and nearby islands.
+
+3. Visit the Underwater World SEA LIFE Mooloolaba Aquarium: Discover an
amazing underwater world filled with sea turtles, sharks, seahorses, and more.
+
+4. Spend a day at Australia Zoo: Home to over 1,200 animals and the late Steve
Irwin's family, this iconic zoo offers up-close encounters with some of
Australia's most famous wildlife.
+
+5. Visit the Glastonbury Estate Winery: Taste locally produced wines at this
picturesque winery, which also features a restaurant and beautiful gardens.
+
+6. Explore the Bulcock Beach Esplanade: This vibrant area offers a variety of
shops, cafes, and restaurants, as well as regular markets on weekends.
+
+7. Take a day trip to Fraser Island: Known for its stunning beaches,
crystal-clear waters, and rainforests, Fraser Island is just a short boat ride
away from Caloundra.
+
+8. Enjoy the Pumicestone Passage: Go boating, kayaking, or fishing in this
beautiful waterway that separates Bribie Island from the mainland.
+
+9. Visit the Powerboat Park: Watch high-speed powerboats compete in various
races at this popular watersports venue.
+
+10. Relax at a spa or wellness center: Pamper yourself with a massage, beauty
treatment, or yoga class at one of Caloundra's many wellness centers.
+----
+
+Similarly to Spring AI, Embabel also supports structured data generation:
+
+[source,groovy]
+----
+@SpringBootApplication
+@EnableAgents(loggingTheme = LoggingThemes.STAR_WARS)
+void main() {
+ try(var context = SpringApplication.run(Structured)) {
+ println context.getBean(OperationContext)
+ .ai()
+ .withDefaultLlm()
+ .createObject('What are some interesting things to do while I am
on vacation in Caloundra?', Itinerary)
+ .itinerary
+ .join('\n')
+ }
+}
+----
+
+The output might look something like:
+
+----
+Activity(Visit the Kings Beach, Kings Beach, Caloundra, Day 1, Morning)
+Activity(Explore Bulcock Beach, Bulcock Beach, Caloundra, Day 1, Afternoon)
+Activity(Dine at Mooloolaba Seafood Market, Mooloolaba Seafood Market,
Mooloolaba, Day 1, Evening)
+Activity(Visit the Aussie World Theme Park, Aussie World, Palmview, Day 2,
Whole day)
+Activity(Relax at Shelly Beach, Shelly Beach, Caloundra, Day 3, Morning)
+Activity(Try Surfing at Currimundi Beach, Currimundi Beach, Currimundi, Day 3,
Afternoon)
+Activity(Explore the Eumundi Markets, Eumundi Markets, Eumundi, Day 4, Morning
to Afternoon)
+----
+
+== Autonomous Agents with Embabel
+
+As a final example, let's look at how Embabel can orchestrate multiple AI
calls using its agent model.
+
+Let's first extend our domain model to be able to have a bunch of alternative
itineraries
+and allow them to be rated.
+
+[source,groovy]
+----
+record Alternatives(Set<Itinerary> content) {
+}
+
+record RatedAlternatives(List<RatedItinerary> content) {
+}
+
+record RatedItinerary(Itinerary itinerary, Rating rating) {
+}
+
+record Rating(double percentage) { }
+----
+
+Our example uses an `@Agent` class to coordinate multiple AI actions —
generating, rating, and selecting itineraries. The `@Action` methods that make
up the agent's capabilities are simple to write, with our domain records as
inputs and outputs.
+
+[source,groovy]
+----
+@Agent(description = "Creates and ranks itineraries for a holiday at a given
location")
+class ItineraryAgent {
+ @Action
+ Alternatives generateItineraries(UserInput userInput, OperationContext
context) {
+ context.ai()
+ .withLlm('mistral:7b')
+ .createObject("Generate 5 sets of: An itinerary of things to do
while on $userInput.content?", Alternatives)
+ }
+
+ @Action
+ RatedAlternatives rateItineraries(Alternatives alternatives,
OperationContext context) {
+ new RatedAlternatives(alternatives.content.collect { itinerary ->
+ var rating = context.ai()
+ .withLlm('qwen3:8b')
+ .createObject("Rate this itinerary on variety and number of
activities: $itinerary?", Rating)
+ new RatedItinerary(itinerary, rating)
+ })
+ }
+
+ @Action
+ @AchievesGoal(description = 'Best itinerary')
+ RatedItinerary bestItinerary(RatedAlternatives ratedAlternatives) {
+ ratedAlternatives.content.max { it.rating.percentage }
+ }
+}
+
+@SpringBootApplication
+@EnableAgents(loggingTheme = LoggingThemes.STAR_WARS)
+void main() {
+ try(var context = SpringApplication.run(Rated)) {
+ println context.getBean(Autonomy)
+ .chooseAndRunAgent('A long-weekend holiday in Caloundra',
ProcessOptions.DEFAULT).output
+ }
+}
+----
+
+The output might look something like (slightly formatted here for readability):
+
+----
+RatedItinerary[
+ itinerary=Itinerary[itinerary=[
+ Activity(Visit Kings Beach, Caloundra, Friday, All day),
+ Activity(Sunset at Mooloolaba Beach, Mooloolaba, Friday, Evening),
+ Activity(Explore Bulcock Beach Markets, Caloundra, Saturday, Morning
to Early Afternoon),
+ Activity(Snorkeling at Dicky Beach, Dicky Beach, Saturday, Afternoon),
+ Activity(Relax at Shelly Beach, Caloundra, Sunday, All day)]],
+ rating=Rating[percentage=80.0]]
+----
+
+This demonstrates how Embabel’s agent model and Groovy’s expressive syntax can
work together to orchestrate multiple AI calls with minimal boilerplate.
+
+== Conclusion
+
+Groovy’s interoperability, concise syntax, and powerful DSL capabilities make
it an excellent language for prototyping and composing AI workflows on the JVM.
+Whether you’re chatting with Ollama, integrating via Spring, or orchestrating
agents with Embabel, Groovy keeps your code clear and compact.
+
+You can find the full source for all these examples at:
+https://github.com/paulk-asert/groovy-ai
+Feel free to experiment with different models and prompts to see what
interesting results you can achieve!