Skip to content

Conversation

@jonathan-buttner
Copy link
Contributor

This PR adds functionality for parsing responses for the upcoming custom service: #125679

The response parsers leverage the MapPathExtractor to retrieve fields from a json response converted into a map.

@jonathan-buttner jonathan-buttner added >non-issue :ml Machine learning Team:ML Meta label for the ML team auto-backport Automatically create backport pull requests when merged v8.19.0 v9.1.0 labels Apr 22, 2025
}

@Override
public boolean equals(Object o) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Needed these so the assertThat calls in the error parser tests can succeed.

Copy link
Member

Choose a reason for hiding this comment

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

Alternatively could ErrorResponse be a record rather than an class

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah that would make it cleaner. At the moment ErrorResponse is a base class and extended in a few places so we'd have to switch that to composition (I don't think we can extend a record 🤔 ).


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

public class CustomServiceSettings {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not all of these values are referenced but they will be once I pull in the rest of the custom service changes in future PRs.


import java.io.IOException;

public interface CustomResponseParser extends ToXContentFragment, NamedWriteable {
Copy link
Contributor Author

@jonathan-buttner jonathan-buttner Apr 22, 2025

Choose a reason for hiding this comment

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

The response parsers need to be a named writeable because the service settings will use a factory to construct the appropriate response parser. The response parser is chosen based on the task type of the service which is provided in the PUT request.

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'll register these in a future PR

Copy link
Member

Choose a reason for hiding this comment

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

How do we plan to handle streaming, since HttpResult and StreamingHttpResult are different? We could maybe have CustomerResponseParser<T> and change the current implementation to BaseCustomResponseParser<T> implements CustomResponseParser<HttpResult> so we can make a StreamingBaseCustomResponseParser<T> implements CustomResponseParser<StreamingHttpResult>?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah good point, I hadn't really thought about that. I think you're suggestion will work well though.

@jonathan-buttner jonathan-buttner marked this pull request as ready for review April 22, 2025 20:00
@elasticsearchmachine
Copy link
Collaborator

Pinging @elastic/ml-core (Team:ML)


import java.io.IOException;

public interface CustomResponseParser extends ToXContentFragment, NamedWriteable {
Copy link
Member

Choose a reason for hiding this comment

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

How do we plan to handle streaming, since HttpResult and StreamingHttpResult are different? We could maybe have CustomerResponseParser<T> and change the current implementation to BaseCustomResponseParser<T> implements CustomResponseParser<HttpResult> so we can make a StreamingBaseCustomResponseParser<T> implements CustomResponseParser<StreamingHttpResult>?


private static HttpResult getMockResult(String jsonString) throws IOException {
var response = mock(HttpResponse.class);
return new HttpResult(response, Strings.toUTF8Bytes(XContentHelper.stripWhitespace(jsonString)));
Copy link
Member

Choose a reason for hiding this comment

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

Ah, stripWhitespace, that's what I need to go from a multi-line pretty-print JSON string to a testable string...

Copy link
Member

@davidkyle davidkyle left a comment

Choose a reason for hiding this comment

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

LGTM

}

@Override
public boolean equals(Object o) {
Copy link
Member

Choose a reason for hiding this comment

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

Alternatively could ErrorResponse be a record rather than an class


if (obj instanceof List<?> == false) {
throw new IllegalArgumentException(
Strings.format("Extracted field is an invalid type, expected a list but received [%s]", obj.getClass().getSimpleName())
Copy link
Member

Choose a reason for hiding this comment

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

It would be useful to include the name of the field in this error and the others e.g

Extracted field [embedding] is an invalid type, expected a list but received [%s]

var rerankIndex = extractOptionalString(responseParserMap, RERANK_PARSER_INDEX, JSON_PARSER, validationException);
var documentText = extractOptionalString(responseParserMap, RERANK_PARSER_DOCUMENT_TEXT, JSON_PARSER, validationException);

if (relevanceScore == null) {
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
if (relevanceScore == null) {
if (validationException.validationErrors().size() > 0) {

@jonathan-buttner jonathan-buttner merged commit 677ab35 into elastic:main Apr 28, 2025
17 checks passed
@jonathan-buttner jonathan-buttner deleted the ml-custom-model-response-parsers branch April 28, 2025 17:15
jonathan-buttner added a commit to jonathan-buttner/elasticsearch that referenced this pull request Apr 28, 2025
* Adding response parsers for custom service

* [CI] Auto commit changes from spotless

* Update x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/custom/response/ErrorResponseParser.java

Co-authored-by: David Kyle <[email protected]>

* Refactoring to include field names in exceptions

* Adding list entry index to error message and field names

* Addressing feedback for validation exception

---------

Co-authored-by: elasticsearchmachine <[email protected]>
Co-authored-by: David Kyle <[email protected]>
@elasticsearchmachine
Copy link
Collaborator

💚 Backport successful

Status Branch Result
8.19

elasticsearchmachine pushed a commit that referenced this pull request Apr 28, 2025
* Adding response parsers for custom service

* [CI] Auto commit changes from spotless

* Update x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/custom/response/ErrorResponseParser.java



* Refactoring to include field names in exceptions

* Adding list entry index to error message and field names

* Addressing feedback for validation exception

---------

Co-authored-by: elasticsearchmachine <[email protected]>
Co-authored-by: David Kyle <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

auto-backport Automatically create backport pull requests when merged :ml Machine learning >non-issue Team:ML Meta label for the ML team v8.19.0 v9.1.0

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants