If an AI capability fits the Python ecosystem better, do not force it into .NET just to keep the solution single-language. Put the Python code behind a small FastAPI service and treat it as a real service boundary.
That works well for model experiments, data science utilities, document processing, evaluation helpers, or libraries that are simply stronger in Python. The .NET application calls an HTTP API instead of importing Python logic directly.
Use Aspire to make that polyglot setup runnable locally. Older examples used CommunityToolkit.Aspire.Hosting.Python.Extensions, but current Aspire puts this in the Aspire.Hosting.Python AppHost package. Model the FastAPI app as a Uvicorn resource, then reference it from the .NET service that calls it.
// AppHost Program.cs
var aiBackend = builder.AddUvicornApp("ai-backend", "../ai_service", "main:app")
.WithUv(); // or .WithPip() for requirements.txt
builder.AddProject<Projects.WebFrontend>("frontend")
.WithReference(aiBackend);
That keeps the Python URL in the application graph instead of scattered through local settings, launch profiles, and client constructors.
Keep the boundary boring. Define request and response models, use health checks, make timeouts explicit, and avoid turning the Python service into a hidden bag of scripts. It should be inspectable, testable, and replaceable.