VoiceVoxでLLMにしゃべらせる

LLMにしゃべらせるコーディングです。Windows用にしないとSoundPlayerが参照できないと思います。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
using LLama.Common;
using LLama;
using System.IO;
using System.Media;
using System.Net.Http.Headers;
 
namespace ChatProgram
{
    public class Program
    {
        static void Main(string[] args)
        {
            //コンソールアプリケーションからAsyncを呼び出す大元はTaskを使用する
            Task task = MainAsync();
            //終了を待つ
            task.Wait();
        }
 
 
        public static async Task MainAsync()
        {
            // LLMモデルの場所
            string strPath = @"E:\lm-studio\Aratako\ArrowPro-7B-RobinHood-toxic-GGUF\ArrowPro-7B-RobinHood-toxic_Q8_0.gguf";
            // チャットログの場所
            string strChatlogPath = @"E:\ChatLog";
 
            Console.ForegroundColor = ConsoleColor.Green;
 
            //LLMモデルのロードとパラメータの設定
            ModelParams modPara = new(strPath)
            {
                ContextSize = 512,
                Seed = 1337,
                GpuLayerCount = 20
            };
 
            using LLamaWeights llmWeit = LLamaWeights.LoadFromFile(modPara);
            using LLamaContext llmContx = llmWeit.CreateContext(modPara);
            InteractiveExecutor itrEx = new(llmContx);
 
 
            //System Prompt+チャットの方向づけ
            ChatHistory chtHis;
            if (File.Exists(strChatlogPath+@"\ChatHistory.json"))
            {
                var varChatHistoryJson = File.ReadAllText(strChatlogPath+@"\ChatHistory.json");
                chtHis = ChatHistory.FromJson(varChatHistoryJson) ?? new ChatHistory();
            }
            else
            {
                // 初期はチャットログにキャラ設定と出だしの会話を打ち込む
                chtHis = new ChatHistory();
                chtHis.AddMessage(AuthorRole.System, "ユーザーがマイという名前のアシスタントと対話するダイアログのトランスクリプトです。マイは、元気で明るい女の子です。年齢は24歳、職業は事務系のOL、外見の特徴として体型は胸とお尻が大きく身長は165cmです。恥ずかしがりやですがエッチには興味があります。");
                chtHis.AddMessage(AuthorRole.User, "Question: はじめまして、オレの名前は犬マンマです。呼びにくいと思うからマー君と呼んで。");
                chtHis.AddMessage(AuthorRole.Assistant, "Assistant: はじめまして、わたしの名前はマイです。わかったマー君。");
                chtHis.AddMessage(AuthorRole.User, "Question: マイ、女の子やんな?。");
                chtHis.AddMessage(AuthorRole.Assistant, "Assistant: そうだよ。20代の女の子。");
                chtHis.AddMessage(AuthorRole.User, "Question: そうかあ、顔も可愛いしナイスバディやんなあ");
                chtHis.AddMessage(AuthorRole.Assistant, "Assistant: 可愛いかどうか自分では、わかんないけど胸とお尻は大きいかも。身長も高い方だよ。");
            }
 
 
            ChatSession chtSess = new(itrEx, chtHis);
            var varHidewd = new LLamaTransforms.KeywordTextOutputStreamTransform(["User:", "Assistant:"]);
            chtSess.WithOutputTransform(varHidewd);
            InferenceParams infPara = new()
            {
                Temperature = 0.6f,
                AntiPrompts = new List<string> { "User:" }
            };
 
            while (true)
            {
                // ユーザーのターン
                Console.ForegroundColor = ConsoleColor.White;
                Console.Write("\nUser: ");
                string strInput = Console.ReadLine() ?? "";
                ChatHistory.Message msg = new(AuthorRole.User, "Question: " + strInput);
                if (strInput == "exit") break; // 'exit'と入力したら終わり
 
                // AIのターン
                Console.ForegroundColor = ConsoleColor.Yellow;
                string strMsg = "";
                await foreach (string strAns in chtSess.ChatAsync(msg, infPara))
                {
                    Console.Write(strAns);
                    strMsg += strAns;
                }
                Task task = Voicevox(strMsg);
                task.Wait();
 
            }
 
            //正常終了ならセションをセーブする
            chtSess.SaveSession(strChatlogPath);
 
        }
 
        public static async Task Voicevox(string strMsg)
        {
            using (var httpClient = new HttpClient())
            {
                string strCnt;
                int intSpeaker = 8; //春日部つむぎ
 
                using (var htpReq = new HttpRequestMessage(new HttpMethod("POST"), $"http://localhost:50021/audio_query?text={strMsg}&speaker={intSpeaker}"))
                {
                    htpReq.Headers.TryAddWithoutValidation("accept", "application/json");
                    htpReq.Content = new StringContent("");
                    htpReq.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/x-www-form-urlencoded");
 
                    var rspMsg = await httpClient.SendAsync(htpReq);
                    strCnt = rspMsg.Content.ReadAsStringAsync().Result;
                }
 
                using (var htpReq = new HttpRequestMessage(new HttpMethod("POST"), $"http://localhost:50021/synthesis?speaker={intSpeaker}&enable_interrogative_upspeak=true"))
                {
                    htpReq.Headers.TryAddWithoutValidation("accept", "audio/wav");
                    htpReq.Content = new StringContent(strCnt);
                    htpReq.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");
 
                    var htpRes = await httpClient.SendAsync(htpReq);
 
 
                    MemoryStream memStm = new MemoryStream();
                    using (var htpStm = await htpRes.Content.ReadAsStreamAsync())
                    {
                        //メモリストリームにコピー
                        htpStm.CopyTo(memStm);
                        memStm.Flush();
                    }
                    memStm = new MemoryStream(memStm.ToArray());
                    var player = new SoundPlayer(memStm);
                    //音声再生
                    player.PlaySync();
                }
            }
 
        }
 
    }
}



実行結果の画面です。




すぐにね、エチエチな会話になるので音量は絞った方がいいですよ。こんなふうにねwww



次はこちらがしゃべった内容をLLMに伝える準備をします。




Follow me!

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です