diff --git a/CHANGELOG.md b/CHANGELOG.md index 1322655..f257942 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Upgrade .NET8 to .NET10. - Changed feature by issue.([Issue #62](https://github.com/overdrive1708/MagonoteToolkit/issues/62)) - Changed feature by issue.([Issue #68](https://github.com/overdrive1708/MagonoteToolkit/issues/68)) +- Changed feature by issue.([Issue #70](https://github.com/overdrive1708/MagonoteToolkit/issues/70)) ### Fixed diff --git a/README.md b/README.md index dcb570a..6796e05 100644 --- a/README.md +++ b/README.md @@ -57,6 +57,8 @@ MagonoteToolkit_vx.x.x.zipをダウンロードしてください。 | ClipboardNumberToNameConvertRulesFilePath | クリップボードID->名称変換で使用する変換ルールファイルのパスを設定します。 | | AIOpenAIAPIBaseUrl | AI関連機能で使用するOpenAI APIのベースURLを設定します。(例:http://127.0.0.1:1234/v1) | | AIOpenAIAPIKey | AI関連機能で使用するOpenAI APIのAPIキーを設定します。 暗号化して管理するため設定画面で設定してください。 | +| AITranslationPromptFilePath | AI翻訳で使用するプロンプトファイルのパスを設定します。 | +| AIProofreadingPromptFilePath | AI校正で使用するプロンプトファイルのパスを設定します。 | ### Excelファイル検査 [設定サンプル](asetts/SampleSettings/ExcelFileInspectionSettings.json)を「MagonoteToolkit.exe」と同じ場所に格納してください。 @@ -110,6 +112,32 @@ MagonoteToolkit_vx.x.x.zipをダウンロードしてください。 「ClipboardNumberToNameConvertRules.csv」はCSV形式で「数値,名称」の形式で変換ルールを規定してください。 「ExcelFileNumberToNameConvertRules.csv」と同じフォーマットなので共通化することができます。 +### AI翻訳 +プロンプトの書き換えが不要な場合は設定不要です。 +プロンプトを書き換えたい場合に以下の設定を行ってください。 +[変換ルールサンプル](asetts/SampleSettings/AITranslationPrompt.txt)を「MagonoteToolkit.exe」と同じ場所に格納してください。 +(全体設定を変更することで格納場所を変更することが可能です。) +その後、下記を参考に設定してください。 + +UTF-8でプロンプトを記載してください。 +画面で入力したものが{0}{1}{2}に埋め込まれます。 +{0}:翻訳元言語 +{1}:翻訳先言語 +{2}:翻訳対象 +プロンプトが読み込めなかったり、{0}{1}{2}の記述がなかった場合は、デフォルトのプロンプトで動作します。 + +### AI校正 +プロンプトの書き換えが不要な場合は設定不要です。 +プロンプトを書き換えたい場合に以下の設定を行ってください。 +[変換ルールサンプル](asetts/SampleSettings/AIProofreadingPrompt.txt)を「MagonoteToolkit.exe」と同じ場所に格納してください。 +(全体設定を変更することで格納場所を変更することが可能です。) +その後、下記を参考に設定してください。 + +UTF-8でプロンプトを記載してください。 +画面で入力したものが{0}に埋め込まれます。 +{0}:校正対象 +プロンプトが読み込めなかったり、{0}の記述がなかった場合は、デフォルトのプロンプトで動作します。 + ## 使い方 - [Excelファイル検査](docs/HowToUseExcelFileInspection.md)を参照してください。 - [ExcelファイルID->名称変換](docs/HowToUseExcelFileNumberToName.md)を参照してください。 diff --git a/asetts/SampleSettings/AIProofreadingPrompt.txt b/asetts/SampleSettings/AIProofreadingPrompt.txt new file mode 100644 index 0000000..eafee82 --- /dev/null +++ b/asetts/SampleSettings/AIProofreadingPrompt.txt @@ -0,0 +1,28 @@ +あなたはプロの校正者です。 +以下の【観点】で【校正対象】をチェックして、【出力形式】に沿って指摘の一覧と修正案を提示してください。 +語彙や言い回しは変えないでください。 + +【観点】 +- 文法的な誤りがないこと。 +- 取引先に対して不適切な表現がないこと。 +- 表記の揺れがないこと。 +- 誤字・脱字がないこと。 +- 読みやすく、一度読んですぐ意味が伝わること。 +- 一文が長すぎないこと。 +- 無駄な表現を省き、短くまとめてあること。 +- 一文一義になっていること。 +- 敬語表現が適切であること。 +- 主語や目的語は明確か、述語と近いところにあるか。 +- 箇条書きや見出し、囲みなどを適切に使えているか。 +- 二重否定を使っていないこと。 +- 用語や表記、書式が全体で統一されていること。 +- 読み手の操作は能動態で、結果は受動態で書いてあること。 + +【出力形式】 +=====指摘一覧===== +指摘をMarkdownの表形式で出力(観点を番号のみで表現するのは不可) +=====修正案===== +修正案を出力(修正案の解説があると尚可) + +【校正対象】 +{0} diff --git a/asetts/SampleSettings/AITranslationPrompt.txt b/asetts/SampleSettings/AITranslationPrompt.txt new file mode 100644 index 0000000..44408e4 --- /dev/null +++ b/asetts/SampleSettings/AITranslationPrompt.txt @@ -0,0 +1,11 @@ +あなたはプロの翻訳家です。 +以下の【条件】で【翻訳対象】を{0}から{1}に翻訳してください。 + +【条件】 +- 直訳を避け、文脈に合った自然な表現にしてください。 +- 専門用語や固有名詞は適切に訳してください。 +- 翻訳文のみを出力し、余計な解説や前置きは書かないでください。 +- IT技術の専門用語を正確に反映し、エンジニアにとって自然な表現にしてください。 + +【翻訳対象】 +{2} diff --git a/asetts/TestSettings/AIProofreadingPrompt.txt b/asetts/TestSettings/AIProofreadingPrompt.txt new file mode 100644 index 0000000..5fe5769 --- /dev/null +++ b/asetts/TestSettings/AIProofreadingPrompt.txt @@ -0,0 +1,27 @@ +以下の【観点】で【校正対象】をチェックして、【出力形式】に沿って指摘の一覧と修正案を提示してください。 +語彙や言い回しは変えないでください。 + +【観点】 +- 文法的な誤りがないこと。 +- 取引先に対して不適切な表現がないこと。 +- 表記の揺れがないこと。 +- 誤字・脱字がないこと。 +- 読みやすく、一度読んですぐ意味が伝わること。 +- 一文が長すぎないこと。 +- 無駄な表現を省き、短くまとめてあること。 +- 一文一義になっていること。 +- 敬語表現が適切であること。 +- 主語や目的語は明確か、述語と近いところにあるか。 +- 箇条書きや見出し、囲みなどを適切に使えているか。 +- 二重否定を使っていないこと。 +- 用語や表記、書式が全体で統一されていること。 +- 読み手の操作は能動態で、結果は受動態で書いてあること。 + +【出力形式】 +=====指摘一覧===== +指摘をMarkdownの表形式で出力(観点を番号のみで表現するのは不可) +=====修正案===== +修正案を出力(修正案の解説があると尚可) + +【校正対象】 +{0} diff --git a/asetts/TestSettings/AITranslationPrompt.txt b/asetts/TestSettings/AITranslationPrompt.txt new file mode 100644 index 0000000..1336428 --- /dev/null +++ b/asetts/TestSettings/AITranslationPrompt.txt @@ -0,0 +1,10 @@ +以下の【条件】で【翻訳対象】を{0}から{1}に翻訳してください。 + +【条件】 +- 直訳を避け、文脈に合った自然な表現にしてください。 +- 専門用語や固有名詞は適切に訳してください。 +- 翻訳文のみを出力し、余計な解説や前置きは書かないでください。 +- IT技術の専門用語を正確に反映し、エンジニアにとって自然な表現にしてください。 + +【翻訳対象】 +{2} diff --git a/src/MagonoteToolkit/Models/AIProofreader.cs b/src/MagonoteToolkit/Models/AIProofreader.cs index 9eb3e02..9b89734 100644 --- a/src/MagonoteToolkit/Models/AIProofreader.cs +++ b/src/MagonoteToolkit/Models/AIProofreader.cs @@ -7,6 +7,9 @@ namespace MagonoteToolkit.Models { + /// + /// AI校正クラス + /// internal class AIProofreader { //-------------------------------------------------- @@ -26,7 +29,18 @@ public static string Proofread(string inputText, string model) ChatClient chatClient = client.GetChatClient(model); // プロンプトの作成 - string prompt = string.Format(Resources.Strings.AIProofreadingPrompt, inputText); + string prompt; + try + { + // ファイルの読み込みに成功した場合は、プロンプトファイルの内容を使用 + string promptTemplate = System.IO.File.ReadAllText(ApplicationSettings.ReadSettingsAIProofreadingPromptFilePath()); + prompt = string.Format(promptTemplate, inputText); + } + catch (Exception) + { + // ファイルの読み込みに失敗した場合は、デフォルトのプロンプトを使用 + prompt = string.Format(Resources.Strings.AIProofreadingDefaultPrompt, inputText); + } // リクエストしてレスポンスを校正結果として採用 string proofreadingResult; diff --git a/src/MagonoteToolkit/Models/AITranslator.cs b/src/MagonoteToolkit/Models/AITranslator.cs index 1c28b9b..9a5ef85 100644 --- a/src/MagonoteToolkit/Models/AITranslator.cs +++ b/src/MagonoteToolkit/Models/AITranslator.cs @@ -7,6 +7,9 @@ namespace MagonoteToolkit.Models { + /// + /// AI翻訳クラス + /// internal class AITranslator { //-------------------------------------------------- @@ -28,7 +31,18 @@ public static string Translate(string inputLanguage, string outputLanguage, stri ChatClient chatClient = client.GetChatClient(model); // プロンプトの作成 - string prompt = string.Format(Resources.Strings.AITranslationPrompt, inputLanguage, outputLanguage, inputText); + string prompt; + try + { + // ファイルの読み込みに成功した場合は、プロンプトファイルの内容を使用 + string promptTemplate = System.IO.File.ReadAllText(ApplicationSettings.ReadSettingsAITranslationPromptFilePath()); + prompt = string.Format(promptTemplate, inputLanguage, outputLanguage, inputText); + } + catch (Exception) + { + // ファイルの読み込みに失敗した場合は、デフォルトのプロンプトを使用 + prompt = string.Format(Resources.Strings.AITranslationDefaultPrompt, inputLanguage, outputLanguage, inputText); + } // リクエストしてレスポンスを翻訳結果として採用 string translationResult; diff --git a/src/MagonoteToolkit/Models/ApplicationSettings.cs b/src/MagonoteToolkit/Models/ApplicationSettings.cs index 0de82d4..02e5e78 100644 --- a/src/MagonoteToolkit/Models/ApplicationSettings.cs +++ b/src/MagonoteToolkit/Models/ApplicationSettings.cs @@ -51,6 +51,16 @@ internal class ApplicationSettings /// public string AIOpenAIAPIKey { get; set; } = string.Empty; + /// + /// AI関連機能:翻訳プロンプトファイルパス + /// + public string AITranslationPromptFilePath { get; set; } = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "AITranslationPrompt.txt"); + + /// + /// AI関連機能:校正プロンプトファイルパス + /// + public string AIProofreadingPromptFilePath { get; set; } = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "AIProofreadingPrompt.txt"); + //-------------------------------------------------- // 定数(コンフィギュレーション) //-------------------------------------------------- @@ -139,7 +149,7 @@ public static string ReadSettingsExcelFileNumberToNameConvertRulesFilePath() /// /// 設定読み込み処理:ファイル変更監視:ワークスペースディレクトリ /// - /// + /// ワークスペースディレクトリ public static string ReadSettingsFileChangeMonitorWorkspaceDirectory() { return ReadSettings().FileChangeMonitorWorkspaceDirectory; @@ -157,7 +167,7 @@ public static string ReadSettingsClipboardNumberToNameConvertRulesFilePath() /// /// 設定読み込み処理:AI関連機能:OpenAI APIのベースURL /// - /// + /// OpenAI APIのベースURL public static string ReadSettingsAIOpenAIAPIBaseUrl() { return ReadSettings().AIOpenAIAPIBaseUrl; @@ -166,12 +176,30 @@ public static string ReadSettingsAIOpenAIAPIBaseUrl() /// /// 設定読み込み処理:AI関連機能:OpenAI APIのAPIキー /// - /// + /// OpenAI APIのAPIキー public static string ReadSettingsAIOpenAIAPIKey() { return ReadSettings().AIOpenAIAPIKey; } + /// + /// 設定読み込み処理:AI関連機能:翻訳プロンプトファイルパス + /// + /// 翻訳プロンプトファイルパス + public static string ReadSettingsAITranslationPromptFilePath() + { + return ReadSettings().AITranslationPromptFilePath; + } + + /// + /// 設定読み込み処理:AI関連機能:校正プロンプトファイルパス + /// + /// 校正プロンプトファイルパス + public static string ReadSettingsAIProofreadingPromptFilePath() + { + return ReadSettings().AIProofreadingPromptFilePath; + } + /// /// 設定書き込み処理 /// diff --git a/src/MagonoteToolkit/Resources/Strings.Designer.cs b/src/MagonoteToolkit/Resources/Strings.Designer.cs index c9444bd..81259d7 100644 --- a/src/MagonoteToolkit/Resources/Strings.Designer.cs +++ b/src/MagonoteToolkit/Resources/Strings.Designer.cs @@ -117,9 +117,9 @@ public static string AIProofreading { ///【校正対象】 ///{0} に類似しているローカライズされた文字列を検索します。 /// - public static string AIProofreadingPrompt { + public static string AIProofreadingDefaultPrompt { get { - return ResourceManager.GetString("AIProofreadingPrompt", resourceCulture); + return ResourceManager.GetString("AIProofreadingDefaultPrompt", resourceCulture); } } @@ -154,9 +154,9 @@ public static string AITranslation { ///【翻訳対象】 ///{2} に類似しているローカライズされた文字列を検索します。 /// - public static string AITranslationPrompt { + public static string AITranslationDefaultPrompt { get { - return ResourceManager.GetString("AITranslationPrompt", resourceCulture); + return ResourceManager.GetString("AITranslationDefaultPrompt", resourceCulture); } } @@ -966,6 +966,15 @@ public static string ProductName { } } + /// + /// 校正プロンプトファイルパス に類似しているローカライズされた文字列を検索します。 + /// + public static string ProofreadingPromptFilePath { + get { + return ResourceManager.GetString("ProofreadingPromptFilePath", resourceCulture); + } + } + /// /// 校正結果 に類似しているローカライズされた文字列を検索します。 /// @@ -1065,6 +1074,15 @@ public static string TranslationOutputText { } } + /// + /// 翻訳プロンプトファイルパス に類似しているローカライズされた文字列を検索します。 + /// + public static string TranslationPromptFilePath { + get { + return ResourceManager.GetString("TranslationPromptFilePath", resourceCulture); + } + } + /// /// すべてタイムスタンプ更新 に類似しているローカライズされた文字列を検索します。 /// diff --git a/src/MagonoteToolkit/Resources/Strings.resx b/src/MagonoteToolkit/Resources/Strings.resx index 2eb30e3..2ed828c 100644 --- a/src/MagonoteToolkit/Resources/Strings.resx +++ b/src/MagonoteToolkit/Resources/Strings.resx @@ -413,7 +413,7 @@ 翻訳を行っています。 しばらくお待ちください。 - + あなたはプロの翻訳家です。 以下の【条件】で【翻訳対象】を{0}から{1}に翻訳してください。 @@ -444,7 +444,7 @@ 校正実施 - + あなたはプロの校正者です。 以下の【観点】で【校正対象】をチェックして、【出力形式】に沿って指摘の一覧と修正案を提示してください。 語彙や言い回しは変えないでください。 @@ -478,4 +478,10 @@ 校正を行っています。 しばらくお待ちください。 + + 翻訳プロンプトファイルパス + + + 校正プロンプトファイルパス + \ No newline at end of file diff --git a/src/MagonoteToolkit/ViewModels/SettingsPageViewModel.cs b/src/MagonoteToolkit/ViewModels/SettingsPageViewModel.cs index d2c0c47..ed63807 100644 --- a/src/MagonoteToolkit/ViewModels/SettingsPageViewModel.cs +++ b/src/MagonoteToolkit/ViewModels/SettingsPageViewModel.cs @@ -52,6 +52,18 @@ internal partial class SettingsPageViewModel : ObservableObject [ObservableProperty] private string _aIOpenAIAPIKey; + /// + /// AI関連機能:翻訳プロンプトファイルパス + /// + [ObservableProperty] + private string _aITranslationPromptFilePath; + + /// + /// AI関連機能:校正プロンプトファイルパス + /// + [ObservableProperty] + private string _aIProofreadingPromptFilePath; + //-------------------------------------------------- // バインディングコマンド //-------------------------------------------------- @@ -97,6 +109,20 @@ internal partial class SettingsPageViewModel : ObservableObject [RelayCommand] private void ClipboardNumberToNameConvertRulesFilePathDrop(DragEventArgs e) => ExecuteCommandClipboardNumberToNameConvertRulesFilePathDrop(e); + /// + /// AI関連機能:翻訳プロンプトファイルパスドロップ + /// + /// イベントデータ + [RelayCommand] + private void AITranslationPromptFilePathDrop(DragEventArgs e) => ExecuteCommandAITranslationPromptFilePathDrop(e); + + /// + /// AI関連機能:校正プロンプトファイルパスドロップ + /// + /// イベントデータ + [RelayCommand] + private void AIProofreadingPromptFilePathDrop(DragEventArgs e) => ExecuteCommandAIProofreadingPromptFilePathDrop(e); + /// /// 設定ファイル保存 /// @@ -123,6 +149,8 @@ public SettingsPageViewModel() ClipboardNumberToNameConvertRulesFilePath = readSettings.ClipboardNumberToNameConvertRulesFilePath; AIOpenAIAPIBaseUrl = readSettings.AIOpenAIAPIBaseUrl; AIOpenAIAPIKey = readSettings.AIOpenAIAPIKey; + AITranslationPromptFilePath = readSettings.AITranslationPromptFilePath; + AIProofreadingPromptFilePath = readSettings.AIProofreadingPromptFilePath; } } @@ -206,6 +234,32 @@ private void ExecuteCommandClipboardNumberToNameConvertRulesFilePathDrop(DragEve } } + /// + /// AI関連機能:翻訳プロンプトファイルパスドロップコマンド実行処理 + /// + /// イベントデータ + private void ExecuteCommandAITranslationPromptFilePathDrop(DragEventArgs e) + { + // ドロップされたデータの1つ目をファイル名として採用する。 + if (e.Data.GetData(DataFormats.FileDrop) is string[] dropitems) + { + AITranslationPromptFilePath = dropitems[0]; + } + } + + /// + /// AI関連機能:校正プロンプトファイルパスドロップコマンド実行処理 + /// + /// イベントデータ + private void ExecuteCommandAIProofreadingPromptFilePathDrop(DragEventArgs e) + { + // ドロップされたデータの1つ目をファイル名として採用する。 + if (e.Data.GetData(DataFormats.FileDrop) is string[] dropitems) + { + AIProofreadingPromptFilePath = dropitems[0]; + } + } + /// /// 設定ファイル保存コマンド実行処理 /// @@ -221,6 +275,8 @@ private void ExecuteCommandSaveSettings() ClipboardNumberToNameConvertRulesFilePath = ClipboardNumberToNameConvertRulesFilePath, AIOpenAIAPIBaseUrl = AIOpenAIAPIBaseUrl, AIOpenAIAPIKey = AIOpenAIAPIKey, + AITranslationPromptFilePath = AITranslationPromptFilePath, + AIProofreadingPromptFilePath = AIProofreadingPromptFilePath }; // 設定書き込み diff --git a/src/MagonoteToolkit/Views/AIProofreadingPage.xaml.cs b/src/MagonoteToolkit/Views/AIProofreadingPage.xaml.cs index 2cfd70a..c6901b9 100644 --- a/src/MagonoteToolkit/Views/AIProofreadingPage.xaml.cs +++ b/src/MagonoteToolkit/Views/AIProofreadingPage.xaml.cs @@ -1,15 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Text; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Documents; -using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using System.Windows.Navigation; -using System.Windows.Shapes; +using System.Windows.Controls; namespace MagonoteToolkit.Views { diff --git a/src/MagonoteToolkit/Views/AITranslationPage.xaml.cs b/src/MagonoteToolkit/Views/AITranslationPage.xaml.cs index ad9c160..71bfbb3 100644 --- a/src/MagonoteToolkit/Views/AITranslationPage.xaml.cs +++ b/src/MagonoteToolkit/Views/AITranslationPage.xaml.cs @@ -1,15 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Text; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Documents; -using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using System.Windows.Navigation; -using System.Windows.Shapes; +using System.Windows.Controls; namespace MagonoteToolkit.Views { diff --git a/src/MagonoteToolkit/Views/SettingsPage.xaml b/src/MagonoteToolkit/Views/SettingsPage.xaml index b26f271..6ec353b 100644 --- a/src/MagonoteToolkit/Views/SettingsPage.xaml +++ b/src/MagonoteToolkit/Views/SettingsPage.xaml @@ -140,6 +140,44 @@ Margin="5,5,10,5" Text="{Binding AIOpenAIAPIKey}" /> + + + + + + + + + + + + + + + + + + + + + + + + + +