Skip to content

Commit 7f0e0c7

Browse files
committed
feat: setup chat orchestration for ollama 🚀
1 parent 4ffc0fc commit 7f0e0c7

File tree

12 files changed

+653
-44
lines changed

12 files changed

+653
-44
lines changed

com.developer.nefarious.zjoule.plugin/META-INF/MANIFEST.MF

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ Export-Package:
2525
com.developer.nefarious.zjoule.plugin.chat,
2626
com.developer.nefarious.zjoule.plugin.chat.memory,
2727
com.developer.nefarious.zjoule.plugin.chat.models,
28+
com.developer.nefarious.zjoule.plugin.chat.ollama,
2829
com.developer.nefarious.zjoule.plugin.chat.openai,
2930
com.developer.nefarious.zjoule.plugin.chat.utils,
3031
com.developer.nefarious.zjoule.plugin.core,

com.developer.nefarious.zjoule.plugin/src/com/developer/nefarious/zjoule/plugin/chat/AIClientFactory.java

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,21 @@
66
import com.developer.nefarious.zjoule.plugin.auth.AuthClientHelper;
77
import com.developer.nefarious.zjoule.plugin.auth.SessionManager;
88
import com.developer.nefarious.zjoule.plugin.chat.memory.MemoryMessageHistory;
9+
import com.developer.nefarious.zjoule.plugin.chat.ollama.OllamaClient;
10+
import com.developer.nefarious.zjoule.plugin.chat.ollama.OllamaClientHelper;
911
import com.developer.nefarious.zjoule.plugin.chat.openai.OpenAIClient;
1012
import com.developer.nefarious.zjoule.plugin.chat.openai.OpenAIClientHelper;
13+
import com.developer.nefarious.zjoule.plugin.memory.IMemoryObject;
1114
import com.developer.nefarious.zjoule.plugin.memory.MemoryAccessToken;
1215
import com.developer.nefarious.zjoule.plugin.memory.MemoryDeployment;
16+
import com.developer.nefarious.zjoule.plugin.memory.MemoryOllamaEndpoint;
17+
import com.developer.nefarious.zjoule.plugin.memory.MemoryOllamaModel;
1318
import com.developer.nefarious.zjoule.plugin.memory.MemoryResourceGroup;
1419
import com.developer.nefarious.zjoule.plugin.memory.MemoryServiceKey;
20+
import com.developer.nefarious.zjoule.plugin.models.AccessToken;
1521
import com.developer.nefarious.zjoule.plugin.models.Deployment;
22+
import com.developer.nefarious.zjoule.plugin.models.OllamaModel;
23+
import com.developer.nefarious.zjoule.plugin.models.ServiceKey;
1624

