mirror of
https://github.com/mii443/AzooKeyKanaKanjiConverter.git
synced 2025-12-03 11:08:33 +00:00
[cli] 完全一致変換のみを出力するモードを追加 (#88)
* cli: add option to report score * cli: 完全一致変換をサポート
This commit is contained in:
@@ -15,6 +15,9 @@ extension Subcommands {
|
|||||||
@Flag(name: [.customLong("disable_prediction")], help: "Disable producing prediction candidates.")
|
@Flag(name: [.customLong("disable_prediction")], help: "Disable producing prediction candidates.")
|
||||||
var disablePrediction = false
|
var disablePrediction = false
|
||||||
|
|
||||||
|
@Flag(name: [.customLong("only_whole_conversion")], help: "Show only whole conversion (完全一致変換).")
|
||||||
|
var onlyWholeConversion = false
|
||||||
|
|
||||||
@Flag(name: [.customLong("report_score")], help: "Show internal score for the candidate.")
|
@Flag(name: [.customLong("report_score")], help: "Show internal score for the candidate.")
|
||||||
var reportScore = false
|
var reportScore = false
|
||||||
|
|
||||||
@@ -25,19 +28,31 @@ extension Subcommands {
|
|||||||
var composingText = ComposingText()
|
var composingText = ComposingText()
|
||||||
composingText.insertAtCursorPosition(input, inputStyle: .direct)
|
composingText.insertAtCursorPosition(input, inputStyle: .direct)
|
||||||
let result = converter.requestCandidates(composingText, options: requestOptions())
|
let result = converter.requestCandidates(composingText, options: requestOptions())
|
||||||
for candidate in result.mainResults.prefix(self.displayTopN) {
|
let mainResults = result.mainResults.filter {
|
||||||
|
!self.onlyWholeConversion || $0.data.reduce(into: "", {$0.append(contentsOf: $1.ruby)}) == input.toKatakana()
|
||||||
|
}
|
||||||
|
for candidate in mainResults.prefix(self.displayTopN) {
|
||||||
if self.reportScore {
|
if self.reportScore {
|
||||||
print("\(candidate.text) \(bold: "score:") \(candidate.value)")
|
print("\(candidate.text) \(bold: "score:") \(candidate.value)")
|
||||||
} else {
|
} else {
|
||||||
print(candidate.text)
|
print(candidate.text)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if self.onlyWholeConversion {
|
||||||
|
// entropyを示す
|
||||||
|
let expValues = mainResults.map { exp(Double($0.value)) }
|
||||||
|
let sumOfExpValues = expValues.reduce(into: 0, +=)
|
||||||
|
// 確率値に補正
|
||||||
|
let probs = expValues.map { $0 / sumOfExpValues }
|
||||||
|
let entropy = -probs.reduce(into: 0) { $0 += $1 * log($1) }
|
||||||
|
print("\(bold: "Entropy:") \(entropy)")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func requestOptions() -> ConvertRequestOptions {
|
func requestOptions() -> ConvertRequestOptions {
|
||||||
.withDefaultDictionary(
|
var option: ConvertRequestOptions = .withDefaultDictionary(
|
||||||
N_best: configNBest,
|
N_best: self.onlyWholeConversion ? max(self.configNBest, self.displayTopN) : self.configNBest,
|
||||||
requireJapanesePrediction: !disablePrediction,
|
requireJapanesePrediction: !self.onlyWholeConversion && !self.disablePrediction,
|
||||||
requireEnglishPrediction: false,
|
requireEnglishPrediction: false,
|
||||||
keyboardLanguage: .ja_JP,
|
keyboardLanguage: .ja_JP,
|
||||||
typographyLetterCandidate: false,
|
typographyLetterCandidate: false,
|
||||||
@@ -52,6 +67,10 @@ extension Subcommands {
|
|||||||
sharedContainerURL: URL(fileURLWithPath: ""),
|
sharedContainerURL: URL(fileURLWithPath: ""),
|
||||||
metadata: .init(appVersionString: "anco")
|
metadata: .init(appVersionString: "anco")
|
||||||
)
|
)
|
||||||
|
if self.onlyWholeConversion {
|
||||||
|
option.requestQuery = .完全一致
|
||||||
|
}
|
||||||
|
return option
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,6 +49,26 @@ public struct ConvertRequestOptions: Sendable {
|
|||||||
self.dictionaryResourceURL = dictionaryResourceURL
|
self.dictionaryResourceURL = dictionaryResourceURL
|
||||||
}
|
}
|
||||||
|
|
||||||
|
package init(N_best: Int = 10, requireJapanesePrediction: Bool, requireEnglishPrediction: Bool, keyboardLanguage: KeyboardLanguage, typographyLetterCandidate: Bool = false, unicodeCandidate: Bool = true, englishCandidateInRoman2KanaInput: Bool = false, fullWidthRomanCandidate: Bool = false, halfWidthKanaCandidate: Bool = false, learningType: LearningType, maxMemoryCount: Int = 65536, shouldResetMemory: Bool = false, dictionaryResourceURL: URL, memoryDirectoryURL: URL, sharedContainerURL: URL, textReplacer: TextReplacer = TextReplacer(), metadata: ConvertRequestOptions.Metadata, requestQuery: RequestQuery) {
|
||||||
|
self.N_best = N_best
|
||||||
|
self.requireJapanesePrediction = requireJapanesePrediction
|
||||||
|
self.requireEnglishPrediction = requireEnglishPrediction
|
||||||
|
self.keyboardLanguage = keyboardLanguage
|
||||||
|
self.typographyLetterCandidate = typographyLetterCandidate
|
||||||
|
self.unicodeCandidate = unicodeCandidate
|
||||||
|
self.englishCandidateInRoman2KanaInput = englishCandidateInRoman2KanaInput
|
||||||
|
self.fullWidthRomanCandidate = fullWidthRomanCandidate
|
||||||
|
self.halfWidthKanaCandidate = halfWidthKanaCandidate
|
||||||
|
self.learningType = learningType
|
||||||
|
self.maxMemoryCount = maxMemoryCount
|
||||||
|
self.shouldResetMemory = shouldResetMemory
|
||||||
|
self.memoryDirectoryURL = memoryDirectoryURL
|
||||||
|
self.sharedContainerURL = sharedContainerURL
|
||||||
|
self.metadata = metadata
|
||||||
|
self.textReplacer = textReplacer
|
||||||
|
self.dictionaryResourceURL = dictionaryResourceURL
|
||||||
|
}
|
||||||
|
|
||||||
public var N_best: Int
|
public var N_best: Int
|
||||||
public var requireJapanesePrediction: Bool
|
public var requireJapanesePrediction: Bool
|
||||||
public var requireEnglishPrediction: Bool
|
public var requireEnglishPrediction: Bool
|
||||||
@@ -71,6 +91,9 @@ public struct ConvertRequestOptions: Sendable {
|
|||||||
// メタデータ
|
// メタデータ
|
||||||
public var metadata: Metadata
|
public var metadata: Metadata
|
||||||
|
|
||||||
|
// MARK: プライベートAPI
|
||||||
|
package var requestQuery: RequestQuery = .default
|
||||||
|
|
||||||
static var `default`: Self {
|
static var `default`: Self {
|
||||||
Self(
|
Self(
|
||||||
N_best: 10,
|
N_best: 10,
|
||||||
@@ -103,4 +126,9 @@ public struct ConvertRequestOptions: Sendable {
|
|||||||
}
|
}
|
||||||
var appVersionString: String
|
var appVersionString: String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
package enum RequestQuery: Sendable {
|
||||||
|
case `default`
|
||||||
|
case 完全一致
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -428,6 +428,10 @@ import SwiftUtils
|
|||||||
let sums: [(CandidateData, Candidate)] = clauseResult.map {($0, converter.processClauseCandidate($0))}
|
let sums: [(CandidateData, Candidate)] = clauseResult.map {($0, converter.processClauseCandidate($0))}
|
||||||
// 文章全体を変換した場合の候補上位5件を作る
|
// 文章全体を変換した場合の候補上位5件を作る
|
||||||
let whole_sentence_unique_candidates = self.getUniqueCandidate(sums.map {$0.1})
|
let whole_sentence_unique_candidates = self.getUniqueCandidate(sums.map {$0.1})
|
||||||
|
if case .完全一致 = options.requestQuery {
|
||||||
|
// 完全一致候補のみが要求されている場合、ここで全てのデータを返してreturnする
|
||||||
|
return ConversionResult(mainResults: whole_sentence_unique_candidates.sorted(by: {$0.value > $1.value}), firstClauseResults: [])
|
||||||
|
}
|
||||||
let sentence_candidates = whole_sentence_unique_candidates.min(count: 5, sortedBy: {$0.value > $1.value})
|
let sentence_candidates = whole_sentence_unique_candidates.min(count: 5, sortedBy: {$0.value > $1.value})
|
||||||
// 予測変換を最大3件作成する
|
// 予測変換を最大3件作成する
|
||||||
let prediction_candidates: [Candidate] = options.requireJapanesePrediction ? Array(self.getUniqueCandidate(self.getPredictionCandidate(sums, composingText: inputData, options: options)).min(count: 3, sortedBy: {$0.value > $1.value})) : []
|
let prediction_candidates: [Candidate] = options.requireJapanesePrediction ? Array(self.getUniqueCandidate(self.getPredictionCandidate(sums, composingText: inputData, options: options)).min(count: 3, sortedBy: {$0.value > $1.value})) : []
|
||||||
|
|||||||
Reference in New Issue
Block a user