diff --git a/.gitignore b/.gitignore
index 8a30d25..b90d767 100644
--- a/.gitignore
+++ b/.gitignore
@@ -396,3 +396,6 @@ FodyWeavers.xsd
# JetBrains Rider
*.sln.iml
+
+# Python Virtual Environments
+.venv
diff --git a/Directory.Packages.props b/Directory.Packages.props
index 875f181..ed76f06 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -2,34 +2,36 @@
true
true
- 8.6.0
- 8.2.0
+ 9.0.0-rc.1.24509.13
9.0.0-preview.9.24507.7
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
-
-
+
+
-
-
-
+
+
+
@@ -40,10 +42,11 @@
-
+
+
@@ -51,11 +54,11 @@
+
-
diff --git a/nuget.config b/nuget.config
index d076cae..45d2e5d 100644
--- a/nuget.config
+++ b/nuget.config
@@ -1,9 +1,10 @@
-
+
+
@@ -12,5 +13,8 @@
+
+
+
diff --git a/seeddata/DataGenerator/DataGenerator.csproj b/seeddata/DataGenerator/DataGenerator.csproj
index 995784a..dcb3e98 100644
--- a/seeddata/DataGenerator/DataGenerator.csproj
+++ b/seeddata/DataGenerator/DataGenerator.csproj
@@ -2,7 +2,7 @@
Exe
- net8.0
+ net9.0
enable
enable
eShopSupport.DataGenerator
diff --git a/src/AppHost/AppHost.csproj b/src/AppHost/AppHost.csproj
index 7dae6ee..8a53487 100644
--- a/src/AppHost/AppHost.csproj
+++ b/src/AppHost/AppHost.csproj
@@ -1,27 +1,25 @@
-
+
Exe
- net8.0
+ net9.0
enable
enable
true
dbe89ad9-90f1-44de-9646-7e98b2d8c69d
-
+
-
-
-
+
\ No newline at end of file
diff --git a/src/AppHost/Ollama/OllamaResourceExtensions.cs b/src/AppHost/Ollama/OllamaResourceExtensions.cs
index c22f708..f2c9e16 100644
--- a/src/AppHost/Ollama/OllamaResourceExtensions.cs
+++ b/src/AppHost/Ollama/OllamaResourceExtensions.cs
@@ -140,7 +140,7 @@ private static async Task DownloadModelAsync(ILogger logger, EndpointReference h
var httpClient = new HttpClient { Timeout = TimeSpan.FromDays(1) };
var request = new HttpRequestMessage(HttpMethod.Post, $"{httpEndpoint.Url}/api/pull") { Content = JsonContent.Create(new { name = modelName }) };
- var response = await httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
+ var response = await httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken);
var responseContentStream = await response.Content.ReadAsStreamAsync(cancellationToken);
var streamReader = new StreamReader(responseContentStream);
var line = (string?)null;
diff --git a/src/AppHost/Program.cs b/src/AppHost/Program.cs
index e49e09d..aa38fc0 100644
--- a/src/AppHost/Program.cs
+++ b/src/AppHost/Program.cs
@@ -43,8 +43,19 @@
var blobStorage = storage.AddBlobs("eshopsupport-blobs");
-var pythonInference = builder.AddPythonUvicornApp("python-inference",
- Path.Combine("..", "PythonInference"), port: 62394);
+var stage = builder.ExecutionContext.IsRunMode ? "base" : /* default stage */ null;
+var pythonInference = builder.AddDockerfile("python-inference", "../PythonInference", /* default dockerfile */ null, stage)
+ .WithHttpEndpoint(port: 57000, targetPort: 8000)
+ .WithContainerRuntimeArgs("--gpus=all")
+ .WithLifetime(ContainerLifetime.Persistent);
+
+if (builder.ExecutionContext.IsRunMode)
+{
+ // Mount app files into the container & enable auto-reload when running in development
+ pythonInference
+ .WithBindMount("../PythonInference", "/app")
+ .WithArgs("--reload");
+}
var redis = builder.AddRedis("redis");
@@ -53,7 +64,7 @@
.WithReference(chatCompletion)
.WithReference(blobStorage)
.WithReference(vectorDb)
- .WithReference(pythonInference)
+ .WithReference(pythonInference.GetEndpoint("http"))
.WithReference(redis)
.WithEnvironment("IdentityUrl", identityEndpoint)
.WithEnvironment("ImportInitialDataDir", Path.Combine(builder.AppHostDirectory, "..", "..", "seeddata", isE2ETest ? "test" : "dev"));
diff --git a/src/AppHost/Python/PythonUvicornAppResourceBuilderExtensions.cs b/src/AppHost/Python/PythonUvicornAppResourceBuilderExtensions.cs
deleted file mode 100644
index b3a2713..0000000
--- a/src/AppHost/Python/PythonUvicornAppResourceBuilderExtensions.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-namespace Aspire.Hosting;
-
-public static class PythonUvicornAppResourceBuilderExtensions
-{
- public static IResourceBuilder AddPythonUvicornApp(this IDistributedApplicationBuilder builder, string name, string workingDirectory, int? port = default, int? targetPort = default)
- {
- return builder.AddResource(new PythonUvicornAppResource(name, "python", workingDirectory))
- .WithArgs("-m", "uvicorn", "main:app")
- .WithHttpEndpoint(env: "UVICORN_PORT", port: port, targetPort: targetPort);
- }
-}
-
-public class PythonUvicornAppResource(string name, string command, string workingDirectory)
- : ExecutableResource(name, command, workingDirectory), IResourceWithServiceDiscovery
-{
-}
diff --git a/src/Backend/Backend.csproj b/src/Backend/Backend.csproj
index 444fb65..b9155fe 100644
--- a/src/Backend/Backend.csproj
+++ b/src/Backend/Backend.csproj
@@ -1,7 +1,7 @@
- net8.0
+ net9.0
enable
enable
eShopSupport.Backend
diff --git a/src/CustomerWebUI/CustomerWebUI.csproj b/src/CustomerWebUI/CustomerWebUI.csproj
index d5f3875..74f8f2a 100644
--- a/src/CustomerWebUI/CustomerWebUI.csproj
+++ b/src/CustomerWebUI/CustomerWebUI.csproj
@@ -1,7 +1,7 @@
- net8.0
+ net9.0
enable
enable
diff --git a/src/DataIngestor/DataIngestor.csproj b/src/DataIngestor/DataIngestor.csproj
index c9d6913..aafccb1 100644
--- a/src/DataIngestor/DataIngestor.csproj
+++ b/src/DataIngestor/DataIngestor.csproj
@@ -1,27 +1,21 @@
-
Exe
- net8.0
+ net9.0
enable
enable
eShopSupport.DataIngestor
$(SolutionDir)\seeddata\DataGenerator\output
- $(NoWarn);SKEXP0001;SKEXP0020;SKEXP0050
- true
+ $(NoWarn);SKEXP0001;SKEXP0050
-
-
+
+
-
-
-
-
diff --git a/src/Evaluator/Evaluator.csproj b/src/Evaluator/Evaluator.csproj
index cf012a8..eb29091 100644
--- a/src/Evaluator/Evaluator.csproj
+++ b/src/Evaluator/Evaluator.csproj
@@ -2,7 +2,7 @@
Exe
- net8.0
+ net9.0
enable
enable
eShopSupport.Evaluator
diff --git a/src/IdentityServer/IdentityServer.csproj b/src/IdentityServer/IdentityServer.csproj
index d826b50..1752833 100644
--- a/src/IdentityServer/IdentityServer.csproj
+++ b/src/IdentityServer/IdentityServer.csproj
@@ -1,7 +1,7 @@
- net8.0
+ net9.0
enable
enable
diff --git a/src/PythonInference/Dockerfile b/src/PythonInference/Dockerfile
new file mode 100644
index 0000000..b66c21f
--- /dev/null
+++ b/src/PythonInference/Dockerfile
@@ -0,0 +1,22 @@
+FROM python:3.12.5-slim AS base
+
+# Set the working directory, the app files could be bind-mounted here
+WORKDIR /app
+
+# Copy the requirements file
+COPY requirements.txt .
+
+# Install dependencies
+RUN pip install --no-cache-dir -r requirements.txt
+
+# Ensure the server is accessible from outside the container
+ENV UVICORN_HOST=0.0.0.0
+
+# Set the entry point to run the application
+ENTRYPOINT ["python", "-m", "uvicorn", "main:app"]
+
+CMD []
+
+FROM base AS publish
+
+COPY . .
\ No newline at end of file
diff --git a/src/PythonInference/PythonInference.pyproj b/src/PythonInference/PythonInference.pyproj
index 9a50be7..90b7cbf 100644
--- a/src/PythonInference/PythonInference.pyproj
+++ b/src/PythonInference/PythonInference.pyproj
@@ -28,5 +28,8 @@
+
+
+
\ No newline at end of file
diff --git a/src/ServiceDefaults/Extensions.cs b/src/ServiceDefaults/Extensions.cs
index ba0978f..a58599e 100644
--- a/src/ServiceDefaults/Extensions.cs
+++ b/src/ServiceDefaults/Extensions.cs
@@ -49,7 +49,8 @@ public static IHostApplicationBuilder ConfigureOpenTelemetry(this IHostApplicati
})
.WithTracing(tracing =>
{
- tracing.AddAspNetCoreInstrumentation()
+ tracing.AddSource(builder.Environment.ApplicationName)
+ .AddAspNetCoreInstrumentation()
// Uncomment the following line to enable gRPC instrumentation (requires the OpenTelemetry.Instrumentation.GrpcNetClient package)
//.AddGrpcClientInstrumentation()
.AddHttpClientInstrumentation()
diff --git a/src/ServiceDefaults/ServiceDefaults.csproj b/src/ServiceDefaults/ServiceDefaults.csproj
index ab367e1..562832f 100644
--- a/src/ServiceDefaults/ServiceDefaults.csproj
+++ b/src/ServiceDefaults/ServiceDefaults.csproj
@@ -1,7 +1,7 @@
- net8.0
+ net9.0
enable
enable
true
diff --git a/src/StaffWebUI/StaffWebUI.csproj b/src/StaffWebUI/StaffWebUI.csproj
index 6d060df..75d0db5 100644
--- a/src/StaffWebUI/StaffWebUI.csproj
+++ b/src/StaffWebUI/StaffWebUI.csproj
@@ -1,7 +1,7 @@
- net8.0
+ net9.0
enable
enable
eShopSupport.StaffWebUI
diff --git a/test/E2ETest/E2ETest.csproj b/test/E2ETest/E2ETest.csproj
index 9e2dca5..6dda83a 100644
--- a/test/E2ETest/E2ETest.csproj
+++ b/test/E2ETest/E2ETest.csproj
@@ -2,7 +2,7 @@
Exe
- net8.0
+ net9.0
enable
enable
diff --git a/test/E2ETest/Infrastructure/AppHostFixture.cs b/test/E2ETest/Infrastructure/AppHostFixture.cs
index f2520a8..e2a80ba 100644
--- a/test/E2ETest/Infrastructure/AppHostFixture.cs
+++ b/test/E2ETest/Infrastructure/AppHostFixture.cs
@@ -1,4 +1,5 @@
-using Aspire.Hosting.Testing;
+using Aspire.Hosting;
+using Aspire.Hosting.Testing;
using eShopSupport.ServiceDefaults.Clients.Backend;
using IdentityModel.Client;
@@ -21,7 +22,7 @@ private async Task InitializeAsync()
Environment.CurrentDirectory = Projects.AppHost.ProjectPath;
Environment.SetEnvironmentVariable("E2E_TEST", "true");
Environment.SetEnvironmentVariable("E2E_TEST_CHAT_COMPLETION_CACHE_DIR",
- Path.Combine(Projects.E2ETest.ProjectPath, "ChatCompletionCache"));
+ Path.Combine(Projects.AppHost.ProjectPath, "ChatCompletionCache"));
var builder = await DistributedApplicationTestingBuilder.CreateAsync();
var app = await builder.BuildAsync();
await app.StartAsync();