feat: Implement OpenRouter model discovery and endpoints

- Added OpenRouterModelDiscovery class for managing model listings and metadata resolution.
- Introduced OpenRouterModelEndpointsResponse and OpenRouterModelsResponse classes for handling API responses.
- Created OpenRouterModelQuery class to encapsulate query parameters for model listing.
- Updated ModelProfile to include OPENROUTER as a model provider.
- Enhanced ModelProfileService to handle default values for maxTokens and maxContextLength.
- Added OpenRouterClientTest for testing model discovery and chat completion functionalities.
- Configured application-test.properties and local-openrouter-chatcompletion.properties for OpenRouter integration.
This commit is contained in:
extio-de
2026-05-10 14:11:06 +02:00
parent 2028d9bea5
commit b95e725aad
16 changed files with 1563 additions and 24 deletions

View File

@@ -21,11 +21,11 @@ public record ModelProfile(
String category) {
public ModelProfile {
if (maxTokens <= 0) {
throw new IllegalArgumentException("Model profile maxTokens must be greater than zero");
if (maxTokens < 0) {
throw new IllegalArgumentException("Model profile maxTokens must be greater than or equal to zero");
}
if (maxContextLength <= 0) {
throw new IllegalArgumentException("Model profile maxContextLength must be greater than zero");
if (maxContextLength < 0) {
throw new IllegalArgumentException("Model profile maxContextLength must be greater than or equal to zero");
}
if (temperature <= 0) {
throw new IllegalArgumentException("Model profile temperature must be greater than zero");
@@ -36,15 +36,12 @@ public record ModelProfile(
if (modelProvider == null) {
throw new IllegalArgumentException("Model profile modelProvider is mandatory and cannot be null");
}
if (url == null || url.isBlank()) {
throw new IllegalArgumentException("Model profile url is mandatory and cannot be empty");
}
if (category == null || category.isBlank()) {
throw new IllegalArgumentException("Model profile category is mandatory and cannot be empty");
}
}
public static enum ModelProvider {
OAI_TEXT_COMPLETION, OAI_CHAT_COMPLETION, OLLAMA;
OAI_TEXT_COMPLETION, OAI_CHAT_COMPLETION, OPENROUTER, OLLAMA;
}
}

View File

@@ -49,11 +49,11 @@ public class ModelProfileService {
final var maxTokens = Optional.ofNullable(resource.getProperty("maxTokens"))
.map(Object::toString)
.map(Integer::parseInt)
.orElseThrow(() -> new IllegalStateException("No model maxTokens found for model: " + modelName));
.orElse(Integer.valueOf(0));
final var maxContextLength = Optional.ofNullable(resource.getProperty("maxContextLength"))
.map(Object::toString)
.map(Integer::parseInt)
.orElseThrow(() -> new IllegalStateException("No model maxContextLength found for model: " + modelName));
.orElse(Integer.valueOf(0));
final var temperature = Optional.ofNullable(resource.getProperty("temperature"))
.map(Object::toString)
.map(Double::parseDouble)
@@ -71,7 +71,7 @@ public class ModelProfileService {
.orElse(null);
final var url = Optional.ofNullable(resource.getProperty("url"))
.map(Object::toString)
.orElseThrow(() -> new IllegalStateException("No model url found for model: " + modelName));
.orElse(null);
final var costPerInToken = Optional.ofNullable(resource.getProperty("cost1MInTokens"))
.map(Object::toString)
.map(value -> new BigDecimal(value))