Skip to content

Commit 31d90b3

Browse files
committed
Quarkus + Podman Desktop AI Lab section
1 parent d9f6a81 commit 31d90b3

7 files changed

Lines changed: 106 additions & 47 deletions
114 KB
Loading
173 KB
Loading
10.3 KB
Loading
442 Bytes
Loading
417 Bytes
Loading

documentation/modules/ROOT/nav.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,6 @@
2727
** xref:18_chains_memory.adoc[Chains and Memory]
2828
** xref:19_agents_tools.adoc[Agents/Tools]
2929
** xref:20_embed_documents.adoc[Embedding Documents]
30-
//** xref:21_podman_ai[Working with Podman Desktop AI]
30+
** xref:21_podman_ai.adoc[Working with Podman Desktop AI]
3131
** xref:22_local_models.adoc[Working with local models]
3232
//** xref:23_kubernetes_kafka_ai.adoc[Bringing Kubernetes and Kafka to the party]
Lines changed: 105 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,48 @@
1-
= Working with Podman Desktop AI
1+
= Working with Podman Desktop AI Lab
22

33
:project-podman-ai-name: quarkus-podman-ai-app
44

55
Throughout this tutorial, we've been working with OpenAI's remote models, however wouldn't it be nice if we could work
6-
with models on our local machine (without incurring costs!)
6+
with models on our local machine (without incurring costs)?
77

8-
We could install models on our local machine with Instructlab or Ollama, however in this case let's start with (arguably) the easiest way: Podman Desktop AI.
8+
Podman Desktop is a GUI tool that helps with running and managing containers on our local machine, but it can also help with running AI models locally as well thanks to its AI Lab extension. Thanks to Quarkus and LangChain4j it then becomes trivial to start developing with these models. Let's find out how!
99

1010

1111
== Installing Podman Desktop AI
1212

13-
First, you must download and install the specific Ollama version on your operating system. https://ollama.com/download[The instructions can be found here, window="_blank"].
13+
First, if you haven't yet, you must download and install Podman Desktop on your operating system. https://podman-desktop.io/downloads[The instructions can be found here, window="_blank"].
1414

15-
Once installed, go ahead and download the local model by running this command:
15+
Once installed, go ahead and start the application and go through the setup process. After that, you should see an "AI Lab" extension in the left menu
1616

17-
[.console-input]
18-
[source,bash]
19-
----
20-
ollama pull llama3:latest
21-
----
17+
image::podman-desktop-ai.png[]
2218

23-
Now, let's run our modal locally:
19+
Go ahead and click on it, and in the AI Lab, select the "Catalog"
2420

25-
[.console-input]
26-
[source,bash]
27-
----
28-
ollama serve
29-
----
21+
image::podman-desktop-ai-catalog.png[]
22+
23+
You should now see a list of available AI Models choose from. You can also import different ones (eg. from Huggingface), but we will use one of the InstructLab models that are already available.
24+
25+
NOTE: If you haven't heard of https://developers.redhat.com/articles/2024/05/07/instructlab-open-source-generative-ai[Instructlab], it's an open source project for enhancing large language models (LLMs) used in generative artificial intelligence (gen AI) applications. You can even contribute to it yourself!
26+
27+
To start using the model, we'll first need to download it, so go ahead and do that with the download button image:podman-desktop-model-download.png[download button,30] next to the instructlab/merlinite-7b-lab-GGUF entry (this might take a little while).
28+
29+
Once downloaded, you can create a new model service by clicking on the rocket button image:podman-desktop-create-model-service.png[rocket button, 30] that will appear where you previously clicked the download button.
30+
31+
You will be taken to the "Creating Model Service" page where you can set the port that should be exposed for the service. Podman Desktop assigns a random available port by default, but let's set it to `*35000*` so we can remember more easily what the port is when we configure our Quarkus application.
32+
33+
image::podman-desktop-create-merlinite-service.png[]
34+
35+
After a few moments, your very own Model service will be running locally on your laptop! You an check the details on the Service details page, including some samples to test out the service with cURL (or even Java!).
36+
37+
Now it's time to go back to our Quarkus application.
3038

31-
== Creating a new project with the Ollama extension
39+
NOTE: The InstructLab service uses the OpenAI protocol, so we can continue to use the quarkus-langchain4j-openai extension for this exercise
3240

