Skip to content

Commit 80ceeca

Browse files
Add AI documentation: setup guides and examples for integrating LLMs … (#4548)
* Add AI documentation: setup guides and examples for integrating LLMs in Vaadin * Move AI into Building Apps * Fix links and minor edits * Add new AI terms * Add spaces and change copy-pasted characters to ASCII ones * Change headings to title case * Rewrite without first-person plurals * Fix vale errors and some warnings --------- Co-authored-by: Petter Holmstrom <[email protected]>
1 parent e66fed4 commit 80ceeca

File tree

11 files changed

+613
-0
lines changed

11 files changed

+613
-0
lines changed

.github/styles/config/vocabularies/Docs/accept.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ Brotli
2323
bun
2424
[bB]undlers?
2525
[cC]acheable
26+
[cC]hatbot
2627
classpath
2728
[cC]onfig(|uration|ure|urer|urator|map)
2829
[cC]onformant
@@ -140,6 +141,7 @@ Node\.js
140141
[nN]ullable
141142
[nN]ullability
142143
OAuth
144+
Ollama
143145
OSGi
144146
Okta
145147
[Oo]nboarding
@@ -238,6 +240,7 @@ DOM
238240
IDE
239241
JDK
240242
MVC
243+
LLMs
241244
PWA
242245
RPC
243246
SPI
192 KB
Loading
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
---
2+
title: AI & LLMs
3+
page-title: AI in Vaadin Applications
4+
description: Leverage AI in your Vaadin applications with practical use cases and setup options that fit your project.
5+
meta-description: Leverage AI in Vaadin. Practical use cases and setup options with Spring AI or LangChain4j, plus UI patterns for streaming chat.
6+
order: 69
7+
---
8+
9+
10+
= AI in Vaadin Applications
11+
12+
In this section, you'll learn how to connect a Vaadin application to a Large Language Model (LLM) and integrate AI features into your workflows. Using common Vaadin application scenarios as examples, you'll explore typical UI patterns for AI integration. The focus is on simple, adaptable examples that you can quickly implement in your own projects.
13+
14+
You'll learn how to:
15+
16+
* connect your application to an AI client with popular Java libraries such as Spring AI and LangChain4j,
17+
* choose Vaadin components that create intuitive, AI-powered workflows -- such as `MessageInput`, `MessageList`, and `Scroller`, and
18+
* deliver real-time updates to users through server push.
19+
20+
section_outline::[]
21+
22+
[NOTE]
23+
This section is a work in progress, and your feedback is welcome. If you have suggestions or find gaps, https://github.com/vaadin/docs[open an issue on GitHub].
Lines changed: 286 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,286 @@
1+
---
2+
title: Quick Start-Guide
3+
page-title: Quick Start-Guide | AI Chatbot with Vaadin
4+
description: A compact chat view with streaming, correct scrolling, and message context.
5+
meta-description: Hands-on tutorial - connect Vaadin to an LLM with Spring, build a streaming chat UI, and apply simple, reusable patterns for prompts, memory, and UX.
6+
order: 20
7+
section-nav: badge-flow
8+
---
9+
10+
11+
= Quick Start-Guide: Add an AI Chat Bot to a Vaadin + Spring Boot Application [badge-flow]#Flow#
12+
13+
This guide shows how to connect a Large Language Model (LLM) into a Vaadin application using Spring AI and Spring Boot. You'll build a minimal chat UI with Vaadin provided components **MessageList** and **MessageInput**, stream responses token-by-token, and keep a conversational tone in the dialog with the AI.
14+
15+
image::images/chatbot-image.png[role=text-center]
16+
17+
**Audience & style:** This quick guide is for Java developers and Vaadin beginners, as well as AI rookies. The sample application is implemented in Spring style and explains in small, practical steps how to integrate AI into Vaadin. Code snippets are available for copy and paste.
18+
19+
20+
== Prerequisites
21+
22+
* Java 17+
23+
* Spring Boot 3.5+ (or newer)
24+
* Vaadin 24.8+
25+
* An OpenAI API key (`OPENAI_API_KEY`)
26+
27+
28+
== 1. Start from a Vaadin Spring Skeleton
29+
30+
Download a Vaadin Spring starter from http://github.com/vaadin/skeleton-starter-flow-spring[GitHub], import it into your preferred IDE, and get it running in your environment.
31+
32+
**Pro Tip**: Starting the application with Hotswap Agent improves your development lifecycle.
33+
34+
Start with a cleaning and remove the default service `GreetService` and clear the existing UI content. You'll implement everything in `MainView`.
35+
36+
37+
== 2. Add Spring AI dependencies
38+
39+
Add the Spring AI BOM and the OpenAI starter to import the necessary dependencies to your project. The BOM takes care of all Spring AI dependencies and provides the consistent version numbers to each sub dependency automatically.
40+
41+
**Maven (`pom.xml`):**
42+
43+
[source,xml]
44+
----
45+
<dependencyManagement>
46+
...
47+
<dependencies>
48+
<dependency>
49+
<groupId>org.springframework.ai</groupId>
50+
<artifactId>spring-ai-bom</artifactId>
51+
<version>1.0.1</version><!-- use the latest stable -->
52+
<type>pom</type>
53+
<scope>import</scope>
54+
</dependency>
55+
</dependencies>
56+
...
57+
</dependencyManagement>
58+
59+
<dependencies>
60+
...
61+
<!-- OpenAI LLM via Spring AI -->
62+
<dependency>
63+
<groupId>org.springframework.ai</groupId>
64+
<artifactId>spring-ai-starter-model-openai</artifactId>
65+
</dependency>
66+
...
67+
</dependencies>
68+
----
69+
70+
*(Gradle users: import the Spring AI BOM and add the same starters.)*
71+
72+
73+
== 3. Configure Your OpenAI Credentials
74+
75+
To access the API of OpenAI you need a license key. The preferred way to provide the key is through an environment variable, as this makes it available to other applications as well. After setting the environment variable on your system, refer to it from `application.properties` like this:
76+
77+
[source,properties]
78+
----
79+
spring.ai.openai.api-key=${OPENAI_API_KEY}
80+
# Optional: pick a model; adjust to what your account supports
81+
# spring.ai.openai.chat.options.model=gpt-5
82+
----
83+
84+
**Tip:** use Spring profiles or your CI/CD's secret store for the key.
85+
86+
87+
== 4. Enable Vaadin Push
88+
89+
To prevent end-users from sitting in front of a blank screen waiting for a response, you'll stream tokens asynchronously and update the UI live with response tokens. To do this, you need to enable server push:
90+
91+
[source,java]
92+
----
93+
// src/main/java/org/vaadin/example/Application.java
94+
95+
import com.vaadin.flow.component.page.AppShellConfigurator;
96+
import com.vaadin.flow.component.page.Push;
97+
import com.vaadin.flow.router.PageTitle;
98+
import com.vaadin.flow.theme.Theme;
99+
import org.springframework.boot.SpringApplication;
100+
import org.springframework.boot.autoconfigure.SpringBootApplication;
101+
102+
@Theme("my-theme")
103+
@PageTitle("AI in Vaadin")
104+
@SpringBootApplication
105+
@Push
106+
public class Application implements AppShellConfigurator {
107+
108+
public static void main(String[] args) {
109+
SpringApplication.run(Application.class, args);
110+
}
111+
}
112+
----
113+
114+
115+
== 5. Create the Chat service (Spring AI)
116+
117+
Create a new class called **ChatService** and annotate it with `@Service`. This service builds a `ChatClient` with a **ChatMemory** advisor in the constructor and exposes a **reactive stream** of tokens.
118+
119+
[source,java]
120+
----
121+
// src/main/java/org/vaadin/example/ChatService.java
122+
package org.vaadin.example;
123+
124+
import org.springframework.ai.chat.client.ChatClient;
125+
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
126+
import org.springframework.ai.chat.memory.ChatMemory;
127+
import org.springframework.stereotype.Service;
128+
import reactor.core.publisher.Flux;
129+
130+
@Service
131+
public class ChatService {
132+
133+
private final ChatClient chatClient;
134+
135+
public ChatService(ChatClient.Builder chatClientBuilder,
136+
ChatMemory chatMemory) {
137+
// Add a memory advisor to the chat client
138+
var chatMemoryAdvisor = MessageChatMemoryAdvisor
139+
.builder(chatMemory)
140+
.build();
141+
142+
// Build the chat client
143+
chatClient = chatClientBuilder
144+
.defaultAdvisors(chatMemoryAdvisor)
145+
.build();
146+
}
147+
148+
public Flux<String> chatStream(String userInput, String chatId) {
149+
return chatClient.prompt()
150+
.advisors(advisorSpec ->
151+
advisorSpec.param(ChatMemory.CONVERSATION_ID, chatId)
152+
)
153+
.user(userInput)
154+
.stream()
155+
.content();
156+
}
157+
}
158+
159+
----
160+
161+
Why a chat memory? **ChatMemory** keeps context of the conversations so users don't have to repeat themselves. The `chatId` keeps the context for a specific chat and doesn't share it with other chats and users.
162+
163+
164+
== 6. Build the Chat UI with Vaadin
165+
166+
Use `MessageList` to render the conversation as Markdown and `MessageInput` to handle the user prompts. Wrap the list in a `Scroller` so long chats don't grow the layout beyond the browser window:
167+
168+
[source,java]
169+
----
170+
// src/main/java/org/vaadin/example/MainView.java
171+
package com.example.application.views.chatbot;
172+
173+
import com.example.application.services.ChatService;
174+
import com.vaadin.flow.component.Composite;
175+
import com.vaadin.flow.component.messages.MessageInput;
176+
import com.vaadin.flow.component.messages.MessageList;
177+
import com.vaadin.flow.component.messages.MessageListItem;
178+
import com.vaadin.flow.component.orderedlayout.Scroller;
179+
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
180+
import com.vaadin.flow.router.Menu;
181+
import com.vaadin.flow.router.PageTitle;
182+
import com.vaadin.flow.router.Route;
183+
import com.vaadin.flow.router.RouteAlias;
184+
import org.vaadin.lineawesome.LineAwesomeIconUrl;
185+
186+
import java.time.Instant;
187+
import java.util.UUID;
188+
189+
@PageTitle("Chat Bot")
190+
@Route("")
191+
@RouteAlias("chat-bot")
192+
@Menu(order = 0, icon = LineAwesomeIconUrl.ROBOT_SOLID)
193+
public class ChatBotView extends Composite<VerticalLayout> {
194+
195+
private final ChatService chatService;
196+
private final MessageList messageList;
197+
private final String chatId = UUID.randomUUID().toString();
198+
199+
public ChatBotView(ChatService chatService) {
200+
this.chatService = chatService;
201+
202+
//Create a scrolling MessageList
203+
messageList = new MessageList();
204+
var scroller = new Scroller(messageList);
205+
scroller.setHeightFull();
206+
getContent().addAndExpand(scroller);
207+
208+
//create a MessageInput and set a submit-listener
209+
var messageInput = new MessageInput();
210+
messageInput.addSubmitListener(this::onSubmit);
211+
messageInput.setWidthFull();
212+
213+
getContent().add(messageInput);
214+
}
215+
216+
private void onSubmit(MessageInput.SubmitEvent submitEvent) {
217+
//create and handle a prompt message
218+
var promptMessage = new MessageListItem(submitEvent.getValue(), Instant.now(), "User");
219+
promptMessage.setUserColorIndex(0);
220+
messageList.addItem(promptMessage);
221+
222+
//create and handle the response message
223+
var responseMessage = new MessageListItem("", Instant.now(), "Bot");
224+
responseMessage.setUserColorIndex(1);
225+
messageList.addItem(responseMessage);
226+
227+
//append a response message to the existing UI
228+
var userPrompt = submitEvent.getValue();
229+
var uiOptional = submitEvent.getSource().getUI();
230+
var ui = uiOptional.orElse(null); //implementation via ifPresent also possible
231+
232+
if (ui != null) {
233+
chatService.chatStream(userPrompt, chatId)
234+
.subscribe(token ->
235+
ui.access(() ->
236+
responseMessage.appendText(token)));
237+
}
238+
}
239+
}
240+
241+
----
242+
243+
**Key UI patterns used here:**
244+
245+
* **Dialog character:** display prompts and responses separately so the difference remains visible.
246+
* **Streaming output:** show tokens as they arrive for perceived performance.
247+
* **Markdown rendering:** richer answers (lists, code blocks, emojis).
248+
* **Sticky scroll:** keep the latest answer in view.
249+
250+
251+
== 7. Run & Iterate
252+
253+
Start the application, open the browser, and try your first prompts.
254+
255+
256+
== What You Built
257+
258+
* A production-ready **chat bot** using Vaadin components
259+
* **Token-by-token streaming** with Vaadin Push
260+
* **Conversation memory** via Spring AI advisors
261+
262+
263+
== Next Possible Steps
264+
265+
* Add a **system prompt** field to steer the assistant (e.g., tone, persona).
266+
* Add **clear chat** and **export** actions.
267+
* Add **feedback** to evaluate responses
268+
* Support **attachments** and **tool calls** (retrieval, functions).
269+
* Log prompts/responses for observability.
270+
271+
272+
== Troubleshooting
273+
274+
* **No streaming updates?** Ensure `@Push` is present and check reverse proxy/WebSocket settings.
275+
* **401 Exception from OpenAI?** Verify `OPENAI_API_KEY` and environment injection in your run configuration.
276+
277+
278+
== Complete File List Recap
279+
280+
* `src/main/java/org/vaadin/example/Application.java` — Spring Boot + `@Push`
281+
* `src/main/java/org/vaadin/example/ChatService.java` — Spring AI client + memory
282+
* `src/main/java/org/vaadin/example/MainView.java` — Vaadin chat UI
283+
* `src/main/resources/application.properties` — OpenAI config
284+
* `pom.xml` — Vaadin + Spring AI dependencies
285+
286+
That's it — your Vaadin application now speaks AI. 🚀
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
---
2+
title: Eclipse IDE
3+
page-title: Configure API key in Eclipse IDE for Vaadin
4+
description: Configure environment variables or VM arguments in Eclipse IDE to provide API keys for your Vaadin project.
5+
meta-description: Configure API keys in Eclipse IDE for your Vaadin project using Run Configurations for environment variables or VM arguments.
6+
order: 30
7+
---
8+
9+
10+
= Eclipse IDE
11+
12+
In Eclipse you need to set the API key explicitly in the Run Configuration.
13+
Choose either **Environment variables** or **VM arguments**:
14+
15+
16+
== Environment Variables
17+
18+
*Open → Run → Run Configurations → Environment → New…*
19+
Add:
20+
21+
----
22+
Name: OPENAI_API_KEY
23+
Value: sk-your-key-here
24+
----
25+
26+
27+
== VM Arguments
28+
29+
*Open → Run → Run Configurations → Arguments → VM arguments*
30+
Add:
31+
32+
----
33+
-DOPENAI_API_KEY=sk-your-key-here
34+
----
35+
36+
image::images/configuration_eclipse.jpg[role=text-center]
37+
38+
In both cases you can reference the variable in your configuration:
39+
40+
[source,properties]
41+
----
42+
spring.ai.openai.api-key=${OPENAI_API_KEY}
43+
----
151 KB
Loading
21.2 KB
Loading

0 commit comments

Comments
 (0)