Skip to content

Commit 7cc9348

Browse files
committed
Environment callback refactor
1 parent 75ad392 commit 7cc9348

File tree

5 files changed

+29
-36
lines changed

5 files changed

+29
-36
lines changed

TensorStack.Python/Common/PipelineOptions.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ public record PipelineOptions
2020
public float FlowShift { get; set; }
2121
public float Strength { get; set; }
2222
public SchedulerType Scheduler { get; set; }
23-
public SchedulerType[] Schedulers { get; set; }
2423
public List<LoraOptions> LoraOptions { get; set; }
2524
public ImageTensor ImageInput { get; set; }
2625
}

TensorStack.Python/Extensions.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using CSnakes.Runtime.Python;
22
using System;
33
using TensorStack.Common.Tensor;
4+
using TensorStack.Python.Common;
45

56
namespace TensorStack.Python
67
{
@@ -43,5 +44,14 @@ public static ReadOnlySpan<int> GetDimensions(this IPyBuffer pyBuffer)
4344
return dimensions;
4445
}
4546

47+
48+
public static void SendMessage(this IProgress<PipelineProgress> progressCallback, string message)
49+
{
50+
progressCallback?.Report(new PipelineProgress
51+
{
52+
Message = message,
53+
Process = "Initialize"
54+
});
55+
}
4656
}
4757
}

TensorStack.Python/PythonManager.cs

Lines changed: 15 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,17 @@ public class PythonManager
2020
private readonly string _pythonPath;
2121
private readonly string _pipelinePath;
2222
private readonly string _pythonVersion = "3.12.10";
23-
private readonly IProgress<PipelineProgress> _progressCallback;
2423

2524
/// <summary>
2625
/// Initializes a new instance of the <see cref="PythonManager"/> class.
2726
/// </summary>
2827
/// <param name="config">The configuration.</param>
2928
/// <param name="progressCallback">The progress callback.</param>
3029
/// <param name="logger">The logger.</param>
31-
public PythonManager(EnvironmentConfig config, IProgress<PipelineProgress> progressCallback = null, ILogger logger = default)
30+
public PythonManager(EnvironmentConfig config, ILogger logger = default)
3231
{
3332
_logger = logger;
3433
_config = config;
35-
_progressCallback = progressCallback;
3634
_pythonPath = Path.GetFullPath(Path.Join(_config.Directory, "Python"));
3735
_pipelinePath = Path.GetFullPath(Path.Join(_config.Directory, "Pipelines"));
3836
CopyInternalPipelineFiles();
@@ -44,15 +42,15 @@ public PythonManager(EnvironmentConfig config, IProgress<PipelineProgress> progr
4442
/// </summary>
4543
/// <param name="isRebuild">Delete and rebuild the environment</param>
4644
/// <param name="isReinstall">Delete and rebuild the environment and base Python installation</param>
47-
public Task<IPythonEnvironment> CreateEnvironmentAsync(bool isRebuild = false, bool isReinstall = false)
45+
public Task<IPythonEnvironment> CreateEnvironmentAsync(bool isRebuild = false, bool isReinstall = false, IProgress<PipelineProgress> progressCallback = null)
4846
{
4947
return Task.Run(async () =>
5048
{
51-
await DownloadAsync(isReinstall);
49+
await DownloadAsync(isReinstall, progressCallback);
5250
if (isReinstall || isRebuild)
5351
await DeleteAsync();
5452

55-
return await CreateAsync();
53+
return await CreateAsync(progressCallback);
5654
});
5755
}
5856

@@ -75,7 +73,7 @@ private async Task<bool> DeleteAsync()
7573
/// Checks if a environment exists
7674
/// </summary>
7775
/// <param name="name">The name.</param>
78-
private bool Exists(string name)
76+
public bool Exists(string name)
7977
{
8078
var path = Path.Combine(_pipelinePath, $".{name}");
8179
return Directory.Exists(path);
@@ -85,14 +83,14 @@ private bool Exists(string name)
8583
/// <summary>
8684
/// Creates the environment.
8785
/// </summary>
88-
private async Task<IPythonEnvironment> CreateAsync()
86+
private async Task<IPythonEnvironment> CreateAsync(IProgress<PipelineProgress> progressCallback = null)
8987
{
9088
var exists = Exists(_config.Environment);
91-
CallbackMessage($"{(exists ? "Loading" : "Creating")} Python Virtual Environment (.{_config.Environment})");
89+
progressCallback.SendMessage($"{(exists ? "Loading" : "Creating")} Python Virtual Environment (.{_config.Environment})");
9290
var requirementsFile = Path.Combine(_pipelinePath, "requirements.txt");
9391
await File.WriteAllLinesAsync(requirementsFile, _config.Requirements);
9492
var environment = PythonEnvironmentHelper.CreateEnvironment(_config.Environment, _pythonPath, _pipelinePath, requirementsFile, _pythonVersion, _logger);
95-
CallbackMessage($"Python Virtual Environment {(exists ? "Loaded" : "Created")}.");
93+
progressCallback.SendMessage($"Python Virtual Environment {(exists ? "Loaded" : "Created")}.");
9694
return environment;
9795
}
9896

@@ -101,22 +99,22 @@ private async Task<IPythonEnvironment> CreateAsync()
10199
/// Downloads and installs Win-Python portable v3.12.10.
102100
/// </summary>
103101
/// <param name="reinstall">if set to <c>true</c> [reinstall].</param>
104-
private async Task DownloadAsync(bool reinstall)
102+
private async Task DownloadAsync(bool reinstall, IProgress<PipelineProgress> progressCallback = null)
105103
{
106104
var subfolder = "WPy64-312100/python";
107105
var exePath = Path.Combine(_pythonPath, "python.exe");
108106
var downloadPath = Path.Combine(_pythonPath, "Winpython64-3.12.10.0dot.zip");
109107
var pythonUrl = "https://github.com/winpython/winpython/releases/download/15.3.20250425final/Winpython64-3.12.10.0dot.zip";
110108
if (reinstall)
111109
{
112-
CallbackMessage($"Reinstalling Python {_pythonVersion}...");
110+
progressCallback.SendMessage($"Reinstalling Python {_pythonVersion}...");
113111
if (File.Exists(downloadPath))
114112
File.Delete(downloadPath);
115113

116114
if (Directory.Exists(_pythonPath))
117115
Directory.Delete(_pythonPath, true);
118116

119-
CallbackMessage($"Python Uninstalled.");
117+
progressCallback.SendMessage($"Python Uninstalled.");
120118
}
121119

122120
// Create Python
@@ -125,7 +123,7 @@ private async Task DownloadAsync(bool reinstall)
125123
// Download Python
126124
if (!File.Exists(downloadPath))
127125
{
128-
CallbackMessage($"Download Python {_pythonVersion}...");
126+
progressCallback.SendMessage($"Download Python {_pythonVersion}...");
129127
using (var httpClient = new HttpClient())
130128
using (var response = await httpClient.GetAsync(pythonUrl))
131129
{
@@ -135,13 +133,13 @@ private async Task DownloadAsync(bool reinstall)
135133
await response.Content.CopyToAsync(stream);
136134
}
137135
}
138-
CallbackMessage("Python Download Complete.");
136+
progressCallback.SendMessage("Python Download Complete.");
139137
}
140138

141139
// Extract ZIP file
142140
if (!File.Exists(exePath))
143141
{
144-
CallbackMessage($"Installing Python {_pythonVersion}...");
142+
progressCallback.SendMessage( $"Installing Python {_pythonVersion}...");
145143
CopyInternalPythonFiles();
146144
using (var archive = ZipFile.OpenRead(downloadPath))
147145
{
@@ -164,25 +162,10 @@ private async Task DownloadAsync(bool reinstall)
164162
}
165163
}
166164
}
167-
CallbackMessage($"Python Install Complete.");
165+
progressCallback.SendMessage($"Python Install Complete.");
168166
}
169167
}
170168

171-
172-
/// <summary>
173-
/// Send a callback message.
174-
/// </summary>
175-
/// <param name="message">The message.</param>
176-
private void CallbackMessage(string message)
177-
{
178-
_progressCallback?.Report(new PipelineProgress
179-
{
180-
Message = message,
181-
Process = "Initialize"
182-
});
183-
}
184-
185-
186169
/// <summary>
187170
/// Copies the internal python files.
188171
/// </summary>

TensorStack.Python/PythonPipeline.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ public Task<Tensor<float>> GenerateAsync(PipelineOptions options, CancellationTo
176176
using (var strength = PyObject.From(options.Strength))
177177
using (var loraOptions = PyObject.From(loraConfig))
178178
using (var inputData = PyObject.From(imageInput?.Memory.ToArray()))
179-
using (var inputShape = PyObject.From(imageInput.Dimensions.ToArray()))
179+
using (var inputShape = PyObject.From(imageInput?.Dimensions.ToArray()))
180180
using (var pythonResult = _functionGenerate.Call(prompt, negativePrompt, guidance, guidance2, steps, steps2, height, width, seed, scheduler, numFrames, shift, flowShift, strength, loraOptions, inputData, inputShape))
181181
{
182182
var result = pythonResult

TensorStack.Python/README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ C# => Python Diffusers Inferface
88
### Qwen Image
99
- QwenImagePipeline
1010
- QwenImageImg2ImgPipeline
11+
- QwenImageEditPipeline
1112
### Wan Video
1213
- WanPipeline
1314
- WanImageToVideoPipeline
@@ -42,10 +43,10 @@ var serverConfig = new EnvironmentConfig
4243
};
4344

4445
// PythonManager
45-
var pythonService = new PythonManager(serverConfig, PipelineProgress.ConsoleCallback);
46+
var pythonService = new PythonManager(serverConfig);
4647

4748
// Create/Load Virtual Environment
48-
await pythonService.CreateEnvironmentAsync();
49+
await pythonService.CreateEnvironmentAsync(PipelineProgress.ConsoleCallback);
4950
```
5051

5152
## Python Pipelines

0 commit comments

Comments
 (0)