With ML Kit's GenAI Proofreading API, you can help users check their grammar and spelling on short pieces of text.
Key capabilities
- Proofread text inputted through keyboard or voice
- Requests will return at least one suggestion. If multiple suggestions are returned, results will be sorted by descending confidence.
Example results
Input |
Input Type |
Output |
this is a short msg |
Keyboard |
This is a short message |
The project is nearly compleete butt needs too be reviewed |
Keyboard |
The project is nearly complete but needs to be reviewed |
Please meat me at the bear, |
Voice |
Please meet me at the bar. |
Getting Started
To get started with the GenAI Proofreading API, add this dependency to your project's build file.
implementation
(
"com.google.mlkit:genai-proofreading:1.0.0-beta1"
)
Then, configure and obtain a Proofreader
client with specific language
and input type settings. Check and ensure the necessary on-device model features
are available (triggering a download if needed). Submit the text you want to
analyze in a ProofreadingRequest
, execute the proofreading inference, and
finally process the returned suggestions for correcting the text.
Kotlin
val
textToProofread
=
"The praject is compleet but needs too be reviewd"
// Define task with required input and output format
val
options
=
ProofreaderOptions
.
builder
(
context
)
// InputType can be KEYBOARD or VOICE. VOICE indicates that
// the user generated text based on audio input.
.
setInputType
(
ProofreaderOptions
.
InputType
.
KEYBOARD
)
// Refer to ProofreaderOptions.Language for available
// languages
.
setLanguage
(
ProofreaderOptions
.
Language
.
ENGLISH
)
.
build
()
val
proofreader
=
Proofreading
.
getClient
(
options
)
suspend
fun
prepareAndStartProofread
()
{
// Check feature availability, status will be one of the
// following: UNAVAILABLE, DOWNLOADABLE, DOWNLOADING, AVAILABLE
val
featureStatus
=
proofreader
.
checkFeatureStatus
().
await
()
if
(
featureStatus
==
FeatureStatus
.
DOWNLOADABLE
)
{
// Download feature if necessary.
// If downloadFeature is not called, the first inference
// request will also trigger the feature to be downloaded
// if it's not already downloaded.
proofreader
.
downloadFeature
(
object
:
DownloadCallback
{
override
fun
onDownloadStarted
(
bytesToDownload
:
Long
)
{
}
override
fun
onDownloadFailed
(
e
:
GenAiException
)
{
}
override
fun
onDownloadProgress
(
totalBytesDownloaded
:
Long
)
{}
override
fun
onDownloadCompleted
()
{
startProofreadingRequest
(
textToProofread
,
proofreader
)
}
})
}
else
if
(
featureStatus
==
FeatureStatus
.
DOWNLOADING
)
{
// Inference request will automatically run once feature is
// downloaded.
// If Gemini Nano is already downloaded on the device, the
// feature-specific LoRA adapter model will be downloaded
// very quickly. However, if Gemini Nano is not already
// downloaded, the download process may take longer.
startProofreadingRequest
(
textToProofread
,
proofreader
)
}
else
if
(
featureStatus
==
FeatureStatus
.
AVAILABLE
)
{
startProofreadingRequest
(
textToProofread
,
proofreader
)
}
}
suspend
fun
startProofreadingRequest
(
text
:
String
,
proofreader
:
Proofreader
)
{
// Create task request
val
proofreadingRequest
=
ProofreadingRequest
.
builder
(
text
).
build
()
// Start proofreading request with non-streaming response
// More than 1 result may be returned. If multiple suggestions
// are returned, results will be sorted by descending confidence.
val
proofreadingResults
=
proofreader
.
runInference
(
proofreadingRequest
).
await
().
results
// You can also start a streaming request
// proofreader.runInference(proofreadingRequest) { newText -
>
// // show new text in UI
// }
}
// Be sure to release the resource when no longer needed
// For example, on viewModel.onCleared() or activity.onDestroy()
proofreader
.
close
()
Java
String
textToProofread
=
"The praject is compleet but needs too be reviewd"
;
// Define task with required input and output format
ProofreaderOptions
proofreaderOptions
=
ProofreaderOptions
.
builder
(
context
)
// InputType can be KEYBOARD or VOICE. VOICE indicates that the
// user generated text based on audio input.
.
setInputType
(
ProofreaderOptions
.
InputType
.
KEYBOARD
)
// Refer to ProofreaderOptions.Language for available languages
.
setLanguage
(
ProofreaderOptions
.
Language
.
ENGLISH
)
.
build
();
Proofreader
proofreader
=
Proofreading
.
getClient
(
proofreaderOptions
);
void
prepareAndStartProofread
(
Context
context
)
throws
ExecutionException
,
InterruptedException
{
// Check feature availability, status will be one of the following:
// UNAVAILABLE, DOWNLOADABLE, DOWNLOADING, AVAILABLE
try
{
int
featureStatus
=
proofreader
.
checkFeatureStatus
().
get
();
if
(
featureStatus
==
FeatureStatus
.
DOWNLOADABLE
)
{
// Download feature if necessary.
// If downloadFeature is not called, the first inference request
// will also trigger the feature to be downloaded if it's not
// already downloaded.
proofreader
.
downloadFeature
(
new
DownloadCallback
()
{
@Override
public
void
onDownloadCompleted
()
{
startProofreadingRequest
(
textToProofread
,
proofreader
);
}
@Override
public
void
onDownloadFailed
(
GenAiException
e
)
{
}
@Override
public
void
onDownloadProgress
(
long
totalBytesDownloaded
)
{
}
@Override
public
void
onDownloadStarted
(
long
bytesDownloaded
)
{
}
});
}
else
if
(
featureStatus
==
FeatureStatus
.
DOWNLOADING
)
{
// Inference request will automatically run once feature is
// downloaded.
// If Gemini Nano is already downloaded on the device, the
// feature-specific LoRA adapter model will be downloaded
// very quickly. However, if Gemini Nano is not already
// downloaded, the download process may take longer.
startProofreadingRequest
(
textToProofread
,
proofreader
);
}
else
if
(
featureStatus
==
FeatureStatus
.
AVAILABLE
)
{
startProofreadingRequest
(
textToProofread
,
proofreader
);
}
}
catch
(
ExecutionException
|
InterruptedException
e
)
{
e
.
printStackTrace
();
}
}
void
startProofreadingRequest
(
String
text
,
Proofreader
proofreader
)
{
// Create task request
ProofreadingRequest
proofreadingRequest
=
ProofreadingRequest
.
builder
(
text
).
build
();
try
{
// Start proofreading request with non-streaming response
// More than 1 result may be returned. If multiple suggestions are
// returned, results will be sorted by descending confidence.
proofreader
.
runInference
(
proofreadingRequest
).
get
().
getResults
();
// You can also start a streaming request
// proofreader.runInference(proofreadingRequest, newText -> {
// // Show new text in UI
// });
}
catch
(
ExecutionException
|
InterruptedException
e
)
{
e
.
printStackTrace
();
}
}
// Be sure to release the resource when no longer needed
// For example, on viewModel.onCleared() or activity.onDestroy()
proofreader
.
close
();
How the model handles different input types
When the model has more information about how the user inputted text (keyboard or voice), it can better predict the type of errors that may be present. Keyboard-inputted text is more prone to misspelling with nearby keys, while voice-inputted text is more prone to misspelling of words with the same pronunciation.
Supported features and limitations
Proofreading is supported for the following languages: English,
Japanese, French, German, Italian, Spanish, and Korean, and they are defined in ProofreaderOptions.Language
. Input should be less than 256 tokens.
Availability of the specific feature configuration (specified by ProofreaderOptions
) may vary depending on the particular device's
configuration and the models that have been downloaded to the device.
The most reliable way for developers to ensure that the intended API feature is
supported on a device with the requested ProofreaderOptions
is to call the checkFeatureStatus()
method. This method provides the definitive status
of feature availability on the device at runtime.
Common setup issues
ML Kit GenAI APIs rely on the Android AICore app to access Gemini Nano. When a device is just setup (including reset), or the AICore app is just reset (e.g. clear data, uninstalled then reinstalled), the AICore app may not have enough time to finish initialization (including downloading latest configurations from server). As a result, the ML Kit GenAI APIs may not function as expected. Here are the common setup error messages you may see and how to handle them:
Example error message | How to handle |
AICore failed with error type 4-CONNECTION_ERROR and error code 601-BINDING_FAILURE: AICore service failed to bind. | This could happen when you install the app using ML Kit GenAI APIs immediately after device setup or when AICore is uninstalled after your app is installed. Updating AICore app then reinstalling your app should fix it. |
AICore failed with error type 3-PREPARATION_ERROR and error code 606-FEATURE_NOT_FOUND: Feature ... is not available. | This could happen when AICore hasn't finished downloading the latest configurations. When the device is connected to the internet, it usually takes a few minutes to a few hours to update. Restarting the device can speed up the update. Note that if the device's bootloader is unlocked, you'll also see this error—this API does not support devices with unlocked bootloaders. |
AICore failed with error type 1-DOWNLOAD_ERROR and error code 0-UNKNOWN: Feature ... failed with failure status 0 and error esz: UNAVAILABLE: Unable to resolve host ... | Keep network connection, wait for a few minutes and retry. |