Merge branch 'SciSharp:master' into master

This commit is contained in:
Haiping 2024-10-27 08:04:27 -05:00 committed by GitHub
commit c06b0144c9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
31 changed files with 270 additions and 13 deletions

View file

@ -12,7 +12,7 @@
**BotSharp** is an open source machine learning framework for AI Bot platform builder. This project involves natural language understanding, computer vision and audio processing technologies, and aims to promote the development and application of intelligent robot assistants in information systems. Out-of-the-box machine learning algorithms allow ordinary programmers to develop artificial intelligence applications faster and easier.
It's written in C# running on .Net Core that is full cross-platform framework, the plug-in and pipeline flow execution design is adopted to completely decouple the plug-ins. C# is a enterprise grade programming language which is widely used to code business logic in information management related system. More friendly to corporate developers. BotSharp adopts machine learning algrithm in C# directly. That will facilitate the feature of the typed language C#, and be more easier when refactoring code in system scope.
It's written in C# running on .Net Core that is full cross-platform framework, the plug-in and pipeline flow execution design is adopted to completely decouple the plug-ins. C# is a enterprise grade programming language which is widely used to code business logic in information management related system. More friendly to corporate developers. BotSharp adopts machine learning algorithm in C# directly. That will facilitate the feature of the typed language C#, and be more easier when refactoring code in system scope.
**BotSharp** is in accordance with components principle strictly, decouples every part that is needed in the platform builder. So you can choose different UI/UX, or pick up a different LLM providers. They are all modulized based on unified interfaces. **BotSharp** provides an advanced Agent abstraction layer to efficiently manage complex application scenarios in enterprises, allowing enterprise developers to efficiently integrate AI into business systems.
@ -22,7 +22,7 @@ It's written in C# running on .Net Core that is full cross-platform framework, t
* Built-in multi-agents and conversation with state management.
* Support multiple LLM Planning approaches to handle different tasks from simple to complex.
* Built-in RAG related interfaces, Memeory based vector searching.
* Built-in RAG related interfaces, Memory based vector searching.
* Support multiple AI platforms (ChatGPT 3.5 / 4.0, PaLM 2, LLaMA 3, Claude Sonnet 3.5, HuggingFace).
* Allow multiple agents with different responsibilities cooperate to complete complex tasks.
* Build, test, evaluate and audit your LLM agent in one place.

View file

@ -37,5 +37,13 @@ public class BuiltInAgentId
/// </summary>
public const string Planner = "282a7128-69a1-44b0-878c-a9159b88f3b9";
/// <summary>
/// SQL statement generation
/// </summary>
public const string SqlDriver = "beda4c12-e1ec-4b4b-b328-3df4a6687c4f";
/// <summary>
/// Programming source code generation
/// </summary>
public const string CodeDriver = "c0ded7d9-3f9d-4ef6-b7ce-56a892dcef62";
}

View file

@ -24,6 +24,11 @@ public class Conversation
public string Channel { get; set; } = ConversationChannel.OpenAPI;
/// <summary>
/// Channel id, like phone number, email address, etc.
/// </summary>
public string ChannelId { get; set; }
public int DialogCount { get; set; }
public List<string> Tags { get; set; } = new();

View file

@ -36,6 +36,9 @@ public class GenericElement
[Translate]
public string Subtitle { get; set; }
[Translate]
public string Text { get; set; }
[JsonPropertyName("image_url")]
public string ImageUrl { get; set; }

View file

@ -36,6 +36,11 @@ public class MessageConfig
/// </summary>
public List<MessageState> States { get; set; } = new();
/// <summary>
/// Conversation tags
/// </summary>
public List<string> Tags { get; set; } = new();
/// <summary>
/// Agent task id
/// </summary>

View file

@ -172,10 +172,12 @@ public partial class ConversationService : IConversationService
{
var state = _services.GetRequiredService<IConversationStateService>();
var channel = state.GetState("channel");
var channelId = state.GetState("channel_id");
var sess = new Conversation
{
Id = _conversationId,
Channel = channel,
ChannelId = channelId,
AgentId = agentId
};
converation = await NewConversation(sess);

View file

@ -69,7 +69,9 @@ public partial class InstructService
};
var messages = BuildDialogs(options);
var completion = CompletionProvider.GetChatCompletion(_services, provider: options.Provider, model: options.Model);
var provider = options.Provider ?? agent?.LlmConfig?.Provider ?? "openai";
var model = options.Model ?? agent?.LlmConfig?.Model ?? "gpt-4o";
var completion = CompletionProvider.GetChatCompletion(_services, provider: provider, model: model);
return await completion.GetChatCompletions(localAgent, messages);
}

View file

