fix: improve word replacement precision and prompt handling - Enhanced word replacement logic, added examples, fixed prompt state management

This commit is contained in:
Beingpax 2025-02-24 18:58:16 +05:45
parent 763967bc35
commit 3aec3b369b
5 changed files with 46 additions and 20 deletions

View File

@ -29,6 +29,9 @@ actor WhisperContext {
func fullTranscribe(samples: [Float]) {
guard let context = context else { return }
// Capture prompt state at start
let currentPrompt = prompt
// Leave 2 processors free (i.e. the high-efficiency cores).
let maxThreads = max(1, min(8, cpuCount() - 2))
print("Selecting \(maxThreads) threads")
@ -49,12 +52,12 @@ actor WhisperContext {
}
// Only use prompt for English language
if selectedLanguage == "en" && prompt != nil {
promptCString = Array(prompt!.utf8CString)
if selectedLanguage == "en" && currentPrompt != nil {
promptCString = Array(currentPrompt!.utf8CString)
params.initial_prompt = promptCString?.withUnsafeBufferPointer { ptr in
ptr.baseAddress
}
print("Using prompt for English transcription: \(prompt!)")
print("Using prompt for English transcription: \(currentPrompt!)")
} else {
promptCString = nil
params.initial_prompt = nil

View File

@ -69,7 +69,8 @@ enum AIPrompts {
IMPORTANT: Only apply replacements if specific words are provided
- Skip any replacement activity if no replacement options are available
- When replacements are provided:
- Replace specified words or phrases exactly as provided
- Replace ONLY exact matches of the specified words/phrases
- Do NOT replace partial matches or similar words
- Apply replacements before other enhancements
- Maintain case sensitivity when applying replacements
- Preserve the flow and readability of the text

View File

@ -2,6 +2,7 @@ import SwiftUI
struct DictionarySettingsView: View {
@State private var selectedSection: DictionarySection = .spellings
@EnvironmentObject private var whisperState: WhisperState
enum DictionarySection: String, CaseIterable {
case spellings = "Correct Spellings"
@ -93,7 +94,7 @@ struct DictionarySettingsView: View {
VStack(alignment: .leading, spacing: 20) {
switch selectedSection {
case .spellings:
DictionaryView()
DictionaryView(whisperState: whisperState)
.background(Color(.windowBackgroundColor).opacity(0.4))
.cornerRadius(10)
case .replacements:

View File

@ -33,9 +33,10 @@ struct DictionaryItem: Identifiable, Hashable, Codable {
class DictionaryManager: ObservableObject {
@Published var items: [DictionaryItem] = []
private let saveKey = "CustomDictionaryItems"
var onDictionaryChanged: (([String]) -> Void)?
@Published var whisperState: WhisperState
init() {
init(whisperState: WhisperState) {
self.whisperState = whisperState
loadItems()
}
@ -53,22 +54,20 @@ class DictionaryManager: ObservableObject {
saveItems()
}
}
notifyDictionaryChanged()
Task { @MainActor in
await whisperState.saveDictionaryItems(items)
}
}
private func saveItems() {
if let encoded = try? JSONEncoder().encode(items) {
UserDefaults.standard.set(encoded, forKey: saveKey)
notifyDictionaryChanged()
Task { @MainActor in
await whisperState.saveDictionaryItems(items)
}
}
}
private func notifyDictionaryChanged() {
// Only include enabled words in the dictionary
let enabledWords = items.filter { $0.isEnabled }.map { $0.word }
onDictionaryChanged?(enabledWords)
}
func addWord(_ word: String) {
let normalizedWord = word.trimmingCharacters(in: .whitespacesAndNewlines)
guard !items.contains(where: { $0.word.lowercased() == normalizedWord.lowercased() }) else {
@ -98,12 +97,16 @@ class DictionaryManager: ObservableObject {
}
struct DictionaryView: View {
@StateObject private var dictionaryManager = DictionaryManager()
@StateObject private var dictionaryManager: DictionaryManager
@EnvironmentObject private var whisperState: WhisperState
@State private var newWord = ""
@State private var showAlert = false
@State private var alertMessage = ""
init(whisperState: WhisperState) {
_dictionaryManager = StateObject(wrappedValue: DictionaryManager(whisperState: whisperState))
}
var body: some View {
VStack(alignment: .leading, spacing: 20) {
// Information Section
@ -177,10 +180,6 @@ struct DictionaryView: View {
Text(alertMessage)
}
.onAppear {
dictionaryManager.onDictionaryChanged = { words in
whisperState.updateDictionaryWords(words)
}
// Initial update
whisperState.updateDictionaryWords(dictionaryManager.allWords)
}
}

View File

@ -89,6 +89,7 @@ class WhisperState: NSObject, ObservableObject, AVAudioRecorderDelegate {
private let recorder = Recorder()
private var recordedFile: URL? = nil
private var dictionaryWords: [String] = []
private let saveKey = "CustomDictionaryItems"
let modelContext: ModelContext
@ -150,6 +151,7 @@ class WhisperState: NSObject, ObservableObject, AVAudioRecorderDelegate {
createModelsDirectoryIfNeeded()
createRecordingsDirectoryIfNeeded()
loadAvailableModels()
loadDictionaryItems()
// Load saved model
if let savedModelName = UserDefaults.standard.string(forKey: "CurrentModel"),
@ -193,6 +195,17 @@ class WhisperState: NSObject, ObservableObject, AVAudioRecorderDelegate {
}
}
private func loadDictionaryItems() {
guard let data = UserDefaults.standard.data(forKey: saveKey) else { return }
// Try loading with new format first
if let savedItems = try? JSONDecoder().decode([DictionaryItem].self, from: data) {
let enabledWords = savedItems.filter { $0.isEnabled }.map { $0.word }
dictionaryWords = enabledWords
updateTranscriptionPrompt()
}
}
// Modify loadModel to be private and async
private func loadModel(_ model: WhisperModel) async throws {
guard whisperContext == nil else { return } // Model already loaded
@ -828,6 +841,15 @@ class WhisperState: NSObject, ObservableObject, AVAudioRecorderDelegate {
return permanentURL
}
func saveDictionaryItems(_ items: [DictionaryItem]) async {
if let encoded = try? JSONEncoder().encode(items) {
UserDefaults.standard.set(encoded, forKey: saveKey)
let enabledWords = items.filter { $0.isEnabled }.map { $0.word }
dictionaryWords = enabledWords
updateTranscriptionPrompt()
}
}
}
struct WhisperModel: Identifiable {