33-
The Ollama extension isn't compatible with other extensions we have used in this tutorial, so we'll create a new project.
41+
42+
43+
== Creating a new project
44+
45+
Some of the exercises we completed previously are not compatible with non-OpenAI models, so let's create a fresh new project
3446

3547
[tabs%sync]
3648
====
@@ -41,8 +53,8 @@ Maven::
4153
[.console-input]
4254
[source,bash,subs="+macros,+attributes"]
4355
----
44-
mvn "io.quarkus.platform:quarkus-maven-plugin:create" -DprojectGroupId="com.redhat.developers" -DprojectArtifactId="{project-ollama-name}" -DprojectVersion="1.0-SNAPSHOT" -Dextensions=rest,langchain4j-ollama
45-
cd {project-ollama-name}
56+
mvn "io.quarkus.platform:quarkus-maven-plugin:create" -DprojectGroupId="com.redhat.developers" -DprojectArtifactId="{project-podman-ai-name}" -DprojectVersion="1.0-SNAPSHOT" -Dextensions=langchain4j-openai,rest
57+
cd {project-podman-ai-name}
4658
----
4759
--
4860
Quarkus CLI::
@@ -52,47 +64,64 @@ Quarkus CLI::
5264
[.console-input]
5365
[source,bash,subs="+macros,+attributes"]
5466
----
55-
quarkus create app -x rest langchain4j-ollama com.redhat.developers:{project-ollama-name}:1.0-SNAPSHOT
56-
cd {project-ollama-name}
67+
quarkus create app -x rest langchain4j-openai com.redhat.developers:{project-podman-ai-name}:1.0-SNAPSHOT
68+
cd {project-podman-ai-name}
5769
----
5870
--
5971
====
6072

61-
== Connect to Ollama
73+
== Connect to the InstructLab Model
6274

63-
Just add these properties to the `application.properties` file available in `src/main/resources`:
75+
Add the following properties in the `application.properties` file available in `src/main/resources`:
6476

6577
[.console-input]
6678
[source,properties]
6779
----
68-
quarkus.langchain4j.ollama.chat-model.model-id=llama3:latest
69-
quarkus.langchain4j.ollama.timeout=120s
80+
quarkus.langchain4j.openai.base-url=http://localhost:35000/v1 #<1>
81+
# Configure openai server to use a specific model
82+
quarkus.langchain4j.openai.chat-model.model-name=instructlab/merlinite-7b-lab-GGUF #<2>
83+
# Set timeout to 3 minutes
84+
quarkus.langchain4j.openai.timeout=180s
85+
# Enable logging of both requests and responses
86+
quarkus.langchain4j.openai.log-requests=true
87+
quarkus.langchain4j.openai.log-responses=true
7088
----
89+
<1> Port number 35000 was what we had defined in podman desktop when we created the model service
90+
<2> The model we selected to serve. If you chose a different model in Podman Desktop, you'll need to update it here as well.
7191

7292
== Create the AI service
7393

7494
Let's create an interface for our AI service.
7595

76-
Create a new `Assistant` Java interface in `src/main/java` in the `com.redhat.developers` package with the following contents:
96+
Create a new `AssistantForInstructLab.java` Java interface in `src/main/java` in the `com.redhat.developers` package with the following contents:
7797

7898
[.console-input]
7999
[source,java]
80100
----
81101
package com.redhat.developers;
82102
103+
import dev.langchain4j.service.SystemMessage;
104+
import dev.langchain4j.service.UserMessage;
83105
import io.quarkiverse.langchain4j.RegisterAiService;
106+
import jakarta.enterprise.context.SessionScoped;
107+
108+
@RegisterAiService()
109+
@SessionScoped
110+
public interface AssistantForInstructLab {
84111
85-
@RegisterAiService
86-
public interface Assistant {
87-
String chat(String message);
112+
@SystemMessage({
113+
"You are a Java developer who likes to over engineer things" #<1>
114+
})
115+
String chat(@UserMessage String userMessage);
88116
}
89117
----
118+
<1> Gives some context to the model
90119

91120
== Create the prompt-base resource
92121

93-
Now we're going to implement a resource that send prompts using the AI service.
122+
Now we're going to implement another REST resource that accepts prompts
94123

95-
Create a new `ExistentialQuestionResource` Java class in `src/main/java` in the `com.redhat.developers` package with the following contents:
124+
Create a new `InstructLabResource.java` Java class in `src/main/java` in the `com.redhat.developers` package with the following contents:
96125

97126
[.console-input]
98127
[source,java]
@@ -103,45 +132,75 @@ import jakarta.inject.Inject;
103132
import jakarta.ws.rs.GET;
104133
import jakarta.ws.rs.Path;
105134
import jakarta.ws.rs.Produces;
135+
import jakarta.ws.rs.QueryParam;
106136
import jakarta.ws.rs.core.MediaType;
107137
108-
@Path("/earth")
109-
public class ExistentialQuestionResource {
138+
@Path("/instructlab")
139+
public class InstructLabResource {
110140
111141
@Inject
112-
Assistant assistant;
142+
AssistantForInstructLab assistant;
113143
114144
@GET
115-
@Path("/flat")
116145
@Produces(MediaType.TEXT_PLAIN)
117-
public String isEarthFlat() {
118-
return assistant.chat("Can you explain why the earth is flat?");
146+
public String prompt(@QueryParam("message") String message) {
147+
return assistant.chat(message);
119148
}
120149
}
121150
----
122151

123152
== Invoke the endpoint
124153

125-
You can check your prompt implementation by pointing your browser to http://localhost:8080/earth/flat[window=_blank]
154+
Let's ask our model to create a class that returns the square root of a given number:
155+
156+
You can check your prompt implementation by pointing your browser to http://localhost:8080/instructlab?message=generate%20a%20class%20that%20returns%20the%20square%20root%20of%20a%20given%20number[window=_blank]
126157

127158
You can also run the following command:
128159

129160
[.console-input]
130161
[source,bash]
131162
----
132-
curl localhost:8080/earth/flat
163+
curl http://localhost:8080/instructlab?message=generate%20a%20class%20that%20returns%20the%20square%20root%20of%20a%20given%20number
133164
----
134165

135-
An example of output (it can vary on each prompt execution):
166+
An example of output (remember, your result will likely be different):
136167

137168
[.console-output]
138169
[source,text]
139170
----
140-
I think there may be a misunderstanding here!
171+
Here is a simple Java class to calculate the square root of a given number using the built-in `Math` class in Java:
172+
173+
```java
174+
public class SquareRootCalculator {
175+
public static void main(String[] args) {
176+
int num = 16; // square root of 16 is 4.0
177+
double result = Math.sqrt(num);
178+
System.out.println("Square root of " + num + ": " + result);
179+
}
180+
}
181+
```
182+
183+
Alternatively, if you want to handle negative numbers or non-integer inputs, you can use the `Math.sqrt()` function directly:
184+
185+
```java
186+
public class SquareRootCalculator {
187+
public static void main(String[] args) {
188+
double num = -16; // square root of -16 is -4.0
189+
double result = Math.sqrt(num);
190+
System.out.println("Square root of " + num + ": " + result);
191+
}
192+
}
193+
```
194+
195+
This will allow you to calculate the square root of any given number, positive or negative, and handle non-integer inputs.
196+
----
197+
198+
Notice that (at least in our case) the LLM responded with a Java class, since we provided in the SystemMessage that the
199+
LLM should respond as if they were a Java engineer.
141200

142-
Actually, the scientific consensus is that the Earth is an oblate spheroid, meaning it's slightly flattened at the poles and bulging at the equator. The evidence from various fields of science, including astronomy, geology, and physics, all point to the fact that our planet is indeed round.
201+
== Going further
143202

144-
Here are some reasons why we know the Earth is not flat:
203+
Feel free to play around with the different models Podman Desktop AI Lab provides. You will notice that some are faster
204+
than others, and some will respond better to specific questions than others, based on how they have been trained.
145205

146-
1. **Ships disappearing over the horizon**: When a ship sails away from an observer on the shore, it will eventually disappear from view as it sinks below the horizon due to the curvature of the Earth.
147-
----
206+
NOTE: If you want to help improve the answers generated by the InstructLab model, feel free to https://github.com/instructlab/community/blob/main/README.md[contribute to the project].

0 commit comments

Comments
 (0)