From a7210e527ef0c4cb33849ecdd89147b482c796f6 Mon Sep 17 00:00:00 2001 From: OLDREDSTONE Date: Mon, 14 Apr 2025 11:15:40 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=BA=86=20AI=20=E5=8A=A9?= =?UTF-8?q?=E6=89=8B=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AIAssistant/Model.cs | 102 +++++++++++++++++++++++++++++++++++++++++++ MainWindow.xaml | 11 ++++- MainWindow.xaml.cs | 13 +++++- RDTKEditor.csproj | 1 + 4 files changed, 124 insertions(+), 3 deletions(-) create mode 100644 AIAssistant/Model.cs diff --git a/AIAssistant/Model.cs b/AIAssistant/Model.cs new file mode 100644 index 0000000..d1d9ca1 --- /dev/null +++ b/AIAssistant/Model.cs @@ -0,0 +1,102 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using CSharpToJsonSchema; +using Ollama; +using RhythmBase.Components; +using System.ComponentModel; + +namespace RDTKEditor.AIAssistant +{ + public class Assistant + { + public const string Deepseek = "deepseek-r1:8b"; + public const string Smollm = "smollm2:135m"; + public const string Qwen_0_5 = "qwen2.5-coder:0.5b"; + public const string Qwen_3 = "qwen2.5-coder:3b"; + public OllamaApiClient Ollama { get; } = new(baseUri: new Uri("http://127.0.0.1:11434/api")); + public Chat Chat { get; } + public Assistant(string modelName) + { + Chat = Ollama.Chat( + model: modelName, + autoCallTools: true + ); + var utils = new RhythmBaseUtils(); + Chat.AddToolService(utils.AsTools().AsOllamaTools(), utils.AsCalls()); + } + public async IAsyncEnumerable GetResponse(string modelName, string userInput) + { + await foreach (var responce in Ollama.Completions.GenerateCompletionAsync(modelName, userInput)) + { + if (responce != null) + { + yield return responce; + } + } + } + } + [GenerateJsonSchema] + public interface IRhythmBaseUtils + { + [Description("创建空关卡")] + public void CreateEmptyLevel(); + [Description("创建关卡模板(默认关卡)")] + public void CreateLevelTemplate(); + [Description("打开关卡")] + public void OpenLevel([Description("关卡路径")] string filepath); + [Description("添加轨道")] + public void AddRow( + [Description("轨道所在的房间")] RDRoomIndex roomIndex, + [Description("轨道名称")] string trackName + ); + [Description("保存关卡")] + public void SaveLevel([Description("关卡路径,后缀为 .rdlevel")] string filepath); + } + public class RhythmBaseUtils : IRhythmBaseUtils + { + private RDLevel? level; + public void CreateEmptyLevel() + { + Console.BackgroundColor = ConsoleColor.Green; + Console.WriteLine($"Called CreateEmptyLevel"); + Console.ResetColor(); + level = []; + } + public void CreateLevelTemplate() + { + Console.BackgroundColor = ConsoleColor.Green; + Console.WriteLine($"Called CreateLevelTemplate"); + Console.ResetColor(); + level = RDLevel.Default; + } + public void OpenLevel(string filepath) + { + Console.BackgroundColor = ConsoleColor.Green; + Console.WriteLine($"Called OpenLevel: {filepath}"); + Console.ResetColor(); + level = RDLevel.Read(filepath); + } + public void AddRow(RDRoomIndex roomIndex, string trackName) + { + Console.BackgroundColor = ConsoleColor.Green; + Console.WriteLine($"Called AddRow: [{roomIndex}] {trackName}"); + Console.ResetColor(); + level?.CreateRow(roomIndex, trackName); + } + public void SaveLevel(string filepath) + { + Console.BackgroundColor = ConsoleColor.Green; + Console.WriteLine($"Called SaveLevel: {filepath}"); + Console.ResetColor(); + string dir = Path.GetDirectoryName(filepath) ?? ""; + if (!string.IsNullOrEmpty(dir)) + { + Directory.CreateDirectory(dir); + } + level?.Write(filepath); + } + } +} diff --git a/MainWindow.xaml b/MainWindow.xaml index df9dfed..1e39e52 100644 --- a/MainWindow.xaml +++ b/MainWindow.xaml @@ -54,12 +54,19 @@ - + + + 传给 AI 的文本 + + + - + diff --git a/MainWindow.xaml.cs b/MainWindow.xaml.cs index f173f26..3fc9987 100644 --- a/MainWindow.xaml.cs +++ b/MainWindow.xaml.cs @@ -1,10 +1,11 @@ using Microsoft.Win32; +using Ollama; +using RDTKEditor.AIAssistant; using RDTKEditor.Models; using RhythmBase.Events; using SkiaSharp; using SkiaSharp.Views.Desktop; using System.ComponentModel; -using System.Diagnostics; using System.Reflection; using System.Windows; using System.Windows.Controls; @@ -17,6 +18,7 @@ namespace RDTKEditor /// public partial class MainWindow : Window { + private Assistant Assistant = new(Assistant.Qwen_3); private SKSizeI _vsScale = new(1600,900); private readonly RDTKView viewModel = new(); public MainWindow() @@ -282,6 +284,15 @@ namespace RDTKEditor IsStroke = true, }); } + + private async void AIAssistantButton_Click(object sender, RoutedEventArgs e) + { + string input = AIAssistantText.Text; + if (string.IsNullOrEmpty(input)) + return; + Message responce = await Assistant.Chat.SendAsync(input); + AIAssistantText.Text = responce.Content; + } } public class MainViewModel : INotifyPropertyChanged { diff --git a/RDTKEditor.csproj b/RDTKEditor.csproj index 875c821..8a08df3 100644 --- a/RDTKEditor.csproj +++ b/RDTKEditor.csproj @@ -10,6 +10,7 @@ +