Class MockScoringModel
- All Implemented Interfaces:
ScoringModel
ScoringModel for tests: it needs no network, scores each document the way the test tells it to, and records
the requests it receives.
Script the answers step by step, one step per request. One call of score(...), scoreAll(...) or
scoreAsync(...) is one request, also when it scores several documents. For example, a model that gives every
document of every request the same score:
MockScoringModel model = MockScoringModel.thatScores(0.8).thenRepeats();
Every that... method creates a mock with its first step, and every then... method adds a step. Each
step answers exactly one request. A request after the last step fails with an IllegalStateException that
shows the query of the request, so a test notices when the code calls the model more often than the script expects,
unless the code under test handles the error itself. score(...) throws it, and scoreAsync(...)
returns a future that fails with it. So a mock that is called more than once, for example to re-rank the results of
every question of a conversation, ends its script with thenRepeats(), which answers every further request
with the last step.
A script can let a request fail and the next one succeed, for example to test how your application handles a
re-ranking model that times out once, with LangChain4j's TimeoutException, and then recovers:
MockScoringModel model = MockScoringModel.thatFails(new TimeoutException("Read timed out"))
.thenScores(document -> document.contains("refund") ? 0.9 : 0.1)
.thenRepeats();
Like on every mock in this package, thatResponds(...) and thenResponds(...) give a step as the whole
response, here a ScoringResponse: the request is answered with exactly that response, including its
metadata, for example the token usage that a cost check reads. The response is used as given, also when its number
of scores differs from the number of documents of the request, for example to test how your code handles a
re-ranking provider that returns too few scores.
Unless a step gives the whole response, a response reports the model name of the request. scoreAsync(...)
completes on another thread, where a step that computes its scores also computes them.
A mock remembers which steps were taken and which requests it received, so create a new one for each test. A mock
shared between tests, for example as a bean, fails with a clear message as soon as its script runs out, unless the
script ends with thenRepeats(). The steps are taken in the order the requests arrive. A mock keeps every
request it receives, so it is not meant for load tests or other long runs.
-
Method Summary
Modifier and TypeMethodDescriptiondoScore(ScoringRequest request) The provider hook behindScoringModel.score(ScoringRequest).doScoreAsync(ScoringRequest request) Answers likedoScore(ScoringRequest), with the next step of the script, and completes the future on another thread, where a step that computes its scores also computes them.The last request received so far.The listeners notified before each call ofScoringModel.score(ScoringRequest)andScoringModel.scoreAsync(ScoringRequest), after each successful call and when a call fails.request()The only request received so far.requests()A copy of the requests received so far, in the order they arrived.scoreAll(List<TextSegment> segments, String query) Scores all providedTextSegments against a given query.static MockScoringModelthatFails(RuntimeException exception) A model whose first request fails with exactly the given exception, also a request without documents.static MockScoringModelthatResponds(ScoringResponse response) A model that answers the first request with exactly the given response, including its metadata, for example its token usage or model name, to test code that reads them, such as a cost check:static MockScoringModelthatScores(double score) A model that answers the first request with the given score for every document.static MockScoringModelthatScores(ToDoubleFunction<String> scores) A model that answers the first request with the score computed from the text of each document.thenFails(RuntimeException exception) Adds a step: the next request fails with exactly the given exception, also a request without documents.Answers every further request with the last step of the script.thenResponds(ScoringResponse response) Adds a step: the next request is answered with exactly the given response, including its metadata, seethatResponds(ScoringResponse).thenScores(double score) Adds a step: every document of the next request gets the given score.thenScores(ToDoubleFunction<String> scores) Adds a step: every document of the next request gets the score computed from its text.withListeners(ScoringModelListener... listeners) Notifies the given listeners of each call, like a real model does.withListeners(List<ScoringModelListener> listeners) Notifies the given listeners of each call, like a real model does.Methods inherited from class Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, waitMethods inherited from interface ScoringModel
defaultRequestParameters, provider, score, score, score, scoreAsync
-
Method Details
-
thenScores
Adds a step: every document of the next request gets the given score.- Throws:
IllegalStateException- if the script already ends withthenRepeats()
-
thenScores
Adds a step: every document of the next request gets the score computed from its text.- Throws:
IllegalStateException- if the script already ends withthenRepeats()
-
thenResponds
Adds a step: the next request is answered with exactly the given response, including its metadata, seethatResponds(ScoringResponse).- Throws:
IllegalStateException- if the script already ends withthenRepeats()
-
thenFails
Adds a step: the next request fails with exactly the given exception, also a request without documents.- Throws:
IllegalStateException- if the script already ends withthenRepeats()
-
thenRepeats
Answers every further request with the last step of the script. Only the last step repeats; the script does not start over. A last step that computes its scores computes them again for each request. Without it, a request after the last step fails. It must be the last call of the script.- Throws:
IllegalStateException- if the script already ends withthenRepeats()
-
withListeners
Notifies the given listeners of each call, like a real model does. -
withListeners
Notifies the given listeners of each call, like a real model does. -
scoreAll
Description copied from interface:ScoringModelScores all providedTextSegments against a given query.- Specified by:
scoreAllin interfaceScoringModel- Parameters:
segments- The list ofTextSegments to score.query- The query against which to score the segments.- Returns:
- the list of scores. The order of scores corresponds to the order of
TextSegments.
-
doScore
Description copied from interface:ScoringModelThe provider hook behindScoringModel.score(ScoringRequest).The default scores the documents with
ScoringModel.scoreAll(List, String), so a model that implements onlyScoringModel.scoreAll(List, String)also supportsScoringModel.score(ScoringRequest). To do so, the default turns each document into aTextSegment, and aTextSegmentcannot be blank: a model that implements onlyScoringModel.scoreAll(List, String)therefore cannot score blank documents throughScoringModel.score(ScoringRequest), and such a request fails with anIllegalArgumentException.To support
listeners, override this method and implementScoringModel.scoreAll(List, String)by callingScoringModel.score(ScoringRequest), so that the listeners are also notified whenScoringModel.scoreAll(List, String)is called. Never makeScoringModel.scoreAll(List, String)callScoringModel.score(ScoringRequest)without overriding this method: each method would call the other.- Specified by:
doScorein interfaceScoringModel- Parameters:
request- the request, with the default parameters already applied.- Returns:
- the scores, in the order of
ScoringRequest.documents(), and the response metadata.
-
doScoreAsync
Answers likedoScore(ScoringRequest), with the next step of the script, and completes the future on another thread, where a step that computes its scores also computes them. It never throws: anullrequest gives a failed future.- Specified by:
doScoreAsyncin interfaceScoringModel- Parameters:
request- the (already defaults-applied) request to score.- Returns:
- a
CompletableFutureof the scores, in the order ofScoringRequest.documents().
-
listeners
Description copied from interface:ScoringModelThe listeners notified before each call ofScoringModel.score(ScoringRequest)andScoringModel.scoreAsync(ScoringRequest), after each successful call and when a call fails. Listeners are configured on the builder of the scoring model. Defaults to an empty list.- Specified by:
listenersin interfaceScoringModel
-
requests
A copy of the requests received so far, in the order they arrived. -
request
The only request received so far.- Throws:
IllegalStateException- if the mock received no request or several requests
-
lastRequest
The last request received so far.- Throws:
IllegalStateException- if the mock received no request
-
thatScores
A model that answers the first request with the given score for every document. Add the next steps withthen...methods, or give every document of every request this score:thatScores(0.8).thenRepeats(). -
thatScores
A model that answers the first request with the score computed from the text of each document. Add the next steps withthen...methods, or compute the scores of every request withthenRepeats(). If the function throws, the request fails with that exception, unchanged. -
thatResponds
A model that answers the first request with exactly the given response, including its metadata, for example its token usage or model name, to test code that reads them, such as a cost check:
The response is used as given, also when its number of scores differs from the number of documents of the request. Add the next steps withMockScoringModel model = MockScoringModel.thatResponds(ScoringResponse.builder() .scores(List.of(0.9, 0.1)) .tokenUsage(new TokenUsage(30)) .build());then...methods, or answer every request with this response:thatResponds(response).thenRepeats(). -
thatFails
A model whose first request fails with exactly the given exception, also a request without documents. To let every request fail, addthenRepeats(). To let later requests succeed, for example to test your own retry logic, add steps withthen...methods.
-