Commit 1185042a authored by Jing Wang's avatar Jing Wang Committed by Chromium LUCI CQ

Update grammar check mojo api and service client.

1. Uprev mojo api of grammar check from chromeos. The mojom interface
is generated with the script
"chromeos/services/machine_learning/public/mojom/roll_mojoms.sh" from
https://chromium-review.googlesource.com/c/chromiumos/platform2/+/2611147
this change need to be submitted after it.

2. The new api will return correction fragments, so update the service
client accordingly, now the grammar correct results are parsed from
fragments.

3. Don't show grammar error when the proposal is to delete the whole
sentence, i.e. when result->candidates.at(0)->text.empty() is true.

4. Update unit tests, in ServiceConnectionTest, move LoadGrammarModel
test before soda test so that it won't crash.

Bug: 1132699
Test: Passed unit tests, also manually tested on nocturne.
Change-Id: I85529f3a26f134e5eea7785bae5ac9c7f9e776f8
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2612788
Commit-Queue: Jing Wang <jiwan@chromium.org>
Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Reviewed-by: default avatarHonglin Yu <honglinyu@chromium.org>
Reviewed-by: default avatarDarren Shen <shend@chromium.org>
Cr-Commit-Position: refs/heads/master@{#845006}
parent e437a995
......@@ -62,12 +62,29 @@ void GrammarServiceClient::ParseGrammarCheckerResult(
chromeos::machine_learning::mojom::GrammarCheckerResultPtr result) const {
if (result->status == GrammarCheckerResult::Status::OK &&
!result->candidates.empty()) {
std::vector<SpellCheckResult> grammar_results;
grammar_results.emplace_back(
SpellCheckResult::GRAMMAR, 0, text.size(),
base::UTF8ToUTF16(result->candidates.at(0)->text));
std::move(callback).Run(true, grammar_results);
const auto& top_candidate = result->candidates.front();
if (!top_candidate->text.empty() && !top_candidate->fragments.empty()) {
std::vector<SpellCheckResult> grammar_results;
for (const auto& fragment : top_candidate->fragments) {
uint32_t end;
if (!base::CheckAdd(fragment->offset, fragment->length)
.AssignIfValid(&end) ||
end > text.size()) {
DLOG(ERROR) << "Grammar checker returns invalid correction "
"fragement, offset: "
<< fragment->offset << ", length: " << fragment->length
<< ", but the text length is " << text.size();
} else {
grammar_results.emplace_back(
SpellCheckResult::GRAMMAR, fragment->offset, fragment->length,
base::UTF8ToUTF16(fragment->replacement));
}
}
std::move(callback).Run(true, grammar_results);
return;
}
}
std::move(callback).Run(false, {});
}
bool GrammarServiceClient::IsAvailable(Profile* profile) const {
......
......@@ -64,15 +64,19 @@ TEST_F(GrammarServiceClientTest, ParsesResults) {
spellcheck::prefs::kSpellCheckUseSpellingService, true);
// Construct fake output
const base::string16 input_text = base::UTF8ToUTF16("fake input");
const base::string16 expected_output = base::UTF8ToUTF16("fake output");
machine_learning::mojom::GrammarCheckerResultPtr result =
machine_learning::mojom::GrammarCheckerResult::New();
result->status = machine_learning::mojom::GrammarCheckerResult::Status::OK;
machine_learning::mojom::GrammarCheckerCandidatePtr candidate =
machine_learning::mojom::GrammarCheckerCandidate::New();
candidate->text = base::UTF16ToUTF8(expected_output);
candidate->text = "fake output";
candidate->score = 0.5f;
machine_learning::mojom::GrammarCorrectionFragmentPtr fragment =
machine_learning::mojom::GrammarCorrectionFragment::New();
fragment->offset = 3;
fragment->length = 5;
fragment->replacement = "fake replacement";
candidate->fragments.emplace_back(std::move(fragment));
result->candidates.emplace_back(std::move(candidate));
fake_service_connection.SetOutputGrammarCheckerResult(result);
......@@ -80,19 +84,18 @@ TEST_F(GrammarServiceClientTest, ParsesResults) {
base::RunLoop().RunUntilIdle();
client.RequestTextCheck(
profile.get(), input_text,
profile.get(), base::UTF8ToUTF16("fake input"),
base::BindOnce(
[](const base::string16& text, const base::string16& expected_output,
bool success, const std::vector<SpellCheckResult>& results) {
[](bool success, const std::vector<SpellCheckResult>& results) {
EXPECT_TRUE(success);
ASSERT_EQ(results.size(), 1U);
EXPECT_EQ(results[0].decoration, SpellCheckResult::GRAMMAR);
EXPECT_EQ(results[0].location, 0);
EXPECT_EQ(results[0].length, static_cast<int>(text.size()));
EXPECT_EQ(results[0].location, 3);
EXPECT_EQ(results[0].length, 5);
ASSERT_EQ(results[0].replacements.size(), 1U);
EXPECT_EQ(results[0].replacements[0], expected_output);
},
input_text, expected_output));
EXPECT_EQ(results[0].replacements[0],
base::UTF8ToUTF16("fake replacement"));
}));
base::RunLoop().RunUntilIdle();
}
......
......@@ -523,6 +523,12 @@ TEST_F(ServiceConnectionTest, FakeGrammarChecker) {
mojom::GrammarCheckerCandidate::New();
candidate->text = "cat";
candidate->score = 0.5f;
mojom::GrammarCorrectionFragmentPtr fragment =
mojom::GrammarCorrectionFragment::New();
fragment->offset = 3;
fragment->length = 5;
fragment->replacement = "dog";
candidate->fragments.emplace_back(std::move(fragment));
result->candidates.emplace_back(std::move(candidate));
fake_service_connection.SetOutputGrammarCheckerResult(result);
......@@ -535,8 +541,15 @@ TEST_F(ServiceConnectionTest, FakeGrammarChecker) {
*infer_callback_done = true;
// Check if the annotation is correct.
ASSERT_EQ(result->status, mojom::GrammarCheckerResult::Status::OK);
ASSERT_EQ(result->candidates.size(), 1UL);
EXPECT_EQ(result->candidates.at(0)->text, "cat");
EXPECT_EQ(result->candidates.at(0)->score, 0.5f);
ASSERT_EQ(result->candidates.at(0)->fragments.size(), 1UL);
EXPECT_EQ(result->candidates.at(0)->fragments.at(0)->offset, 3U);
EXPECT_EQ(result->candidates.at(0)->fragments.at(0)->length, 5U);
EXPECT_EQ(result->candidates.at(0)->fragments.at(0)->replacement,
"dog");
},
&infer_callback_done));
base::RunLoop().RunUntilIdle();
......
......@@ -3,6 +3,10 @@
// found in the LICENSE file.
// Datatypes and interfaces of grammar checker API.
// Grammar check API is implemented in Chrome OS platform2 repo
// src/platform2/ml/grammar_checker_impl.h
// It is running inside the ML sandbox and consumed only from the Chrome browser
// process.
// NOTE: This mojom exists in two places and must be kept in sync:
// Chromium: //chromeos/services/machine_learning/public/mojom/
......@@ -25,6 +29,18 @@ struct GrammarCheckerQuery {
string language;
};
// A span with suggested corrections.
struct GrammarCorrectionFragment {
// The start offset in the original text.
uint32 offset;
// The length of the fragment in the original text.
uint32 length;
// The replacement string.
string replacement;
};
// One possible candidate returned from the grammar checker model.
struct GrammarCheckerCandidate {
// Corrected text.
......@@ -32,6 +48,9 @@ struct GrammarCheckerCandidate {
// Score of the text. Log of conditional probability.
float score;
// The list of individual corrections.
array<GrammarCorrectionFragment> fragments;
};
// The grammar check response.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment