Aida-chiyo-Talk-app

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

commit f94ffb47214afb0a837e6044bd4518ba1492ae43
parent 6d32586a0c88aa43cbd94a3eb4a4327cfa71d86b
Author: Minerva-Juppiter <ryouturn@gmail.com>
Date:   Mon, 14 Aug 2023 09:18:12 +0900


Diffstat:
AA3RTService.cs | 77+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
MAida chiyo Talk app.csproj | 16++++++++++++++++
MMainController.cs | 67+++++++++++--------------------------------------------------------
AOutput.cs | 16++++++++++++++++
APython.py | 2++
APython.spec | 50++++++++++++++++++++++++++++++++++++++++++++++++++
ARinnaAIPython.cmd | 6++++++
ARinnaAIPython.exe | 0
DRinnaAIPython.py | 45---------------------------------------------
MTalkAI.cs | 76+++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------
AVoiceVox.cs | 66++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
11 files changed, 301 insertions(+), 120 deletions(-)

diff --git a/A3RTService.cs b/A3RTService.cs @@ -0,0 +1,77 @@ +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Aida_chiyo_Talk_app +{ + internal class A3RTService + { + private string APIKEY; + + /// <summary> + /// コンストラクタ + /// </summary> + internal A3RTService() + { + // App.configから設定を取得 + APIKEY = "DZZqpz3HVnJL4LGk57u8ZfmgfAIjrB3B"; + + // 必要な情報が取得できない場合はエラー + if (string.IsNullOrEmpty(APIKEY)) + { + throw new ArgumentException("A3RT_APIKEY is empty"); + } + } + + /// <summary> + /// 対話APIを実行し、応答文を返す + /// </summary> + /// <param name="message">発言</param> + /// <returns>応答</returns> + internal async Task<string> MakeRequestAsync(string message) + { + HttpClient client = new HttpClient(); + + // リクエストURL + string uri = $"https://api.a3rt.recruit-tech.co.jp/talk/v1/smalltalk"; + + // リクエスト本文 + var content = new FormUrlEncodedContent( + new Dictionary<string, string> + { + { "apikey", APIKEY }, + { "query", message } + }); + + // APIを実行し、レスポンス本文を取得 + HttpResponseMessage response = await client.PostAsync(uri, content); + JObject rss = await response.Content.ReadAsAsync<JObject>(); + + // HTTPステータスが異常であればエラー + if (!response.IsSuccessStatusCode) + { + throw new ApplicationException( + $"API failed. code={response.StatusCode}"); + } + + // 何も返さなかった場合は、何か埋めて返しておく + if ((int)rss["status"] == 2000) + { + return "..."; + } + // APIがエラーを出していればエラー + else if ((int)rss["status"] != 0) + { + Console.WriteLine(rss); + throw new ApplicationException( + $"API failed. "); + } + + // レスポンス本文から応答文のみを抽出して返す + return (string)rss["results"][0]["reply"]; + } + } +} diff --git a/Aida chiyo Talk app.csproj b/Aida chiyo Talk app.csproj @@ -12,6 +12,22 @@ <PackageReference Include="IronPython" Version="3.4.1" /> <PackageReference Include="Microsoft.AspNet.WebApi.Client" Version="5.2.9" /> <PackageReference Include="Microsoft.ML" Version="2.0.1" /> + <PackageReference Include="System.Windows.Extensions" Version="7.0.0" /> + </ItemGroup> + + <ItemGroup> + <None Update="Python.py"> + <CopyToOutputDirectory>Always</CopyToOutputDirectory> + </None> + <None Update="RinnaAIPython.cmd"> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </None> + <None Update="RinnaAIPython.exe"> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </None> + <None Update="RinnaAIPython.py"> + <CopyToOutputDirectory>Always</CopyToOutputDirectory> + </None> </ItemGroup> </Project> diff --git a/MainController.cs b/MainController.cs @@ -25,67 +25,22 @@ namespace Aida_chiyo_Talk_app public void Talkcon() { Inputs inputs = new Inputs(); - string input = inputs.InputConsole(); + //string input = inputs.InputConsole(); - TalkEngine talkEngine = new TalkEngine(); - string answer = talkEngine.CallTalkAPI(input).ToString(); - - Console.WriteLine(answer); - } - - public void PythonTest() - { - Inputs inputs = new Inputs(); - string input = inputs.InputConsole(); - - var script = @" - def get_x(): - import torch - return 1"; + var output = new Output(); - var engine = Python.CreateEngine(); - dynamic scope = engine.CreateScope(); - engine.Execute(script, scope); + TalkAI talkAI = new TalkAI(); + talkAI.TalkAIcon(); - var x = scope.get_x(); - Console.WriteLine("x is {0}", x); + talkAI.A3RTcon(); /* - ScriptRuntime py = Python.CreateRuntime(); - dynamic script = py.UseFile("Python.py"); - - string importPy = string.Empty; - try - { - importPy = script.ToString(); - }catch (Exception ex) - { - Console.WriteLine(ex.ToString()); - } - if (importPy == "import is true") - { - Console.WriteLine("import was ended"); - } - else - { - Console.WriteLine("import was not ended"); - Console.WriteLine(importPy); - } - - string loadmodel = string.Empty; - try - { - loadmodel = script.ToString(); - }catch(Exception ex) - { - Console.WriteLine(ex.ToString()); - } - if(loadmodel == "importModel_is_true") - { - Console.WriteLine("Model was loaded"); - } - else + TalkEngine talkEngine = new TalkEngine(); + string answer = talkEngine.CallTalkAPI(input).ToString(); + while (input != "exit") { - Console.WriteLine("model was not loaded"); + answer = talkEngine.CallTalkAPI(input).ToString(); + output.OutputConsole(answer); + input = inputs.InputConsole(); } */ } diff --git a/Output.cs b/Output.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Aida_chiyo_Talk_app +{ + internal class Output + { + public void OutputConsole(string output) + { + Console.WriteLine(output); + } + } +} diff --git a/Python.py b/Python.py @@ -0,0 +1 @@ +print("Python was called")+ \ No newline at end of file diff --git a/Python.spec b/Python.spec @@ -0,0 +1,50 @@ +# -*- mode: python ; coding: utf-8 -*- + + +block_cipher = None + + +a = Analysis( + ['Python.py'], + pathex=[], + binaries=[], + datas=[], + hiddenimports=[], + hookspath=[], + hooksconfig={}, + runtime_hooks=[], + excludes=[], + win_no_prefer_redirects=False, + win_private_assemblies=False, + cipher=block_cipher, + noarchive=False, +) +pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher) + +exe = EXE( + pyz, + a.scripts, + [], + exclude_binaries=True, + name='Python', + debug=False, + bootloader_ignore_signals=False, + strip=False, + upx=True, + console=True, + disable_windowed_traceback=False, + argv_emulation=False, + target_arch=None, + codesign_identity=None, + entitlements_file=None, +) +coll = COLLECT( + exe, + a.binaries, + a.zipfiles, + a.datas, + strip=False, + upx=True, + upx_exclude=[], + name='Python', +) diff --git a/RinnaAIPython.cmd b/RinnaAIPython.cmd @@ -0,0 +1,6 @@ + +@echo off +rem This script was created by Nuitka to execute 'RinnaAIPython.exe' with Python DLL being found. +set PATH=c:\users\tetsu\appdata\local\programs\python\PYTHON~2;%PATH% +set PYTHONHOME=C:\Users\tetsu\AppData\Local\Programs\Python\Python310 +"%~dp0.\RinnaAIPython.exe" %* diff --git a/RinnaAIPython.exe b/RinnaAIPython.exe Binary files differ. diff --git a/RinnaAIPython.py b/RinnaAIPython.py @@ -1,44 +0,0 @@ -# coding: shift-jis -import torch -from transformers import AutoTokenizer, AutoModelForCausalLM - -print("we are loading model") - -# モデルのダウンロード。 -tokenizer = AutoTokenizer.from_pretrained("rinna/japanese-gpt-neox-3.6b-instruction-sft", use_fast=False) -model = AutoModelForCausalLM.from_pretrained("rinna/japanese-gpt-neox-3.6b-instruction-sft") - -# GPUが使える状態なら使用する。 -device = torch.device("cuda" if torch.cuda.is_available() else "cpu") -model = model.to(device) - -print("model was loaded") - -# 対話の開始 -#print("会話を始めましょう!何か質問して下さい。") -while True: - #user_input = input("ユーザー: ") - user_input = input() - - # ユーザーの入力をプロンプトに追加 - prompt = f"<NL>ユーザー: {user_input}<NL>システム: " - - # プロンプトをrinnaに与えて、回答を生成する。 - token_ids = tokenizer.encode(prompt, add_special_tokens=False, return_tensors="pt").to(device) - - with torch.no_grad(): - output_ids = model.generate( - token_ids, - do_sample=True, - max_length=128, - temperature=0.7, - pad_token_id=tokenizer.pad_token_id, - bos_token_id=tokenizer.bos_token_id, - eos_token_id=tokenizer.eos_token_id - ) - - # rinnaからの回答を取得する。 - output = tokenizer.decode(output_ids.tolist()[0][token_ids.size(1):]) - output = output.replace("<NL>", "\n") - #print("システム:", output) - print(output)- \ No newline at end of file diff --git a/TalkAI.cs b/TalkAI.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; +using System.Reflection; using System.Text; using System.Threading.Tasks; @@ -10,21 +11,26 @@ namespace Aida_chiyo_Talk_app { internal class TalkAI { - public String FileName { get; set; } - public String WorkingDirectory { get; set; } - public String Arguments { get; set; } - public String InputString { get; set; } - public String StandardOutput { get; set; } + public String FileName = string.Empty; + //public String Arguments = @"C:\Users\tetsu\source\repos\Aida chiyo Talk app\RinnaAIPython.dist\RinnaAIPython.exe"; + public string Arguments = @"C:\Users\tetsu\source\repos\Aida chiyo Talk app\dist\Python\Python.exe"; + public String InputString = string.Empty; public int ExitCode { get; set; } - private StringBuilder standardOutputStringBuilder = new StringBuilder(); - public string TalkAIcon() + public void TalkAIcon() { + string answer; + //Assembly Assembly = Assembly.GetEntryAssembly(); + //string WorkingDirectory = Assembly.Location; + //where is python + Output output = new Output(); + Inputs inputs = new Inputs(); + FileName = @"RinnaAIPython.cmd"; + ProcessStartInfo processStartInfo = new ProcessStartInfo(); processStartInfo.FileName = FileName; - processStartInfo.WorkingDirectory = WorkingDirectory; - processStartInfo.Arguments = Arguments; - + //processStartInfo.WorkingDirectory = WorkingDirectory; + //processStartInfo.Arguments = Arguments; processStartInfo.CreateNoWindow = true; processStartInfo.UseShellExecute = false; processStartInfo.RedirectStandardInput = true; @@ -33,24 +39,42 @@ namespace Aida_chiyo_Talk_app Process process = new System.Diagnostics.Process(); process.StartInfo = processStartInfo; - process.OutputDataReceived += Process_OutputDataReceived; - process.ErrorDataReceived += Process_ErrorDataReceived; process.Start(); + output.OutputConsole("calling Python"); - using(StreamWriter streamWriter = process.StandardInput) + + Console.WriteLine(process.StandardOutput.ReadLine()); + answer = process.StandardOutput.ReadLine(); + while (answer != "model was loaded") { - streamWriter.Write(InputString); + if(answer != null) + { + output.OutputConsole(answer); + } } + + output.OutputConsole("model was loaded"); - process.BeginOutputReadLine(); - process.BeginErrorReadLine(); + InputString = inputs.InputConsole(); - process.WaitForExit(); - this.ExitCode = process.ExitCode; - this.StandardOutput = standardOutputStringBuilder.ToString(); + VoiceVox voiceVox = new VoiceVox(); + while (InputString != "exit") + { + process.StandardInput.WriteLine(InputString); + answer = process.StandardOutput.ReadLine(); + while(answer == null) + { + } + answer = answer.Replace("</s>", ""); + output.OutputConsole(answer); + voiceVox.VoiceVoxCon(answer); + InputString = inputs.InputConsole(); + } + this.ExitCode = process.ExitCode; + Console.WriteLine(ExitCode.ToString()); } private void Process_OutputDataReceived(object sender, DataReceivedEventArgs e) @@ -62,5 +86,19 @@ namespace Aida_chiyo_Talk_app { throw new NotImplementedException(); } + + + public void A3RTcon() + { + A3RTService a3RTService = new A3RTService(); + Inputs inputs = new Inputs(); + Output output = new Output(); + string input = inputs.InputConsole(); + while (true) + { + output.OutputConsole(a3RTService.MakeRequestAsync(input).ToString()); + input = inputs.InputConsole(); + } + } } } diff --git a/VoiceVox.cs b/VoiceVox.cs @@ -0,0 +1,66 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Media; +using System.Net.Http.Headers; +using System.Text; +using System.Threading.Tasks; + +namespace Aida_chiyo_Talk_app +{ + internal class VoiceVox + { + public async Task VoiceVoxCon(string input) + { + //https://qiita.com/oyahun/items/e01e56878dc011cdc094 + + using (var httpClient = new HttpClient()) + { + string query; + int speaker = 1; + string text = input; + + // 音声クエリを生成 + using (var request = new HttpRequestMessage(new HttpMethod("POST"), $"http://localhost:50021/audio_query?text={text}&speaker={speaker}")) + { + request.Headers.TryAddWithoutValidation("accept", "application/json"); + + request.Content = new StringContent(""); + request.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/x-www-form-urlencoded"); + + var response = await httpClient.SendAsync(request); + + query = response.Content.ReadAsStringAsync().Result; + //Console.WriteLine(query); + } + + // 音声クエリから音声合成 + using (var request = new HttpRequestMessage(new HttpMethod("POST"), "http://localhost:50021/synthesis?speaker=1&enable_interrogative_upspeak=true")) + { + request.Headers.TryAddWithoutValidation("accept", "audio/wav"); + + request.Content = new StringContent(query); + request.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json"); + + var response = await httpClient.SendAsync(request); + + // 音声を保存 + using (var fileStream = System.IO.File.Create("test.wav")) + { + using (var httpStream = await response.Content.ReadAsStreamAsync()) + { + httpStream.CopyTo(fileStream); + fileStream.Flush(); + } + } + } + } + + //読み込む + var player = new SoundPlayer("test.wav"); + //再生する + player.PlaySync(); + //Console.WriteLine("再生完了"); + } + } +}