Skip to content

Commit 77daba6

Browse files
authored
Merge pull request #9 from Dannyj1/chat-completion-0.0.2
Update ChatCompletion to Mistral API version 0.0.2. BREAKING CHANGE: Large parts of ChatCompletionRequest were rewritten to support certain changes in the Mistral API. See MIGRATION.md for more information.
2 parents c9a4d3f + ebc2d74 commit 77daba6

51 files changed

Lines changed: 2698 additions & 356 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/build.yml

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,36 @@
1-
name: SonarCloud
1+
name: SonarQube
22
on:
33
push:
44
branches:
55
- master
66
pull_request:
7-
types: [ opened, synchronize, reopened ]
7+
types: [opened, synchronize, reopened]
88
jobs:
99
build:
1010
name: Build and analyze
1111
runs-on: ubuntu-latest
1212
steps:
13-
- uses: actions/checkout@v3
13+
- uses: actions/checkout@v4
1414
with:
1515
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
1616
- name: Set up JDK 17
17-
uses: actions/setup-java@v3
17+
uses: actions/setup-java@v4
1818
with:
1919
java-version: 17
2020
distribution: 'zulu' # Alternative distribution options are available
21-
- name: Cache SonarCloud packages
22-
uses: actions/cache@v3
21+
- name: Cache SonarQube packages
22+
uses: actions/cache@v4
2323
with:
2424
path: ~/.sonar/cache
2525
key: ${{ runner.os }}-sonar
2626
restore-keys: ${{ runner.os }}-sonar
2727
- name: Cache Gradle packages
28-
uses: actions/cache@v3
28+
uses: actions/cache@v4
2929
with:
3030
path: ~/.gradle/caches
3131
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }}
3232
restore-keys: ${{ runner.os }}-gradle
3333
- name: Build and analyze
3434
env:
35-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any
3635
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
37-
run: ./gradlew build sonar --info
36+
run: ./gradlew build sonar --info

.github/workflows/codeql.yml

Lines changed: 30 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -47,42 +47,42 @@ jobs:
4747
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
4848

4949
steps:
50-
- name: Checkout repository
51-
uses: actions/checkout@v4
50+
- name: Checkout repository
51+
uses: actions/checkout@v4
5252

53-
- uses: actions/setup-java@v1
54-
with:
55-
java-version: 17
53+
- uses: actions/setup-java@v1
54+
with:
55+
java-version: 17
5656

57-
# Initializes the CodeQL tools for scanning.
58-
- name: Initialize CodeQL
59-
uses: github/codeql-action/init@v3
60-
with:
61-
languages: ${{ matrix.language }}
62-
# If you wish to specify custom queries, you can do so here or in a config file.
63-
# By default, queries listed here will override any specified in a config file.
64-
# Prefix the list here with "+" to use these queries and those in the config file.
57+
# Initializes the CodeQL tools for scanning.
58+
- name: Initialize CodeQL
59+
uses: github/codeql-action/init@v3
60+
with:
61+
languages: ${{ matrix.language }}
62+
# If you wish to specify custom queries, you can do so here or in a config file.
63+
# By default, queries listed here will override any specified in a config file.
64+
# Prefix the list here with "+" to use these queries and those in the config file.
6565

66-
# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
67-
queries: security-extended
66+
# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
67+
queries: security-extended
6868

6969

70-
# Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift).
71-
# If this step fails, then you should remove it and run the build manually (see below)
72-
- name: Autobuild
73-
uses: github/codeql-action/autobuild@v3
70+
# Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift).
71+
# If this step fails, then you should remove it and run the build manually (see below)
72+
- name: Autobuild
73+
uses: github/codeql-action/autobuild@v3
7474

75-
# ℹ️ Command-line programs to run using the OS shell.
76-
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
75+
# ℹ️ Command-line programs to run using the OS shell.
76+
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
7777

78-
# If the Autobuild fails above, remove it and uncomment the following three lines.
79-
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
78+
# If the Autobuild fails above, remove it and uncomment the following three lines.
79+
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
8080

81-
# - run: |
82-
# echo "Run, Build Application using script"
83-
# ./location_of_script_within_repo/buildscript.sh
81+
# - run: |
82+
# echo "Run, Build Application using script"
83+
# ./location_of_script_within_repo/buildscript.sh
8484

85-
- name: Perform CodeQL Analysis
86-
uses: github/codeql-action/analyze@v3
87-
with:
88-
category: "/language:${{matrix.language}}"
85+
- name: Perform CodeQL Analysis
86+
uses: github/codeql-action/analyze@v3
87+
with:
88+
category: "/language:${{matrix.language}}"

CHANGELOG.md

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,24 @@
1-
# 1.1.0
1+
# 2.0.0
22

3+
- **BREAKING**: Major refactor of message handling for chat completions:
4+
- The `nl.dannyj.mistral.models.completion.Message` class has been removed.
5+
- Introduced `nl.dannyj.mistral.models.completion.message.ChatMessage` as an abstract base class for messages.
6+
- New concrete message classes: `SystemMessage`, `UserMessage`, `AssistantMessage`, `ToolMessage`.
7+
- Message content is now represented by `List<nl.dannyj.mistral.models.completion.content.ContentChunk>` (e.g., `TextChunk`, `ImageURLChunk`) to support multi-modal inputs.
8+
- `ChatCompletionRequest` now expects `List<ChatMessage>`.
9+
- Streaming: `DeltaChoice` now contains a `nl.dannyj.mistral.models.completion.message.DeltaMessage` object which holds the actual delta (`role`, `content`, `toolCalls`).
10+
- **BREAKING**: Changes to `nl.dannyj.mistral.models.completion.Choice`:
11+
- The `finishReason` field type changed from `String` to `nl.dannyj.mistral.models.completion.FinishReason` (enum).
12+
- The `logProbs` field has been removed.
13+
- **BREAKING**: `encodingFormat` field removed from `EmbeddingRequest` as it is no longer supported by the API.
14+
- **BREAKING**: The `nl.dannyj.mistral.models.model.ModelPermission` class has been removed.
15+
- **BREAKING**: Package changes for core classes:
16+
- `MessageChunk` moved to `nl.dannyj.mistral.models.completion.message.MessageChunk`.
17+
- `MessageRole` moved to `nl.dannyj.mistral.models.completion.message.MessageRole`.
18+
- Added support for function calling (tools).
19+
- Added `nl.dannyj.mistral.models.model.ModelCapabilities` to provide model capability information (e.g., `supportsVision()`, `supportsFunctionCalling()`).
20+
- Increased default read timeout to 120 seconds.
21+
- Made it easier to configure timeouts ([issue #7](https://github.com/Dannyj1/mistral-java-client/issues/7))
322
- Update jackson-databind from 2.16.1 to 2.18.3
423
- Update jakarta.validation-api from 3.1.0-M1 to 3.1.1
5-
- Update okio from 3.8.0 to 3.11.0
24+
- Update okio from 3.8.0 to 3.11.0

CODE_OF_CONDUCT.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ Violating these terms may lead to a permanent ban.
106106
### 4. Permanent Ban
107107

108108
**Community Impact**: Demonstrating a pattern of violation of community
109-
standards, including sustained inappropriate behavior, harassment of an
109+
standards, including sustained inappropriate behavior, harassment of an
110110
individual, or aggression toward or disparagement of classes of individuals.
111111

112112
**Consequence**: A permanent ban from any sort of public interaction within

MIGRATION.md

Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
# Migration Guide: Updating Message Handling
2+
3+
This guide outlines the necessary changes to migrate your code from the previous message handling structure (using the
4+
`Message` class) to the new structure introduced to support multi-modal content and
5+
tool calls, based on the abstract `ChatMessage` class.
6+
7+
## Core Changes
8+
9+
1. **Message Class Removed:** The old `Message` class has been removed.
10+
2. **ChatMessage Hierarchy:** A new abstract base class `ChatMessage` has been
11+
introduced. Specific message types now extend this class:
12+
- `SystemMessage`
13+
- `UserMessage`
14+
- `AssistantMessage`
15+
- `ToolMessage`
16+
3. **Multi-Modal Content:** Messages (primarily `UserMessage`, `AssistantMessage`, `ToolMessage`) now use a
17+
`List<ContentChunk>` for their `content` field to support text, images, etc. The
18+
`ContentChunk` interface has implementations like `TextChunk`,
19+
`ImageURLChunk`, etc.
20+
- `getTextContent()` helper methods were introduced to prevent having to loop over `ContentChunk`s to find `TextChunk`s
21+
4. **Tool Calls:** `AssistantMessage` now includes a `List<ToolCall> toolCalls` field, and a `ToolMessage` message type was introduced to support function calling/tools.
22+
5. **Streaming Deltas:** The `DeltaChoice` class (used in streaming responses via `MessageChunk`) now contains a
23+
`DeltaMessage` object (accessible via `getDelta()`). This `DeltaMessage`
24+
object, in turn, holds the partial delta fields: `role`, `content` (as `List<ContentChunk>`), and `toolCalls`.
25+
26+
## Migration Steps
27+
28+
### 1. Update `ChatCompletionRequest` Message List
29+
30+
The `messages` field in `ChatCompletionRequest` now expects `List<ChatMessage>` instead of `List<Message>`.
31+
32+
**Before:**
33+
34+
```java
35+
import nl.dannyj.mistral.models.completion.Message;
36+
37+
// ...
38+
List<Message> messages = ...;
39+
ChatCompletionRequest request = ChatCompletionRequest.builder()
40+
.messages(messages)
41+
// ...
42+
.build();
43+
```
44+
45+
**After:**
46+
47+
```java
48+
import nl.dannyj.mistral.models.completion.ChatMessage;
49+
50+
// ...
51+
List<ChatMessage> messages = ...; // See MessageListBuilder changes below
52+
ChatCompletionRequest request = ChatCompletionRequest.builder()
53+
.messages(messages)
54+
// ...
55+
.build();
56+
```
57+
58+
### 2. Update `MessageListBuilder` Usage
59+
60+
The `MessageListBuilder` now works with `ChatMessage` and its subclasses.
61+
62+
**Before:**
63+
64+
```java
65+
import nl.dannyj.mistral.models.completion.Message;
66+
import nl.dannyj.mistral.builders.MessageListBuilder;
67+
68+
// ...
69+
List<Message> messages = new MessageListBuilder()
70+
.system("System prompt")
71+
.user("User query")
72+
.assistant("Assistant response")
73+
.build();
74+
```
75+
76+
**After:**
77+
78+
```java
79+
import nl.dannyj.mistral.models.completion.ChatMessage;
80+
import nl.dannyj.mistral.builders.MessageListBuilder;
81+
82+
// ...
83+
List<ChatMessage> messages = new MessageListBuilder()
84+
.system("System prompt") // Creates SystemMessage
85+
.user("User query") // Creates UserMessage
86+
.assistant("Assistant response") // Creates AssistantMessage (text only)
87+
// .assistant(listOfToolCalls) // Use this overload for tool calls
88+
// .tool("Tool result", "tool_call_id_123") // Creates ToolMessage
89+
.build();
90+
91+
// Alternatively, add pre-constructed messages:
92+
// messages = new MessageListBuilder()
93+
// .message(new SystemMessage("System prompt"))
94+
// .message(new UserMessage("User query"))
95+
// .message(AssistantMessage.fromText("Assistant response")) // Factory method
96+
// .build();
97+
```
98+
99+
### 3. Update Handling of Non-Streaming Responses (`ChatCompletionResponse`)
100+
101+
The `message` field within the `Choice` object (obtained from `ChatCompletionResponse.getChoices()`) is now specifically
102+
an `AssistantMessage`.
103+
104+
**Before:**
105+
106+
```java
107+
ChatCompletionResponse response = client.createChatCompletion(request);
108+
Message responseMsg = response.getChoices().get(0).getMessage();
109+
String content = responseMsg.getContent();
110+
System.out.println(content);
111+
```
112+
113+
**After:**
114+
115+
```java
116+
import nl.dannyj.mistral.models.completion.message.AssistantMessage;
117+
import nl.dannyj.mistral.models.completion.content.ContentChunk;
118+
import nl.dannyj.mistral.models.completion.content.TextChunk;
119+
120+
// ...
121+
ChatCompletionResponse response = client.createChatCompletion(request);
122+
AssistantMessage responseMsg = response.getChoices().get(0).getMessage();
123+
124+
// Extract text content (handle potential multi-modal content)
125+
String textContent = "";
126+
if (responseMsg.getContent() != null) {
127+
for (ContentChunk chunk : responseMsg.getContent()) {
128+
if (chunk instanceof TextChunk textChunk) {
129+
textContent += textChunk.getText(); // Append text from TextChunks
130+
}
131+
// Handle other chunk types (ImageURLChunk, etc.) if necessary
132+
}
133+
}
134+
System.out.println(textContent);
135+
136+
// Check for tool calls if applicable
137+
if (responseMsg.getToolCalls() != null) {
138+
// Process tool calls
139+
}
140+
```
141+
142+
### 4. Update Handling of Streaming Responses (`ChatCompletionChunkCallback`)
143+
144+
The `onChunkReceived` method receives `MessageChunk`. The structure within `MessageChunk.getChoices().get(0)` (which is
145+
a `DeltaChoice`) has changed. Access `role`, `content`, and `toolCalls` directly from the `DeltaChoice` object.
146+
147+
**Before:**
148+
149+
```java
150+
client.createChatCompletionStream(request, new ChatCompletionChunkCallback() {
151+
@Override
152+
public void onChunkReceived(MessageChunk chunk) {
153+
// Old structure assumed delta was nested in a Message object
154+
String contentDelta = chunk.getChoices().get(0).getMessage().getContent();
155+
if (contentDelta != null) {
156+
System.out.print(contentDelta);
157+
}
158+
}
159+
// ... onComplete, onError
160+
});
161+
```
162+
163+
**After:**
164+
165+
```java
166+
import nl.dannyj.mistral.models.completion.DeltaChoice;
167+
import nl.dannyj.mistral.models.completion.message.DeltaMessage; // <-- Add this import
168+
import nl.dannyj.mistral.models.completion.message.MessageChunk; // <-- Updated import path
169+
import nl.dannyj.mistral.models.completion.content.ContentChunk;
170+
import nl.dannyj.mistral.models.completion.content.TextChunk;
171+
// ...
172+
client.createChatCompletionStream(request, new ChatCompletionChunkCallback() {
173+
@Override
174+
public void onChunkReceived(MessageChunk chunk) {
175+
if (chunk.getChoices() == null || chunk.getChoices().isEmpty()) return;
176+
177+
DeltaChoice deltaChoice = chunk.getChoices().get(0);
178+
DeltaMessage delta = deltaChoice.getDelta(); // <-- Get the DeltaMessage
179+
180+
// Check for text content delta using the convenience method
181+
String textDelta = delta.getTextContent();
182+
183+
if (textDelta != null) {
184+
System.out.print(textDelta);
185+
}
186+
187+
}
188+
// ... onComplete, onError
189+
});
190+
```
191+
192+
### 5. Update Handling of `Choice` Object in `ChatCompletionResponse`
193+
194+
The `Choice` class, which is part of the `ChatCompletionResponse.getChoices()`, has the following breaking changes:
195+
196+
#### `finishReason` Type Change
197+
- The `finishReason` field is now of type `FinishReason` (an enum) instead of a raw `String`.
198+
- **Before:** `String finishReason = choice.getFinishReason();`
199+
- **After:** `FinishReason finishReason = choice.getFinishReason();`
200+
- To get the underlying string value (e.g., "stop", "length"), you can call `finishReason.getReason()`.
201+
202+
#### Example: Handling `finishReason` (within the context of iterating choices from `ChatCompletionResponse`)
203+
204+
**Before(inside loop processing `choice`):**
205+
```java
206+
String reason = choice.getFinishReason();
207+
if ("stop".equals(reason)) {
208+
// ...
209+
}
210+
```
211+
212+
**After(inside loop processing `choice`):**
213+
```java
214+
import nl.dannyj.mistral.models.completion.FinishReason; // Ensure import
215+
// ...
216+
FinishReason reason = choice.getFinishReason();
217+
if (reason == FinishReason.STOP) {
218+
// ...
219+
}
220+
// Or, to compare with the string value:
221+
// if ("stop".equals(reason.getReason())) { ... }
222+
```
223+
224+
#### `logProbs` Field Removal
225+
- The `logProbs` field (previously a `String`) has been removed from the `Choice` class as it is no longer returned by the API.

0 commit comments

Comments
 (0)