Skip to content

Commit

Permalink
[.Net][AutoGen.DotnetInteractive] add DotnetInteractiveStdioConnector (
Browse files Browse the repository at this point in the history
…microsoft#3337)

* add DotnetInteractiveStdioCOnector

* update

* update

* comment out DotnetInteractive test

* add header

* update
  • Loading branch information
LittleLittleCloud authored Aug 10, 2024
1 parent 972b4ed commit f49ed29
Show file tree
Hide file tree
Showing 9 changed files with 367 additions and 186 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public async Task CodeSnippet1()

#region code_snippet_1_1
var kernel = DotnetInteractiveKernelBuilder
.CreateDefaultBuilder() // add C# and F# kernels
.CreateDefaultInProcessKernelBuilder() // add C# and F# kernels
.Build();
#endregion code_snippet_1_1

Expand Down Expand Up @@ -67,7 +67,7 @@ public async Task CodeSnippet1()

#region code_snippet_1_4
var pythonKernel = DotnetInteractiveKernelBuilder
.CreateDefaultBuilder()
.CreateDefaultInProcessKernelBuilder()
.AddPythonKernel(venv: "python3")
.Build();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public static async Task RunAsync()
var instance = new Example04_Dynamic_GroupChat_Coding_Task();

var kernel = DotnetInteractiveKernelBuilder
.CreateDefaultBuilder()
.CreateDefaultInProcessKernelBuilder()
.AddPythonKernel("python3")
.Build();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,9 @@ public static async Task<IAgent> CreateReviewerAgentAsync(OpenAIClient openAICli
public static async Task RunWorkflowAsync()
{
long the39thFibonacciNumber = 63245986;
var kernel = DotnetInteractiveKernelBuilder.CreateDefaultBuilder().Build();
var kernel = DotnetInteractiveKernelBuilder
.CreateDefaultInProcessKernelBuilder()
.Build();

var config = LLMConfiguration.GetAzureOpenAIGPT3_5_Turbo();
var openaiClient = new OpenAIClient(new Uri(config.Endpoint), new Azure.AzureKeyCredential(config.ApiKey));
Expand Down Expand Up @@ -344,7 +346,9 @@ public static async Task RunAsync()
var config = LLMConfiguration.GetAzureOpenAIGPT3_5_Turbo();
var openaiClient = new OpenAIClient(new Uri(config.Endpoint), new Azure.AzureKeyCredential(config.ApiKey));

var kernel = DotnetInteractiveKernelBuilder.CreateDefaultBuilder().Build();
var kernel = DotnetInteractiveKernelBuilder
.CreateDefaultInProcessKernelBuilder()
.Build();
#region create_group_chat
var reviewer = await CreateReviewerAgentAsync(openaiClient, config.DeploymentName);
var coder = await CreateCoderAgentAsync(openaiClient, config.DeploymentName);
Expand Down
117 changes: 9 additions & 108 deletions dotnet/src/AutoGen.DotnetInteractive/DotnetInteractiveKernelBuilder.cs
Original file line number Diff line number Diff line change
@@ -1,127 +1,28 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// DotnetInteractiveKernelBuilder.cs

#if NET8_0_OR_GREATER
using AutoGen.DotnetInteractive.Extension;
using Microsoft.DotNet.Interactive;
using Microsoft.DotNet.Interactive.Commands;
using Microsoft.DotNet.Interactive.CSharp;
using Microsoft.DotNet.Interactive.FSharp;
using Microsoft.DotNet.Interactive.Jupyter;
using Microsoft.DotNet.Interactive.PackageManagement;
using Microsoft.DotNet.Interactive.PowerShell;

namespace AutoGen.DotnetInteractive;

public class DotnetInteractiveKernelBuilder
public static class DotnetInteractiveKernelBuilder
{
private readonly CompositeKernel compositeKernel;

private DotnetInteractiveKernelBuilder()
#if NET8_0_OR_GREATER
public static InProccessDotnetInteractiveKernelBuilder CreateEmptyInProcessKernelBuilder()
{
this.compositeKernel = new CompositeKernel();

// add jupyter connector
this.compositeKernel.AddKernelConnector(
new ConnectJupyterKernelCommand()
.AddConnectionOptions(new JupyterHttpKernelConnectionOptions())
.AddConnectionOptions(new JupyterLocalKernelConnectionOptions()));
return new InProccessDotnetInteractiveKernelBuilder();
}

/// <summary>
/// Create an empty builder.
/// </summary>
/// <returns></returns>
public static DotnetInteractiveKernelBuilder CreateEmptyBuilder()
{
return new DotnetInteractiveKernelBuilder();
}

/// <summary>
/// Create a default builder with C# and F# kernels.
/// </summary>
public static DotnetInteractiveKernelBuilder CreateDefaultBuilder()
public static InProccessDotnetInteractiveKernelBuilder CreateDefaultInProcessKernelBuilder()
{
return new DotnetInteractiveKernelBuilder()
return new InProccessDotnetInteractiveKernelBuilder()
.AddCSharpKernel()
.AddFSharpKernel();
}
#endif

public DotnetInteractiveKernelBuilder AddCSharpKernel(IEnumerable<string>? aliases = null)
{
aliases ??= ["c#", "C#"];
// create csharp kernel
var csharpKernel = new CSharpKernel()
.UseNugetDirective((k, resolvedPackageReference) =>
{

k.AddAssemblyReferences(resolvedPackageReference
.SelectMany(r => r.AssemblyPaths));
return Task.CompletedTask;
})
.UseKernelHelpers()
.UseWho()
.UseMathAndLaTeX()
.UseValueSharing();

this.AddKernel(csharpKernel, aliases);

return this;
}

public DotnetInteractiveKernelBuilder AddFSharpKernel(IEnumerable<string>? aliases = null)
{
aliases ??= ["f#", "F#"];
// create fsharp kernel
var fsharpKernel = new FSharpKernel()
.UseDefaultFormatting()
.UseKernelHelpers()
.UseWho()
.UseMathAndLaTeX()
.UseValueSharing();

this.AddKernel(fsharpKernel, aliases);

return this;
}

public DotnetInteractiveKernelBuilder AddPowershellKernel(IEnumerable<string>? aliases = null)
{
aliases ??= ["pwsh", "powershell"];
// create powershell kernel
var powershellKernel = new PowerShellKernel()
.UseProfiles()
.UseValueSharing();

this.AddKernel(powershellKernel, aliases);

return this;
}

public DotnetInteractiveKernelBuilder AddPythonKernel(string venv, string kernelName = "python", IEnumerable<string>? aliases = null)
{
aliases ??= [kernelName];
// create python kernel
var magicCommand = $"#!connect jupyter --kernel-name {kernelName} --kernel-spec {venv}";
var connectCommand = new SubmitCode(magicCommand);
var result = this.compositeKernel.SendAsync(connectCommand).Result;

result.ThrowOnCommandFailed();

return this;
}

public CompositeKernel Build()
{
return this.compositeKernel
.UseDefaultMagicCommands()
.UseImportMagicCommand();
}

private DotnetInteractiveKernelBuilder AddKernel(Kernel kernel, IEnumerable<string>? aliases = null)
public static DotnetInteractiveStdioKernelConnector CreateKernelBuilder(string workingDirectory, string kernelName = "root-proxy")
{
this.compositeKernel.Add(kernel, aliases);
return this;
return new DotnetInteractiveStdioKernelConnector(workingDirectory, kernelName);
}
}
#endif
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// DotnetInteractiveStdioKernelConnector.cs

using AutoGen.DotnetInteractive.Extension;
using Microsoft.DotNet.Interactive;
using Microsoft.DotNet.Interactive.Commands;
using Microsoft.DotNet.Interactive.Connection;

namespace AutoGen.DotnetInteractive;

public class DotnetInteractiveStdioKernelConnector
{
private string workingDirectory;
private InteractiveService interactiveService;
private string kernelName;
private List<SubmitCode> setupCommands = new List<SubmitCode>();

internal DotnetInteractiveStdioKernelConnector(string workingDirectory, string kernelName = "root-proxy")
{
this.workingDirectory = workingDirectory;
this.interactiveService = new InteractiveService(workingDirectory);
this.kernelName = kernelName;
}

public DotnetInteractiveStdioKernelConnector RestoreDotnetInteractive()
{
if (this.interactiveService.RestoreDotnetInteractive())
{
return this;
}
else
{
throw new Exception("Failed to restore dotnet interactive tool.");
}
}

public DotnetInteractiveStdioKernelConnector AddPythonKernel(
string venv,
string kernelName = "python")
{
var magicCommand = $"#!connect jupyter --kernel-name {kernelName} --kernel-spec {venv}";
var connectCommand = new SubmitCode(magicCommand);

this.setupCommands.Add(connectCommand);

return this;
}

public async Task<Kernel> BuildAsync(CancellationToken ct = default)
{
var compositeKernel = new CompositeKernel();
var url = KernelHost.CreateHostUri(this.kernelName);
var cmd = new string[]
{
"dotnet",
"tool",
"run",
"dotnet-interactive",
$"[cb-{this.kernelName}]",
"stdio",
//"--default-kernel",
//"csharp",
"--working-dir",
$@"""{workingDirectory}""",
};
var connector = new StdIoKernelConnector(
cmd,
this.kernelName,
url,
new DirectoryInfo(this.workingDirectory));
var rootProxyKernel = await connector.CreateRootProxyKernelAsync();
rootProxyKernel.KernelInfo.SupportedKernelCommands.Add(new(nameof(SubmitCode)));
var dotnetKernel = await connector.CreateProxyKernelAsync(".NET");
foreach (var setupCommand in this.setupCommands)
{
var setupCommandResult = await rootProxyKernel.SendAsync(setupCommand, ct);
setupCommandResult.ThrowOnCommandFailed();
}

return rootProxyKernel;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// InProccessDotnetInteractiveKernelBuilder.cs

#if NET8_0_OR_GREATER
using AutoGen.DotnetInteractive.Extension;
using Microsoft.DotNet.Interactive;
using Microsoft.DotNet.Interactive.Commands;
using Microsoft.DotNet.Interactive.CSharp;
using Microsoft.DotNet.Interactive.FSharp;
using Microsoft.DotNet.Interactive.Jupyter;
using Microsoft.DotNet.Interactive.PackageManagement;
using Microsoft.DotNet.Interactive.PowerShell;

namespace AutoGen.DotnetInteractive;

/// <summary>
/// Build an in-proc dotnet interactive kernel.
/// </summary>
public class InProccessDotnetInteractiveKernelBuilder
{
private readonly CompositeKernel compositeKernel;

internal InProccessDotnetInteractiveKernelBuilder()
{
this.compositeKernel = new CompositeKernel();

// add jupyter connector
this.compositeKernel.AddKernelConnector(
new ConnectJupyterKernelCommand()
.AddConnectionOptions(new JupyterHttpKernelConnectionOptions())
.AddConnectionOptions(new JupyterLocalKernelConnectionOptions()));
}

public InProccessDotnetInteractiveKernelBuilder AddCSharpKernel(IEnumerable<string>? aliases = null)
{
aliases ??= ["c#", "C#", "csharp"];
// create csharp kernel
var csharpKernel = new CSharpKernel()
.UseNugetDirective((k, resolvedPackageReference) =>
{

k.AddAssemblyReferences(resolvedPackageReference
.SelectMany(r => r.AssemblyPaths));
return Task.CompletedTask;
})
.UseKernelHelpers()
.UseWho()
.UseMathAndLaTeX()
.UseValueSharing();

this.AddKernel(csharpKernel, aliases);

return this;
}

public InProccessDotnetInteractiveKernelBuilder AddFSharpKernel(IEnumerable<string>? aliases = null)
{
aliases ??= ["f#", "F#", "fsharp"];
// create fsharp kernel
var fsharpKernel = new FSharpKernel()
.UseDefaultFormatting()
.UseKernelHelpers()
.UseWho()
.UseMathAndLaTeX()
.UseValueSharing();

this.AddKernel(fsharpKernel, aliases);

return this;
}

public InProccessDotnetInteractiveKernelBuilder AddPowershellKernel(IEnumerable<string>? aliases = null)
{
aliases ??= ["pwsh", "powershell"];
// create powershell kernel
var powershellKernel = new PowerShellKernel()
.UseProfiles()
.UseValueSharing();

this.AddKernel(powershellKernel, aliases);

return this;
}

public InProccessDotnetInteractiveKernelBuilder AddPythonKernel(string venv, string kernelName = "python")
{
// create python kernel
var magicCommand = $"#!connect jupyter --kernel-name {kernelName} --kernel-spec {venv}";
var connectCommand = new SubmitCode(magicCommand);
var result = this.compositeKernel.SendAsync(connectCommand).Result;

result.ThrowOnCommandFailed();

return this;
}

public CompositeKernel Build()
{
return this.compositeKernel
.UseDefaultMagicCommands()
.UseImportMagicCommand();
}

private InProccessDotnetInteractiveKernelBuilder AddKernel(Kernel kernel, IEnumerable<string>? aliases = null)
{
this.compositeKernel.Add(kernel, aliases);
return this;
}
}
#endif
Loading

0 comments on commit f49ed29

Please sign in to comment.