diff --git a/src/Plugins/BotSharp.Plugin.PythonInterpreter/BotSharp.Plugin.PythonInterpreter.csproj b/src/Plugins/BotSharp.Plugin.PythonInterpreter/BotSharp.Plugin.PythonInterpreter.csproj
index ab15acf7..db85df01 100644
--- a/src/Plugins/BotSharp.Plugin.PythonInterpreter/BotSharp.Plugin.PythonInterpreter.csproj
+++ b/src/Plugins/BotSharp.Plugin.PythonInterpreter/BotSharp.Plugin.PythonInterpreter.csproj
@@ -33,7 +33,7 @@
-
+
diff --git a/src/Plugins/BotSharp.Plugin.PythonInterpreter/Functions/PyInterpretationFn.cs b/src/Plugins/BotSharp.Plugin.PythonInterpreter/Functions/PyInterpretationFn.cs
index 818340b9..7706f984 100644
--- a/src/Plugins/BotSharp.Plugin.PythonInterpreter/Functions/PyInterpretationFn.cs
+++ b/src/Plugins/BotSharp.Plugin.PythonInterpreter/Functions/PyInterpretationFn.cs
@@ -1,8 +1,7 @@
-using BotSharp.Abstraction.Conversations.Models;
-using BotSharp.Abstraction.Functions;
-using BotSharp.Abstraction.Interpreters.Models;
+using BotSharp.Abstraction.Routing;
using Microsoft.Extensions.Logging;
using Python.Runtime;
+using System.Runtime;
using System.Text.Json;
using System.Threading.Tasks;
@@ -26,7 +25,40 @@ public class PyInterpretationFn : IFunctionCallback
public async Task Execute(RoleDialogModel message)
{
- var args = JsonSerializer.Deserialize(message.FunctionArgs);
+ var agentService = _services.GetRequiredService();
+ var convService = _services.GetRequiredService();
+ var routingCtx = _services.GetRequiredService();
+
+ var args = JsonSerializer.Deserialize(message.FunctionArgs);
+
+ var agent = await agentService.GetAgent(message.CurrentAgentId);
+ var inst = GetPyCodeGenerationInstruction(message.CurrentAgentId);
+ var innerAgent = new Agent
+ {
+ Id = agent.Id,
+ Name = agent.Name,
+ Instruction = inst,
+ LlmConfig = GetLlmConfig(),
+ TemplateDict = new Dictionary
+ {
+ { "user_requirement", args?.UserRquirement ?? string.Empty }
+ }
+ };
+
+ var dialogs = routingCtx.GetDialogs();
+ if (dialogs.IsNullOrEmpty())
+ {
+ dialogs = convService.GetDialogHistory();
+ }
+
+ dialogs.Add(new RoleDialogModel(AgentRole.User, "Please follow the instruction and chat context to generate valid python code.")
+ {
+ CurrentAgentId = message.CurrentAgentId,
+ MessageId = message.MessageId
+ });
+
+ var response = await GetChatCompletion(innerAgent, dialogs);
+ var ret = response.JsonContent();
using (Py.GIL())
{
@@ -40,7 +72,7 @@ public class PyInterpretationFn : IFunctionCallback
// Execute a simple Python script
using var locals = new PyDict();
- PythonEngine.Exec(args.Script, null, locals);
+ PythonEngine.Exec(ret.PythonCode, null, locals);
// Console.WriteLine($"Result from Python: {result}");
message.Content = stringIO.getvalue();
@@ -51,4 +83,74 @@ public class PyInterpretationFn : IFunctionCallback
return true;
}
+
+ private async Task GetChatCompletion(Agent agent, List dialogs)
+ {
+ try
+ {
+ var (provider, model) = GetLlmProviderModel();
+ var completion = CompletionProvider.GetChatCompletion(_services, provider: provider, model: model);
+ var response = await completion.GetChatCompletions(agent, dialogs);
+ return response.Content;
+ }
+ catch (Exception ex)
+ {
+ var error = $"Error when plotting chart. {ex.Message}";
+ _logger.LogWarning(ex, error);
+ return error;
+ }
+ }
+
+ private string GetPyCodeGenerationInstruction(string agentId)
+ {
+ var db = _services.GetRequiredService();
+ var state = _services.GetRequiredService();
+
+ var templateContent = string.Empty;
+ var templateName = state.GetState("python_generate_template");
+
+ if (!string.IsNullOrEmpty(templateName))
+ {
+ templateContent = db.GetAgentTemplate(agentId, templateName);
+ }
+ else
+ {
+ templateName = "util-code-python_generate_instruction";
+ templateContent = db.GetAgentTemplate(BuiltInAgentId.UtilityAssistant, templateName);
+ }
+
+ return templateContent;
+ }
+
+ private (string, string) GetLlmProviderModel()
+ {
+ var provider = "openai";
+ var model = "gpt-5";
+
+ var state = _services.GetRequiredService();
+ provider = state.GetState("py_generator_llm_provider")
+ //.IfNullOrEmptyAs(_settings.ChartPlot?.LlmProvider)
+ .IfNullOrEmptyAs(provider);
+ model = state.GetState("py_generator_llm_model")
+ //.IfNullOrEmptyAs(_settings.ChartPlot?.LlmModel)
+ .IfNullOrEmptyAs(model);
+
+ return (provider, model);
+ }
+
+ private AgentLlmConfig GetLlmConfig()
+ {
+ var maxOutputTokens = 8192;
+ var reasoningEffortLevel = "minimal";
+
+ var state = _services.GetRequiredService();
+ maxOutputTokens = int.TryParse(state.GetState("py_generator_max_output_tokens"), out var tokens) ? tokens : maxOutputTokens;
+ reasoningEffortLevel = state.GetState("py_generator_reasoning_effort_level").IfNullOrEmptyAs(reasoningEffortLevel);
+
+ return new AgentLlmConfig
+ {
+ MaxOutputTokens = maxOutputTokens,
+ ReasoningEffortLevel = reasoningEffortLevel
+ };
+ }
}
diff --git a/src/Plugins/BotSharp.Plugin.PythonInterpreter/InterpreterPlugin.cs b/src/Plugins/BotSharp.Plugin.PythonInterpreter/InterpreterPlugin.cs
index 7d195286..2e1e723b 100644
--- a/src/Plugins/BotSharp.Plugin.PythonInterpreter/InterpreterPlugin.cs
+++ b/src/Plugins/BotSharp.Plugin.PythonInterpreter/InterpreterPlugin.cs
@@ -1,4 +1,5 @@
using BotSharp.Abstraction.Interpreters.Settings;
+using BotSharp.Abstraction.Settings;
using BotSharp.Plugin.PythonInterpreter.Hooks;
using Microsoft.AspNetCore.Builder;
using Python.Runtime;
@@ -15,6 +16,12 @@ public class InterpreterPlugin : IBotSharpAppPlugin
public void RegisterDI(IServiceCollection services, IConfiguration config)
{
+ services.AddSingleton(provider =>
+ {
+ var settingService = provider.GetRequiredService();
+ return settingService.Bind("Interpreter");
+ });
+
services.AddScoped();
}
diff --git a/src/Plugins/BotSharp.Plugin.PythonInterpreter/LlmContext/LlmContextIn.cs b/src/Plugins/BotSharp.Plugin.PythonInterpreter/LlmContext/LlmContextIn.cs
new file mode 100644
index 00000000..bcac0e8b
--- /dev/null
+++ b/src/Plugins/BotSharp.Plugin.PythonInterpreter/LlmContext/LlmContextIn.cs
@@ -0,0 +1,9 @@
+using System.Text.Json.Serialization;
+
+namespace BotSharp.Plugin.PythonInterpreter.LlmContext;
+
+public class LlmContextIn
+{
+ [JsonPropertyName("user_requirement")]
+ public string UserRquirement { get; set; }
+}
diff --git a/src/Plugins/BotSharp.Plugin.PythonInterpreter/LlmContext/LlmContextOut.cs b/src/Plugins/BotSharp.Plugin.PythonInterpreter/LlmContext/LlmContextOut.cs
new file mode 100644
index 00000000..b074a004
--- /dev/null
+++ b/src/Plugins/BotSharp.Plugin.PythonInterpreter/LlmContext/LlmContextOut.cs
@@ -0,0 +1,9 @@
+using System.Text.Json.Serialization;
+
+namespace BotSharp.Plugin.PythonInterpreter.LlmContext;
+
+public class LlmContextOut
+{
+ [JsonPropertyName("python_code")]
+ public string PythonCode { get; set; }
+}
diff --git a/src/Plugins/BotSharp.Plugin.PythonInterpreter/Using.cs b/src/Plugins/BotSharp.Plugin.PythonInterpreter/Using.cs
index 8cc31aa1..00a172fa 100644
--- a/src/Plugins/BotSharp.Plugin.PythonInterpreter/Using.cs
+++ b/src/Plugins/BotSharp.Plugin.PythonInterpreter/Using.cs
@@ -14,5 +14,12 @@ global using BotSharp.Abstraction.Agents.Settings;
global using BotSharp.Abstraction.Conversations;
global using BotSharp.Abstraction.Functions.Models;
global using BotSharp.Abstraction.Repositories;
+global using BotSharp.Abstraction.Conversations.Models;
+global using BotSharp.Abstraction.Functions;
+global using BotSharp.Abstraction.Interpreters.Models;
+
+
+global using BotSharp.Core.Infrastructures;
global using BotSharp.Plugin.PythonInterpreter.Enums;
+global using BotSharp.Plugin.PythonInterpreter.LlmContext;
diff --git a/src/Plugins/BotSharp.Plugin.PythonInterpreter/data/agents/6745151e-6d46-4a02-8de4-1c4f21c7da95/functions/util-code-python_interpreter.json b/src/Plugins/BotSharp.Plugin.PythonInterpreter/data/agents/6745151e-6d46-4a02-8de4-1c4f21c7da95/functions/util-code-python_interpreter.json
index ac2b2a91..ee5a708e 100644
--- a/src/Plugins/BotSharp.Plugin.PythonInterpreter/data/agents/6745151e-6d46-4a02-8de4-1c4f21c7da95/functions/util-code-python_interpreter.json
+++ b/src/Plugins/BotSharp.Plugin.PythonInterpreter/data/agents/6745151e-6d46-4a02-8de4-1c4f21c7da95/functions/util-code-python_interpreter.json
@@ -1,19 +1,14 @@
{
- "name": "python_interpreter",
- "description": "write and execute python code, print the result in Console",
+ "name": "util-code-python_interpreter",
+ "description": "If the user requests you generating python code to complete tasks, you can call this function to generate python code to execute.",
"parameters": {
"type": "object",
"properties": {
- "script": {
+ "user_requirement": {
"type": "string",
- "description": "python code"
- },
- "language": {
- "type": "string",
- "enum": [ "python" ],
- "description": "python code"
+ "description": "The requirement that user posted for generating python code."
}
},
- "required": [ "language", "script" ]
+ "required": [ "user_requirement" ]
}
}
\ No newline at end of file
diff --git a/src/Plugins/BotSharp.Plugin.PythonInterpreter/data/agents/6745151e-6d46-4a02-8de4-1c4f21c7da95/templates/util-code-python_interpreter.fn.liquid b/src/Plugins/BotSharp.Plugin.PythonInterpreter/data/agents/6745151e-6d46-4a02-8de4-1c4f21c7da95/templates/util-code-python_interpreter.fn.liquid
index 8dd2425f..9037aaff 100644
--- a/src/Plugins/BotSharp.Plugin.PythonInterpreter/data/agents/6745151e-6d46-4a02-8de4-1c4f21c7da95/templates/util-code-python_interpreter.fn.liquid
+++ b/src/Plugins/BotSharp.Plugin.PythonInterpreter/data/agents/6745151e-6d46-4a02-8de4-1c4f21c7da95/templates/util-code-python_interpreter.fn.liquid
@@ -1 +1 @@
-Write and execute Python script in python_interpreter function, and use python function print(a) to output the result in stand output.
\ No newline at end of file
+Please call function util-code-python_interpreter if user wants to generate python code to complete tasks.
\ No newline at end of file