using OllamaSharp; using System.Collections.ObjectModel; using System.Diagnostics; using System.IO; using System.Reflection; using System.Text; using System.Windows; namespace YwxApp.AiChat.ViewModels { /// /// 0、Current class: /// public class ShareOllamaObject { #region Field | Property | Collection | Command #region Field private bool _ollamaEnabled = false; //ollama connected state private string _ollamaAppPath; //ollama app path. private int recordIndex = 0; //current record index. private string _remoteHost = "192.168.1.6"; //current record; private string _remotePort = "11434"; //current record; private string _currentPath; private Chat chat; //build interactive chat model object. private OllamaApiClient _ollama; //OllamaAPI object. #endregion #region Property public string RemoteHost { get { return _remoteHost; } set { _remoteHost = value; } } public string RemotePort { get { return _remotePort; } set { _remotePort = value; } } public string OllamaAppPath { get { return _ollamaAppPath; } set { _ollamaAppPath = value; } } public bool OllamaEnabled { get { return _ollamaEnabled; } set { _ollamaEnabled = value; } } public OllamaApiClient Ollama { get { return _ollama; } set { _ollama = value; } } public Chat Chat { get { return chat; } set { chat = value; } } public string CurrentPath { get => _currentPath; } public int RecordIndex { get => recordIndex; set { recordIndex = value; _currentPath = $"{Environment.CurrentDirectory}//Data//{DateTime.Today.ToString("yyyyMMdd")}" + $"//{DateTime.Today.ToString("yyyyMMdd")}_{recordIndex}.txt"; } } #endregion #region Collection public ObservableCollection ModelList { get; set; } #endregion #endregion #region Constructor public ShareOllamaObject() { RecordIndex = 0; WriteDataToFileAsync(""); Init(OllamaAppPath, "llama3.2:9b"); } #endregion #region other method /// /// initialite method /// private void Init(string appPath, string modelName) { OllamaAppPath = appPath; try { // 设置默认设备为GPU Environment.SetEnvironmentVariable("OLLAMA_DEFAULT_DEVICE", "gpu"); //判断路径是否存在 if (OllamaAppPath == string.Empty || OllamaAppPath == null) OllamaAppPath = @"ollama app.exe"; //路径存在获取应用名 if (File.Exists(OllamaAppPath)) OllamaAppPath = Path.GetFileName(OllamaAppPath); //获取环境Ollama环境变量:用于找到 :ollama app.exe var filePath = FindExeInPath(OllamaAppPath); //如果路径存在,启动Ollama if (File.Exists(filePath)) CheckStartProcess(OllamaAppPath); //连接Ollama,并设置初始模型 _ollama = new OllamaApiClient(new Uri("http://192.168.1.6:11434")); //获取本地可用的模型列表 ModelList = (ObservableCollection)GetModelList(); var tmepModelName = ModelList.FirstOrDefault(name => name.ToLower().Contains("llama3.2")); if (tmepModelName != null) _ollama.SelectedModel = tmepModelName; else if (ModelList.Count > 0) _ollama.SelectedModel = ModelList[ModelList.Count - 1]; if (ModelList.FirstOrDefault(name => name.Equals(modelName)) != null) _ollama.SelectedModel = modelName; //Ollama服务启用成功 OllamaEnabled = true; } catch (Exception) { OllamaEnabled = false; } } public void ConnectRemotelyOllamaServer() { _ollama = new OllamaApiClient(new Uri("http://192.168.1.6:11434")); //获取本地可用的模型列表 ModelList = (ObservableCollection)GetModelList(); } /// /// update the model selected by Ollama /// public void UpdataSelectedModel(string model) { Ollama.SelectedModel = model; OllamaEnabled = true; } /// /// Start Ollama app and relevant server. /// public async void StartOllama(string appPath, string modelName) { Init(appPath, modelName); await Task.Delay(1); } /// /// get model list /// public Collection GetModelList() { var models = _ollama.ListLocalModelsAsync(); var modelList = new ObservableCollection(); foreach (var model in models.Result) { modelList.Add(model.Name); } return modelList; } #endregion #region starting or closeing method of Ollama(server). /// /// Finds whether the specified application name is configured in the system environment. /// If it exists, return the full path, otherwise return null /// public static string FindExeInPath(string exeName) { // get environment variable "Path" value var pathVariable = Environment.GetEnvironmentVariable("PATH"); // Split string string[] paths = pathVariable.Split(Path.PathSeparator); foreach (string path in paths) { string fullPath = Path.Combine(path, exeName); if (File.Exists(fullPath)) { return fullPath; } } return null; } /// ///Startup program Specifies a program, enters a program name, and determines whether the program is running. /// If it is running, exit directly, otherwise run the program according to the input path. /// public static void CheckStartProcess(string processPath) { string processName = Path.GetFileName(processPath); CheckStartProcess(processName, processPath); } /// /// Startup program Specifies a program, enters a program name, and determines whether the program is running. /// If it is running, exit directly, otherwise run the program according to the input path. /// public static void CheckStartProcess(string processName, string processPath) { // Check whather the program is running if (!IsProcessRunning(processName)) { Console.WriteLine($"{processName} is not running. Starting the process..."); StartProcess(processPath); } else Console.WriteLine($"{processName} is already running."); } /// /// Enter the program path to start the program /// public static void StartProcess(string processPath) { try { Process.Start(processPath); Console.WriteLine("Process started successfully."); } catch (Exception ex) { Console.WriteLine($"Error starting process: {ex.Message}"); } } /// /// Check whather the process is running /// public static bool IsProcessRunning(string processName) { Process[] processes = Process.GetProcessesByName(processName); return processes.Length > 0; } /// /// close the process with the specify name. /// /// public static void CloseProcess(string processName) { try { foreach (var process in Process.GetProcessesByName(processName)) { process.Kill(); process.WaitForExit(); Application.Current.Shutdown(); } } catch (Exception ex) { MessageBox.Show($"无法关闭【{processName}】进程: {ex.Message}"); } } /// /// get current process name /// public static string GetProgramName() { Assembly assembly = Assembly.GetExecutingAssembly(); return assembly.GetName().Name; } #endregion #region File save /// /// Save record /// public void WriteDataToFileAsync(string data, int retryCount = 5, int delayMilliseconds = 500) { //Get the directory where the file located. string directoryPath = Path.GetDirectoryName(CurrentPath); // if directory exists't ,create directory(include all must directory). if (!string.IsNullOrEmpty(directoryPath) && !Directory.Exists(directoryPath)) { Directory.CreateDirectory(directoryPath); } for (int i = 0; i < retryCount; i++) { try { using (FileStream fs = new FileStream(CurrentPath, FileMode.Append, FileAccess.Write, FileShare.ReadWrite)) using (StreamWriter writer = new StreamWriter(fs, Encoding.UTF8)) { writer.WriteAsync(data); } return; // successful writed exit the loop. } catch (IOException ex) { if (i == retryCount - 1) { throw; //If the maximum number of retries is reached , a exception is thrown } Task.Delay(delayMilliseconds); // Wait a while and try again } catch (Exception ex) { throw; //other exception is thrown } } } #endregion } }