@ -10,7 +10,7 @@ namespace BotSharp.Core.Repository
var utcNow = DateTime.UtcNow;
conversation.CreatedTime = utcNow;
conversation.UpdatedTime = utcNow;
conversation.Tags = conversation.Tags ?? new();
conversation.Tags ??= new();
var dir = Path.Combine(_dbSettings.FileRepository, _conversationSettings.DataDir, conversation.Id);
if (!Directory.Exists(dir))

View file

@ -35,6 +35,7 @@ public class ConversationController : ControllerBase
{
AgentId = agentId,
Channel = channel == default ? ConversationChannel.OpenAPI : channel.Value,
Tags = config.Tags ?? new(),
TaskId = config.TaskId
};
conv = await service.NewConversation(conv);

View file

@ -37,7 +37,7 @@ public class ChatCompletionProvider : IChatCompletion
}
var settingsService = _services.GetRequiredService<ILlmProviderService>();
var settings = settingsService.GetSetting("anthropic", agent.LlmConfig?.Model ?? "claude-3-haiku");
var settings = settingsService.GetSetting(Provider, _model ?? agent.LlmConfig?.Model ?? "claude-3-haiku");
var client = new AnthropicClient(new APIAuthentication(settings.ApiKey));
var (prompt, parameters) = PrepareOptions(agent, conversations, settings);

View file

@ -0,0 +1,37 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<Compile Remove="data\generated_code\**" />
<EmbeddedResource Remove="data\generated_code\**" />
<None Remove="data\generated_code\**" />
</ItemGroup>
<ItemGroup>
<None Remove="data\agents\c0ded7d9-3f9d-4ef6-b7ce-56a892dcef62\agent.json" />
<None Remove="data\agents\c0ded7d9-3f9d-4ef6-b7ce-56a892dcef62\functions\save_source_code.json" />
<None Remove="data\agents\c0ded7d9-3f9d-4ef6-b7ce-56a892dcef62\instructions\instruction.liquid" />
</ItemGroup>
<ItemGroup>
<Content Include="data\agents\c0ded7d9-3f9d-4ef6-b7ce-56a892dcef62\agent.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="data\agents\c0ded7d9-3f9d-4ef6-b7ce-56a892dcef62\functions\save_source_code.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="data\agents\c0ded7d9-3f9d-4ef6-b7ce-56a892dcef62\instructions\instruction.liquid">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Infrastructure\BotSharp.Abstraction\BotSharp.Abstraction.csproj" />
</ItemGroup>
</Project>

View file

@ -0,0 +1,22 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace BotSharp.Plugin.CodeDriver;
public class CodeDriverPlugin : IBotSharpPlugin
{
public string Id => "c0dedea7-70e3-4c35-a047-18479d7c403e";
public string Name => "Code Driver";
public string Description => "Convert the user requirements into corresponding SQL statements";
public string IconUrl => "https://cdn-icons-png.flaticon.com/512/3176/3176315.png";
public string[] AgentIds =
[
BuiltInAgentId.CodeDriver
];
public void RegisterDI(IServiceCollection services, IConfiguration config)
{
}
}

View file

@ -0,0 +1,49 @@
using BotSharp.Abstraction.Conversations.Models;
using BotSharp.Abstraction.Functions;
using BotSharp.Plugin.CodeDriver.Models;
using Microsoft.Extensions.DependencyInjection;
using System.Text.Json;
namespace BotSharp.Plugin.CodeDriver.Functions;
public class SaveSourceCodeFn : IFunctionCallback
{
public string Name => "save_source_code";
private readonly IServiceProvider _services;
public SaveSourceCodeFn(IServiceProvider services)
{
_services = services;
}
public async Task<bool> Execute(RoleDialogModel message)
{
var args = JsonSerializer.Deserialize<SaveSourceCodeArgs>(message.FunctionArgs);
var dir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "..", "..", "..", "ai_generated_code");
if (!Directory.Exists(dir))
{
Directory.CreateDirectory(dir);
}
var path = Path.GetFullPath(dir, args.FilePath);
var source = args.SourceCode;
// Delete the file if it exists
File.Delete(path);
// Create a FileStream with sharing capabilities
using FileStream fs = new FileStream(
path,
FileMode.OpenOrCreate, // Create or overwrite the file
FileAccess.ReadWrite, // Allow read and write operations
FileShare.Read); // Allow other processes to read and write
// Write some data to the file
using StreamWriter writer = new StreamWriter(fs);
writer.WriteLine(source);
return true;
}
}

View file

@ -0,0 +1,12 @@
using System.Text.Json.Serialization;
namespace BotSharp.Plugin.CodeDriver.Models;
public class SaveSourceCodeArgs
{
[JsonPropertyName("file_path")]
public string FilePath { get; set; } = string.Empty;
[JsonPropertyName("source_code")]
public string SourceCode { get; set; } = string.Empty;
}

View file

@ -0,0 +1,2 @@
global using BotSharp.Abstraction.Agents.Enums;
global using BotSharp.Abstraction.Plugins;

View file

@ -0,0 +1,17 @@
{
"id": "c0ded7d9-3f9d-4ef6-b7ce-56a892dcef62",
"name": "Code Driver",
"description": "Write executable program code according to user needs, such as HTTP API written in Python.",
"iconUrl": "https://cdn-icons-png.flaticon.com/512/4208/4208366.png",
"type": "task",
"createdDateTime": "2024-10-23T00:00:00Z",
"updatedDateTime": "2024-11-23T00:00:00Z",
"disabled": false,
"isPublic": true,
"profiles": [ "database" ],
"llmConfig": {
"provider": "openai",
"model": "gpt-4o",
"max_recursion_depth": 10
}
}

View file

@ -0,0 +1,19 @@
{
"name": "save_source_code",
"description": "Save the source code to file",
"parameters": {
"type": "object",
"properties": {
"file_path": {
"type": "string",
"description": "source code of file relative path start with project folder name"
},
"source_code": {
"type": "string",
"description": "source code"
}
},
"required": [ "file_path", "source_code" ]
}
}

View file

@ -0,0 +1,19 @@
You are a software developer who is good at writing program code according to user needs, such as HTTP API written in Python.
Current project source code structure is:
my_fastapi_app/
├── main.py
├── apis/
│ └── datetime_api.py
├── __init__.py
You are using below tools and technologies:
* FastAPI framework
* Python programming language
* Swagger Open API
Your response must meet below requirements:
* Every API should be placed in a separate file under folder of "apis";
* Call function save_source_code to save the code;
* Write Swagger comments for each API;
* Update main.py to include those updated APIs;

View file

@ -90,6 +90,7 @@ namespace BotSharp.Plugin.ExcelHandler.Services
{
var numTables = workbook.NumberOfSheets;
var commandList = new List<SqlContextOut>();
var state = _services.GetRequiredService<IConversationStateService>();
for (int sheetIdx = 0; sheetIdx < numTables; sheetIdx++)
{
@ -109,15 +110,17 @@ namespace BotSharp.Plugin.ExcelHandler.Services
commandList.Add(commandResult);
continue;
}
var (isInsertSuccess, insertMessage) = SqlInsertDataFn(sheet);
string table = $"{_database}.{_tableName}";
state.SetState("tmp_table", table);
var (isInsertSuccess, insertMessage) = SqlInsertDataFn(sheet);
string exampleData = GetInsertExample(table);
commandResult = new SqlContextOut
{
isSuccessful = isInsertSuccess,
Message = $"{insertMessage}\r\nExample Data: {exampleData}",
Message = $"{insertMessage}\r\nExample Data: {exampleData}. \r\n The remaining data contains different values. ",
FileName = _currentFileName
};
commandList.Add(commandResult);

View file

@ -3,6 +3,9 @@ You are a knowledge extractor for knowledge base. Extract the answer in "SQL Ans
* Skip the question/answer for tmp table.
* Don't include tmp table in the answer.
* Include all the explanation comments as additional knowledge.
* Don't replace the parameter in the question.
* Replace the specific id in answer based on the question.
* Don't need multiple set of query solutions for the same question. Only keep one.
=====
User Questions:

View file

@ -7,6 +7,7 @@ public class ConversationDocument : MongoBase
public string? TaskId { get; set; }
public string Title { get; set; }
public string Channel { get; set; }
public string ChannelId { get; set; }
public string Status { get; set; }
public int DialogCount { get; set; }
public List<string> Tags { get; set; }

View file

@ -17,6 +17,7 @@ public partial class MongoRepository
UserId = !string.IsNullOrEmpty(conversation.UserId) ? conversation.UserId : string.Empty,
Title = conversation.Title,
Channel = conversation.Channel,
ChannelId = conversation.ChannelId,
TaskId = conversation.TaskId,
Status = conversation.Status,
Tags = conversation.Tags ?? new(),

View file

@ -25,11 +25,14 @@ public class PrimaryStagePlanFn : IFunctionCallback
state.SetState("max_tokens", "4096");
var task = JsonSerializer.Deserialize<PrimaryRequirementRequest>(message.FunctionArgs);
var searchQuestions = new List<string>(task.Questions);
searchQuestions.AddRange(task.NormQuestions);
searchQuestions = searchQuestions.Distinct().ToList();
// Get knowledge from vectordb
var hooks = _services.GetServices<IKnowledgeHook>();
var knowledges = new List<string>();
foreach (var question in task.Questions)
foreach (var question in searchQuestions)
{
foreach (var hook in hooks)
{

View file

@ -7,4 +7,7 @@ public class PrimaryRequirementRequest
[JsonPropertyName("questions")]
public string[] Questions { get; set; } = [];
[JsonPropertyName("norm_questions")]
public string[] NormQuestions { get; set; } = [];
}

View file

@ -10,10 +10,35 @@
},
"questions": {
"type": "array",
"description": "Rephrase user requirements in details and in multiple ways, don't miss any information especially for those line items, values and numbers.",
"description": "Break down user requirements in details and in multiple ways, don't miss any entity type/value",
"items": {
"type": "string",
"description": "Question converted from requirement in different ways to search in the knowledge base, be short and you can refer to the global knowledge.One question should contain only one main topic."
"description": "Question converted from requirement in different ways to search in the knowledge base, be short and you can refer to the global knowledge.One question should contain only one main topic that with one entity type."
}
},
"norm_questions": {
"type": "array",
"description": "normalize the generated questions, remove specific entity value.",
"items": {
"type": "string",
"description": "Normalized question"
}
},
"entities": {
"type": "array",
"description": "entities with type and value",
"items": {
"type": "object",
"properties": {
"type": {
"type": "string",
"description": "entity type"
},
"value": {
"type": "string",
"description": "entity value"
}
}
}
}
},