1725
/**
1826
* A factory class responsible for creating instances of {@link IAIClient}.
@@ -41,11 +49,11 @@ public static IAIClient getClient() {
4149

4250
private static IAIClient getClientForSapAiCore() {
4351
// Load memory components for access token, service key, resource group, deployment, and message history.
44-
MemoryAccessToken memoryAccessToken = MemoryAccessToken.getInstance();
45-
MemoryServiceKey memoryServiceKey = MemoryServiceKey.getInstance();
46-
MemoryResourceGroup memoryResourceGroup = MemoryResourceGroup.getInstance();
47-
MemoryDeployment memoryDeployment = MemoryDeployment.getInstance();
48-
MemoryMessageHistory memoryMessageHistory = MemoryMessageHistory.getInstance();
52+
MemoryMessageHistory memoryMessageHistory = MemoryMessageHistory.getInstance();
53+
IMemoryObject<AccessToken> memoryAccessToken = MemoryAccessToken.getInstance();
54+
IMemoryObject<ServiceKey> memoryServiceKey = MemoryServiceKey.getInstance();
55+
IMemoryObject<String> memoryResourceGroup = MemoryResourceGroup.getInstance();
56+
IMemoryObject<Deployment> memoryDeployment = MemoryDeployment.getInstance();
4957

5058
// Initialize authentication helpers and the authentication client.
5159
AuthClientHelper authHelper = new AuthClientHelper();
@@ -64,7 +72,12 @@ private static IAIClient getClientForSapAiCore() {
6472
}
6573

6674
private static IAIClient getClientForOllama() {
67-
return null;
75+
MemoryMessageHistory memoryMessageHistory = MemoryMessageHistory.getInstance();
76+
IMemoryObject<String> memoryOllamaEndpoint = MemoryOllamaEndpoint.getInstance();
77+
IMemoryObject<OllamaModel> memoryOllamaModel = MemoryOllamaModel.getInstance();
78+
79+
OllamaClientHelper helper = new OllamaClientHelper(memoryOllamaModel);
80+
return new OllamaClient(memoryMessageHistory, memoryOllamaEndpoint, helper);
6881

6982
}
7083

com.developer.nefarious.zjoule.plugin/src/com/developer/nefarious/zjoule/plugin/chat/IAIClient.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@ public interface IAIClient {
4949
/**
5050
* Updates the chat message history with the provided list of messages.
5151
*
52-
* @param messages the list of {@link IChatMessage} objects to save as the updated chat history.
52+
* @param chatMessages the list of {@link IChatMessage} objects to save as the updated chat history.
5353
*/
54-
void setMessageHistory(final List<IChatMessage> messages);
54+
void setMessageHistory(final List<IChatMessage> chatMessages);
5555

5656
}

