Skip to content
Open
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
f52f5e2
Add Mixedbread AI Rerank support
Evgenii-Kazannik Jan 7, 2026
0a184ca
Add Mixedbread AI Rerank support tests
Evgenii-Kazannik Jan 12, 2026
dc1f701
Merge branch 'main' into Add-Mixedbread-AI-Rerank-support
Evgenii-Kazannik Jan 13, 2026
6133d64
Apply spotless
Evgenii-Kazannik Jan 13, 2026
6b63ffb
Add Mixedbread AI Rerank support
Evgenii-Kazannik Jan 14, 2026
2cd922c
Merge branch 'main' into Add-Mixedbread-AI-Rerank-support
Evgenii-Kazannik Jan 14, 2026
9ec0f7d
Add action creator tests
Evgenii-Kazannik Jan 20, 2026
3fd0d23
Merge branch 'main' into Add-Mixedbread-AI-Rerank-support
Evgenii-Kazannik Jan 20, 2026
4cb12db
Make windows size configurable
Evgenii-Kazannik Jan 22, 2026
18d5ce4
Address comments and add service tests
Evgenii-Kazannik Jan 22, 2026
fd98ef0
Merge branch 'main' into Add-Mixedbread-AI-Rerank-support
Evgenii-Kazannik Jan 27, 2026
5bbffe1
[CI] Update transport version definitions
Jan 27, 2026
83a6497
Switch to new approach for transport version
Evgenii-Kazannik Jan 28, 2026
fbd6d5d
Use ConstructingObjectParser
Evgenii-Kazannik Jan 28, 2026
f4c5c0d
Address comments
Evgenii-Kazannik Jan 28, 2026
c72e6a2
Merge remote-tracking branch 'origin/Add-Mixedbread-AI-Rerank-support…
Evgenii-Kazannik Jan 28, 2026
faa5ce8
[CI] Auto commit changes from spotless
Jan 28, 2026
36f7994
Fix the test
Evgenii-Kazannik Jan 28, 2026
87f09e5
Checkstyle fix
Evgenii-Kazannik Jan 28, 2026
fa208ee
Fix the test
Evgenii-Kazannik Jan 28, 2026
5ed8e6a
Clean up
Evgenii-Kazannik Jan 29, 2026
6c3bc8f
Clean up
Evgenii-Kazannik Jan 29, 2026
cd94963
Merge branch 'main' into Add-Mixedbread-AI-Rerank-support
Evgenii-Kazannik Jan 29, 2026
81f9aca
[CI] Update transport version definitions
Jan 29, 2026
e447752
ci: retrigger
Evgenii-Kazannik Jan 29, 2026
59d97d8
Merge branch 'main' into Add-Mixedbread-AI-Rerank-support
Evgenii-Kazannik Jan 30, 2026
68108cf
[CI] Update transport version definitions
Jan 30, 2026
2ab34e0
Address comments and refactor
Evgenii-Kazannik Feb 1, 2026
65f2b64
Merge branch 'main' into Add-Mixedbread-AI-Rerank-support
Evgenii-Kazannik Feb 2, 2026
a20144f
[CI] Update transport version definitions
Feb 2, 2026
9b1a82c
Address comments
Evgenii-Kazannik Feb 2, 2026
84aab0e
[CI] Update transport version definitions
Feb 3, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@
import org.elasticsearch.xpack.inference.services.llama.embeddings.LlamaEmbeddingsServiceSettings;
import org.elasticsearch.xpack.inference.services.mistral.completion.MistralChatCompletionServiceSettings;
import org.elasticsearch.xpack.inference.services.mistral.embeddings.MistralEmbeddingsServiceSettings;
import org.elasticsearch.xpack.inference.services.mixedbread.rerank.MixedbreadRerankServiceSettings;
import org.elasticsearch.xpack.inference.services.mixedbread.rerank.MixedbreadRerankTaskSettings;
import org.elasticsearch.xpack.inference.services.nvidia.completion.NvidiaChatCompletionServiceSettings;
import org.elasticsearch.xpack.inference.services.nvidia.embeddings.NvidiaEmbeddingsServiceSettings;
import org.elasticsearch.xpack.inference.services.nvidia.embeddings.NvidiaEmbeddingsTaskSettings;
Expand Down Expand Up @@ -187,6 +189,7 @@ public static List<NamedWriteableRegistry.Entry> getNamedWriteables() {
addAi21NamedWriteables(namedWriteables);
addOpenShiftAiNamedWriteables(namedWriteables);
addNvidiaNamedWriteables(namedWriteables);
addMixedbreadNamedWriteables(namedWriteables);

addUnifiedNamedWriteables(namedWriteables);

Expand Down Expand Up @@ -942,4 +945,17 @@ private static void addElasticNamedWriteables(List<NamedWriteableRegistry.Entry>
)
);
}

