I am trying to build on device lexicon using IINKRecognitionAssetsBuilder but I am having problem with referencing it inside .conf file. Below is the code I use for initialising INKEngine:
// Configure the iink runtime environment
let configurationPath = Bundle.main.bundlePath.appending("/recognition-assets/conf")
do {
// Tells the engine where to load the recognition assets from.
try engine.configuration.set(stringArray: [configurationPath],
forKey:"configuration-manager.search-path")
} catch {
print("Should not happen, please check your resources assets : " + error.localizedDescription)
return nil
}
// Set the temporary directory
do {
try engine.configuration.set(string: NSTemporaryDirectory(),
forKey: "content-package.temp-folder")
} catch {
print("Failed to set temporary folder: " + error.localizedDescription)
return nil
}
do {
let assetsBuilder = engine.createRecognitionAssetsBuilder()
try assetsBuilder?.compile("Text Lexicon", data: "tvoja")
let myDirectoryPath = FileManager.default.documentDirectoryPath().appending("/myDirectory") // This folder is inside /Documents folder
if FileManager.default.fileExists(atPath: myDirectoryPath) == false {
// Create folder if needed.
try FileManager.default.createDirectory(atPath: myDirectoryPath, withIntermediateDirectories: false)
}
let lexPath = FileManager.default.documentDirectoryPath().appending("/myDirectory/custom-grammar.res")
try assetsBuilder?.store(lexPath)
try engine.configuration.set(string: "text", forKey: "text.configuration.name")
} catch {
print(error)
}
And now I have a problem how to reference it inside .conf file.
Bundle-Version: 1.0
Bundle-Name: en_US
Configuration-Script:
AddResDir ../resources/
AddResDir myResources/ --> This doesn't work because I am getting errors when I try to use INKEditor.
Name: text
Type: Text
Configuration-Script:
AddResource en_US/en_US-ak-cur.res
AddResource en_US/en_US-lk-text.res
AddResource en_US/lexicon.res
AddResource custom-grammar.res
EnableAlienCharacters
SetTextListSize 1
SetWordListSize 5
SetCharListSize 1
I see that in Android you are using AddResDir /data/user/0/com.sample/app_sample but this isn't available in iOS. Can you help me obtaining correct path for AddResDir?
Thanks,
Josip
Best Answer
J
Josip Bernat
said
over 1 year ago
Hi Gwenaëlle,
Thanks! When I separate words with newline character it works.
I want to say how my previous implementation in the end didn't work but after using your approach to copy everything from bundle folder to my own it started working. In case that somebody needs it here is how it looks like.
1. I copy everything from recognition-assets to /Documents/RecognitionAssets
let bundleAssetsPath = Bundle.main.bundlePath.appending("/recognition-assets")
let localAssetsPath = FileManager.default.documentDirectoryPath().appending("/\(Self.recognitionAssetsFolderName)")
do {
if FileManager.default.fileExists(atPath: localAssetsPath) == false {
try FileManager.default.createDirectory(atPath: localAssetsPath, withIntermediateDirectories: false)
}
let contents = try FileManager.default.contentsOfDirectory(atPath: bundleAssetsPath)
for item in contents {
let atURL = URL(fileURLWithPath: "\(bundleAssetsPath)/\(item)")
let toPath = localAssetsPath.appending("/\(atURL.lastPathComponent)")
if FileManager.default.fileExists(atPath: toPath) {
try FileManager.default.removeItem(atPath: toPath)
}
try FileManager.default.copyItem(atPath: atURL.path, toPath: toPath)
}
} catch {
print("An error occurred while copying recognition assets: \(error)")
}
2. Configure configuration-manager.search-path
do {
// Tells the engine where to load the recognition assets from.
let confPath = localAssetsPath.appending("/conf")
try engine.configuration.set(stringArray: [confPath],
forKey:"configuration-manager.search-path")
} catch {
print("Should not happen, please check your resources assets : " + error.localizedDescription)
return nil
}
3. Load custom dictionary
let words = storedCustomDictionary() ?? ""
do {
let assetsBuilder = engine.createRecognitionAssetsBuilder()
try assetsBuilder?.compile("Text Lexicon", data: words)
let lexPath = FileManager.default
.documentDirectoryPath()
.appending("/\(Self.recognitionAssetsFolderName)/resources/custom-grammar.res")
try assetsBuilder?.store(lexPath)
try engine.configuration.set(string: "text", forKey: "text.configuration.name")
} catch {
print(error)
}
When using AddResDir it is recommended to use relative path rather than absolute ones, in order to avoid any deployment issue
So to fix your path issue, we advise you to extract the content of your "recognition-assets" folder at runtime under your /myDirectory in your documentDirectoryPath
and to only work within documentDirectoryPath: thus all your files .res and .conf will be located within the documentDirectoryPath making it possible to use relative paths.
You should update your configuration-manager.search-path accordingly.
We have another remark, though, as you seem to want to mix foreign words within english ones. As the ak (alphabet knowledge) is based on the en_US one, this might not be the best option if you are adding word containing characters that are specific to this language.
Have you considered the other option that is configuring the recognition engine with the other language? Indeed default configurations for all languages but English variants also attach a “secondary English” LK that allows the engine to recognize a mix of the target language and English. Except for this particular case, it is not expected to mix languages together.
Best regards,
Gwenaëlle
J
Josip Bernat
said
over 1 year ago
Hi Gwenaelle,
Using a a secondary language won't work because some clients have business specific phrases or abbreviations and I was hoping that custom lexicon could help me with that.
I was able to make it work by using following:
Bundle-Version: 1.0
Bundle-Name: en_US
Configuration-Script:
AddResDir ../resources/
AddResDir ../myResources --> it is important that you don't add / at the end.
Name: text
Type: Text
Configuration-Script:
AddResource en_US/en_US-ak-cur.res
AddResource en_US/en_US-lk-text.res
AddResource en_US/lexicon.res
#AddResource custom-grammar.res
EnableAlienCharacters
SetTextListSize 1
SetWordListSize 5
SetCharListSize 1
And then save your custom lexicon into documents directory:
Interestingly I didn't have to update configuration-manager.search-path.
At the moment I have only a single word inside my custom lexicon. If I want to add multiple words how should I write them? I.e. should I separate them with commas or with newline character?
G
Gwenaelle @MyScript
said
over 1 year ago
Hi Josip,
Thank you for your update.
In the lexicon, each word must be added in a separate line. See some examples
So you should indeed separate them with a newline character.
Best regards,
Gwenaëlle
J
Josip Bernat
said
over 1 year ago
Answer
Hi Gwenaëlle,
Thanks! When I separate words with newline character it works.
I want to say how my previous implementation in the end didn't work but after using your approach to copy everything from bundle folder to my own it started working. In case that somebody needs it here is how it looks like.
1. I copy everything from recognition-assets to /Documents/RecognitionAssets
let bundleAssetsPath = Bundle.main.bundlePath.appending("/recognition-assets")
let localAssetsPath = FileManager.default.documentDirectoryPath().appending("/\(Self.recognitionAssetsFolderName)")
do {
if FileManager.default.fileExists(atPath: localAssetsPath) == false {
try FileManager.default.createDirectory(atPath: localAssetsPath, withIntermediateDirectories: false)
}
let contents = try FileManager.default.contentsOfDirectory(atPath: bundleAssetsPath)
for item in contents {
let atURL = URL(fileURLWithPath: "\(bundleAssetsPath)/\(item)")
let toPath = localAssetsPath.appending("/\(atURL.lastPathComponent)")
if FileManager.default.fileExists(atPath: toPath) {
try FileManager.default.removeItem(atPath: toPath)
}
try FileManager.default.copyItem(atPath: atURL.path, toPath: toPath)
}
} catch {
print("An error occurred while copying recognition assets: \(error)")
}
2. Configure configuration-manager.search-path
do {
// Tells the engine where to load the recognition assets from.
let confPath = localAssetsPath.appending("/conf")
try engine.configuration.set(stringArray: [confPath],
forKey:"configuration-manager.search-path")
} catch {
print("Should not happen, please check your resources assets : " + error.localizedDescription)
return nil
}
3. Load custom dictionary
let words = storedCustomDictionary() ?? ""
do {
let assetsBuilder = engine.createRecognitionAssetsBuilder()
try assetsBuilder?.compile("Text Lexicon", data: words)
let lexPath = FileManager.default
.documentDirectoryPath()
.appending("/\(Self.recognitionAssetsFolderName)/resources/custom-grammar.res")
try assetsBuilder?.store(lexPath)
try engine.configuration.set(string: "text", forKey: "text.configuration.name")
} catch {
print(error)
}
And that's it. Thanks again!
G
Gwenaelle @MyScript
said
over 1 year ago
Hi Josip,
We are glad you succeeded in building your lexicon.
Thank you for sharing with all users your working code for building your own lexicon!
Josip Bernat
Hi,
I am trying to build on device lexicon using IINKRecognitionAssetsBuilder but I am having problem with referencing it inside .conf file. Below is the code I use for initialising INKEngine:
And now I have a problem how to reference it inside .conf file.
Bundle-Version: 1.0
Bundle-Name: en_US
Configuration-Script:
AddResDir ../resources/
AddResDir myResources/ --> This doesn't work because I am getting errors when I try to use INKEditor.
Name: text
Type: Text
Configuration-Script:
AddResource en_US/en_US-ak-cur.res
AddResource en_US/en_US-lk-text.res
AddResource en_US/lexicon.res
AddResource custom-grammar.res
EnableAlienCharacters
SetTextListSize 1
SetWordListSize 5
SetCharListSize 1
I see that in Android you are using AddResDir /data/user/0/com.sample/app_sample but this isn't available in iOS. Can you help me obtaining correct path for AddResDir?
Thanks,
Josip
Hi Gwenaëlle,
Thanks! When I separate words with newline character it works.
I want to say how my previous implementation in the end didn't work but after using your approach to copy everything from bundle folder to my own it started working. In case that somebody needs it here is how it looks like.
This is my en_US.conf file
1. I copy everything from recognition-assets to /Documents/RecognitionAssets
2. Configure configuration-manager.search-path
3. Load custom dictionary
And that's it. Thanks again!
- Oldest First
- Popular
- Newest First
Sorted by Oldest FirstGwenaelle @MyScript
Hi Josip,
Thank you for your question.
When using AddResDir it is recommended to use relative path rather than absolute ones, in order to avoid any deployment issue
So to fix your path issue, we advise you to extract the content of your "recognition-assets" folder at runtime under your /myDirectory in your documentDirectoryPath
and to only work within documentDirectoryPath: thus all your files .res and .conf will be located within the documentDirectoryPath making it possible to use relative paths.
You should update your configuration-manager.search-path accordingly.
We have another remark, though, as you seem to want to mix foreign words within english ones. As the ak (alphabet knowledge) is based on the en_US one, this might not be the best option if you are adding word containing characters that are specific to this language.
Have you considered the other option that is configuring the recognition engine with the other language? Indeed default configurations for all languages but English variants also attach a “secondary English” LK that allows the engine to recognize a mix of the target language and English. Except for this particular case, it is not expected to mix languages together.
Best regards,
Gwenaëlle
Josip Bernat
Hi Gwenaelle,
Using a a secondary language won't work because some clients have business specific phrases or abbreviations and I was hoping that custom lexicon could help me with that.
I was able to make it work by using following:
And then save your custom lexicon into documents directory:
Interestingly I didn't have to update configuration-manager.search-path.
At the moment I have only a single word inside my custom lexicon. If I want to add multiple words how should I write them? I.e. should I separate them with commas or with newline character?
Gwenaelle @MyScript
Hi Josip,
Thank you for your update.
In the lexicon, each word must be added in a separate line. See some examples
So you should indeed separate them with a newline character.
Best regards,
Gwenaëlle
Josip Bernat
Hi Gwenaëlle,
Thanks! When I separate words with newline character it works.
I want to say how my previous implementation in the end didn't work but after using your approach to copy everything from bundle folder to my own it started working. In case that somebody needs it here is how it looks like.
This is my en_US.conf file
1. I copy everything from recognition-assets to /Documents/RecognitionAssets
2. Configure configuration-manager.search-path
3. Load custom dictionary
And that's it. Thanks again!
Gwenaelle @MyScript
Hi Josip,
We are glad you succeeded in building your lexicon.
Thank you for sharing with all users your working code for building your own lexicon!
Best regards,
Gwenaëlle