View file

@ -8,7 +8,8 @@ Thinking process:
- If there is extra knowledge or relationship needed between steps, set the need_breakdown_task to true for both steps.
- If the solution mentioned "related solutions" is needed, set the need_breakdown_task to true.
- You should find the relationships between data structure based on the task knowledge strictly. If lack of information, set the need_breakdown_task to true.
- If you need to lookup the dictionary to verify or get the enum/term/dictionary value, set the need_lookup_dictionary to true.
- If you need to lookup the dictionary to verify or get the enum/term/dictionary value(exclude example data from attachment), set the need_lookup_dictionary to true.
- Don't set need_lookup_dictionary to true for attachment data.
- Seperate the dictionary lookup and need additional information/knowledge into different subtask.
3. Input argument must reference to corresponding variable name that retrieved by previous steps, variable name must start with '@';
4. Output all the subtasks as much detail as possible in JSON: [{{ response_format }}]

View file

@ -41,6 +41,12 @@ public class ExecuteQueryFn : IFunctionCallback
_ => throw new NotImplementedException($"Database type {settings.DatabaseType} is not supported.")
};
if (refinedArgs.SqlStatements.Length == 1 && refinedArgs.SqlStatements[0].StartsWith("DROP TABLE"))
{
message.Content = "Drop table successfully";
return true;
}
if (results.Count() == 0)
{
message.Content = "No record found";

View file

@ -1,3 +1,4 @@
using BotSharp.Abstraction.Agents.Enums;
using BotSharp.Abstraction.Planning;
namespace BotSharp.Plugin.SqlDriver;
@ -9,6 +10,11 @@ public class SqlDriverPlugin : IBotSharpPlugin
public string Description => "Convert the user requirements into corresponding SQL statements";
public string IconUrl => "https://uxwing.com/wp-content/themes/uxwing/download/file-and-folder-type/sql-icon.png";
public string[] AgentIds =
[
BuiltInAgentId.SqlDriver
];
public void RegisterDI(IServiceCollection services, IConfiguration config)
{
services.AddScoped(provider =>

View file

@ -1,6 +1,6 @@
{
"name": "verify_dictionary_term",
"description": "Get id from dictionary table by keyword. Call this function only if need_lookup_dictionary is true and is_insert is false",
"description": "Get id from dictionary table by keyword. Call this function only if need_lookup_dictionary is true and is_insert is false. You can only query one table at a time.",
"parameters": {
"type": "object",
"properties": {
@ -18,7 +18,7 @@
},
"tables": {
"type": "array",
"description": "all related tables",
"description": "all related dictionary tables",
"items": {
"type": "string",
"description": "table name"

View file

@ -2,6 +2,7 @@
"id": "beda4c12-e1ec-4b4b-b328-3df4a6687c4f",
"name": "SQL Driver",
"description": "Execute the sql query in database from the latest dialog.",
"iconUrl": "https://cdn-icons-png.flaticon.com/512/3161/3161158.png",
"type": "task",
"createdDateTime": "2023-11-15T13:49:00Z",
"updatedDateTime": "2023-11-15T13:49:00Z",

View file

@ -108,6 +108,7 @@ namespace BotSharp.Plugin.Twilio.Services
var states = new List<MessageState>
{
new("channel", ConversationChannel.Phone),
new("channel_id", message.From),
new("calling_phone", message.From)
};
states.AddRange(message.States.Select(kvp => new MessageState(kvp.Key, kvp.Value)));