diff --git a/docs/release_notes.md b/docs/release_notes.md
index e5d59842b..6effc3ae7 100644
--- a/docs/release_notes.md
+++ b/docs/release_notes.md
@@ -26,6 +26,7 @@
- [Orchestration] Added `GPT_52` model for `OrchestrationAiModel`.
- [OpenAi] Added `GPT_52` model from `OpenAiModel`.
- [Orchestration] Added `GEMINI_EMBEDDING` model for `OrchestrationEmbeddingModel`.
+- [Orchestration] Added citations for Perplexity `SONAR` model in `client.chatCompletion().getOriginalResponse().getFinalResult().getCitations()`
### 📈 Improvements
diff --git a/sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/controllers/OrchestrationController.java b/sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/controllers/OrchestrationController.java
index d9e95d1b7..a164a1c24 100644
--- a/sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/controllers/OrchestrationController.java
+++ b/sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/controllers/OrchestrationController.java
@@ -8,6 +8,7 @@
import com.sap.ai.sdk.orchestration.OrchestrationFilterException;
import com.sap.ai.sdk.orchestration.model.AzureContentSafetyInput;
import com.sap.ai.sdk.orchestration.model.AzureContentSafetyOutput;
+import com.sap.ai.sdk.orchestration.model.Citation;
import com.sap.ai.sdk.orchestration.model.DPIEntities;
import com.sap.cloud.sdk.cloudplatform.thread.ThreadContextExecutors;
import java.io.IOException;
@@ -408,4 +409,27 @@ Object completionWithFallback(
}
return response.getContent();
}
+
+ @GetMapping("/citations")
+ @Nonnull
+ Object citations(
+ @Nullable @RequestParam(value = "format", required = false) final String format) {
+ final var response = service.citations();
+ if ("json".equals(format)) {
+ return response;
+ }
+
+ final StringBuilder content = new StringBuilder(response.getContent().replaceAll("\n", "
"));
+ final var citations = response.getOriginalResponse().getFinalResult().getCitations();
+
+ if (!citations.isEmpty()) {
+ content.append("
Citations:");
+ for (final Citation citation : citations) {
+ content.append(
+ "
%d. %s"
+ .formatted(citation.getRefId(), citation.getUrl(), citation.getTitle()));
+ }
+ }
+ return content.toString();
+ }
}
diff --git a/sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/services/OrchestrationService.java b/sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/services/OrchestrationService.java
index 91f9b1ab2..296a0fed9 100644
--- a/sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/services/OrchestrationService.java
+++ b/sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/services/OrchestrationService.java
@@ -4,6 +4,7 @@
import static com.sap.ai.sdk.orchestration.OrchestrationAiModel.GPT_41_NANO;
import static com.sap.ai.sdk.orchestration.OrchestrationAiModel.GPT_5_MINI;
import static com.sap.ai.sdk.orchestration.OrchestrationAiModel.Parameter.TEMPERATURE;
+import static com.sap.ai.sdk.orchestration.OrchestrationAiModel.SONAR;
import static com.sap.ai.sdk.orchestration.OrchestrationEmbeddingModel.TEXT_EMBEDDING_3_SMALL;
import static com.sap.ai.sdk.orchestration.OrchestrationTemplateReference.ScopeEnum.RESOURCE_GROUP;
@@ -857,4 +858,16 @@ public OrchestrationChatResponse completionWithFallbackAllFail(
.withLlmConfig(new OrchestrationAiModel("broken_name_2", Map.of(), "latest"));
return client.chatCompletion(prompt, brokenConfig, secondBrokenConfig);
}
+
+ /**
+ * Chat request using the SONAR model which provides citations.
+ *
+ * @return the assistant response object with citations
+ */
+ @Nonnull
+ public OrchestrationChatResponse citations() {
+ val prompt = new OrchestrationPrompt("Where does \"Hello World\" come from?");
+ val sonarConfig = new OrchestrationModuleConfig().withLlmConfig(SONAR);
+ return client.chatCompletion(prompt, sonarConfig);
+ }
}
diff --git a/sample-code/spring-app/src/main/resources/static/index.html b/sample-code/spring-app/src/main/resources/static/index.html
index 3567e7a0d..d6d37ad8f 100644
--- a/sample-code/spring-app/src/main/resources/static/index.html
+++ b/sample-code/spring-app/src/main/resources/static/index.html
@@ -328,6 +328,19 @@