reformatting
This commit is contained in:
|
Before Width: | Height: | Size: 172 KiB After Width: | Height: | Size: 172 KiB |
@@ -8,8 +8,8 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Folder Include="Models\" />
|
<Folder Include="models\" />
|
||||||
<AvaloniaResource Include="Assets\**" />
|
<AvaloniaResource Include="assets\**" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace finder2e_foundry_converter.Services
|
||||||
|
{
|
||||||
|
public interface ILlmService
|
||||||
|
{
|
||||||
|
Task<List<string>> GetModelsAsync(string baseUrl);
|
||||||
|
Task<string> GenerateResponseAsync(string baseUrl, string model, string text, List<string> imagePaths);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,7 +8,7 @@ using System.Text.Json.Serialization;
|
|||||||
|
|
||||||
namespace finder2e_foundry_converter.Services
|
namespace finder2e_foundry_converter.Services
|
||||||
{
|
{
|
||||||
public class LlmService
|
public class LmStudioService : ILlmService
|
||||||
{
|
{
|
||||||
private readonly HttpClient _httpClient = new HttpClient();
|
private readonly HttpClient _httpClient = new HttpClient();
|
||||||
|
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Net.Http.Json;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace finder2e_foundry_converter.Services
|
||||||
|
{
|
||||||
|
public class OllamaService : ILlmService
|
||||||
|
{
|
||||||
|
private readonly HttpClient _httpClient = new HttpClient();
|
||||||
|
|
||||||
|
public async Task<List<string>> GetModelsAsync(string baseUrl)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var response = await _httpClient.GetFromJsonAsync<OllamaModelsResponse>($"{baseUrl.TrimEnd('/')}/api/tags");
|
||||||
|
if (response?.Models == null) return new List<string>();
|
||||||
|
|
||||||
|
return response.Models.Select(m => m.Name).ToList();
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return new List<string> { "Error: Ollama not found" };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<string> GenerateResponseAsync(string baseUrl, string model, string text, List<string> imagePaths)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var images = new List<string>();
|
||||||
|
foreach (var path in imagePaths)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(path)) continue;
|
||||||
|
var bytes = await System.IO.File.ReadAllBytesAsync(path);
|
||||||
|
images.Add(Convert.ToBase64String(bytes));
|
||||||
|
}
|
||||||
|
|
||||||
|
var requestBody = new
|
||||||
|
{
|
||||||
|
model = model,
|
||||||
|
messages = new[]
|
||||||
|
{
|
||||||
|
new { role = "user", content = text, images = images.Count > 0 ? images.ToArray() : null }
|
||||||
|
},
|
||||||
|
stream = false
|
||||||
|
};
|
||||||
|
|
||||||
|
var response = await _httpClient.PostAsJsonAsync($"{baseUrl.TrimEnd('/')}/api/chat", requestBody);
|
||||||
|
var body = await response.Content.ReadAsStringAsync();
|
||||||
|
|
||||||
|
using var doc = JsonDocument.Parse(body);
|
||||||
|
if (doc.RootElement.TryGetProperty("error", out var error))
|
||||||
|
{
|
||||||
|
return $"Error: {error.GetString()}";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (doc.RootElement.TryGetProperty("message", out var message))
|
||||||
|
{
|
||||||
|
return message.GetProperty("content").GetString() ?? "No content returned";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "No response returned.";
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return $"Error: {ex.Message}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class OllamaModelsResponse
|
||||||
|
{
|
||||||
|
[JsonPropertyName("models")]
|
||||||
|
public List<OllamaModelData>? Models { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private class OllamaModelData
|
||||||
|
{
|
||||||
|
[JsonPropertyName("name")]
|
||||||
|
public string Name { get; set; } = string.Empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,18 +14,38 @@ namespace finder2e_foundry_converter.ViewModels
|
|||||||
{
|
{
|
||||||
public partial class MainWindowViewModel : ViewModelBase
|
public partial class MainWindowViewModel : ViewModelBase
|
||||||
{
|
{
|
||||||
private readonly LlmService _llmService = new LlmService();
|
private readonly LmStudioService _lmStudioService = new();
|
||||||
|
private readonly OllamaService _ollamaService = new();
|
||||||
|
|
||||||
|
private ILlmService CurrentService => SelectedProvider == "Ollama" ? (ILlmService)_ollamaService : _lmStudioService;
|
||||||
|
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
|
[NotifyPropertyChangedFor(nameof(CurrentAddress))]
|
||||||
private string _lmStudioAddress = "http://localhost:1234";
|
private string _lmStudioAddress = "http://localhost:1234";
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
[NotifyPropertyChangedFor(nameof(CurrentAddress))]
|
||||||
|
private string _ollamaAddress = "http://localhost:11434";
|
||||||
|
|
||||||
|
public string CurrentAddress
|
||||||
|
{
|
||||||
|
get => SelectedProvider == "Ollama" ? OllamaAddress : LmStudioAddress;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (SelectedProvider == "Ollama") OllamaAddress = value;
|
||||||
|
else LmStudioAddress = value;
|
||||||
|
OnPropertyChanged(nameof(CurrentAddress));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
private bool _isAddressVisible = false;
|
private bool _isAddressVisible = false;
|
||||||
|
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
|
[NotifyPropertyChangedFor(nameof(CurrentAddress))]
|
||||||
private string _selectedProvider = "LM Studio";
|
private string _selectedProvider = "LM Studio";
|
||||||
|
|
||||||
public ObservableCollection<string> Providers { get; } = new() { "LM Studio" };
|
public ObservableCollection<string> Providers { get; } = new() { "LM Studio", "Ollama" };
|
||||||
|
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
private string? _selectedModel;
|
private string? _selectedModel;
|
||||||
@@ -52,6 +72,13 @@ namespace finder2e_foundry_converter.ViewModels
|
|||||||
_ = StartModelRefreshLoop();
|
_ = StartModelRefreshLoop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
partial void OnSelectedProviderChanged(string value)
|
||||||
|
{
|
||||||
|
Models.Clear();
|
||||||
|
SelectedModel = null;
|
||||||
|
_ = RefreshModels();
|
||||||
|
}
|
||||||
|
|
||||||
[RelayCommand]
|
[RelayCommand]
|
||||||
private void ToggleAddress()
|
private void ToggleAddress()
|
||||||
{
|
{
|
||||||
@@ -61,13 +88,7 @@ namespace finder2e_foundry_converter.ViewModels
|
|||||||
[RelayCommand]
|
[RelayCommand]
|
||||||
private async Task RefreshModels()
|
private async Task RefreshModels()
|
||||||
{
|
{
|
||||||
if (SelectedProvider != "LM Studio")
|
var models = await CurrentService.GetModelsAsync(CurrentAddress);
|
||||||
{
|
|
||||||
IsErrorVisible = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var models = await _llmService.GetModelsAsync(LmStudioAddress);
|
|
||||||
|
|
||||||
Models.Clear();
|
Models.Clear();
|
||||||
foreach (var m in models)
|
foreach (var m in models)
|
||||||
@@ -85,7 +106,7 @@ namespace finder2e_foundry_converter.ViewModels
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ErrorText = models.FirstOrDefault() ?? "Error connecting to LM Studio";
|
ErrorText = models.FirstOrDefault() ?? $"Error connecting to {SelectedProvider}";
|
||||||
IsErrorVisible = true;
|
IsErrorVisible = true;
|
||||||
IsAddressVisible = true; // Auto-show on failure
|
IsAddressVisible = true; // Auto-show on failure
|
||||||
}
|
}
|
||||||
@@ -101,7 +122,7 @@ namespace finder2e_foundry_converter.ViewModels
|
|||||||
}
|
}
|
||||||
|
|
||||||
StatusMessage = "Generating...";
|
StatusMessage = "Generating...";
|
||||||
var result = await _llmService.GenerateResponseAsync(LmStudioAddress, SelectedModel, Description, ImageItems.Select(i => i.Path).ToList());
|
var result = await CurrentService.GenerateResponseAsync(CurrentAddress, SelectedModel, Description, ImageItems.Select(i => i.Path).ToList());
|
||||||
StatusMessage = result;
|
StatusMessage = result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
mc:Ignorable="d" d:DesignWidth="500" d:DesignHeight="600"
|
mc:Ignorable="d" d:DesignWidth="500" d:DesignHeight="600"
|
||||||
x:Class="finder2e_foundry_converter.Views.MainWindow"
|
x:Class="finder2e_foundry_converter.Views.MainWindow"
|
||||||
x:DataType="vm:MainWindowViewModel"
|
x:DataType="vm:MainWindowViewModel"
|
||||||
Icon="/Assets/avalonia-logo.ico"
|
Icon="/assets/avalonia-logo.ico"
|
||||||
Title="Finder2e Foundry Converter"
|
Title="Finder2e Foundry Converter"
|
||||||
Width="500" Height="600"
|
Width="500" Height="600"
|
||||||
DragDrop.AllowDrop="True">
|
DragDrop.AllowDrop="True">
|
||||||
@@ -30,8 +30,8 @@
|
|||||||
<TextBlock Text="{Binding ErrorText}" Foreground="Red" HorizontalAlignment="Center" IsVisible="{Binding IsErrorVisible}"/>
|
<TextBlock Text="{Binding ErrorText}" Foreground="Red" HorizontalAlignment="Center" IsVisible="{Binding IsErrorVisible}"/>
|
||||||
|
|
||||||
<StackPanel IsVisible="{Binding IsAddressVisible}" Spacing="5">
|
<StackPanel IsVisible="{Binding IsAddressVisible}" Spacing="5">
|
||||||
<Label Content="LM Studio Address:"/>
|
<Label Content="{Binding SelectedProvider, StringFormat='{}{0} Address:'}"/>
|
||||||
<TextBox Text="{Binding LmStudioAddress}" PlaceholderText="http://localhost:1234"/>
|
<TextBox Text="{Binding CurrentAddress}" PlaceholderText="http://localhost:11434"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
<Label Content="Model:"/>
|
<Label Content="Model:"/>
|
||||||
Reference in New Issue
Block a user