Skip to content

Commit 3c252b9

Browse files
authored
Merge pull request #595 from hchen2020/master
python interpreter
2 parents 081b20c + 828b0aa commit 3c252b9

File tree

14 files changed

+237
-1
lines changed

14 files changed

+237
-1
lines changed

BotSharp.sln

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "FileStorages", "FileStorage
105105
EndProject
106106
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BotSharp.Plugin.TencentCos", "src\Plugins\BotSharp.Plugin.TencentCos\BotSharp.Plugin.TencentCos.csproj", "{BF029B0A-768B-43A1-8D91-E70B95505716}"
107107
EndProject
108+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Interpreters", "Interpreters", "{C4C59872-3C8A-450D-83D5-2BE402D610D5}"
109+
EndProject
110+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BotSharp.Plugin.PythonInterpreter", "src\Plugins\BotSharp.Plugin.PythonInterpreter\BotSharp.Plugin.PythonInterpreter.csproj", "{05E6E405-5021-406E-8A5E-0A7CEC881F6D}"
111+
EndProject
108112
Global
109113
GlobalSection(SolutionConfigurationPlatforms) = preSolution
110114
Debug|Any CPU = Debug|Any CPU
@@ -425,6 +429,14 @@ Global
425429
{BF029B0A-768B-43A1-8D91-E70B95505716}.Release|Any CPU.Build.0 = Release|Any CPU
426430
{BF029B0A-768B-43A1-8D91-E70B95505716}.Release|x64.ActiveCfg = Release|Any CPU
427431
{BF029B0A-768B-43A1-8D91-E70B95505716}.Release|x64.Build.0 = Release|Any CPU
432+
{05E6E405-5021-406E-8A5E-0A7CEC881F6D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
433+
{05E6E405-5021-406E-8A5E-0A7CEC881F6D}.Debug|Any CPU.Build.0 = Debug|Any CPU
434+
{05E6E405-5021-406E-8A5E-0A7CEC881F6D}.Debug|x64.ActiveCfg = Debug|Any CPU
435+
{05E6E405-5021-406E-8A5E-0A7CEC881F6D}.Debug|x64.Build.0 = Debug|Any CPU
436+
{05E6E405-5021-406E-8A5E-0A7CEC881F6D}.Release|Any CPU.ActiveCfg = Release|Any CPU
437+
{05E6E405-5021-406E-8A5E-0A7CEC881F6D}.Release|Any CPU.Build.0 = Release|Any CPU
438+
{05E6E405-5021-406E-8A5E-0A7CEC881F6D}.Release|x64.ActiveCfg = Release|Any CPU
439+
{05E6E405-5021-406E-8A5E-0A7CEC881F6D}.Release|x64.Build.0 = Release|Any CPU
428440
EndGlobalSection
429441
GlobalSection(SolutionProperties) = preSolution
430442
HideSolutionNode = FALSE
@@ -475,6 +487,8 @@ Global
475487
{54E83C6F-54EE-4ADC-8D72-93C009CC4FB4} = {51AFE054-AE99-497D-A593-69BAEFB5106F}
476488
{38B37C0D-1930-4D47-BCBF-E358EC1096B1} = {2635EC9B-2E5F-4313-AC21-0B847F31F36C}
477489
{BF029B0A-768B-43A1-8D91-E70B95505716} = {38B37C0D-1930-4D47-BCBF-E358EC1096B1}
490+
{C4C59872-3C8A-450D-83D5-2BE402D610D5} = {2635EC9B-2E5F-4313-AC21-0B847F31F36C}
491+
{05E6E405-5021-406E-8A5E-0A7CEC881F6D} = {C4C59872-3C8A-450D-83D5-2BE402D610D5}
478492
EndGlobalSection
479493
GlobalSection(ExtensibilityGlobals) = postSolution
480494
SolutionGuid = {A9969D89-C98B-40A5-A12B-FC87E55B3A19}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
namespace BotSharp.Abstraction.Interpreters.Models;
2+
3+
public class InterpretationRequest
4+
{
5+
[JsonPropertyName("script")]
6+
public string Script { get; set; } = null!;
7+
8+
[JsonPropertyName("language")]
9+
public string Language { get; set; } = null!;
10+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>$(TargetFramework)</TargetFramework>
5+
<Nullable>enable</Nullable>
6+
<LangVersion>$(LangVersion)</LangVersion>
7+
<VersionPrefix>$(BotSharpVersion)</VersionPrefix>
8+
<GeneratePackageOnBuild>$(GeneratePackageOnBuild)</GeneratePackageOnBuild>
9+
<GenerateDocumentationFile>$(GenerateDocumentationFile)</GenerateDocumentationFile>
10+
<OutputPath>$(SolutionDir)packages</OutputPath>
11+
</PropertyGroup>
12+
13+
<ItemGroup>
14+
<None Remove="data\agents\6745151e-6d46-4a02-8de4-1c4f21c7da95\functions\python_interpreter.json" />
15+
<None Remove="data\agents\6745151e-6d46-4a02-8de4-1c4f21c7da95\templates\python_interpreter.fn.liquid" />
16+
</ItemGroup>
17+
18+
<ItemGroup>
19+
<Content Include="data\agents\6745151e-6d46-4a02-8de4-1c4f21c7da95\functions\python_interpreter.json">
20+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
21+
</Content>
22+
<Content Include="data\agents\6745151e-6d46-4a02-8de4-1c4f21c7da95\templates\python_interpreter.fn.liquid">
23+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
24+
</Content>
25+
</ItemGroup>
26+
27+
<ItemGroup>
28+
<PackageReference Include="pythonnet" Version="3.0.3" />
29+
</ItemGroup>
30+
31+
<ItemGroup>
32+
<ProjectReference Include="..\..\Infrastructure\BotSharp.Abstraction\BotSharp.Abstraction.csproj" />
33+
</ItemGroup>
34+
35+
</Project>
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
namespace BotSharp.Plugin.PythonInterpreter.Enums;
2+
3+
public class UtilityName
4+
{
5+
public const string PythonInterpreter = "python-interpreter";
6+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
using BotSharp.Abstraction.Conversations.Models;
2+
using BotSharp.Abstraction.Functions;
3+
using BotSharp.Abstraction.Interpreters.Models;
4+
using Microsoft.Extensions.Logging;
5+
using Python.Runtime;
6+
using System.Text.Json;
7+
using System.Threading.Tasks;
8+
9+
namespace BotSharp.Plugin.PythonInterpreter.Functions;
10+
11+
public class InterpretationFn : IFunctionCallback
12+
{
13+
public string Name => "python_interpreter";
14+
public string Indication => "Interpreting python code";
15+
16+
private readonly IServiceProvider _services;
17+
private readonly ILogger _logger;
18+
19+
public async Task<bool> Execute(RoleDialogModel message)
20+
{
21+
var args = JsonSerializer.Deserialize<InterpretationRequest>(message.FunctionArgs);
22+
23+
using (Py.GIL())
24+
{
25+
// Import necessary Python modules
26+
dynamic sys = Py.Import("sys");
27+
dynamic io = Py.Import("io");
28+
29+
// Redirect standard output to capture it
30+
dynamic stringIO = io.StringIO();
31+
sys.stdout = stringIO;
32+
33+
// Execute a simple Python script
34+
using var locals = new PyDict();
35+
PythonEngine.Exec(args.Script, null, locals);
36+
37+
// Console.WriteLine($"Result from Python: {result}");
38+
message.Content = stringIO.getvalue();
39+
40+
// Restore the original stdout
41+
sys.stdout = sys.__stdout__;
42+
}
43+
44+
return true;
45+
}
46+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
namespace BotSharp.Plugin.PythonInterpreter.Hooks;
2+
3+
public class InterpreterAgentHook : AgentHookBase
4+
{
5+
private static string FUNCTION_NAME = "python_interpreter";
6+
7+
public override string SelfId => string.Empty;
8+
9+
public InterpreterAgentHook(IServiceProvider services, AgentSettings settings)
10+
: base(services, settings)
11+
{
12+
}
13+
public override void OnAgentLoaded(Agent agent)
14+
{
15+
var conv = _services.GetRequiredService<IConversationService>();
16+
var isConvMode = conv.IsConversationMode();
17+
var isEnabled = !agent.Utilities.IsNullOrEmpty() && agent.Utilities.Contains(UtilityName.PythonInterpreter);
18+
19+
if (isConvMode && isEnabled)
20+
{
21+
var (prompt, fn) = GetPromptAndFunction();
22+
if (fn != null)
23+
{
24+
if (!string.IsNullOrWhiteSpace(prompt))
25+
{
26+
agent.Instruction += $"\r\n\r\n{prompt}\r\n\r\n";
27+
}
28+
29+
if (agent.Functions == null)
30+
{
31+
agent.Functions = new List<FunctionDef> { fn };
32+
}
33+
else
34+
{
35+
agent.Functions.Add(fn);
36+
}
37+
}
38+
}
39+
40+
base.OnAgentLoaded(agent);
41+
}
42+
43+
private (string, FunctionDef?) GetPromptAndFunction()
44+
{
45+
var db = _services.GetRequiredService<IBotSharpRepository>();
46+
var agent = db.GetAgent(BuiltInAgentId.UtilityAssistant);
47+
var prompt = agent?.Templates?.FirstOrDefault(x => x.Name.IsEqualTo($"{FUNCTION_NAME}.fn"))?.Content ?? string.Empty;
48+
var loadAttachmentFn = agent?.Functions?.FirstOrDefault(x => x.Name.IsEqualTo(FUNCTION_NAME));
49+
return (prompt, loadAttachmentFn);
50+
}
51+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
namespace BotSharp.Plugin.PythonInterpreter.Hooks;
2+
3+
public class InterpreterUtilityHook : IAgentUtilityHook
4+
{
5+
public void AddUtilities(List<string> utilities)
6+
{
7+
utilities.Add(UtilityName.PythonInterpreter);
8+
}
9+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
using BotSharp.Plugin.PythonInterpreter.Hooks;
2+
3+
namespace BotSharp.Plugin.PythonInterpreter;
4+
5+
public class InterpreterPlugin : IBotSharpPlugin
6+
{
7+
public string Id => "23174e08-e866-4173-824a-cf1d97afa8d0";
8+
public string Name => "Python Interpreter";
9+
public string Description => "Python Interpreter enables AI to write and execute Python code within a secure, sandboxed environment.";
10+
public string? IconUrl => "https://static.vecteezy.com/system/resources/previews/012/697/295/non_2x/3d-python-programming-language-logo-free-png.png";
11+
12+
public void RegisterDI(IServiceCollection services, IConfiguration config)
13+
{
14+
services.AddScoped<IAgentHook, InterpreterAgentHook>();
15+
services.AddScoped<IAgentUtilityHook, InterpreterUtilityHook>();
16+
}
17+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
global using System;
2+
global using System.Linq;
3+
global using System.Collections.Generic;
4+
5+
global using Microsoft.Extensions.Configuration;
6+
global using Microsoft.Extensions.DependencyInjection;
7+
8+
global using BotSharp.Abstraction.Agents;
9+
global using BotSharp.Abstraction.Plugins;
10+
global using BotSharp.Abstraction.Utilities;
11+
global using BotSharp.Abstraction.Agents.Enums;
12+
global using BotSharp.Abstraction.Agents.Models;
13+
global using BotSharp.Abstraction.Agents.Settings;
14+
global using BotSharp.Abstraction.Conversations;
15+
global using BotSharp.Abstraction.Functions.Models;
16+
global using BotSharp.Abstraction.Repositories;
17+
18+
global using BotSharp.Plugin.PythonInterpreter.Enums;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"name": "python_interpreter",
3+
"description": "write and execute python code, print the result in Console",
4+
"parameters": {
5+
"type": "object",
6+
"properties": {
7+
"script": {
8+
"type": "string",
9+
"description": "python code"
10+
},
11+
"language": {
12+
"type": "string",
13+
"enum": [ "python" ],
14+
"description": "python code"
15+
}
16+
},
17+
"required": [ "language", "script" ]
18+
}
19+
}

0 commit comments

Comments
 (0)