Merge pull request #513 from iceljc/features/upgrade-open-ai
Features/upgrade open ai
This commit is contained in:
commit
16b1285a86
|
|
@ -4,5 +4,4 @@ public class AgentTool
|
|||
{
|
||||
public const string FileAnalyzer = "file-analyzer";
|
||||
public const string ImageGenerator = "image-generator";
|
||||
public const string HttpHandler = "http-handler";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,6 @@
|
|||
namespace BotSharp.Abstraction.Agents;
|
||||
|
||||
public interface IAgentToolHook
|
||||
{
|
||||
void AddTools(List<string> tools);
|
||||
}
|
||||
|
|
@ -29,4 +29,6 @@ public interface IBotSharpFileService
|
|||
/// <param name="data"></param>
|
||||
/// <returns></returns>
|
||||
(string, byte[]) GetFileInfoFromData(string data);
|
||||
|
||||
string GetFileContentType(string filePath);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -86,10 +86,8 @@ public partial class AgentService
|
|||
|
||||
foreach (var file in Directory.GetFiles(templateDir))
|
||||
{
|
||||
var fileName = file.Split(Path.DirectorySeparatorChar).Last();
|
||||
var splitIdx = fileName.LastIndexOf(".");
|
||||
var name = fileName.Substring(0, splitIdx);
|
||||
var extension = fileName.Substring(splitIdx + 1);
|
||||
var name = Path.GetFileNameWithoutExtension(file);
|
||||
var extension = Path.GetExtension(file).Substring(1);
|
||||
if (extension.IsEqualTo(_agentSettings.TemplateFormat))
|
||||
{
|
||||
var content = File.ReadAllText(file);
|
||||
|
|
@ -102,11 +100,28 @@ public partial class AgentService
|
|||
|
||||
private List<FunctionDef> FetchFunctionsFromFile(string fileDir)
|
||||
{
|
||||
var file = Path.Combine(fileDir, "functions.json");
|
||||
if (!File.Exists(file)) return new List<FunctionDef>();
|
||||
var functions = new List<FunctionDef>();
|
||||
var functionDir = Path.Combine(fileDir, "functions");
|
||||
|
||||
var functionsJson = File.ReadAllText(file);
|
||||
var functions = JsonSerializer.Deserialize<List<FunctionDef>>(functionsJson, _options);
|
||||
if (!Directory.Exists(functionDir)) return functions;
|
||||
|
||||
foreach (var file in Directory.GetFiles(functionDir))
|
||||
{
|
||||
try
|
||||
{
|
||||
var extension = Path.GetExtension(file).Substring(1);
|
||||
if (extension != "json") continue;
|
||||
|
||||
var json = File.ReadAllText(file);
|
||||
var function = JsonSerializer.Deserialize<FunctionDef>(json, _options);
|
||||
functions.Add(function);
|
||||
}
|
||||
catch
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
return functions;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -57,11 +57,13 @@ public partial class AgentService : IAgentService
|
|||
|
||||
public IEnumerable<string> GetAgentTools()
|
||||
{
|
||||
var tools = typeof(AgentTool).GetFields(BindingFlags.Public | BindingFlags.Static)
|
||||
.Where(f => f.IsLiteral && f.FieldType == typeof(string))
|
||||
.Select(x => x.GetRawConstantValue()?.ToString())
|
||||
.ToList();
|
||||
var tools = new List<string>();
|
||||
|
||||
return tools;
|
||||
var hooks = _services.GetServices<IAgentToolHook>();
|
||||
foreach (var hook in hooks)
|
||||
{
|
||||
hook.AddTools(tools);
|
||||
}
|
||||
return tools.Where(x => !string.IsNullOrWhiteSpace(x)).Distinct().OrderBy(x => x).ToList();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,10 +48,11 @@
|
|||
<ItemGroup>
|
||||
<None Remove="data\agents\00000000-0000-0000-0000-000000000000\agent.json" />
|
||||
<None Remove="data\agents\00000000-0000-0000-0000-000000000000\instruction.liquid" />
|
||||
<None Remove="data\agents\00000000-0000-0000-0000-000000000000\functions.json" />
|
||||
<None Remove="data\agents\00000000-0000-0000-0000-000000000000\templates\load_attachment_prompt.liquid" />
|
||||
<None Remove="data\agents\00000000-0000-0000-0000-000000000000\functions\load_attachment.json" />
|
||||
<None Remove="data\agents\00000000-0000-0000-0000-000000000000\templates\load_attachment.fn.liquid" />
|
||||
<None Remove="data\agents\01dcc3e5-0af7-49e6-ad7a-a760bd12dc4b\agent.json" />
|
||||
<None Remove="data\agents\01dcc3e5-0af7-49e6-ad7a-a760bd12dc4b\functions.json" />
|
||||
<None Remove="data\agents\01dcc3e5-0af7-49e6-ad7a-a760bd12dc4b\functions\human_intervention_needed.json" />
|
||||
<None Remove="data\agents\01dcc3e5-0af7-49e6-ad7a-a760bd12dc4b\instruction.liquid" />
|
||||
<None Remove="data\agents\01fcc3e5-0af7-49e6-ad7a-a760bd12dc4d\agent.json" />
|
||||
<None Remove="data\agents\01fcc3e5-0af7-49e6-ad7a-a760bd12dc4d\instruction.liquid" />
|
||||
|
|
@ -81,10 +82,13 @@
|
|||
<Content Include="data\agents\01dcc3e5-0af7-49e6-ad7a-a760bd12dc4b\agent.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="data\agents\01dcc3e5-0af7-49e6-ad7a-a760bd12dc4b\instruction.liquid">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="data\agents\01dcc3e5-0af7-49e6-ad7a-a760bd12dc4b\functions.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="data\agents\01dcc3e5-0af7-49e6-ad7a-a760bd12dc4b\instruction.liquid">
|
||||
<Content Include="data\agents\01dcc3e5-0af7-49e6-ad7a-a760bd12dc4b\functions\human_intervention_needed.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="data\agents\01fcc3e5-0af7-49e6-ad7a-a760bd12dc4d\agent.json">
|
||||
|
|
@ -156,10 +160,10 @@
|
|||
<Content Include="data\agents\00000000-0000-0000-0000-000000000000\instruction.liquid">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="data\agents\00000000-0000-0000-0000-000000000000\functions.json">
|
||||
<Content Include="data\agents\00000000-0000-0000-0000-000000000000\functions\load_attachment.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="data\agents\00000000-0000-0000-0000-000000000000\templates\load_attachment_prompt.liquid">
|
||||
<Content Include="data\agents\00000000-0000-0000-0000-000000000000\templates\load_attachment.fn.liquid">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="data\plugins\config.json">
|
||||
|
|
|
|||
|
|
@ -66,8 +66,7 @@ public partial class BotSharpFileService : IBotSharpFileService
|
|||
return (contentType, Convert.FromBase64String(base64Str));
|
||||
}
|
||||
|
||||
#region Private methods
|
||||
private string GetFileContentType(string filePath)
|
||||
public string GetFileContentType(string filePath)
|
||||
{
|
||||
string contentType;
|
||||
var provider = new FileExtensionContentTypeProvider();
|
||||
|
|
@ -79,6 +78,7 @@ public partial class BotSharpFileService : IBotSharpFileService
|
|||
return contentType;
|
||||
}
|
||||
|
||||
#region Private methods
|
||||
private bool ExistDirectory(string? dir)
|
||||
{
|
||||
return !string.IsNullOrEmpty(dir) && Directory.Exists(dir);
|
||||
|
|
|
|||
|
|
@ -17,5 +17,6 @@ public class FilePlugin : IBotSharpPlugin
|
|||
services.AddScoped<IBotSharpFileService, BotSharpFileService>();
|
||||
|
||||
services.AddScoped<IAgentHook, AttachmentProcessingHook>();
|
||||
services.AddScoped<IAgentToolHook, FileAnalyzerToolHook>();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,8 +19,8 @@ public class AttachmentProcessingHook : AgentHookBase
|
|||
|
||||
if (isConvMode && isEnabled)
|
||||
{
|
||||
var (prompt, loadAttachmentFn) = GetLoadAttachmentFn();
|
||||
if (loadAttachmentFn != null)
|
||||
var (prompt, fn) = GetPromptAndFunction();
|
||||
if (fn != null)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(prompt))
|
||||
{
|
||||
|
|
@ -29,11 +29,11 @@ public class AttachmentProcessingHook : AgentHookBase
|
|||
|
||||
if (agent.Functions == null)
|
||||
{
|
||||
agent.Functions = new List<FunctionDef> { loadAttachmentFn };
|
||||
agent.Functions = new List<FunctionDef> { fn };
|
||||
}
|
||||
else
|
||||
{
|
||||
agent.Functions.Add(loadAttachmentFn);
|
||||
agent.Functions.Add(fn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -41,13 +41,13 @@ public class AttachmentProcessingHook : AgentHookBase
|
|||
base.OnAgentLoaded(agent);
|
||||
}
|
||||
|
||||
private (string, FunctionDef?) GetLoadAttachmentFn()
|
||||
private (string, FunctionDef?) GetPromptAndFunction()
|
||||
{
|
||||
var fnName = "load_attachment";
|
||||
var fn = "load_attachment";
|
||||
var db = _services.GetRequiredService<IBotSharpRepository>();
|
||||
var agent = db.GetAgent(TOOL_ASSISTANT);
|
||||
var prompt = agent?.Templates?.FirstOrDefault(x => x.Name.IsEqualTo($"{fnName}_prompt"))?.Content ?? string.Empty;
|
||||
var loadAttachmentFn = agent?.Functions?.FirstOrDefault(x => x.Name.IsEqualTo(fnName));
|
||||
var prompt = agent?.Templates?.FirstOrDefault(x => x.Name.IsEqualTo($"{fn}.fn"))?.Content ?? string.Empty;
|
||||
var loadAttachmentFn = agent?.Functions?.FirstOrDefault(x => x.Name.IsEqualTo(fn));
|
||||
return (prompt, loadAttachmentFn);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
|
||||
namespace BotSharp.Core.Files.Hooks;
|
||||
|
||||
public class FileAnalyzerToolHook : IAgentToolHook
|
||||
{
|
||||
public void AddTools(List<string> tools)
|
||||
{
|
||||
tools.Add(AgentTool.FileAnalyzer);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
using BotSharp.Abstraction.Routing.Models;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
|
||||
namespace BotSharp.Core.Repository
|
||||
{
|
||||
|
|
@ -194,11 +195,24 @@ namespace BotSharp.Core.Repository
|
|||
var (agent, agentFile) = GetAgentFromFile(agentId);
|
||||
if (agent == null) return;
|
||||
|
||||
var functionFile = Path.Combine(_dbSettings.FileRepository, _agentSettings.DataDir,
|
||||
agentId, AGENT_FUNCTIONS_FILE);
|
||||
var functionDir = Path.Combine(_dbSettings.FileRepository, _agentSettings.DataDir,
|
||||
agentId, AGENT_FUNCTIONS_FOLDER);
|
||||
|
||||
var functionText = JsonSerializer.Serialize(inputFunctions, _options);
|
||||
File.WriteAllText(functionFile, functionText);
|
||||
if (Directory.Exists(functionDir))
|
||||
{
|
||||
Directory.Delete(functionDir, true);
|
||||
}
|
||||
Directory.CreateDirectory(functionDir);
|
||||
|
||||
foreach (var func in inputFunctions)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(func.Name)) continue;
|
||||
|
||||
var text = JsonSerializer.Serialize(func, _options);
|
||||
var file = Path.Combine(functionDir, $"{func.Name}.json");
|
||||
File.WriteAllText(file, text);
|
||||
Thread.Sleep(200);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateAgentTemplates(string agentId, List<AgentTemplate> templates)
|
||||
|
|
@ -208,7 +222,7 @@ namespace BotSharp.Core.Repository
|
|||
var (agent, agentFile) = GetAgentFromFile(agentId);
|
||||
if (agent == null) return;
|
||||
|
||||
var templateDir = Path.Combine(_dbSettings.FileRepository, _agentSettings.DataDir, agentId, "templates");
|
||||
var templateDir = Path.Combine(_dbSettings.FileRepository, _agentSettings.DataDir, agentId, AGENT_TEMPLATES_FOLDER);
|
||||
|
||||
if (!Directory.Exists(templateDir))
|
||||
{
|
||||
|
|
@ -234,7 +248,7 @@ namespace BotSharp.Core.Repository
|
|||
var (agent, agentFile) = GetAgentFromFile(agentId);
|
||||
if (agent == null) return;
|
||||
|
||||
var responseDir = Path.Combine(_dbSettings.FileRepository, _agentSettings.DataDir, agentId, "responses");
|
||||
var responseDir = Path.Combine(_dbSettings.FileRepository, _agentSettings.DataDir, agentId, AGENT_RESPONSES_FOLDER);
|
||||
if (!Directory.Exists(responseDir))
|
||||
{
|
||||
Directory.CreateDirectory(responseDir);
|
||||
|
|
@ -305,7 +319,7 @@ namespace BotSharp.Core.Repository
|
|||
public List<string> GetAgentResponses(string agentId, string prefix, string intent)
|
||||
{
|
||||
var responses = new List<string>();
|
||||
var dir = Path.Combine(_dbSettings.FileRepository, _agentSettings.DataDir, agentId, "responses");
|
||||
var dir = Path.Combine(_dbSettings.FileRepository, _agentSettings.DataDir, agentId, AGENT_RESPONSES_FOLDER);
|
||||
if (!Directory.Exists(dir)) return responses;
|
||||
|
||||
foreach (var file in Directory.GetFiles(dir))
|
||||
|
|
@ -399,7 +413,7 @@ namespace BotSharp.Core.Repository
|
|||
|
||||
public string GetAgentTemplate(string agentId, string templateName)
|
||||
{
|
||||
var dir = Path.Combine(_dbSettings.FileRepository, _agentSettings.DataDir, agentId, "templates");
|
||||
var dir = Path.Combine(_dbSettings.FileRepository, _agentSettings.DataDir, agentId, AGENT_TEMPLATES_FOLDER);
|
||||
if (!Directory.Exists(dir)) return string.Empty;
|
||||
|
||||
foreach (var file in Directory.GetFiles(dir))
|
||||
|
|
@ -421,7 +435,7 @@ namespace BotSharp.Core.Repository
|
|||
{
|
||||
if (string.IsNullOrEmpty(agentId) || template == null) return false;
|
||||
|
||||
var dir = Path.Combine(_dbSettings.FileRepository, _agentSettings.DataDir, agentId, "templates");
|
||||
var dir = Path.Combine(_dbSettings.FileRepository, _agentSettings.DataDir, agentId, AGENT_TEMPLATES_FOLDER);
|
||||
if (!Directory.Exists(dir)) return false;
|
||||
|
||||
var foundTemplate = Directory.GetFiles(dir).FirstOrDefault(f =>
|
||||
|
|
@ -460,7 +474,7 @@ namespace BotSharp.Core.Repository
|
|||
if (string.IsNullOrEmpty(agentDir)) return false;
|
||||
|
||||
// Delete agent user relationships
|
||||
var usersDir = Path.Combine(_dbSettings.FileRepository, "users");
|
||||
var usersDir = Path.Combine(_dbSettings.FileRepository, USERS_FOLDER);
|
||||
if (Directory.Exists(usersDir))
|
||||
{
|
||||
foreach (var userDir in Directory.GetDirectories(usersDir))
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ public partial class FileRepository
|
|||
|
||||
foreach (var agentDir in Directory.GetDirectories(dir))
|
||||
{
|
||||
var taskDir = Path.Combine(agentDir, "tasks");
|
||||
var taskDir = Path.Combine(agentDir, AGENT_TASKS_FOLDER);
|
||||
if (!Directory.Exists(taskDir)) continue;
|
||||
|
||||
var agentId = agentDir.Split(Path.DirectorySeparatorChar).Last();
|
||||
|
|
@ -84,7 +84,7 @@ public partial class FileRepository
|
|||
var agentDir = Path.Combine(_dbSettings.FileRepository, _agentSettings.DataDir, agentId);
|
||||
if (!Directory.Exists(agentDir)) return null;
|
||||
|
||||
var taskDir = Path.Combine(agentDir, "tasks");
|
||||
var taskDir = Path.Combine(agentDir, AGENT_TASKS_FOLDER);
|
||||
if (!Directory.Exists(taskDir)) return null;
|
||||
|
||||
var taskFile = FindTaskFileById(taskDir, taskId);
|
||||
|
|
@ -106,7 +106,7 @@ public partial class FileRepository
|
|||
var agentDir = Path.Combine(_dbSettings.FileRepository, _agentSettings.DataDir, task.AgentId);
|
||||
if (!Directory.Exists(agentDir)) return;
|
||||
|
||||
var taskDir = Path.Combine(agentDir, "tasks");
|
||||
var taskDir = Path.Combine(agentDir, AGENT_TASKS_FOLDER);
|
||||
if (!Directory.Exists(taskDir))
|
||||
{
|
||||
Directory.CreateDirectory(taskDir);
|
||||
|
|
@ -140,7 +140,7 @@ public partial class FileRepository
|
|||
var agentDir = Path.Combine(_dbSettings.FileRepository, _agentSettings.DataDir, task.AgentId);
|
||||
if (!Directory.Exists(agentDir)) return;
|
||||
|
||||
var taskDir = Path.Combine(agentDir, "tasks");
|
||||
var taskDir = Path.Combine(agentDir, AGENT_TASKS_FOLDER);
|
||||
if (!Directory.Exists(taskDir)) return;
|
||||
|
||||
var taskFile = FindTaskFileById(taskDir, task.Id);
|
||||
|
|
@ -195,7 +195,7 @@ public partial class FileRepository
|
|||
var agentDir = Path.Combine(_dbSettings.FileRepository, _agentSettings.DataDir, agentId);
|
||||
if (!Directory.Exists(agentDir) || taskIds.IsNullOrEmpty()) return false;
|
||||
|
||||
var taskDir = Path.Combine(agentDir, "tasks");
|
||||
var taskDir = Path.Combine(agentDir, AGENT_TASKS_FOLDER);
|
||||
if (!Directory.Exists(taskDir)) return false;
|
||||
|
||||
var deletedTasks = new List<string>();
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ public partial class FileRepository
|
|||
{
|
||||
foreach (var user in _users)
|
||||
{
|
||||
var dir = Path.Combine(_dbSettings.FileRepository, "users", user.Id);
|
||||
var dir = Path.Combine(_dbSettings.FileRepository, USERS_FOLDER, user.Id);
|
||||
if (!Directory.Exists(dir))
|
||||
{
|
||||
Directory.CreateDirectory(dir);
|
||||
|
|
@ -69,7 +69,7 @@ public partial class FileRepository
|
|||
var agents = _userAgents.Where(x => x.UserId == uid).ToList();
|
||||
if (agents.Any())
|
||||
{
|
||||
var dir = Path.Combine(_dbSettings.FileRepository, "users", uid);
|
||||
var dir = Path.Combine(_dbSettings.FileRepository, USERS_FOLDER, uid);
|
||||
var path = Path.Combine(dir, USER_AGENT_FILE);
|
||||
File.WriteAllText(path, JsonSerializer.Serialize(agents, _options));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,12 +25,12 @@ public partial class FileRepository
|
|||
{
|
||||
var userId = Guid.NewGuid().ToString();
|
||||
user.Id = userId;
|
||||
var dir = Path.Combine(_dbSettings.FileRepository, "users", userId);
|
||||
var dir = Path.Combine(_dbSettings.FileRepository, USERS_FOLDER, userId);
|
||||
if (!Directory.Exists(dir))
|
||||
{
|
||||
Directory.CreateDirectory(dir);
|
||||
}
|
||||
var path = Path.Combine(dir, "user.json");
|
||||
var path = Path.Combine(dir, USER_FILE);
|
||||
File.WriteAllText(path, JsonSerializer.Serialize(user, _options));
|
||||
}
|
||||
|
||||
|
|
@ -38,8 +38,8 @@ public partial class FileRepository
|
|||
{
|
||||
var user = GetUserById(userId);
|
||||
user.Verified = true;
|
||||
var dir = Path.Combine(_dbSettings.FileRepository, "users", user.Id);
|
||||
var path = Path.Combine(dir, "user.json");
|
||||
var dir = Path.Combine(_dbSettings.FileRepository, USERS_FOLDER, user.Id);
|
||||
var path = Path.Combine(dir, USER_FILE);
|
||||
File.WriteAllText(path, JsonSerializer.Serialize(user, _options));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@ public partial class FileRepository : IBotSharpRepository
|
|||
|
||||
private const string AGENT_FILE = "agent.json";
|
||||
private const string AGENT_INSTRUCTION_FILE = "instruction";
|
||||
private const string AGENT_FUNCTIONS_FILE = "functions.json";
|
||||
private const string AGENT_SAMPLES_FILE = "samples.txt";
|
||||
private const string USER_FILE = "user.json";
|
||||
private const string USER_AGENT_FILE = "agents.json";
|
||||
|
|
@ -36,6 +35,11 @@ public partial class FileRepository : IBotSharpRepository
|
|||
private const string AGENT_TASK_PREFIX = "#metadata";
|
||||
private const string AGENT_TASK_SUFFIX = "/metadata";
|
||||
private const string TRANSLATION_MEMORY_FILE = "memory.json";
|
||||
private const string AGENT_FUNCTIONS_FOLDER = "functions";
|
||||
private const string AGENT_TEMPLATES_FOLDER = "templates";
|
||||
private const string AGENT_RESPONSES_FOLDER = "responses";
|
||||
private const string AGENT_TASKS_FOLDER = "tasks";
|
||||
private const string USERS_FOLDER = "users";
|
||||
|
||||
public FileRepository(
|
||||
IServiceProvider services,
|
||||
|
|
@ -79,7 +83,7 @@ public partial class FileRepository : IBotSharpRepository
|
|||
return _users.AsQueryable();
|
||||
}
|
||||
|
||||
var dir = Path.Combine(_dbSettings.FileRepository, "users");
|
||||
var dir = Path.Combine(_dbSettings.FileRepository, USERS_FOLDER);
|
||||
_users = new List<User>();
|
||||
if (Directory.Exists(dir))
|
||||
{
|
||||
|
|
@ -142,7 +146,7 @@ public partial class FileRepository : IBotSharpRepository
|
|||
return _userAgents.AsQueryable();
|
||||
}
|
||||
|
||||
var dir = Path.Combine(_dbSettings.FileRepository, "users");
|
||||
var dir = Path.Combine(_dbSettings.FileRepository, USERS_FOLDER);
|
||||
_userAgents = new List<UserAgent>();
|
||||
if (Directory.Exists(dir))
|
||||
{
|
||||
|
|
@ -194,11 +198,28 @@ public partial class FileRepository : IBotSharpRepository
|
|||
|
||||
private List<FunctionDef> FetchFunctions(string fileDir)
|
||||
{
|
||||
var file = Path.Combine(fileDir, AGENT_FUNCTIONS_FILE);
|
||||
if (!File.Exists(file)) return new List<FunctionDef>();
|
||||
var functions = new List<FunctionDef>();
|
||||
var functionDir = Path.Combine(fileDir, AGENT_FUNCTIONS_FOLDER);
|
||||
|
||||
var functionsJson = File.ReadAllText(file);
|
||||
var functions = JsonSerializer.Deserialize<List<FunctionDef>>(functionsJson, _options);
|
||||
if (!Directory.Exists(functionDir)) return functions;
|
||||
|
||||
foreach ( var file in Directory.GetFiles(functionDir))
|
||||
{
|
||||
try
|
||||
{
|
||||
var extension = Path.GetExtension(file).Substring(1);
|
||||
if (extension != "json") continue;
|
||||
|
||||
var json = File.ReadAllText(file);
|
||||
var function = JsonSerializer.Deserialize<FunctionDef>(json, _options);
|
||||
functions.Add(function);
|
||||
}
|
||||
catch
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
return functions;
|
||||
}
|
||||
|
||||
|
|
@ -213,7 +234,7 @@ public partial class FileRepository : IBotSharpRepository
|
|||
private List<AgentTemplate> FetchTemplates(string fileDir)
|
||||
{
|
||||
var templates = new List<AgentTemplate>();
|
||||
var templateDir = Path.Combine(fileDir, "templates");
|
||||
var templateDir = Path.Combine(fileDir, AGENT_TEMPLATES_FOLDER);
|
||||
if (!Directory.Exists(templateDir)) return templates;
|
||||
|
||||
foreach (var file in Directory.GetFiles(templateDir))
|
||||
|
|
@ -235,7 +256,7 @@ public partial class FileRepository : IBotSharpRepository
|
|||
private List<AgentTask> FetchTasks(string fileDir)
|
||||
{
|
||||
var tasks = new List<AgentTask>();
|
||||
var taskDir = Path.Combine(fileDir, "tasks");
|
||||
var taskDir = Path.Combine(fileDir, AGENT_TASKS_FOLDER);
|
||||
if (!Directory.Exists(taskDir)) return tasks;
|
||||
|
||||
foreach (var file in Directory.GetFiles(taskDir))
|
||||
|
|
@ -252,7 +273,7 @@ public partial class FileRepository : IBotSharpRepository
|
|||
private List<AgentResponse> FetchResponses(string fileDir)
|
||||
{
|
||||
var responses = new List<AgentResponse>();
|
||||
var responseDir = Path.Combine(fileDir, "responses");
|
||||
var responseDir = Path.Combine(fileDir, AGENT_RESPONSES_FOLDER);
|
||||
if (!Directory.Exists(responseDir)) return responses;
|
||||
|
||||
foreach (var file in Directory.GetFiles(responseDir))
|
||||
|
|
|
|||
|
|
@ -1,20 +0,0 @@
|
|||
[
|
||||
{
|
||||
"name": "load_attachment",
|
||||
"description": "If the user's request is related to analyzing files and/or images, you can call this function to analyze files and images.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"user_request": {
|
||||
"type": "string",
|
||||
"description": "The request posted by user, which is related to analyzing requested files. User can request for multiple files to process at one time."
|
||||
},
|
||||
"file_types": {
|
||||
"type": "string",
|
||||
"description": "The file types requested by user to analyze, such as image, png, jpeg, and pdf. There can be multiple file types in a single request. An example output is, 'image,pdf'."
|
||||
}
|
||||
},
|
||||
"required": [ "user_request", "file_types" ]
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"name": "load_attachment",
|
||||
"description": "If the user's request is related to analyzing files and/or images, you can call this function to analyze files and images.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"user_request": {
|
||||
"type": "string",
|
||||
"description": "The request posted by user, which is related to analyzing requested files. User can request for multiple files to process at one time."
|
||||
},
|
||||
"file_types": {
|
||||
"type": "string",
|
||||
"description": "The file types requested by user to analyze, such as image, png, jpeg, and pdf. There can be multiple file types in a single request. An example output is, 'image,pdf'."
|
||||
}
|
||||
},
|
||||
"required": [ "user_request", "file_types" ]
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"name": "human_intervention_needed",
|
||||
"description": "If user wants to speak to human customer service.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"reason": {
|
||||
"type": "string",
|
||||
"description": "why customer needs customer service."
|
||||
},
|
||||
"summary": {
|
||||
"type": "string",
|
||||
"description": "the whole conversation summary with important information"
|
||||
}
|
||||
},
|
||||
"required": [ "reason", "summary" ]
|
||||
}
|
||||
}
|
||||
|
|
@ -3,6 +3,7 @@ using BotSharp.Abstraction.Instructs;
|
|||
using BotSharp.Abstraction.Instructs.Models;
|
||||
using BotSharp.Core.Infrastructures;
|
||||
using BotSharp.OpenAPI.ViewModels.Instructs;
|
||||
using NetTopologySuite.IO;
|
||||
|
||||
namespace BotSharp.OpenAPI.Controllers;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,7 @@
|
|||
using BotSharp.Abstraction.MLTasks;
|
||||
using BotSharp.Abstraction.Plugins;
|
||||
using BotSharp.Abstraction.Settings;
|
||||
using BotSharp.Plugin.AzureOpenAI.Providers;
|
||||
using BotSharp.Plugin.AzureOpenAI.Settings;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace BotSharp.Platform.AzureAi;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.1</TargetFramework>
|
||||
<TargetFramework>$(TargetFramework)</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<LangVersion>$(LangVersion)</LangVersion>
|
||||
<VersionPrefix>$(BotSharpVersion)</VersionPrefix>
|
||||
|
|
@ -11,7 +11,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Azure.AI.OpenAI" Version="1.0.0-beta.17" />
|
||||
<PackageReference Include="Azure.AI.OpenAI" Version="2.0.0-beta.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -1,21 +1,4 @@
|
|||
using Azure.AI.OpenAI;
|
||||
using BotSharp.Abstraction.Agents;
|
||||
using BotSharp.Abstraction.Agents.Enums;
|
||||
using BotSharp.Abstraction.Agents.Models;
|
||||
using BotSharp.Abstraction.Conversations;
|
||||
using BotSharp.Abstraction.Conversations.Models;
|
||||
using BotSharp.Abstraction.Files;
|
||||
using BotSharp.Abstraction.Loggers;
|
||||
using BotSharp.Abstraction.MLTasks;
|
||||
using BotSharp.Abstraction.Utilities;
|
||||
using BotSharp.Plugin.AzureOpenAI.Settings;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using OpenAI.Chat;
|
||||
|
||||
namespace BotSharp.Plugin.AzureOpenAI.Providers;
|
||||
|
||||
|
|
@ -49,22 +32,24 @@ public class ChatCompletionProvider : IChatCompletion
|
|||
}
|
||||
|
||||
var client = ProviderHelper.GetClient(Provider, _model, _services);
|
||||
var (prompt, chatCompletionsOptions) = PrepareOptions(agent, conversations);
|
||||
chatCompletionsOptions.DeploymentName = _model;
|
||||
var response = client.GetChatCompletions(chatCompletionsOptions);
|
||||
var choice = response.Value.Choices[0];
|
||||
var message = choice.Message;
|
||||
var chatClient = client.GetChatClient(_model);
|
||||
var (prompt, messages, options) = PrepareOptions(agent, conversations);
|
||||
|
||||
var response = chatClient.CompleteChat(messages, options);
|
||||
var value = response.Value;
|
||||
var reason = value.FinishReason;
|
||||
var content = value.Content;
|
||||
var text = content.FirstOrDefault()?.Text ?? string.Empty;
|
||||
|
||||
RoleDialogModel responseMessage;
|
||||
|
||||
if (choice.FinishReason == CompletionsFinishReason.FunctionCall)
|
||||
if (reason == ChatFinishReason.FunctionCall)
|
||||
{
|
||||
responseMessage = new RoleDialogModel(AgentRole.Function, message.Content)
|
||||
responseMessage = new RoleDialogModel(AgentRole.Function, text)
|
||||
{
|
||||
CurrentAgentId = agent.Id,
|
||||
MessageId = conversations.Last().MessageId,
|
||||
FunctionName = message.FunctionCall.Name,
|
||||
FunctionArgs = message.FunctionCall.Arguments
|
||||
FunctionName = value.FunctionCall.FunctionName,
|
||||
FunctionArgs = value.FunctionCall.FunctionArguments
|
||||
};
|
||||
|
||||
// Somethings LLM will generate a function name with agent name.
|
||||
|
|
@ -73,28 +58,20 @@ public class ChatCompletionProvider : IChatCompletion
|
|||
responseMessage.FunctionName = responseMessage.FunctionName.Split('.').Last();
|
||||
}
|
||||
}
|
||||
else if (choice.FinishReason == CompletionsFinishReason.ToolCalls)
|
||||
else if (reason == ChatFinishReason.ToolCalls)
|
||||
{
|
||||
// Add the assistant message with tool calls to the conversation history
|
||||
// ChatRequestAssistantMessage toolCallHistoryMessage = new(message);
|
||||
// chatCompletionsOptions.Messages.Add(toolCallHistoryMessage);
|
||||
|
||||
// Add a new tool message for each tool call that is resolved
|
||||
var toolCall = message.ToolCalls.First() as ChatCompletionsFunctionToolCall;
|
||||
// var toolCallResponseMessage = GetToolCallResponseMessage(toolCall);
|
||||
// Now make a new request with all the messages thus far, including the original
|
||||
|
||||
responseMessage = new RoleDialogModel(AgentRole.Function, message.Content)
|
||||
var toolCall = value.ToolCalls.FirstOrDefault();
|
||||
responseMessage = new RoleDialogModel(AgentRole.Function, text)
|
||||
{
|
||||
CurrentAgentId = agent.Id,
|
||||
MessageId = conversations.Last().MessageId,
|
||||
FunctionName = toolCall.Name,
|
||||
FunctionArgs = toolCall.Arguments
|
||||
FunctionName = toolCall?.FunctionName,
|
||||
FunctionArgs = toolCall?.FunctionArguments
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
responseMessage = new RoleDialogModel(AgentRole.Assistant, message.Content)
|
||||
responseMessage = new RoleDialogModel(AgentRole.Assistant, text)
|
||||
{
|
||||
CurrentAgentId = agent.Id,
|
||||
MessageId = conversations.Last().MessageId
|
||||
|
|
@ -109,8 +86,8 @@ public class ChatCompletionProvider : IChatCompletion
|
|||
Prompt = prompt,
|
||||
Provider = Provider,
|
||||
Model = _model,
|
||||
PromptCount = response.Value.Usage.PromptTokens,
|
||||
CompletionCount = response.Value.Usage.CompletionTokens
|
||||
PromptCount = response.Value.Usage.InputTokens,
|
||||
CompletionCount = response.Value.Usage.OutputTokens
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -131,14 +108,16 @@ public class ChatCompletionProvider : IChatCompletion
|
|||
}
|
||||
|
||||
var client = ProviderHelper.GetClient(Provider, _model, _services);
|
||||
var (prompt, chatCompletionsOptions) = PrepareOptions(agent, conversations);
|
||||
var chatClient = client.GetChatClient(_model);
|
||||
var (prompt, messages, options) = PrepareOptions(agent, conversations);
|
||||
|
||||
chatCompletionsOptions.DeploymentName = _model;
|
||||
var response = await client.GetChatCompletionsAsync(chatCompletionsOptions);
|
||||
var choice = response.Value.Choices[0];
|
||||
var message = choice.Message;
|
||||
var response = await chatClient.CompleteChatAsync(messages, options);
|
||||
var value = response.Value;
|
||||
var reason = value.FinishReason;
|
||||
var content = value.Content;
|
||||
var text = content.FirstOrDefault()?.Text ?? string.Empty;
|
||||
|
||||
var msg = new RoleDialogModel(AgentRole.Assistant, message.Content)
|
||||
var msg = new RoleDialogModel(AgentRole.Assistant, text)
|
||||
{
|
||||
CurrentAgentId = agent.Id
|
||||
};
|
||||
|
|
@ -151,20 +130,20 @@ public class ChatCompletionProvider : IChatCompletion
|
|||
Prompt = prompt,
|
||||
Provider = Provider,
|
||||
Model = _model,
|
||||
PromptCount = response.Value.Usage.PromptTokens,
|
||||
CompletionCount = response.Value.Usage.CompletionTokens
|
||||
PromptCount = response.Value.Usage.InputTokens,
|
||||
CompletionCount = response.Value.Usage.OutputTokens
|
||||
});
|
||||
}
|
||||
|
||||
if (choice.FinishReason == CompletionsFinishReason.FunctionCall)
|
||||
if (reason == ChatFinishReason.FunctionCall)
|
||||
{
|
||||
_logger.LogInformation($"[{agent.Name}]: {message.FunctionCall.Name}({message.FunctionCall.Arguments})");
|
||||
_logger.LogInformation($"[{agent.Name}]: {value.FunctionCall.FunctionName}({value.FunctionCall.FunctionArguments})");
|
||||
|
||||
var funcContextIn = new RoleDialogModel(AgentRole.Function, message.Content)
|
||||
var funcContextIn = new RoleDialogModel(AgentRole.Function, text)
|
||||
{
|
||||
CurrentAgentId = agent.Id,
|
||||
FunctionName = message.FunctionCall.Name,
|
||||
FunctionArgs = message.FunctionCall.Arguments
|
||||
FunctionName = value.FunctionCall.FunctionName,
|
||||
FunctionArgs = value.FunctionCall.FunctionArguments
|
||||
};
|
||||
|
||||
// Somethings LLM will generate a function name with agent name.
|
||||
|
|
@ -188,37 +167,33 @@ public class ChatCompletionProvider : IChatCompletion
|
|||
public async Task<bool> GetChatCompletionsStreamingAsync(Agent agent, List<RoleDialogModel> conversations, Func<RoleDialogModel, Task> onMessageReceived)
|
||||
{
|
||||
var client = ProviderHelper.GetClient(Provider, _model, _services);
|
||||
var (prompt, chatCompletionsOptions) = PrepareOptions(agent, conversations);
|
||||
chatCompletionsOptions.DeploymentName = _model;
|
||||
var response = await client.GetChatCompletionsStreamingAsync(chatCompletionsOptions);
|
||||
var chatClient = client.GetChatClient(_model);
|
||||
var (prompt, messages, options) = PrepareOptions(agent, conversations);
|
||||
|
||||
var response = chatClient.CompleteChatStreamingAsync(messages, options);
|
||||
|
||||
string output = "";
|
||||
await foreach (var choice in response)
|
||||
{
|
||||
if (choice.FinishReason == CompletionsFinishReason.FunctionCall)
|
||||
if (choice.FinishReason == ChatFinishReason.FunctionCall)
|
||||
{
|
||||
Console.Write(choice.FunctionArgumentsUpdate);
|
||||
Console.Write(choice.FunctionCallUpdate?.FunctionArgumentsUpdate);
|
||||
|
||||
await onMessageReceived(new RoleDialogModel(ChatRole.Assistant.ToString(), choice.FunctionArgumentsUpdate));
|
||||
await onMessageReceived(new RoleDialogModel(AgentRole.Assistant, choice.FunctionCallUpdate?.FunctionArgumentsUpdate));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (choice.ContentUpdate == null)
|
||||
continue;
|
||||
Console.Write(choice.ContentUpdate);
|
||||
if (choice.ContentUpdate.IsNullOrEmpty()) continue;
|
||||
|
||||
_logger.LogInformation(choice.ContentUpdate);
|
||||
_logger.LogInformation(choice.ContentUpdate[0]?.Text);
|
||||
|
||||
await onMessageReceived(new RoleDialogModel(choice.Role.ToString(), choice.ContentUpdate));
|
||||
|
||||
output = "";
|
||||
await onMessageReceived(new RoleDialogModel(choice.Role.ToString(), choice.ContentUpdate[0]?.Text ?? string.Empty));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
protected (string, ChatCompletionsOptions) PrepareOptions(Agent agent, List<RoleDialogModel> conversations)
|
||||
protected (string, IEnumerable<ChatMessage>, ChatCompletionOptions) PrepareOptions(Agent agent, List<RoleDialogModel> conversations)
|
||||
{
|
||||
var agentService = _services.GetRequiredService<IAgentService>();
|
||||
var fileService = _services.GetRequiredService<IBotSharpFileService>();
|
||||
|
|
@ -227,75 +202,67 @@ public class ChatCompletionProvider : IChatCompletion
|
|||
var settings = settingsService.GetSetting(Provider, _model);
|
||||
var allowMultiModal = settings != null && settings.MultiModal;
|
||||
|
||||
var chatCompletionsOptions = new ChatCompletionsOptions();
|
||||
|
||||
var messages = new List<ChatMessage>();
|
||||
|
||||
var temperature = float.Parse(state.GetState("temperature", "0.0"));
|
||||
var maxTokens = int.Parse(state.GetState("max_tokens", "1024"));
|
||||
var options = new ChatCompletionOptions()
|
||||
{
|
||||
Temperature = temperature,
|
||||
MaxTokens = maxTokens
|
||||
};
|
||||
|
||||
foreach (var function in agent.Functions)
|
||||
{
|
||||
if (!agentService.RenderFunction(agent, function)) continue;
|
||||
|
||||
var property = agentService.RenderFunctionProperty(agent, function);
|
||||
|
||||
options.Tools.Add(ChatTool.CreateFunctionTool(
|
||||
functionName: function.Name,
|
||||
functionDescription: function.Description,
|
||||
functionParameters: BinaryData.FromObjectAsJson(property)));
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(agent.Instruction))
|
||||
{
|
||||
var instruction = agentService.RenderedInstruction(agent);
|
||||
chatCompletionsOptions.Messages.Add(new ChatRequestSystemMessage(instruction));
|
||||
messages.Add(new SystemChatMessage(instruction));
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(agent.Knowledges))
|
||||
{
|
||||
chatCompletionsOptions.Messages.Add(new ChatRequestSystemMessage(agent.Knowledges));
|
||||
messages.Add(new SystemChatMessage(agent.Knowledges));
|
||||
}
|
||||
|
||||
var samples = ProviderHelper.GetChatSamples(agent.Samples);
|
||||
foreach (var message in samples)
|
||||
foreach (var sample in samples)
|
||||
{
|
||||
chatCompletionsOptions.Messages.Add(message.Role == AgentRole.User ?
|
||||
new ChatRequestUserMessage(message.Content) :
|
||||
new ChatRequestAssistantMessage(message.Content));
|
||||
}
|
||||
|
||||
foreach (var function in agent.Functions)
|
||||
{
|
||||
if (agentService.RenderFunction(agent, function))
|
||||
{
|
||||
var property = agentService.RenderFunctionProperty(agent, function);
|
||||
|
||||
// legacy function call
|
||||
/*chatCompletionsOptions.Functions.Add(new FunctionDefinition
|
||||
{
|
||||
Name = function.Name,
|
||||
Description = function.Description,
|
||||
Parameters = BinaryData.FromObjectAsJson(property)
|
||||
});*/
|
||||
|
||||
// new chat tool
|
||||
chatCompletionsOptions.Tools.Add(new ChatCompletionsFunctionToolDefinition
|
||||
{
|
||||
Name = function.Name,
|
||||
Description = function.Description,
|
||||
Parameters = BinaryData.FromObjectAsJson(property)
|
||||
});
|
||||
}
|
||||
messages.Add(sample.Role == AgentRole.User ? new UserChatMessage(sample.Content) : new AssistantChatMessage(sample.Content));
|
||||
}
|
||||
|
||||
foreach (var message in conversations)
|
||||
{
|
||||
if (message.Role == ChatRole.Function)
|
||||
if (message.Role == AgentRole.Function)
|
||||
{
|
||||
chatCompletionsOptions.Messages.Add(new ChatRequestAssistantMessage(string.Empty)
|
||||
messages.Add(new AssistantChatMessage(string.Empty)
|
||||
{
|
||||
FunctionCall = new FunctionCall(message.FunctionName, message.FunctionArgs ?? String.Empty),
|
||||
FunctionCall = new ChatFunctionCall(message.FunctionName, message.FunctionArgs ?? string.Empty)
|
||||
});
|
||||
|
||||
chatCompletionsOptions.Messages.Add(new ChatRequestFunctionMessage(message.FunctionName, message.Content));
|
||||
// chatCompletionsOptions.Messages.Add(new ChatRequestToolMessage(message.Content, message.ToolCallId));
|
||||
messages.Add(new FunctionChatMessage(message.FunctionName, message.Content));
|
||||
}
|
||||
else if (message.Role == ChatRole.User)
|
||||
else if (message.Role == AgentRole.User)
|
||||
{
|
||||
var text = !string.IsNullOrWhiteSpace(message.Payload) ? message.Payload : message.Content;
|
||||
var textPart = ChatMessageContentPart.CreateTextMessageContentPart(text);
|
||||
var chat = new UserChatMessage(textPart)
|
||||
{
|
||||
ParticipantName = message.FunctionName
|
||||
};
|
||||
|
||||
ChatRequestUserMessage userMessage = null;
|
||||
if (allowMultiModal)
|
||||
{
|
||||
var chatItems = new List<ChatMessageContentItem>()
|
||||
{
|
||||
new ChatMessageTextContentItem(text)
|
||||
};
|
||||
|
||||
if (!message.Files.IsNullOrEmpty())
|
||||
{
|
||||
foreach (var file in message.Files)
|
||||
|
|
@ -303,127 +270,97 @@ public class ChatCompletionProvider : IChatCompletion
|
|||
if (!string.IsNullOrEmpty(file.FileUrl))
|
||||
{
|
||||
var uri = new Uri(file.FileUrl);
|
||||
chatItems.Add(new ChatMessageImageContentItem(uri, ChatMessageImageDetailLevel.Low));
|
||||
var contentPart = ChatMessageContentPart.CreateImageMessageContentPart(uri, ImageChatMessageContentPartDetail.Low);
|
||||
chat = new UserChatMessage(textPart, contentPart) { ParticipantName = message.FunctionName };
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(file.FileData))
|
||||
{
|
||||
var (contentType, bytes) = fileService.GetFileInfoFromData(file.FileData);
|
||||
using var stream = new MemoryStream(bytes, 0, bytes.Length);
|
||||
chatItems.Add(new ChatMessageImageContentItem(stream, contentType, ChatMessageImageDetailLevel.Low));
|
||||
var contentPart = ChatMessageContentPart.CreateImageMessageContentPart(BinaryData.FromBytes(bytes), contentType, ImageChatMessageContentPartDetail.Low);
|
||||
chat = new UserChatMessage(textPart, contentPart) { ParticipantName = message.FunctionName };
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(file.FileStorageUrl))
|
||||
{
|
||||
var contentType = fileService.GetFileContentType(file.FileStorageUrl);
|
||||
using var stream = File.OpenRead(file.FileStorageUrl);
|
||||
chatItems.Add(new ChatMessageImageContentItem(stream, file.ContentType, ChatMessageImageDetailLevel.Low));
|
||||
var contentPart = ChatMessageContentPart.CreateImageMessageContentPart(BinaryData.FromStream(stream), contentType, ImageChatMessageContentPartDetail.Low);
|
||||
chat = new UserChatMessage(textPart, contentPart) { ParticipantName = message.FunctionName };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//if (!string.IsNullOrEmpty(message.ImageUrl))
|
||||
//{
|
||||
// var uri = new Uri(message.ImageUrl);
|
||||
// userMessage.MultimodalContentItems.Add(
|
||||
// new ChatMessageImageContentItem(uri, ChatMessageImageDetailLevel.Low));
|
||||
//}
|
||||
|
||||
userMessage = new ChatRequestUserMessage(chatItems)
|
||||
{
|
||||
// To display Planner name in log
|
||||
Name = message.FunctionName,
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
userMessage = new ChatRequestUserMessage(text)
|
||||
{
|
||||
// To display Planner name in log
|
||||
Name = message.FunctionName,
|
||||
};
|
||||
}
|
||||
|
||||
chatCompletionsOptions.Messages.Add(userMessage);
|
||||
messages.Add(chat);
|
||||
}
|
||||
else if (message.Role == ChatRole.Assistant)
|
||||
else if (message.Role == AgentRole.Assistant)
|
||||
{
|
||||
chatCompletionsOptions.Messages.Add(new ChatRequestAssistantMessage(message.Content));
|
||||
messages.Add(new AssistantChatMessage(message.Content));
|
||||
}
|
||||
}
|
||||
|
||||
// https://community.openai.com/t/cheat-sheet-mastering-temperature-and-top-p-in-chatgpt-api-a-few-tips-and-tricks-on-controlling-the-creativity-deterministic-output-of-prompt-responses/172683
|
||||
//var state = _services.GetRequiredService<IConversationStateService>();
|
||||
var temperature = float.Parse(state.GetState("temperature", "0.0"));
|
||||
var samplingFactor = float.Parse(state.GetState("sampling_factor", "0.0"));
|
||||
chatCompletionsOptions.Temperature = temperature;
|
||||
chatCompletionsOptions.NucleusSamplingFactor = samplingFactor;
|
||||
chatCompletionsOptions.MaxTokens = int.Parse(state.GetState("max_tokens", "1024"));
|
||||
// chatCompletionsOptions.FrequencyPenalty = 0;
|
||||
// chatCompletionsOptions.PresencePenalty = 0;
|
||||
|
||||
var prompt = GetPrompt(chatCompletionsOptions);
|
||||
|
||||
return (prompt, chatCompletionsOptions);
|
||||
var prompt = GetPrompt(messages, options);
|
||||
return (prompt, messages, options);
|
||||
}
|
||||
|
||||
private string GetPrompt(ChatCompletionsOptions chatCompletionsOptions)
|
||||
|
||||
private string GetPrompt(IEnumerable<ChatMessage> messages, ChatCompletionOptions options)
|
||||
{
|
||||
var prompt = string.Empty;
|
||||
|
||||
if (chatCompletionsOptions.Messages.Count > 0)
|
||||
if (!messages.IsNullOrEmpty())
|
||||
{
|
||||
// System instruction
|
||||
var verbose = string.Join("\r\n", chatCompletionsOptions.Messages
|
||||
.Where(x => x.Role == AgentRole.System)
|
||||
.Select(x => x as ChatRequestSystemMessage).Select(x =>
|
||||
var verbose = string.Join("\r\n", messages
|
||||
.Select(x => x as SystemChatMessage)
|
||||
.Where(x => x != null)
|
||||
.Select(x =>
|
||||
{
|
||||
if (!string.IsNullOrEmpty(x.Name))
|
||||
if (!string.IsNullOrEmpty(x.ParticipantName))
|
||||
{
|
||||
// To display Agent name in log
|
||||
return $"[{x.Name}]: {x.Content}";
|
||||
return $"[{x.ParticipantName}]: {x.Content.FirstOrDefault()?.Text ?? string.Empty}";
|
||||
}
|
||||
return $"{x.Role}: {x.Content}";
|
||||
return $"{AgentRole.System}: {x.Content.FirstOrDefault()?.Text ?? string.Empty}";
|
||||
}));
|
||||
prompt += $"{verbose}\r\n";
|
||||
|
||||
prompt += "\r\n[CONVERSATION]";
|
||||
verbose = string.Join("\r\n", chatCompletionsOptions.Messages
|
||||
.Where(x => x.Role != AgentRole.System).Select(x =>
|
||||
verbose = string.Join("\r\n", messages
|
||||
.Where(x => (x as SystemChatMessage) == null)
|
||||
.Select(x =>
|
||||
{
|
||||
if (x.Role == ChatRole.Function)
|
||||
var fnMessage = x as FunctionChatMessage;
|
||||
if (fnMessage != null)
|
||||
{
|
||||
var m = x as ChatRequestFunctionMessage;
|
||||
return $"{m.Role}: {m.Content}";
|
||||
return $"{AgentRole.Function}: {fnMessage.Content.FirstOrDefault()?.Text ?? string.Empty}";
|
||||
}
|
||||
else if (x.Role == ChatRole.User)
|
||||
|
||||
var userMessage = x as UserChatMessage;
|
||||
if (userMessage != null)
|
||||
{
|
||||
var m = x as ChatRequestUserMessage;
|
||||
var content = m.Content ?? string.Join(", ", m.MultimodalContentItems
|
||||
.Where(m => m is ChatMessageTextContentItem)
|
||||
.Select(m => (m as ChatMessageTextContentItem)?.Text));
|
||||
return !string.IsNullOrEmpty(m.Name) && m.Name != "route_to_agent" ?
|
||||
$"{m.Name}: {content}" :
|
||||
$"{m.Role}: {content}";
|
||||
var content = x.Content.FirstOrDefault()?.Text ?? string.Empty;
|
||||
return !string.IsNullOrEmpty(userMessage.ParticipantName) && userMessage.ParticipantName != "route_to_agent" ?
|
||||
$"{userMessage.ParticipantName}: {content}" :
|
||||
$"{AgentRole.User}: {content}";
|
||||
}
|
||||
else if (x.Role == ChatRole.Assistant)
|
||||
|
||||
var assistMessage = x as AssistantChatMessage;
|
||||
if (assistMessage != null)
|
||||
{
|
||||
var m = x as ChatRequestAssistantMessage;
|
||||
return m.FunctionCall != null ?
|
||||
$"{m.Role}: Call function {m.FunctionCall.Name}({m.FunctionCall.Arguments})" :
|
||||
$"{m.Role}: {m.Content}";
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NotImplementedException("Not found role");
|
||||
return assistMessage.FunctionCall != null ?
|
||||
$"{AgentRole.Assistant}: Call function {assistMessage.FunctionCall.FunctionName}({assistMessage.FunctionCall.FunctionArguments})" :
|
||||
$"{AgentRole.Assistant}: {assistMessage.Content.FirstOrDefault()?.Text ?? string.Empty}";
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}));
|
||||
prompt += $"\r\n{verbose}\r\n";
|
||||
}
|
||||
|
||||
if (chatCompletionsOptions.Tools.Count > 0)
|
||||
if (!options.Tools.IsNullOrEmpty())
|
||||
{
|
||||
var functions = string.Join("\r\n", chatCompletionsOptions.Tools.Select(x =>
|
||||
var functions = string.Join("\r\n", options.Tools.Select(fn =>
|
||||
{
|
||||
var fn = x as ChatCompletionsFunctionToolDefinition;
|
||||
return $"\r\n{fn.Name}: {fn.Description}\r\n{fn.Parameters}";
|
||||
return $"\r\n{fn.FunctionName}: {fn.FunctionDescription}\r\n{fn.FunctionParameters}";
|
||||
}));
|
||||
prompt += $"\r\n[FUNCTIONS]{functions}\r\n";
|
||||
}
|
||||
|
|
@ -435,15 +372,4 @@ public class ChatCompletionProvider : IChatCompletion
|
|||
{
|
||||
_model = model;
|
||||
}
|
||||
|
||||
ChatRequestToolMessage GetToolCallResponseMessage(ChatCompletionsToolCall toolCall)
|
||||
{
|
||||
var functionToolCall = toolCall as ChatCompletionsFunctionToolCall;
|
||||
// Validate and process the JSON arguments for the function call
|
||||
string unvalidatedArguments = functionToolCall.Arguments;
|
||||
var functionResultData = (object)null; // GetYourFunctionResultData(unvalidatedArguments);
|
||||
// Here, replacing with an example as if returned from "GetYourFunctionResultData"
|
||||
functionResultData = "31 celsius";
|
||||
return new ChatRequestToolMessage(functionResultData.ToString(), toolCall.Id);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,4 @@
|
|||
using Azure.AI.OpenAI;
|
||||
using BotSharp.Abstraction.Agents.Enums;
|
||||
using BotSharp.Abstraction.Agents.Models;
|
||||
using BotSharp.Abstraction.Conversations;
|
||||
using BotSharp.Abstraction.Conversations.Models;
|
||||
using BotSharp.Abstraction.Loggers;
|
||||
using BotSharp.Abstraction.MLTasks;
|
||||
using BotSharp.Plugin.AzureOpenAI.Settings;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using OpenAI.Images;
|
||||
|
||||
namespace BotSharp.Plugin.AzureOpenAI.Providers;
|
||||
|
||||
|
|
@ -47,21 +34,23 @@ public class ImageGenerationProvider : IImageGeneration
|
|||
}
|
||||
|
||||
var client = ProviderHelper.GetClient(Provider, _model, _services);
|
||||
var options = PrepareOptions(conversations);
|
||||
var response = await client.GetImageGenerationsAsync(options);
|
||||
var image = response.Value.Data.First();
|
||||
var (prompt, options) = PrepareOptions(conversations);
|
||||
var imageClient = client.GetImageClient(_model);
|
||||
|
||||
var response = imageClient.GenerateImage(prompt, options);
|
||||
var value = response.Value;
|
||||
|
||||
var content = string.Empty;
|
||||
if (!string.IsNullOrEmpty(image.RevisedPrompt))
|
||||
if (!string.IsNullOrEmpty(value.RevisedPrompt))
|
||||
{
|
||||
content = image.RevisedPrompt;
|
||||
content = value.RevisedPrompt;
|
||||
}
|
||||
|
||||
var responseMessage = new RoleDialogModel(AgentRole.Assistant, content)
|
||||
{
|
||||
CurrentAgentId = agent.Id,
|
||||
MessageId = conversations.LastOrDefault()?.MessageId ?? string.Empty,
|
||||
Data = image.Url.AbsoluteUri ?? image.Base64Data
|
||||
Data = options.ResponseFormat == GeneratedImageFormat.Uri ? value.ImageUri?.AbsoluteUri : value.ImageBytes
|
||||
};
|
||||
|
||||
// After
|
||||
|
|
@ -69,10 +58,10 @@ public class ImageGenerationProvider : IImageGeneration
|
|||
{
|
||||
await hook.AfterGenerated(responseMessage, new TokenStatsModel
|
||||
{
|
||||
Prompt = options.Prompt,
|
||||
Prompt = prompt,
|
||||
Provider = Provider,
|
||||
Model = _model,
|
||||
PromptCount = options.Prompt.Split(' ', StringSplitOptions.RemoveEmptyEntries).Count(),
|
||||
PromptCount = prompt.Split(' ', StringSplitOptions.RemoveEmptyEntries).Count(),
|
||||
CompletionCount = content.Split(' ', StringSplitOptions.RemoveEmptyEntries).Count()
|
||||
});
|
||||
}
|
||||
|
|
@ -80,25 +69,99 @@ public class ImageGenerationProvider : IImageGeneration
|
|||
return responseMessage;
|
||||
}
|
||||
|
||||
private ImageGenerationOptions PrepareOptions(List<RoleDialogModel> conversations)
|
||||
private (string, ImageGenerationOptions) PrepareOptions(List<RoleDialogModel> conversations)
|
||||
{
|
||||
var state = _services.GetRequiredService<IConversationStateService>();
|
||||
var prompt = conversations.LastOrDefault()?.Payload ?? conversations.LastOrDefault()?.Content ?? string.Empty;
|
||||
|
||||
var sizeValue = !string.IsNullOrEmpty(state.GetState("image_size")) ? state.GetState("image_size") : "1024x1024";
|
||||
var qualityValue = !string.IsNullOrEmpty(state.GetState("image_quality")) ? state.GetState("image_quality") : "standard";
|
||||
var state = _services.GetRequiredService<IConversationStateService>();
|
||||
var size = state.GetState("image_size");
|
||||
var quality = state.GetState("image_quality");
|
||||
var style = state.GetState("image_style");
|
||||
|
||||
var options = new ImageGenerationOptions
|
||||
{
|
||||
DeploymentName = _model,
|
||||
Prompt = conversations.LastOrDefault()?.Payload ?? conversations.LastOrDefault()?.Content ?? string.Empty,
|
||||
Size = new ImageSize(sizeValue),
|
||||
Quality = new ImageGenerationQuality(qualityValue)
|
||||
Size = GetImageSize(size),
|
||||
Quality = GetImageQuality(quality),
|
||||
Style = GetImageStyle(style),
|
||||
ResponseFormat = GeneratedImageFormat.Uri
|
||||
};
|
||||
return options;
|
||||
return (prompt, options);
|
||||
}
|
||||
|
||||
public void SetModelName(string model)
|
||||
{
|
||||
_model = model;
|
||||
}
|
||||
|
||||
private GeneratedImageSize GetImageSize(string size)
|
||||
{
|
||||
var value = !string.IsNullOrEmpty(size) ? size : "1024x1024";
|
||||
|
||||
GeneratedImageSize retSize;
|
||||
switch (value)
|
||||
{
|
||||
case "256x256":
|
||||
retSize = GeneratedImageSize.W256xH256;
|
||||
break;
|
||||
case "512x512":
|
||||
retSize = GeneratedImageSize.W512xH512;
|
||||
break;
|
||||
case "1024x1024":
|
||||
retSize = GeneratedImageSize.W1024xH1024;
|
||||
break;
|
||||
case "1024x1792":
|
||||
retSize = GeneratedImageSize.W1024xH1792;
|
||||
break;
|
||||
case "1792x1024":
|
||||
retSize = GeneratedImageSize.W1792xH1024;
|
||||
break;
|
||||
default:
|
||||
retSize = GeneratedImageSize.W1024xH1024;
|
||||
break;
|
||||
}
|
||||
|
||||
return retSize;
|
||||
}
|
||||
|
||||
private GeneratedImageQuality GetImageQuality(string quality)
|
||||
{
|
||||
var value = !string.IsNullOrEmpty(quality) ? quality : "standard";
|
||||
|
||||
GeneratedImageQuality retQuality;
|
||||
switch (value)
|
||||
{
|
||||
case "standard":
|
||||
retQuality = GeneratedImageQuality.Standard;
|
||||
break;
|
||||
case "hd":
|
||||
retQuality = GeneratedImageQuality.High;
|
||||
break;
|
||||
default:
|
||||
retQuality = GeneratedImageQuality.Standard;
|
||||
break;
|
||||
}
|
||||
|
||||
return retQuality;
|
||||
}
|
||||
|
||||
private GeneratedImageStyle GetImageStyle(string style)
|
||||
{
|
||||
var value = !string.IsNullOrEmpty(style) ? style : "natural";
|
||||
|
||||
GeneratedImageStyle retStyle;
|
||||
switch (value)
|
||||
{
|
||||
case "standard":
|
||||
retStyle = GeneratedImageStyle.Natural;
|
||||
break;
|
||||
case "vivid":
|
||||
retStyle = GeneratedImageStyle.Vivid;
|
||||
break;
|
||||
default:
|
||||
retStyle = GeneratedImageStyle.Natural;
|
||||
break;
|
||||
}
|
||||
|
||||
return retStyle;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,3 @@
|
|||
using BotSharp.Plugin.AzureOpenAI.Settings;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
|
||||
namespace BotSharp.Plugin.AzureOpenAI.Providers;
|
||||
|
||||
public class OpenAiChatCompletionProvider : ChatCompletionProvider
|
||||
|
|
|
|||
|
|
@ -1,7 +1,3 @@
|
|||
using BotSharp.Plugin.AzureOpenAI.Settings;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
|
||||
namespace BotSharp.Plugin.AzureOpenAI.Providers;
|
||||
|
||||
public class OpenAiImageGenerationProvider : ImageGenerationProvider
|
||||
|
|
|
|||
|
|
@ -1,10 +1,7 @@
|
|||
using Azure.AI.OpenAI;
|
||||
using Azure;
|
||||
using System;
|
||||
using BotSharp.Abstraction.Conversations.Models;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using BotSharp.Abstraction.MLTasks;
|
||||
using OpenAI;
|
||||
using System.ClientModel;
|
||||
|
||||
namespace BotSharp.Plugin.AzureOpenAI.Providers;
|
||||
|
||||
|
|
@ -15,8 +12,8 @@ public class ProviderHelper
|
|||
var settingsService = services.GetRequiredService<ILlmProviderService>();
|
||||
var settings = settingsService.GetSetting(provider, model);
|
||||
var client = provider == "openai" ?
|
||||
new OpenAIClient($"{settings.ApiKey}") :
|
||||
new OpenAIClient(new Uri(settings.Endpoint), new AzureKeyCredential(settings.ApiKey));
|
||||
new OpenAIClient(new ApiKeyCredential(settings.ApiKey)) :
|
||||
new AzureOpenAIClient(new Uri(settings.Endpoint), new AzureKeyCredential(settings.ApiKey));
|
||||
return client;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,16 +1,4 @@
|
|||
using Azure.AI.OpenAI;
|
||||
using BotSharp.Abstraction.MLTasks;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using BotSharp.Plugin.AzureOpenAI.Settings;
|
||||
using BotSharp.Abstraction.Conversations;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using BotSharp.Abstraction.Conversations.Models;
|
||||
using BotSharp.Abstraction.Agents.Enums;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using BotSharp.Abstraction.Agents.Models;
|
||||
using BotSharp.Abstraction.Loggers;
|
||||
using OpenAI.Chat;
|
||||
|
||||
namespace BotSharp.Plugin.AzureOpenAI.Providers;
|
||||
|
||||
|
|
@ -51,30 +39,28 @@ public class TextCompletionProvider : ITextCompletion
|
|||
})).ToArray());
|
||||
|
||||
var client = ProviderHelper.GetClient(Provider, _model, _services);
|
||||
var chatClient = client.GetChatClient(_model);
|
||||
|
||||
var completionsOptions = new CompletionsOptions()
|
||||
var messages = new List<ChatMessage>()
|
||||
{
|
||||
Prompts =
|
||||
{
|
||||
text
|
||||
},
|
||||
MaxTokens = 256,
|
||||
new UserChatMessage(text)
|
||||
};
|
||||
completionsOptions.StopSequences.Add($"{AgentRole.Assistant}:");
|
||||
|
||||
var state = _services.GetRequiredService<IConversationStateService>();
|
||||
var temperature = float.Parse(state.GetState("temperature", "0.0"));
|
||||
var samplingFactor = float.Parse(state.GetState("sampling_factor", "0.0"));
|
||||
completionsOptions.Temperature = temperature;
|
||||
completionsOptions.NucleusSamplingFactor = samplingFactor;
|
||||
completionsOptions.DeploymentName = _model;
|
||||
var response = await client.GetCompletionsAsync(completionsOptions);
|
||||
var completionOptions = new ChatCompletionOptions()
|
||||
{
|
||||
MaxTokens = 256,
|
||||
Temperature = temperature
|
||||
};
|
||||
|
||||
var response = await chatClient.CompleteChatAsync(messages, completionOptions);
|
||||
|
||||
// OpenAI
|
||||
var completion = "";
|
||||
foreach (var t in response.Value.Choices)
|
||||
foreach (var t in response.Value.Content)
|
||||
{
|
||||
completion += t.Text;
|
||||
completion += t?.Text ?? string.Empty;
|
||||
};
|
||||
|
||||
// After chat completion hook
|
||||
|
|
@ -89,8 +75,8 @@ public class TextCompletionProvider : ITextCompletion
|
|||
Prompt = text,
|
||||
Provider = Provider,
|
||||
Model = _model,
|
||||
PromptCount = response.Value.Usage.PromptTokens,
|
||||
CompletionCount = response.Value.Usage.CompletionTokens
|
||||
PromptCount = response.Value.Usage.InputTokens,
|
||||
CompletionCount = response.Value.Usage.OutputTokens
|
||||
})).ToArray());
|
||||
|
||||
return completion.Trim();
|
||||
|
|
|
|||
17
src/Plugins/BotSharp.Plugin.AzureOpenAI/Using.cs
Normal file
17
src/Plugins/BotSharp.Plugin.AzureOpenAI/Using.cs
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
global using System;
|
||||
global using System.Collections.Generic;
|
||||
global using System.Linq;
|
||||
global using System.IO;
|
||||
global using System.Threading.Tasks;
|
||||
global using Microsoft.Extensions.DependencyInjection;
|
||||
global using Microsoft.Extensions.Logging;
|
||||
global using BotSharp.Abstraction.Agents.Enums;
|
||||
global using BotSharp.Abstraction.Agents.Models;
|
||||
global using BotSharp.Abstraction.Conversations;
|
||||
global using BotSharp.Abstraction.Conversations.Models;
|
||||
global using BotSharp.Abstraction.Loggers;
|
||||
global using BotSharp.Abstraction.MLTasks;
|
||||
global using BotSharp.Abstraction.Agents;
|
||||
global using BotSharp.Abstraction.Files;
|
||||
global using BotSharp.Abstraction.Utilities;
|
||||
global using BotSharp.Plugin.AzureOpenAI.Settings;
|
||||
|
|
@ -11,6 +11,8 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="data\agents\00000000-0000-0000-0000-000000000000\functions\handle_http_request.json" />
|
||||
<None Remove="data\agents\00000000-0000-0000-0000-000000000000\templates\handle_http_request.fn.liquid" />
|
||||
<None Remove="data\agents\87c458fc-ec5f-40ae-8ed6-05dda8a07523\agent.json" />
|
||||
<None Remove="data\agents\87c458fc-ec5f-40ae-8ed6-05dda8a07523\functions.json" />
|
||||
<None Remove="data\agents\87c458fc-ec5f-40ae-8ed6-05dda8a07523\instruction.liquid" />
|
||||
|
|
@ -26,6 +28,12 @@
|
|||
<Content Include="data\agents\87c458fc-ec5f-40ae-8ed6-05dda8a07523\instruction.liquid">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="data\agents\00000000-0000-0000-0000-000000000000\functions\handle_http_request.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="data\agents\00000000-0000-0000-0000-000000000000\templates\handle_http_request.fn.liquid">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
6
src/Plugins/BotSharp.Plugin.HttpHandler/Enums/Tool.cs
Normal file
6
src/Plugins/BotSharp.Plugin.HttpHandler/Enums/Tool.cs
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
namespace BotSharp.Plugin.HttpHandler.Enums;
|
||||
|
||||
public class Tool
|
||||
{
|
||||
public const string HttpHandler = "http-handler";
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
using BotSharp.Abstraction.Agents;
|
||||
using BotSharp.Abstraction.Agents.Settings;
|
||||
using BotSharp.Abstraction.Functions.Models;
|
||||
using BotSharp.Abstraction.Repositories;
|
||||
using BotSharp.Plugin.HttpHandler.Enums;
|
||||
|
||||
namespace BotSharp.Plugin.HttpHandler.Hooks;
|
||||
|
||||
public class HttpHandlerHook : AgentHookBase
|
||||
{
|
||||
private static string TOOL_ASSISTANT = Guid.Empty.ToString();
|
||||
|
||||
public override string SelfId => string.Empty;
|
||||
|
||||
public HttpHandlerHook(IServiceProvider services, AgentSettings settings)
|
||||
: base(services, settings)
|
||||
{
|
||||
}
|
||||
|
||||
public override void OnAgentLoaded(Agent agent)
|
||||
{
|
||||
var conv = _services.GetRequiredService<IConversationService>();
|
||||
var isConvMode = conv.IsConversationMode();
|
||||
var isEnabled = !agent.Tools.IsNullOrEmpty() && agent.Tools.Contains(Tool.HttpHandler);
|
||||
|
||||
if (isConvMode && isEnabled)
|
||||
{
|
||||
var (prompt, fn) = GetPromptAndFunction();
|
||||
if (fn != null)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(prompt))
|
||||
{
|
||||
agent.Instruction += $"\r\n\r\n{prompt}\r\n\r\n";
|
||||
}
|
||||
|
||||
if (agent.Functions == null)
|
||||
{
|
||||
agent.Functions = new List<FunctionDef> { fn };
|
||||
}
|
||||
else
|
||||
{
|
||||
agent.Functions.Add(fn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
base.OnAgentLoaded(agent);
|
||||
}
|
||||
|
||||
private (string, FunctionDef?) GetPromptAndFunction()
|
||||
{
|
||||
var fn = "handle_http_request";
|
||||
var db = _services.GetRequiredService<IBotSharpRepository>();
|
||||
var agent = db.GetAgent(TOOL_ASSISTANT);
|
||||
var prompt = agent?.Templates?.FirstOrDefault(x => x.Name.IsEqualTo($"{fn}.fn"))?.Content ?? string.Empty;
|
||||
var loadAttachmentFn = agent?.Functions?.FirstOrDefault(x => x.Name.IsEqualTo(fn));
|
||||
return (prompt, loadAttachmentFn);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
using BotSharp.Abstraction.Agents;
|
||||
using BotSharp.Plugin.HttpHandler.Enums;
|
||||
|
||||
namespace BotSharp.Plugin.HttpHandler.Hooks;
|
||||
|
||||
public class HttpHandlerToolHook : IAgentToolHook
|
||||
{
|
||||
public void AddTools(List<string> tools)
|
||||
{
|
||||
tools.Add(Tool.HttpHandler);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
using BotSharp.Abstraction.Http.Settings;
|
||||
using BotSharp.Abstraction.Agents;
|
||||
using BotSharp.Abstraction.Settings;
|
||||
using BotSharp.Plugin.HttpHandler.Hooks;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
namespace BotSharp.Plugin.HttpHandler;
|
||||
|
|
@ -19,5 +20,8 @@ public class HttpHandlerPlugin : IBotSharpPlugin
|
|||
var settingService = provider.GetRequiredService<ISettingService>();
|
||||
return settingService.Bind<HttpSettings>("Http");
|
||||
});
|
||||
|
||||
services.AddScoped<IAgentHook, HttpHandlerHook>();
|
||||
services.AddScoped<IAgentToolHook, HttpHandlerToolHook>();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"name": "handle_http_request",
|
||||
"description": "If the user requests to send an http request, you need to capture the http method and request content, and then call this function to send the http request.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"request_url": {
|
||||
"type": "string",
|
||||
"description": "The http url that is requested. It can be an absolute url that starts with 'http' or 'https', or a relative url that starts with '/'"
|
||||
},
|
||||
"http_method": {
|
||||
"type": "string",
|
||||
"description": "The http method that is requested, e.g., GET, POST, PUT, and DELETE."
|
||||
},
|
||||
"request_content": {
|
||||
"type": "string",
|
||||
"description": "The http request content. It must be in json format.."
|
||||
}
|
||||
},
|
||||
"required": [ "request_url", "http_method" ]
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
Please call handle_http_request if user wants to send an http request.
|
||||
|
|
@ -13,6 +13,10 @@
|
|||
<ItemGroup>
|
||||
<None Remove="data\agents\beda4c12-e1ec-4b4b-b328-3df4a6687c4f\agent.json" />
|
||||
<None Remove="data\agents\beda4c12-e1ec-4b4b-b328-3df4a6687c4f\functions.json" />
|
||||
<None Remove="data\agents\beda4c12-e1ec-4b4b-b328-3df4a6687c4f\functions\get_table_columns.json" />
|
||||
<None Remove="data\agents\beda4c12-e1ec-4b4b-b328-3df4a6687c4f\functions\lookup_dictionary.json" />
|
||||
<None Remove="data\agents\beda4c12-e1ec-4b4b-b328-3df4a6687c4f\functions\sql_insert.json" />
|
||||
<None Remove="data\agents\beda4c12-e1ec-4b4b-b328-3df4a6687c4f\functions\sql_select.json" />
|
||||
<None Remove="data\agents\beda4c12-e1ec-4b4b-b328-3df4a6687c4f\instruction.liquid" />
|
||||
<None Remove="data\agents\beda4c12-e1ec-4b4b-b328-3df4a6687c4f\templates\lookup_dictionary.liquid" />
|
||||
</ItemGroup>
|
||||
|
|
@ -21,15 +25,27 @@
|
|||
<Content Include="data\agents\beda4c12-e1ec-4b4b-b328-3df4a6687c4f\agent.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="data\agents\beda4c12-e1ec-4b4b-b328-3df4a6687c4f\functions.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="data\agents\beda4c12-e1ec-4b4b-b328-3df4a6687c4f\instruction.liquid">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="data\agents\beda4c12-e1ec-4b4b-b328-3df4a6687c4f\functions.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="data\agents\beda4c12-e1ec-4b4b-b328-3df4a6687c4f\templates\lookup_dictionary.liquid">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="data\agents\beda4c12-e1ec-4b4b-b328-3df4a6687c4f\functions\get_table_columns.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="data\agents\beda4c12-e1ec-4b4b-b328-3df4a6687c4f\functions\lookup_dictionary.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="data\agents\beda4c12-e1ec-4b4b-b328-3df4a6687c4f\functions\sql_insert.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="data\agents\beda4c12-e1ec-4b4b-b328-3df4a6687c4f\functions\sql_select.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"name": "get_table_columns",
|
||||
"description": "Get related table columns and foreign key informations",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"table": {
|
||||
"type": "string",
|
||||
"description": "table name"
|
||||
}
|
||||
},
|
||||
"required": [ "table" ]
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
{
|
||||
"name": "lookup_dictionary",
|
||||
"description": "Get id from dictionary table by keyword if tool or solution mentioned this approach",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"table": {
|
||||
"type": "string",
|
||||
"description": "table name"
|
||||
},
|
||||
"keyword": {
|
||||
"type": "string",
|
||||
"description": "table name"
|
||||
},
|
||||
"reason": {
|
||||
"type": "string",
|
||||
"description": "the reason why you need to call lookup_dictionary"
|
||||
},
|
||||
"columns": {
|
||||
"type": "array",
|
||||
"description": "columns",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"description": "column"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [ "table", "keyword", "reason", "columns" ]
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
{
|
||||
"name": "sql_insert",
|
||||
"description": "Insert query is generated if the record doesn't exist.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"sql_statement": {
|
||||
"type": "string",
|
||||
"description": "INSERT SQL statement. The value should use the parameter name like @field."
|
||||
},
|
||||
"reason": {
|
||||
"type": "string",
|
||||
"description": "reason"
|
||||
},
|
||||
"table": {
|
||||
"type": "string",
|
||||
"description": "related table"
|
||||
},
|
||||
"parameters": {
|
||||
"type": "array",
|
||||
"description": "a list of parameters in the statement match with the variables",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"description": "{name:'', value:''}",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "field name"
|
||||
},
|
||||
"value": {
|
||||
"type": "string",
|
||||
"description": "real value inferred by the context"
|
||||
}
|
||||
},
|
||||
"required": [ "name", "value" ]
|
||||
}
|
||||
},
|
||||
"return_field": {
|
||||
"type": "object",
|
||||
"description": "the name and alias for the return field",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "field name"
|
||||
},
|
||||
"alias": {
|
||||
"type": "string",
|
||||
"description": "meaningful field alias"
|
||||
}
|
||||
},
|
||||
"required": [ "name", "alias" ]
|
||||
}
|
||||
},
|
||||
"required": [ "sql_statement", "reason", "table", "parameters", "return_field" ]
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
{
|
||||
"name": "sql_select",
|
||||
"description": "Get the specific value from table",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"sql_statement": {
|
||||
"type": "string",
|
||||
"description": "SQL statement with SELECT"
|
||||
},
|
||||
"reason": {
|
||||
"type": "string",
|
||||
"description": "reason"
|
||||
},
|
||||
"table": {
|
||||
"type": "string",
|
||||
"description": "related table"
|
||||
},
|
||||
"parameters": {
|
||||
"type": "array",
|
||||
"description": "data criteria for the query",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"description": "the name and value for the parameter",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "field name"
|
||||
},
|
||||
"value": {
|
||||
"type": "string",
|
||||
"description": "real value inferred by the context"
|
||||
}
|
||||
},
|
||||
"required": [ "name", "value" ]
|
||||
}
|
||||
},
|
||||
"return_field": {
|
||||
"type": "object",
|
||||
"description": "the name and alias for the return field",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "field in the table"
|
||||
},
|
||||
"alias": {
|
||||
"type": "string",
|
||||
"description": "meaningful field alias"
|
||||
}
|
||||
},
|
||||
"required": [ "name", "value" ]
|
||||
}
|
||||
},
|
||||
"required": [ "sql_statement", "reason", "table", "parameters", "return_field" ]
|
||||
}
|
||||
}
|
||||
|
|
@ -25,6 +25,20 @@
|
|||
<ItemGroup>
|
||||
<None Remove="data\agents\f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b\agent.json" />
|
||||
<None Remove="data\agents\f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b\functions.json" />
|
||||
<None Remove="data\agents\f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b\functions\change_checkbox.json" />
|
||||
<None Remove="data\agents\f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b\functions\change_list_value.json" />
|
||||
<None Remove="data\agents\f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b\functions\check_radio_button.json" />
|
||||
<None Remove="data\agents\f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b\functions\click_button.json" />
|
||||
<None Remove="data\agents\f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b\functions\click_element.json" />
|
||||
<None Remove="data\agents\f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b\functions\close_browser.json" />
|
||||
<None Remove="data\agents\f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b\functions\extract_data_from_page.json" />
|
||||
<None Remove="data\agents\f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b\functions\go_to_page.json" />
|
||||
<None Remove="data\agents\f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b\functions\input_user_password.json" />
|
||||
<None Remove="data\agents\f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b\functions\input_user_text.json" />
|
||||
<None Remove="data\agents\f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b\functions\open_browser.json" />
|
||||
<None Remove="data\agents\f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b\functions\scroll_page.json" />
|
||||
<None Remove="data\agents\f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b\functions\send_http_request.json" />
|
||||
<None Remove="data\agents\f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b\functions\take_screenshot.json" />
|
||||
<None Remove="data\agents\f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b\instruction.liquid" />
|
||||
<None Remove="data\agents\f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b\templates\extract_data.liquid" />
|
||||
<None Remove="data\agents\f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b\templates\html_parser.liquid" />
|
||||
|
|
@ -47,6 +61,48 @@
|
|||
<Content Include="data\agents\f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b\templates\html_parser.liquid">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="data\agents\f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b\functions\change_checkbox.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="data\agents\f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b\functions\change_list_value.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="data\agents\f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b\functions\check_radio_button.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="data\agents\f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b\functions\click_button.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="data\agents\f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b\functions\click_element.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="data\agents\f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b\functions\close_browser.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="data\agents\f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b\functions\extract_data_from_page.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="data\agents\f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b\functions\go_to_page.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="data\agents\f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b\functions\input_user_password.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="data\agents\f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b\functions\input_user_text.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="data\agents\f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b\functions\open_browser.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="data\agents\f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b\functions\scroll_page.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="data\agents\f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b\functions\send_http_request.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="data\agents\f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b\functions\take_screenshot.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"name": "change_checkbox",
|
||||
"description": "Check or uncheck checkbox",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"element_text": {
|
||||
"type": "string",
|
||||
"description": "the element title"
|
||||
},
|
||||
"update_value": {
|
||||
"type": "string",
|
||||
"description": "check or uncheck"
|
||||
},
|
||||
"match_rule": {
|
||||
"type": "string",
|
||||
"description": "text matching rule: EndWith, StartWith, Contains, Match"
|
||||
}
|
||||
},
|
||||
"required": [ "element_text", "update_value", "match_rule" ]
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"name": "change_list_value",
|
||||
"description": "Update value from dropdown list or radio button",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"element_name": {
|
||||
"type": "string",
|
||||
"description": "the html selection element name."
|
||||
},
|
||||
"update_value": {
|
||||
"type": "string",
|
||||
"description": "the value in the list."
|
||||
}
|
||||
},
|
||||
"required": [ "element_name", "update_value" ]
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"name": "check_radio_button",
|
||||
"description": "Check value in a radio button",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"element_text": {
|
||||
"type": "string",
|
||||
"description": "the element title"
|
||||
},
|
||||
"update_value": {
|
||||
"type": "string",
|
||||
"description": "the value in the radio button."
|
||||
},
|
||||
"match_rule": {
|
||||
"type": "string",
|
||||
"description": "text matching rule: EndWith, StartWith, Contains, Match"
|
||||
}
|
||||
},
|
||||
"required": [ "update_value", "element_text", "match_rule" ]
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"name": "click_button",
|
||||
"description": "Click a button in a web page.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"element_name": {
|
||||
"type": "string",
|
||||
"description": "the html element name."
|
||||
}
|
||||
},
|
||||
"required": [ "element_name" ]
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
{
|
||||
"name": "click_element",
|
||||
"description": "Click or check an element contains some text",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"element_type": {
|
||||
"type": "string",
|
||||
"description": "the element tag name"
|
||||
},
|
||||
"element_text": {
|
||||
"type": "string",
|
||||
"description": "text or placeholder shown in the element."
|
||||
},
|
||||
"attribute_name": {
|
||||
"type": "string",
|
||||
"description": "attribute name in the element"
|
||||
},
|
||||
"attribute_value": {
|
||||
"type": "string",
|
||||
"description": "attribute value in the element"
|
||||
},
|
||||
"match_rule": {
|
||||
"type": "string",
|
||||
"description": "text matching rule: EndWith, StartWith, Contains, Match"
|
||||
}
|
||||
},
|
||||
"required": [ "element_type", "element_text", "match_rule" ]
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"name": "close_browser",
|
||||
"description": "Close browser",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
},
|
||||
"required": []
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"name": "extract_data_from_page",
|
||||
"description": "Extract data from current web page.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"question": {
|
||||
"type": "string",
|
||||
"description": "the information user wants to know"
|
||||
}
|
||||
},
|
||||
"required": [ "question" ]
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"name": "go_to_page",
|
||||
"description": "go to another page",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"url": {
|
||||
"type": "string",
|
||||
"description": "page url start with https://"
|
||||
}
|
||||
},
|
||||
"required": [ "url" ]
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"name": "input_user_password",
|
||||
"description": "Input password in current web page",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"password": {
|
||||
"type": "string",
|
||||
"description": "user password"
|
||||
}
|
||||
},
|
||||
"required": [ "password" ]
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
{
|
||||
"name": "input_user_text",
|
||||
"description": "Input non-sensitive text in current web page.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"element_text": {
|
||||
"type": "string",
|
||||
"description": "text or placeholder shown in the element."
|
||||
},
|
||||
"input_text": {
|
||||
"type": "string",
|
||||
"description": "non-sensitive text user provided."
|
||||
},
|
||||
"press_enter": {
|
||||
"type": "boolean",
|
||||
"description": "whether to press Enter key"
|
||||
},
|
||||
"attribute_name": {
|
||||
"type": "string",
|
||||
"description": "attribute name in the element"
|
||||
},
|
||||
"attribute_value": {
|
||||
"type": "string",
|
||||
"description": "attribute value in the element"
|
||||
}
|
||||
},
|
||||
"required": [ "element_text", "input_text" ]
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"name": "open_browser",
|
||||
"description": "open a browser",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"url": {
|
||||
"type": "string",
|
||||
"description": "website url starts with https://"
|
||||
}
|
||||
},
|
||||
"required": [ "url" ]
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"name": "scroll_page",
|
||||
"description": "Scroll page down or up",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"direction": {
|
||||
"type": "string",
|
||||
"description": "down, up, left, right"
|
||||
}
|
||||
},
|
||||
"required": [ "direction" ]
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"name": "send_http_request",
|
||||
"description": "Send http request to remote server",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"url": {
|
||||
"type": "string",
|
||||
"description": "page url start with https://"
|
||||
},
|
||||
"payload": {
|
||||
"type": "string",
|
||||
"description": "request body"
|
||||
}
|
||||
},
|
||||
"required": [ "url", "payload" ]
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"name": "take_screenshot",
|
||||
"description": "Tak screenshot to show current page screen",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
},
|
||||
"required": []
|
||||
}
|
||||
}
|
||||
|
|
@ -292,7 +292,8 @@
|
|||
"BotSharp.Plugin.WebDriver",
|
||||
"BotSharp.Plugin.LLamaSharp",
|
||||
"BotSharp.Plugin.SparkDesk",
|
||||
"BotSharp.Plugin.MetaGLM"
|
||||
"BotSharp.Plugin.MetaGLM",
|
||||
"BotSharp.Plugin.HttpHandler"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.1</TargetFramework>
|
||||
|
|
@ -24,13 +24,18 @@
|
|||
<None Remove="data\agents\8970b1e5-d260-4e2c-90b1-f1415a257c18\templates\task.place_pizza_order.liquid" />
|
||||
<None Remove="data\agents\b284db86-e9c2-4c25-a59e-4649797dd130\agent.json" />
|
||||
<None Remove="data\agents\b284db86-e9c2-4c25-a59e-4649797dd130\functions.json" />
|
||||
<None Remove="data\agents\b284db86-e9c2-4c25-a59e-4649797dd130\functions\get_order_status.json" />
|
||||
<None Remove="data\agents\b284db86-e9c2-4c25-a59e-4649797dd130\instruction.liquid" />
|
||||
<None Remove="data\agents\c2b57a74-ae4e-4c81-b3ad-9ac5bff982bd\agent.json" />
|
||||
<None Remove="data\agents\c2b57a74-ae4e-4c81-b3ad-9ac5bff982bd\functions.json" />
|
||||
<None Remove="data\agents\c2b57a74-ae4e-4c81-b3ad-9ac5bff982bd\functions\get_pizza_price.json" />
|
||||
<None Remove="data\agents\c2b57a74-ae4e-4c81-b3ad-9ac5bff982bd\functions\get_pizza_types.json" />
|
||||
<None Remove="data\agents\c2b57a74-ae4e-4c81-b3ad-9ac5bff982bd\functions\place_an_order.json" />
|
||||
<None Remove="data\agents\c2b57a74-ae4e-4c81-b3ad-9ac5bff982bd\instruction.liquid" />
|
||||
<None Remove="data\agents\c2b57a74-ae4e-4c81-b3ad-9ac5bff982bd\responses\func.get_pizza_price.0.liquid" />
|
||||
<None Remove="data\agents\fe8c60aa-b114-4ef3-93cb-a8efeac80f75\agent.json" />
|
||||
<None Remove="data\agents\fe8c60aa-b114-4ef3-93cb-a8efeac80f75\functions.json" />
|
||||
<None Remove="data\agents\fe8c60aa-b114-4ef3-93cb-a8efeac80f75\functions\make_payment.json" />
|
||||
<None Remove="data\agents\fe8c60aa-b114-4ef3-93cb-a8efeac80f75\instruction.liquid" />
|
||||
<None Remove="data\users\10d12798-08fb-4aa6-977b-5dd94d82dbfe\user.json" />
|
||||
<None Remove="data\users\456e35c5-caf0-4d45-9084-b44a8ca717e4\user.json" />
|
||||
|
|
@ -87,6 +92,21 @@
|
|||
<Content Include="data\users\e465af5f-044f-414b-b670-92834929b96c\user.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="data\agents\b284db86-e9c2-4c25-a59e-4649797dd130\functions\get_order_status.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="data\agents\c2b57a74-ae4e-4c81-b3ad-9ac5bff982bd\functions\get_pizza_price.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="data\agents\c2b57a74-ae4e-4c81-b3ad-9ac5bff982bd\functions\get_pizza_types.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="data\agents\c2b57a74-ae4e-4c81-b3ad-9ac5bff982bd\functions\place_an_order.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="data\agents\fe8c60aa-b114-4ef3-93cb-a8efeac80f75\functions\make_payment.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="$(SolutionName)==BotSharp">
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"name": "get_order_status",
|
||||
"description": "get order status like delivery remaining time",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"order_number": {
|
||||
"type": "string",
|
||||
"description": "order number."
|
||||
}
|
||||
},
|
||||
"required": [ "order_number" ]
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"name": "get_pizza_price",
|
||||
"description": "call this function to get the pizza price",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"pizza_type": {
|
||||
"type": "string",
|
||||
"description": "The pizza type."
|
||||
},
|
||||
"quantity": {
|
||||
"type": "string",
|
||||
"description": "quantity of pizza."
|
||||
}
|
||||
},
|
||||
"required": [ "pizza_type", "quantity" ]
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"name": "get_pizza_types",
|
||||
"description": "get all pizza types",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {},
|
||||
"required": []
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"name": "place_an_order",
|
||||
"description": "Place an order when user has confirmed the pizza type and quantity.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"pizza_type": {
|
||||
"type": "string",
|
||||
"description": "The pizza type."
|
||||
},
|
||||
"quantity": {
|
||||
"type": "number",
|
||||
"description": "quantity of pizza."
|
||||
},
|
||||
"unit_price": {
|
||||
"type": "number",
|
||||
"description": "unit price"
|
||||
}
|
||||
},
|
||||
"required": [ "pizza_type", "quantity", "unit_price" ]
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"name": "make_payment",
|
||||
"description": "call this function to make payment",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"order_number": {
|
||||
"type": "string",
|
||||
"description": "order number."
|
||||
},
|
||||
"total_amount": {
|
||||
"type": "string",
|
||||
"description": "total amount."
|
||||
}
|
||||
},
|
||||
"required": [ "order_number", "total_amount" ]
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue