mirror of
https://github.com/mii443/AzooKeyKanaKanjiConverter.git
synced 2025-08-22 15:05:26 +00:00
support zenz-v3
This commit is contained in:
@ -8,7 +8,7 @@ let options = ConvertRequestOptions.withDefaultDictionary(
|
||||
zenzaiMode: .on(
|
||||
weight: url,
|
||||
inferenceLimit: 1,
|
||||
versionDependentMode: .v2(.init(profile: "三輪/azooKeyの開発者", leftSideContext: "私の名前は"))
|
||||
versionDependentMode: .v3(.init(profile: "三輪/azooKeyの開発者", leftSideContext: "私の名前は"))
|
||||
)
|
||||
// ...
|
||||
)
|
||||
|
@ -38,7 +38,7 @@ extension Subcommands {
|
||||
shouldResetMemory: false,
|
||||
memoryDirectoryURL: URL(fileURLWithPath: ""),
|
||||
sharedContainerURL: URL(fileURLWithPath: ""),
|
||||
zenzaiMode: self.zenzWeightPath.isEmpty ? .off : .on(weight: URL(string: self.zenzWeightPath)!, inferenceLimit: .max, versionDependentMode: .v2(.init())),
|
||||
zenzaiMode: self.zenzWeightPath.isEmpty ? .off : .on(weight: URL(string: self.zenzWeightPath)!, inferenceLimit: .max, versionDependentMode: .v3(.init())),
|
||||
metadata: .init(versionString: "anco for debugging")
|
||||
)
|
||||
}
|
||||
|
@ -25,12 +25,16 @@ extension Subcommands {
|
||||
var roman2kana = false
|
||||
@Option(name: [.customLong("config_zenzai_inference_limit")], help: "inference limit for zenzai.")
|
||||
var configZenzaiInferenceLimit: Int = .max
|
||||
@Flag(name: [.customLong("config_zenzai_rich_n_best")], help: "enable profile prompting for zenz-v2.")
|
||||
@Flag(name: [.customLong("config_zenzai_rich_n_best")], help: "enable rich n_best generation for zenzai.")
|
||||
var configRequestRichCandidates = false
|
||||
@Option(name: [.customLong("config_profile")], help: "enable rich n_best generation for zenzai.")
|
||||
var configZenzV2Profile: String?
|
||||
@Option(name: [.customLong("config_profile")], help: "enable profile prompting for zenz-v2 and later.")
|
||||
var configZenzaiProfile: String?
|
||||
@Option(name: [.customLong("config_topic")], help: "enable topic prompting for zenz-v3 and later.")
|
||||
var configZenzaiTopic: String?
|
||||
@Flag(name: [.customLong("zenz_v1")], help: "Use zenz_v1 model.")
|
||||
var zenzV1 = false
|
||||
@Flag(name: [.customLong("zenz_v2")], help: "Use zenz_v2 model.")
|
||||
var zenzV2 = false
|
||||
|
||||
static let configuration = CommandConfiguration(commandName: "session", abstract: "Start session for incremental input.")
|
||||
|
||||
@ -192,8 +196,10 @@ extension Subcommands {
|
||||
func requestOptions(memoryDirectory: URL, leftSideContext: String) -> ConvertRequestOptions {
|
||||
let zenzaiVersionDependentMode: ConvertRequestOptions.ZenzaiVersionDependentMode = if self.zenzV1 {
|
||||
.v1
|
||||
} else if self.zenzV2 {
|
||||
.v2(.init(profile: self.configZenzaiProfile, leftSideContext: leftSideContext))
|
||||
} else {
|
||||
.v2(.init(profile: self.configZenzV2Profile, leftSideContext: leftSideContext))
|
||||
.v3(.init(profile: self.configZenzaiProfile, topic: self.configZenzaiTopic, leftSideContext: leftSideContext))
|
||||
}
|
||||
var option: ConvertRequestOptions = .withDefaultDictionary(
|
||||
N_best: self.onlyWholeConversion ? max(self.configNBest, self.displayTopN) : self.configNBest,
|
||||
|
@ -154,14 +154,37 @@ public struct ConvertRequestOptions: Sendable {
|
||||
public var leftSideContext: String?
|
||||
}
|
||||
|
||||
public struct ZenzaiV3DependentMode: Sendable, Equatable, Hashable {
|
||||
public init(profile: String? = nil, topic: String? = nil, style: String? = nil, preference: String? = nil, leftSideContext: String? = nil) {
|
||||
self.profile = profile
|
||||
self.topic = topic
|
||||
self.style = style
|
||||
self.preference = preference
|
||||
self.leftSideContext = leftSideContext
|
||||
}
|
||||
|
||||
/// プロフィールコンテクストを設定した場合、プロフィールを反映したプロンプトが自動的に付与されます。プロフィールは10〜20文字程度の長さにとどめることを推奨します。
|
||||
public var profile: String?
|
||||
/// topicを設定した場合、話題にあった変換が自動的に優先されます。話題は10〜20文字程度の長さにとどめることを推奨します。
|
||||
public var topic: String?
|
||||
/// styleを設定した場合、文章のスタイルにあった変換が自動的に優先されます。スタイルは10〜20文字程度の長さにとどめることを推奨します。
|
||||
public var style: String?
|
||||
/// preferenceコンテクストを設定した場合、ユーザの書き方の好みに合わせた変換が自動的に優先されます。preferenceは10〜20文字程度の長さにとどめることを推奨します。
|
||||
public var preference: String?
|
||||
/// 左側の文字列を文脈として与えます。
|
||||
public var leftSideContext: String?
|
||||
}
|
||||
|
||||
public enum ZenzVersion: Sendable, Equatable, Hashable {
|
||||
case v1
|
||||
case v2
|
||||
case v3
|
||||
}
|
||||
|
||||
public enum ZenzaiVersionDependentMode: Sendable, Equatable, Hashable {
|
||||
case v1
|
||||
case v2(ZenzaiV2DependentMode)
|
||||
case v3(ZenzaiV3DependentMode)
|
||||
|
||||
public var version: ZenzVersion {
|
||||
switch self {
|
||||
@ -169,6 +192,8 @@ public struct ConvertRequestOptions: Sendable {
|
||||
return .v1
|
||||
case .v2:
|
||||
return .v2
|
||||
case .v3:
|
||||
return .v3
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -179,7 +204,7 @@ public struct ConvertRequestOptions: Sendable {
|
||||
weightURL: URL(fileURLWithPath: ""),
|
||||
inferenceLimit: 10,
|
||||
requestRichCandidates: false,
|
||||
versionDependentMode: .v2(.init())
|
||||
versionDependentMode: .v3(.init())
|
||||
)
|
||||
|
||||
/// activate *Zenzai* - Neural Kana-Kanji Conversiion Engine
|
||||
@ -188,7 +213,7 @@ public struct ConvertRequestOptions: Sendable {
|
||||
/// - inferenceLimit: applying inference count limitation. Smaller limit makes conversion faster but quality will be worse. (Default: 10)
|
||||
/// - requestRichCandidates: when this flag is true, the converter spends more time but generate richer N-Best candidates for candidate list view. Usually this option is not recommended for live conversion.
|
||||
/// - versionDependentMode: specify zenz model version and its configuration.
|
||||
public static func on(weight: URL, inferenceLimit: Int = 10, requestRichCandidates: Bool = false, versionDependentMode: ZenzaiVersionDependentMode = .v2(.init())) -> Self {
|
||||
public static func on(weight: URL, inferenceLimit: Int = 10, requestRichCandidates: Bool = false, versionDependentMode: ZenzaiVersionDependentMode = .v3(.init())) -> Self {
|
||||
ZenzaiMode(
|
||||
enabled: true,
|
||||
weightURL: weight,
|
||||
|
@ -62,7 +62,7 @@ import SwiftUtils
|
||||
return []
|
||||
}
|
||||
guard options.zenzaiMode.versionDependentMode.version == .v2 else {
|
||||
print("next character prediction requires zenz-v2 models, not zenz-v1")
|
||||
print("next character prediction requires zenz-v2 models, not zenz-v1 nor zenz-v3 and later")
|
||||
return []
|
||||
}
|
||||
let results = zenz.predictNextCharacter(leftSideContext: leftSideContext, count: count)
|
||||
|
@ -263,30 +263,75 @@ class ZenzContext {
|
||||
conditions.append("辞書:\(userDictionaryPrompt)")
|
||||
}
|
||||
// プロフィールがある場合はこれを条件に追加
|
||||
if case .v2(let mode) = versionDependentConfig, let profile = mode.profile, !profile.isEmpty {
|
||||
let pf = profile.suffix(25)
|
||||
conditions.append("プロフィール:\(profile)")
|
||||
switch versionDependentConfig {
|
||||
case .v1: break
|
||||
case .v2(let mode):
|
||||
if let profile = mode.profile, !profile.isEmpty {
|
||||
let pf = profile.suffix(25)
|
||||
conditions.append("プロフィール:\(pf)")
|
||||
}
|
||||
case .v3(let mode):
|
||||
if let profile = mode.profile, !profile.isEmpty {
|
||||
let pf = profile.suffix(25)
|
||||
conditions.append("\u{EE03}\(pf)")
|
||||
}
|
||||
if let topic = mode.topic, !topic.isEmpty {
|
||||
let tp = topic.suffix(25)
|
||||
conditions.append("\u{EE04}\(tp)")
|
||||
}
|
||||
if let style = mode.style, !style.isEmpty {
|
||||
let st = style.suffix(25)
|
||||
conditions.append("\u{EE05}\(st)")
|
||||
}
|
||||
if let preference = mode.preference, !preference.isEmpty {
|
||||
let pr = preference.suffix(25)
|
||||
conditions.append("\u{EE06}\(pr)")
|
||||
}
|
||||
}
|
||||
// 左文脈を取得
|
||||
// プロフィールがある場合はこれを条件に追加
|
||||
let leftSideContext = if case .v2(let mode) = versionDependentConfig, let leftSideContext = mode.leftSideContext {
|
||||
String(leftSideContext.suffix(40))
|
||||
} else {
|
||||
""
|
||||
let leftSideContext: String = switch versionDependentConfig {
|
||||
case .v1: ""
|
||||
case .v2(let mode):
|
||||
if let leftSideContext = mode.leftSideContext {
|
||||
String(leftSideContext.suffix(40))
|
||||
} else {
|
||||
""
|
||||
}
|
||||
case .v3(let mode):
|
||||
if let leftSideContext = mode.leftSideContext {
|
||||
String(leftSideContext.suffix(40))
|
||||
} else {
|
||||
""
|
||||
}
|
||||
}
|
||||
let inputTag = "\u{EE00}"
|
||||
let outputTag = "\u{EE01}"
|
||||
let contextTag = "\u{EE02}"
|
||||
// プロンプトを作成
|
||||
let prompt: String = if !conditions.isEmpty {
|
||||
// 条件がemptyでない場合は「・」でつなぎ、「発言:」を末尾に追加
|
||||
inputTag + input + contextTag + conditions.joined(separator: "・") + "・発言:\(leftSideContext)" + outputTag
|
||||
} else if !leftSideContext.isEmpty {
|
||||
// 条件がemptyの場合、単にleftSideContextを追加
|
||||
inputTag + input + contextTag + leftSideContext + outputTag
|
||||
} else {
|
||||
// そのまま
|
||||
let prompt: String = switch versionDependentConfig {
|
||||
case .v1:
|
||||
inputTag + input + outputTag
|
||||
case .v2:
|
||||
if !conditions.isEmpty {
|
||||
// 条件がemptyでない場合は「・」でつなぎ、「発言:」を末尾に追加
|
||||
inputTag + input + contextTag + conditions.joined(separator: "・") + "・発言:\(leftSideContext)" + outputTag
|
||||
} else if !leftSideContext.isEmpty {
|
||||
// 条件がemptyの場合、単にleftSideContextを追加
|
||||
inputTag + input + contextTag + leftSideContext + outputTag
|
||||
} else {
|
||||
// そのまま
|
||||
inputTag + input + outputTag
|
||||
}
|
||||
case .v3:
|
||||
if !leftSideContext.isEmpty {
|
||||
// leftSideContextがEmptyでなければ下記の通り処理
|
||||
// contextがinputに前置されるように変更された(KV-cachingの効率化のため)
|
||||
conditions.joined(separator: "") + contextTag + leftSideContext + inputTag + input + outputTag
|
||||
} else {
|
||||
// そのまま
|
||||
conditions.joined(separator: "") + inputTag + input + outputTag
|
||||
}
|
||||
}
|
||||
// Therefore, tokens = prompt_tokens + candidate_tokens is an appropriate operation.
|
||||
let prompt_tokens = self.tokenize(text: prompt, add_bos: true, add_eos: false)
|
||||
|
Reference in New Issue
Block a user