-
Notifications
You must be signed in to change notification settings - Fork 25.6k
[ML] Adding response parsers for custom service #127179
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[ML] Adding response parsers for custom service #127179
Conversation
| } | ||
|
|
||
| @Override | ||
| public boolean equals(Object o) { |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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 { |
There was a problem hiding this comment.
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 { |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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>?
There was a problem hiding this comment.
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.
|
Pinging @elastic/ml-core (Team:ML) |
|
|
||
| import java.io.IOException; | ||
|
|
||
| public interface CustomResponseParser extends ToXContentFragment, NamedWriteable { |
There was a problem hiding this comment.
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))); |
There was a problem hiding this comment.
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...
davidkyle
left a comment
There was a problem hiding this 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) { |
There was a problem hiding this comment.
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()) |
There was a problem hiding this comment.
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]
...ain/java/org/elasticsearch/xpack/inference/services/custom/response/ErrorResponseParser.java
Outdated
Show resolved
Hide resolved
| var rerankIndex = extractOptionalString(responseParserMap, RERANK_PARSER_INDEX, JSON_PARSER, validationException); | ||
| var documentText = extractOptionalString(responseParserMap, RERANK_PARSER_DOCUMENT_TEXT, JSON_PARSER, validationException); | ||
|
|
||
| if (relevanceScore == null) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| if (relevanceScore == null) { | |
| if (validationException.validationErrors().size() > 0) { |
…inference/services/custom/response/ErrorResponseParser.java Co-authored-by: David Kyle <[email protected]>
…m-model-response-parsers
* 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]>
💚 Backport successful
|
* 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]>
This PR adds functionality for parsing responses for the upcoming custom service: #125679
The response parsers leverage the
MapPathExtractorto retrieve fields from a json response converted into a map.