com.developer.nefarious.zjoule.plugin/src/com/developer/nefarious/zjoule/plugin/chat/memory/MemoryMessageHistory.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
*/
1414
public class MemoryMessageHistory implements IMemoryMessageHistory {
1515

16-
/** Singleton instance of {@code MemoryMessageHistory}. */
16+
/** Singleton instance of {@code IMemoryMessageHistory}. */
1717
private static MemoryMessageHistory instance;
1818

1919
/** Serializer for converting objects to and from serialized formats. */
@@ -23,9 +23,9 @@ public class MemoryMessageHistory implements IMemoryMessageHistory {
2323
private IEclipseMemory eclipseMemory;
2424

2525
/**
26-
* Retrieves the singleton instance of {@code MemoryMessageHistory}.
26+
* Retrieves the singleton instance of {@code IMemoryMessageHistory}.
2727
*
28-
* @return the singleton instance of {@code MemoryMessageHistory}.
28+
* @return the singleton instance of {@code IMemoryMessageHistory}.
2929
* @throws IllegalStateException if the instance is not initialized.
3030
*/
3131
public static MemoryMessageHistory getInstance() {

com.developer.nefarious.zjoule.plugin/src/com/developer/nefarious/zjoule/plugin/chat/ollama/OllamaChatMessage.java

Lines changed: 76 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,83 @@
33
import com.developer.nefarious.zjoule.plugin.chat.IChatMessage;
44
import com.developer.nefarious.zjoule.plugin.models.Role;
55

6+
/**
7+
* Represents a chat message exchanged with the Ollama model.
8+
* The {@code OllamaChatMessage} class implements {@link IChatMessage} and
9+
* encapsulates the role and content of a message in the chat context.
10+
*/
611
public class OllamaChatMessage implements IChatMessage {
12+
713

8-
@Override
9-
public String getMessage() {
10-
// TODO Auto-generated method stub
11-
return null;
12-
}
13-
14-
@Override
15-
public Role getRole() {
16-
// TODO Auto-generated method stub
17-
return null;
18-
}
14+
/** The role of the message (e.g., user, system, assistant). */
15+
private Role role;
16+
17+
/** The content of the message. */
18+
private String content;
19+
20+
/**
21+
* Default constructor for creating an empty {@code OllamaChatMessage}.
22+
*/
23+
public OllamaChatMessage() { }
24+
25+
/**
26+
* Constructs a new {@code OllamaChatMessage} with the specified role and content.
27+
*
28+
* @param role the role of the message (e.g., {@link Role#USER}, {@link Role#SYSTEM}).
29+
* @param content the content of the message.
30+
*/
31+
public OllamaChatMessage(final Role role, final String content) {
32+
this.role = role;
33+
this.content = content;
34+
}
35+
36+
/**
37+
* Retrieves the content of the message.
38+
*
39+
* @return the content of the message as a {@link String}.
40+
*/
41+
public String getContent() {
42+
return content;
43+
}
44+
45+
/**
46+
* Retrieves the message content.
47+
* This is the implementation of the {@link IChatMessage#getMessage()} method.
48+
*
49+
* @return the message content as a {@link String}.
50+
*/
51+
@Override
52+
public String getMessage() {
53+
return content;
54+
}
55+
56+
/**
57+
* Retrieves the role associated with the message.
58+
* This is the implementation of the {@link IChatMessage#getRole()} method.
59+
*
60+
* @return the role of the message as a {@link Role}.
61+
*/
62+
@Override
63+
public Role getRole() {
64+
return role;
65+
}
66+
67+
/**
68+
* Sets the content of the message.
69+
*
70+
* @param content the new content of the message.
71+
*/
72+
public void setContent(final String content) {
73+
this.content = content;
74+
}
75+
76+
/**
77+
* Sets the role of the message.
78+
*
79+
* @param role the new role of the message (e.g., {@link Role#USER}, {@link Role#SYSTEM}).
80+
*/
81+
public void setRole(final Role role) {
82+
this.role = role;
83+
}
1984

2085
}
Lines changed: 66 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,94 @@
11
package com.developer.nefarious.zjoule.plugin.chat.ollama;
22

33
import java.io.IOException;
4+
import java.net.URI;
5+
import java.net.http.HttpClient;
6+
import java.net.http.HttpRequest;
7+
import java.net.http.HttpRequest.BodyPublisher;
8+
import java.net.http.HttpResponse;
9+
import java.util.Collections;
410
import java.util.List;
11+
import java.util.stream.Collectors;
512

613
import com.developer.nefarious.zjoule.plugin.chat.IAIClient;
714
import com.developer.nefarious.zjoule.plugin.chat.IChatMessage;
15+
import com.developer.nefarious.zjoule.plugin.chat.memory.IMemoryMessageHistory;
16+
import com.developer.nefarious.zjoule.plugin.chat.models.Message;
17+
import com.developer.nefarious.zjoule.plugin.chat.models.MessageHistory;
18+
import com.developer.nefarious.zjoule.plugin.memory.IMemoryObject;
819
import com.developer.nefarious.zjoule.plugin.models.Role;
920

1021
public class OllamaClient implements IAIClient {
1122

23+
private HttpClient httpClient;
24+
25+
private IMemoryMessageHistory memoryMessageHistory;
26+
27+
private IMemoryObject<String> memoryOllamaEndpoint;
28+
29+
private IOllamaClientHelper helper;
30+
1231
public OllamaClient(
13-
) {
14-
32+
final IMemoryMessageHistory memoryMessageHistory,
33+
final IMemoryObject<String> memoryOllamaEndpoint,
34+
final IOllamaClientHelper ollamaClientHelper) {
35+
this.httpClient = HttpClient.newHttpClient();
36+
this.memoryMessageHistory = memoryMessageHistory;
37+
this.memoryOllamaEndpoint = memoryOllamaEndpoint;
38+
helper = ollamaClientHelper;
1539
}
1640

1741
@Override
18-
public IChatMessage chatCompletion(List<IChatMessage> messages) throws IOException, InterruptedException {
19-
// TODO Auto-generated method stub
20-
return null;
42+
public IChatMessage chatCompletion(final List<IChatMessage> messages) throws IOException, InterruptedException {
43+
URI endpoint = createChatEndpoint();
44+
45+
BodyPublisher requestBody = helper.createRequestBody(messages);
46+
47+
HttpRequest request = HttpRequest.newBuilder()
48+
.uri(endpoint)
49+
.POST(requestBody)
50+
.build();
51+
52+
HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
53+
54+
return helper.convertResponseToObject(response.body());
2155
}
2256

2357
@Override
24-
public IChatMessage createMessage(Role role, String userPrompt) {
25-
// TODO Auto-generated method stub
26-
return null;
58+
public IChatMessage createMessage(final Role role, final String userPrompt) {
59+
return new OllamaChatMessage(role, userPrompt);
2760
}
2861

2962
@Override
3063
public List<IChatMessage> getMessageHistory() {
31-
// TODO Auto-generated method stub
32-
return null;
64+
MessageHistory messageHistory = memoryMessageHistory.load();
65+
if (messageHistory == null) {
66+
return Collections.emptyList();
67+
}
68+
69+
List<Message> messages = messageHistory.getMessages();
70+
if (messages == null || messages.isEmpty()) {
71+
return Collections.emptyList();
72+
}
73+
74+
return messages.stream().map(message ->
75+
new OllamaChatMessage(message.getRole(), message.getContent()))
76+
.collect(Collectors.toList());
3377
}
3478

3579
@Override
36-
public void setMessageHistory(List<IChatMessage> messages) {
37-
// TODO Auto-generated method stub
38-
80+
public void setMessageHistory(final List<IChatMessage> chatMessages) {
81+
MessageHistory newMessageHistory = new MessageHistory();
82+
newMessageHistory.setMessages(chatMessages.stream().map(
83+
chatMessage -> new Message(chatMessage.getRole(), chatMessage.getMessage()))
84+
.collect(Collectors.toList()));
85+
memoryMessageHistory.save(newMessageHistory);
3986
}
87+
88+
private URI createChatEndpoint() {
89+
String endpoint = memoryOllamaEndpoint.load();
90+
String endpointInStringFormat = endpoint + "/api/chat";
91+
return URI.create(endpointInStringFormat);
92+
}
4093

4194
}
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,44 @@
11
package com.developer.nefarious.zjoule.plugin.chat.ollama;
22

3+
import java.net.http.HttpRequest;
34
import java.net.http.HttpRequest.BodyPublisher;
45
import java.util.List;
56

67
import com.developer.nefarious.zjoule.plugin.chat.IChatMessage;
8+
import com.developer.nefarious.zjoule.plugin.memory.IMemoryObject;
9+
import com.developer.nefarious.zjoule.plugin.models.OllamaModel;
10+
import com.google.gson.Gson;
711

812
public class OllamaClientHelper implements IOllamaClientHelper {
13+
14+
private IMemoryObject<OllamaModel> memoryOllamaModel;
15+
16+
public OllamaClientHelper(final IMemoryObject<OllamaModel> memoryOllamaModel) {
17+
this.memoryOllamaModel = memoryOllamaModel;
18+
}
919

1020
@Override
11-
public IChatMessage convertResponseToObject(String serializedResponseBody) {
12-
// TODO Auto-generated method stub
13-
return null;
21+
public IChatMessage convertResponseToObject(final String serializedResponseBody) {
22+
Gson gson = new Gson();
23+
OllamaRequestResponse deserializedResponseBody = gson.fromJson(serializedResponseBody, OllamaRequestResponse.class);
24+
return deserializedResponseBody.getMessage();
1425
}
1526

1627
@Override
17-
public BodyPublisher createRequestBody(List<IChatMessage> messages) {
18-
// TODO Auto-generated method stub
19-
return null;
28+
public BodyPublisher createRequestBody(final List<IChatMessage> messages) {
29+
OllamaRequestBody requestBody = new OllamaRequestBody();
30+
31+
requestBody.setModel(getSelectedModel());
32+
requestBody.setMessages(messages);
33+
requestBody.setStream(false);
34+
35+
BodyPublisher bodyPublisher = HttpRequest.BodyPublishers.ofString(requestBody.toString());
36+
return HttpRequest.BodyPublishers.fromPublisher(bodyPublisher);
37+
}
38+
39+
private String getSelectedModel() {
40+
OllamaModel ollamaModel = memoryOllamaModel.load();
41+
return ollamaModel.getName();
2042
}
2143

22-
}
44+
}

0 commit comments

Comments
 (0)