Skip to content

Commit 77a4533

Browse files
authored
Merge branch 'main' into fix/cve-scan
2 parents 932cb6b + cd821c6 commit 77a4533

File tree

14 files changed

+343
-59
lines changed

14 files changed

+343
-59
lines changed

.github/workflows/prepare-release.yaml

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,11 @@ jobs:
5959
git add .
6060
git commit -m "Update to version ${{ steps.determine-versions.outputs.RELEASE_VERSION }}"
6161
62+
# Create release notes
63+
python .pipeline/scripts/release_notes_automation.py --version ${{ steps.determine-versions.outputs.RELEASE_VERSION }} --folder "docs/release-notes"
64+
git add .
65+
git commit -m "Add new release notes"
66+
6267
# We need to get the commit id, and push the branch so the release tag will point at the right commit afterwards
6368
RELEASE_COMMIT_ID=$(git log -1 --pretty=format:"%H")
6469
echo "RELEASE_COMMIT_ID=$RELEASE_COMMIT_ID" >> $GITHUB_OUTPUT
@@ -135,11 +140,16 @@ jobs:
135140
git config --global user.email "[email protected]"
136141
git config --global user.name "SAP Cloud SDK Bot"
137142
138-
- name: "Set New Version"
143+
- name: "Set New Version and Reset Release Notes"
139144
run: |
140145
python .pipeline/scripts/set-release-versions.py --version ${{ needs.bump-version.outputs.new-version }}
141146
git add .
142147
git commit -m "Update to version ${{ needs.bump-version.outputs.new-version }}"
148+
149+
# Reset release notes for next version
150+
cp .pipeline/scripts/release_notes_template.md docs/release-notes/release_notes.md
151+
git add docs/release-notes/release_notes.md
152+
git commit -m "Reset release notes"
143153
git push
144154
145155
- name: "Create Code PR"
@@ -148,7 +158,6 @@ jobs:
148158
149159
PR_URL=$(gh pr create --title "Release ${{ needs.bump-version.outputs.release-version }}" --body "## TODOs
150160
- [ ] Review the changes in [the release commit]($COMMIT_URL)
151-
- [ ] Update the Release notes
152161
- [ ] Review the [Draft Release](${{ needs.create-release.outputs.release-url }})
153162
- [ ] Review **and approve** this PR
154163
- [ ] Trigger the [Perform Release Workflow](${{ github.event.repository.html_url }}/actions/workflows/perform-release.yml)
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
import argparse
2+
import os
3+
import re
4+
from datetime import datetime
5+
6+
7+
def read_file(file_name):
8+
with open(file_name, 'r', encoding="utf8") as file:
9+
return file.read()
10+
11+
12+
def write_file(file_name, data):
13+
with open(file_name, 'w', encoding="utf8") as file:
14+
file.write(data)
15+
16+
unchanged_sections = [
17+
"""### 🚧 Known Issues
18+
19+
-
20+
21+
""",
22+
"""### 🔧 Compatibility Notes
23+
24+
-
25+
26+
""",
27+
"""### ✨ New Functionality
28+
29+
-
30+
31+
""",
32+
"""### 📈 Improvements
33+
34+
-
35+
36+
""",
37+
"""### 🐛 Fixed Issues
38+
39+
-
40+
"""]
41+
42+
def remove_unchanged_sections(file, unchanged_sections):
43+
for unchanged_section in unchanged_sections:
44+
# if file contains unchanged_section, remove it
45+
file = re.sub(unchanged_section, "", file)
46+
return file
47+
48+
def set_header(file, version):
49+
date = datetime.today().strftime('%B %d, %Y')
50+
# Replace the first line with: ## 5.2.0 - January 17, 2024
51+
file = re.sub("^## .*", "## " + version + " - " + date, file)
52+
return file
53+
54+
def link_github_release(file, version):
55+
old_github_release_link = "\[All Release Changes\]\(https://github.com/SAP/ai-sdk-java/releases/\)"
56+
new_github_release_link = "[All Release Changes](https://github.com/SAP/ai-sdk-java/releases/tag/rel%2F"+version+")"
57+
file = re.sub(old_github_release_link, new_github_release_link, file)
58+
return file
59+
60+
61+
62+
releases_pattern = re.compile(r"^## ")
63+
def count_releases(filename):
64+
count = 0
65+
with open(filename, 'r', encoding="utf-8") as file:
66+
for line in file:
67+
if releases_pattern.match(line):
68+
count += 1
69+
return count
70+
71+
def find_target_file(version):
72+
# release-notes-X-to-Y.mdx with every 15 versions the index increases by 15 and stays the same for 15 versions
73+
minor_version = int(version.split(".")[1])
74+
index = minor_version // 15 * 15
75+
return "release-notes-" + str(index) + "-to-" + str(index + 14) + ".mdx"
76+
77+
def write_release_notes(folder, target_file):
78+
absolute_target_file = os.path.join(folder, target_file)
79+
80+
# if target_file is a file, prepend the new release notes at the top
81+
if os.path.isfile(absolute_target_file):
82+
existing_file = read_file(absolute_target_file)
83+
write_file(absolute_target_file, file + "\n" + existing_file)
84+
# if target_file is not a file, create it
85+
else:
86+
write_file(absolute_target_file, file)
87+
88+
89+
file_name = "docs/release-notes/release_notes.md"
90+
91+
if __name__ == '__main__':
92+
parser = argparse.ArgumentParser(description='SAP Cloud SDK for AI (for Java) - Release Notes formatting script.')
93+
94+
parser.add_argument('--version', metavar='VERSION', help='The version to be released.', required=True)
95+
parser.add_argument('--folder', metavar='FOLDER', help='The ai-sdk-java/docs/release-notes folder.', required=True)
96+
args = parser.parse_args()
97+
98+
file = read_file(file_name)
99+
file = remove_unchanged_sections(file, unchanged_sections)
100+
file = set_header(file, args.version)
101+
file = link_github_release(file, args.version)
102+
103+
target_file = find_target_file(args.version)
104+
105+
106+
folder_path = args.folder
107+
write_release_notes(folder_path, target_file)
108+
109+
# delete (temporary) release-notes file so it does not appear in the released version
110+
os.remove(file_name)
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
## 0.X.0-SNAPSHOT
2+
3+
[All Release Changes](https://github.com/SAP/ai-sdk-java/releases/)
4+
5+
### 🚧 Known Issues
6+
7+
-
8+
9+
### 🔧 Compatibility Notes
10+
11+
-
12+
13+
### ✨ New Functionality
14+
15+
-
16+
17+
### 📈 Improvements
18+
19+
-
20+
21+
### 🐛 Fixed Issues
22+
23+
-
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
## 0.X.0-SNAPSHOT
2+
3+
[All Release Changes](https://github.com/SAP/ai-sdk-java/releases/)
4+
5+
### 🚧 Known Issues
6+
7+
-
8+
9+
### 🔧 Compatibility Notes
10+
11+
-
12+
13+
### ✨ New Functionality
14+
15+
-
16+
17+
### 📈 Improvements
18+
19+
-
20+
21+
### 🐛 Fixed Issues
22+
23+
-
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.sap.ai.sdk.orchestration;
2+
3+
import javax.annotation.Nonnull;
4+
import lombok.Value;
5+
import lombok.experimental.Accessors;
6+
7+
/** Represents a chat message as 'assistant' to the orchestration service. */
8+
@Value
9+
@Accessors(fluent = true)
10+
public class AssistantMessage implements Message {
11+
12+
/** The role of the assistant. */
13+
@Nonnull String role = "assistant";
14+
15+
/** The content of the message. */
16+
@Nonnull String content;
17+
}

orchestration/src/main/java/com/sap/ai/sdk/orchestration/ConfigToRequestTransformer.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ static CompletionPostRequest toCompletionPostRequest(
3131
.orchestrationConfig(
3232
OrchestrationConfig.create().moduleConfigurations(toModuleConfigs(configCopy)))
3333
.inputParams(prompt.getTemplateParameters())
34-
.messagesHistory(prompt.getMessagesHistory());
34+
.messagesHistory(
35+
prompt.getMessagesHistory().stream().map(Message::createChatMessage).toList());
3536
}
3637

3738
@Nonnull
@@ -46,7 +47,8 @@ static TemplatingModuleConfig toTemplateModuleConfig(
4647
*/
4748
val messages = template instanceof Template t ? t.getTemplate() : List.<ChatMessage>of();
4849
val messagesWithPrompt = new ArrayList<>(messages);
49-
messagesWithPrompt.addAll(prompt.getMessages());
50+
messagesWithPrompt.addAll(
51+
prompt.getMessages().stream().map(Message::createChatMessage).toList());
5052
if (messagesWithPrompt.isEmpty()) {
5153
throw new IllegalStateException(
5254
"A prompt is required. Pass at least one message or configure a template with messages or a template reference.");
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package com.sap.ai.sdk.orchestration;
2+
3+
import com.sap.ai.sdk.orchestration.model.ChatMessage;
4+
import javax.annotation.Nonnull;
5+
6+
/** Interface representing convenience wrappers of chat message to the orchestration service. */
7+
public sealed interface Message permits UserMessage, AssistantMessage, SystemMessage {
8+
9+
/**
10+
* A convenience method to create a user message.
11+
*
12+
* @param msg the message content.
13+
* @return the user message.
14+
*/
15+
@Nonnull
16+
static UserMessage user(@Nonnull final String msg) {
17+
return new UserMessage(msg);
18+
}
19+
20+
/**
21+
* A convenience method to create an assistant message.
22+
*
23+
* @param msg the message content.
24+
* @return the assistant message.
25+
*/
26+
@Nonnull
27+
static AssistantMessage assistant(@Nonnull final String msg) {
28+
return new AssistantMessage(msg);
29+
}
30+
31+
/**
32+
* A convenience method to create a system message.
33+
*
34+
* @param msg the message content.
35+
* @return the system message.
36+
*/
37+
@Nonnull
38+
static SystemMessage system(@Nonnull final String msg) {
39+
return new SystemMessage(msg);
40+
}
41+
42+
/**
43+
* Converts the message to a serializable ChatMessage object.
44+
*
45+
* @return the corresponding {@code ChatMessage} object.
46+
*/
47+
@Nonnull
48+
default ChatMessage createChatMessage() {
49+
return ChatMessage.create().role(role()).content(content());
50+
}
51+
52+
/**
53+
* Returns the role of the assistant.
54+
*
55+
* @return the role.
56+
*/
57+
@Nonnull
58+
String role();
59+
60+
/**
61+
* Returns the content of the message.
62+
*
63+
* @return the content.
64+
*/
65+
@Nonnull
66+
String content();
67+
}

orchestration/src/main/java/com/sap/ai/sdk/orchestration/OrchestrationClient.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,9 @@ public OrchestrationChatResponse executeRequestFromJsonModuleConfig(
169169
}
170170

171171
final ObjectNode requestJson = JACKSON.createObjectNode();
172-
requestJson.set("messages_history", JACKSON.valueToTree(prompt.getMessagesHistory()));
172+
final var chatMessageHistory =
173+
prompt.getMessagesHistory().stream().map(Message::createChatMessage).toList();
174+
requestJson.set("messages_history", JACKSON.valueToTree(chatMessageHistory));
173175
requestJson.set("input_params", JACKSON.valueToTree(prompt.getTemplateParameters()));
174176

175177
final JsonNode moduleConfigJson;

orchestration/src/main/java/com/sap/ai/sdk/orchestration/OrchestrationPrompt.java

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package com.sap.ai.sdk.orchestration;
22

3-
import com.sap.ai.sdk.orchestration.model.ChatMessage;
43
import com.sap.ai.sdk.orchestration.model.OrchestrationConfig;
54
import java.util.ArrayList;
65
import java.util.Arrays;
@@ -22,17 +21,17 @@
2221
@Value
2322
@Getter(AccessLevel.PACKAGE)
2423
public class OrchestrationPrompt {
25-
@Nonnull List<ChatMessage> messages = new ArrayList<>();
24+
@Nonnull List<Message> messages = new ArrayList<>();
2625
@Nonnull Map<String, String> templateParameters = new TreeMap<>();
27-
@Nonnull List<ChatMessage> messagesHistory = new ArrayList<>();
26+
@Nonnull List<Message> messagesHistory = new ArrayList<>();
2827

2928
/**
3029
* Initialize a prompt with the given user message.
3130
*
3231
* @param message A user message.
3332
*/
3433
public OrchestrationPrompt(@Nonnull final String message) {
35-
messages.add(ChatMessage.create().role("user").content(message));
34+
messages.add(new UserMessage(message));
3635
}
3736

3837
/**
@@ -41,8 +40,7 @@ public OrchestrationPrompt(@Nonnull final String message) {
4140
* @param message The first message.
4241
* @param messages Optionally, more messages.
4342
*/
44-
public OrchestrationPrompt(
45-
@Nonnull final ChatMessage message, @Nonnull final ChatMessage... messages) {
43+
public OrchestrationPrompt(@Nonnull final Message message, @Nonnull final Message... messages) {
4644
this.messages.add(message);
4745
this.messages.addAll(Arrays.asList(messages));
4846
}
@@ -53,7 +51,7 @@ public OrchestrationPrompt(
5351
* @param inputParams The input parameters as entries of template variables and their contents.
5452
*/
5553
public OrchestrationPrompt(
56-
@Nonnull final Map<String, String> inputParams, @Nonnull final ChatMessage... messages) {
54+
@Nonnull final Map<String, String> inputParams, @Nonnull final Message... messages) {
5755
this.templateParameters.putAll(inputParams);
5856
this.messages.addAll(Arrays.asList(messages));
5957
}
@@ -64,7 +62,7 @@ public OrchestrationPrompt(
6462
* @param messagesHistory The chat history to add.
6563
*/
6664
@Nonnull
67-
public OrchestrationPrompt messageHistory(@Nonnull final List<ChatMessage> messagesHistory) {
65+
public OrchestrationPrompt messageHistory(@Nonnull final List<Message> messagesHistory) {
6866
this.messagesHistory.clear();
6967
this.messagesHistory.addAll(messagesHistory);
7068
return this;
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.sap.ai.sdk.orchestration;
2+
3+
import javax.annotation.Nonnull;
4+
import lombok.Value;
5+
import lombok.experimental.Accessors;
6+
7+
/** Represents a chat message as 'system' to the orchestration service. */
8+
@Value
9+
@Accessors(fluent = true)
10+
public class SystemMessage implements Message {
11+
12+
/** The role of the assistant. */
13+
@Nonnull String role = "system";
14+
15+
/** The content of the message. */
16+
@Nonnull String content;
17+
}

0 commit comments

Comments
 (0)