private static void addMixedbreadNamedWriteables(List<NamedWriteableRegistry.Entry> namedWriteables) {
namedWriteables.add(
new NamedWriteableRegistry.Entry(
ServiceSettings.class,
MixedbreadRerankServiceSettings.NAME,
MixedbreadRerankServiceSettings::new
)
);
namedWriteables.add(
new NamedWriteableRegistry.Entry(TaskSettings.class, MixedbreadRerankTaskSettings.NAME, MixedbreadRerankTaskSettings::new)
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@
import org.elasticsearch.xpack.inference.services.jinaai.JinaAIService;
import org.elasticsearch.xpack.inference.services.llama.LlamaService;
import org.elasticsearch.xpack.inference.services.mistral.MistralService;
import org.elasticsearch.xpack.inference.services.mixedbread.MixedbreadService;
import org.elasticsearch.xpack.inference.services.nvidia.NvidiaService;
import org.elasticsearch.xpack.inference.services.openai.OpenAiService;
import org.elasticsearch.xpack.inference.services.openshiftai.OpenShiftAiService;
Expand Down Expand Up @@ -561,6 +562,7 @@ public List<InferenceServiceExtension.Factory> getInferenceServiceFactories() {
context -> new GoogleAiStudioService(httpFactory.get(), serviceComponents.get(), context),
context -> new GoogleVertexAiService(httpFactory.get(), serviceComponents.get(), context),
context -> new MistralService(httpFactory.get(), serviceComponents.get(), context),
context -> new MixedbreadService(httpFactory.get(), serviceComponents.get(), context),
context -> new AnthropicService(httpFactory.get(), serviceComponents.get(), context),
context -> new AmazonBedrockService(httpFactory.get(), amazonBedrockFactory.get(), serviceComponents.get(), context),
context -> new AlibabaCloudSearchService(httpFactory.get(), serviceComponents.get(), context),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

package org.elasticsearch.xpack.inference.services.mixedbread;

import org.apache.http.client.utils.URIBuilder;
import org.elasticsearch.ElasticsearchStatusException;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.settings.SecureString;
import org.elasticsearch.rest.RestStatus;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.Objects;

public record MixedbreadAccount(URI baseUri, SecureString apiKey) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's remove this class since I don't think we need the base uri and store the api key in the base model similar to how openai does it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done


public static MixedbreadAccount of(MixedbreadModel model) {
try {
var uri = model.baseUri() != null ? model.baseUri() : new URIBuilder().setScheme("https").setHost("api.mixedbread.com").build();
return new MixedbreadAccount(uri, model.apiKey());
} catch (URISyntaxException e) {
// using bad request here so that potentially sensitive URL information does not get logged
throw new ElasticsearchStatusException(
Strings.format("Failed to construct %s URL", MixedbreadService.NAME),
RestStatus.BAD_REQUEST,
e
);
}
}

public MixedbreadAccount {
Objects.requireNonNull(baseUri);
Objects.requireNonNull(apiKey);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

package org.elasticsearch.xpack.inference.services.mixedbread;

public class MixedbreadConstants {
public static final String VERSION_1 = "v1";
public static final String RERANK_PATH = "rerank";
Copy link

Copilot AI Jan 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The constant RERANK_PATH is defined as "rerank" here but in MixedbreadRerankModel.java it's defined as "reranking". This inconsistency could lead to incorrect API paths being constructed. These should be unified to use the same value.

Suggested change
public static final String RERANK_PATH = "rerank";
public static final String RERANK_PATH = "reranking";

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mixedbread supports both. I left "rerank". Done

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While both may work, the documentation for Mixedbread reranking uses reranking as the endpoint, so that's what we should be using.


// common service settings fields
public static final String MODEL_FIELD = "model";

public static final String INPUT_FIELD = "input";

// rerank task settings fields
public static final String QUERY_FIELD = "query";

public static final String DOCUMENTS_FIELD = "documents";

// rerank task settings fields
public static final String RETURN_DOCUMENTS_FIELD = "return_documents";
public static final String TOP_K_FIELD = "top_k";

private MixedbreadConstants() {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

package org.elasticsearch.xpack.inference.services.mixedbread;

import org.elasticsearch.common.settings.SecureString;
import org.elasticsearch.core.Nullable;
import org.elasticsearch.inference.ModelConfigurations;
import org.elasticsearch.inference.ModelSecrets;
import org.elasticsearch.inference.ServiceSettings;
import org.elasticsearch.inference.TaskSettings;
import org.elasticsearch.xpack.inference.external.action.ExecutableAction;
import org.elasticsearch.xpack.inference.services.RateLimitGroupingModel;
import org.elasticsearch.xpack.inference.services.ServiceUtils;
import org.elasticsearch.xpack.inference.services.mixedbread.action.MixedbreadActionVisitor;
import org.elasticsearch.xpack.inference.services.settings.ApiKeySecrets;
import org.elasticsearch.xpack.inference.services.settings.RateLimitSettings;

import java.net.URI;
import java.util.Map;
import java.util.Objects;

/**
* Abstract class representing a Mixedbread model for inference.
* This class extends RateLimitGroupingModel and provides common functionality for Mixedbread models.
*/
public abstract class MixedbreadModel extends RateLimitGroupingModel {
private final SecureString apiKey;
private final MixedbreadRateLimitServiceSettings rateLimitServiceSettings;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Take a look at the other model implementations that I mentioned earlier or Ai21Model. We should need MixedbreadRateLimitServiceSettings. I think we can just use RateLimitSettings.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

replaced MixedbreadRateLimitServiceSettings with RateLimitSettings

private final URI uri;

public MixedbreadModel(
ModelConfigurations configurations,
ModelSecrets secrets,
@Nullable ApiKeySecrets apiKeySecrets,
MixedbreadRateLimitServiceSettings rateLimitServiceSettings,
URI uri
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The uri field should be made private final instead of protected.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

) {
super(configurations, secrets);

this.rateLimitServiceSettings = Objects.requireNonNull(rateLimitServiceSettings);
apiKey = ServiceUtils.apiKey(apiKeySecrets);
this.uri = uri;
}

protected MixedbreadModel(MixedbreadModel model, TaskSettings taskSettings) {
super(model, taskSettings);

rateLimitServiceSettings = model.rateLimitServiceSettings();
apiKey = model.apiKey();
uri = model.uri();
}

protected MixedbreadModel(MixedbreadModel model, ServiceSettings serviceSettings) {
super(model, serviceSettings);

rateLimitServiceSettings = model.rateLimitServiceSettings();
apiKey = model.apiKey();
uri = model.uri();
}

public SecureString apiKey() {
return apiKey;
}

public MixedbreadRateLimitServiceSettings rateLimitServiceSettings() {
return rateLimitServiceSettings;
}

public abstract ExecutableAction accept(MixedbreadActionVisitor creator, Map<String, Object> taskSettings);

public URI uri() {
return uri;
}

public RateLimitSettings rateLimitSettings() {
return rateLimitServiceSettings.rateLimitSettings();
}

public int rateLimitGroupingHash() {
return apiKey().hashCode();
}

public URI baseUri() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After refactoring the url stuff, we shouldn't need this method and uri().

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I deleted the baseUri() yet uri() seems to be needed. I'll check it again

return rateLimitServiceSettings.uri();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

package org.elasticsearch.xpack.inference.services.mixedbread;

import org.elasticsearch.xpack.inference.services.settings.RateLimitSettings;

import java.net.URI;

public interface MixedbreadRateLimitServiceSettings {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's remove this since I don't think we need the uri().

Copy link
Contributor Author

@Evgenii-Kazannik Evgenii-Kazannik Jan 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

RateLimitSettings rateLimitSettings();

URI uri();
}
Loading
Loading