diff --git a/src/Infrastructure/BotSharp.Abstraction/Agents/Enums/BuiltInAgentId.cs b/src/Infrastructure/BotSharp.Abstraction/Agents/Enums/BuiltInAgentId.cs
index dc1fb3123..58da1fd42 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Agents/Enums/BuiltInAgentId.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Agents/Enums/BuiltInAgentId.cs
@@ -2,9 +2,33 @@ namespace BotSharp.Abstraction.Agents.Enums;
public class BuiltInAgentId
{
+ ///
+ /// A routing agent can be used as a base router.
+ ///
public const string AIAssistant = "01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a";
+
+ ///
+ /// A demo agent used for open domain chatting
+ ///
public const string Chatbot = "01e2fc5c-2c89-4ec7-8470-7688608b496c";
+
+ ///
+ /// Human customer service
+ ///
public const string HumanSupport = "01dcc3e5-0af7-49e6-ad7a-a760bd12dc4b";
+
+ ///
+ /// Used as a container to host the shared tools/ utilities built in different plugins.
+ ///
public const string UtilityAssistant = "6745151e-6d46-4a02-8de4-1c4f21c7da95";
+
+ ///
+ /// Used when router can't route to any existing task agent
+ ///
public const string Fallback = "01fcc3e5-0af7-49e6-ad7a-a760bd12dc4d";
+
+ ///
+ /// Used by knowledgebase plugin to acquire domain knowledge
+ ///
+ public const string Learner = "01acc3e5-0af7-49e6-ad7a-a760bd12dc40";
}
diff --git a/src/Infrastructure/BotSharp.Abstraction/Infrastructures/Enums/StateConst.cs b/src/Infrastructure/BotSharp.Abstraction/Infrastructures/Enums/StateConst.cs
index 442c8ef81..c452b7abb 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Infrastructures/Enums/StateConst.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Infrastructures/Enums/StateConst.cs
@@ -7,6 +7,7 @@ public class StateConst
public const string NEXT_ACTION_AGENT = "next_action_agent";
public const string NEXT_ACTION_REASON = "next_action_reason";
public const string USER_GOAL_AGENT = "user_goal_agent";
+ public const string AGENT_REDIRECTION_REASON = "agent_redirection_reason";
public const string LANGUAGE = "language";
}
diff --git a/src/Infrastructure/BotSharp.Abstraction/Knowledges/Models/ExtractedKnowledge.cs b/src/Infrastructure/BotSharp.Abstraction/Knowledges/Models/ExtractedKnowledge.cs
new file mode 100644
index 000000000..0043c437a
--- /dev/null
+++ b/src/Infrastructure/BotSharp.Abstraction/Knowledges/Models/ExtractedKnowledge.cs
@@ -0,0 +1,10 @@
+namespace BotSharp.Abstraction.Knowledges.Models;
+
+public class ExtractedKnowledge
+{
+ [JsonPropertyName("question")]
+ public string Question { get; set; } = string.Empty;
+
+ [JsonPropertyName("answer")]
+ public string Answer { get; set; } = string.Empty;
+}
diff --git a/src/Infrastructure/BotSharp.Abstraction/VectorStorage/IVectorDb.cs b/src/Infrastructure/BotSharp.Abstraction/VectorStorage/IVectorDb.cs
index c385153a9..68aaaa785 100644
--- a/src/Infrastructure/BotSharp.Abstraction/VectorStorage/IVectorDb.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/VectorStorage/IVectorDb.cs
@@ -4,6 +4,6 @@ public interface IVectorDb
{
Task> GetCollections();
Task CreateCollection(string collectionName, int dim);
- Task Upsert(string collectionName, string id, float[] vector, string text, Dictionary? payload = null);
- Task> Search(string collectionName, float[] vector, int limit = 5);
+ Task Upsert(string collectionName, string id, float[] vector, string text, Dictionary? payload = null);
+ Task> Search(string collectionName, float[] vector, string returnFieldName, int limit = 5, float confidence = 0.5f);
}
diff --git a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.SendMessage.cs b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.SendMessage.cs
index 753a34491..790c64e2d 100644
--- a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.SendMessage.cs
+++ b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.SendMessage.cs
@@ -19,11 +19,7 @@ public async Task SendMessage(string agentId,
Agent agent = await agentService.LoadAgent(agentId);
var content = $"Received [{agent.Name}] {message.Role}: {message.Content}";
-#if DEBUG
- Console.WriteLine(content);
-#else
_logger.LogInformation(content);
-#endif
message.CurrentAgentId = agent.Id;
if (string.IsNullOrEmpty(message.SenderId))
diff --git a/src/Infrastructure/BotSharp.Core/Routing/Functions/RouteToAgentFn.cs b/src/Infrastructure/BotSharp.Core/Routing/Functions/RouteToAgentFn.cs
index c9abf5511..7bf3171bd 100644
--- a/src/Infrastructure/BotSharp.Core/Routing/Functions/RouteToAgentFn.cs
+++ b/src/Infrastructure/BotSharp.Core/Routing/Functions/RouteToAgentFn.cs
@@ -89,6 +89,7 @@ public async Task Execute(RoleDialogModel message)
// Stack redirection agent
_context.Push(agentId, reason: $"REDIRECTION {reason}");
message.Content = reason;
+ states.SetState(StateConst.AGENT_REDIRECTION_REASON, reason, isNeedVersion: false);
}
}
diff --git a/src/Infrastructure/BotSharp.Core/data/agents/01fcc3e5-0af7-49e6-ad7a-a760bd12dc4d/instruction.liquid b/src/Infrastructure/BotSharp.Core/data/agents/01fcc3e5-0af7-49e6-ad7a-a760bd12dc4d/instruction.liquid
index ced0264cd..7e170f72c 100644
--- a/src/Infrastructure/BotSharp.Core/data/agents/01fcc3e5-0af7-49e6-ad7a-a760bd12dc4d/instruction.liquid
+++ b/src/Infrastructure/BotSharp.Core/data/agents/01fcc3e5-0af7-49e6-ad7a-a760bd12dc4d/instruction.liquid
@@ -1 +1,4 @@
-You are a smart AI Assistant.
\ No newline at end of file
+You are a smart AI Assistant.
+{% if agent_redirection_reason %}
+You've been reached out because: {{ agent_redirection_reason }}
+{% endif %}
\ No newline at end of file
diff --git a/src/Infrastructure/BotSharp.Core/data/agents/01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a/templates/planner_prompt.hf.liquid b/src/Infrastructure/BotSharp.Core/data/agents/01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a/templates/planner_prompt.hf.liquid
index 2404a04c3..740ed1341 100644
--- a/src/Infrastructure/BotSharp.Core/data/agents/01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a/templates/planner_prompt.hf.liquid
+++ b/src/Infrastructure/BotSharp.Core/data/agents/01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a/templates/planner_prompt.hf.liquid
@@ -1 +1 @@
-Break down the user’s most recent needs and figure out the instruction of next step.
\ No newline at end of file
+Break down the user’s most recent needs and figure out the instruction of next step without explanation.
\ No newline at end of file
diff --git a/src/Plugins/BotSharp.Plugin.AnthropicAI/BotSharp.Plugin.AnthropicAI.csproj b/src/Plugins/BotSharp.Plugin.AnthropicAI/BotSharp.Plugin.AnthropicAI.csproj
index 708917195..5574afe56 100644
--- a/src/Plugins/BotSharp.Plugin.AnthropicAI/BotSharp.Plugin.AnthropicAI.csproj
+++ b/src/Plugins/BotSharp.Plugin.AnthropicAI/BotSharp.Plugin.AnthropicAI.csproj
@@ -11,7 +11,7 @@
-
+
diff --git a/src/Plugins/BotSharp.Plugin.AnthropicAI/Providers/ChatCompletionProvider.cs b/src/Plugins/BotSharp.Plugin.AnthropicAI/Providers/ChatCompletionProvider.cs
index 872021098..1a3a829b3 100644
--- a/src/Plugins/BotSharp.Plugin.AnthropicAI/Providers/ChatCompletionProvider.cs
+++ b/src/Plugins/BotSharp.Plugin.AnthropicAI/Providers/ChatCompletionProvider.cs
@@ -1,4 +1,5 @@
using Anthropic.SDK.Common;
+using BotSharp.Abstraction.Conversations;
using BotSharp.Abstraction.MLTasks.Settings;
using System.Text.Json;
using System.Text.Json.Nodes;
@@ -160,13 +161,17 @@ public Task GetChatCompletionsStreamingAsync(Agent agent, List();
+ var temperature = decimal.Parse(state.GetState("temperature", "0.0"));
+ var maxToken = int.Parse(state.GetState("max_tokens", "512"));
+
var parameters = new MessageParameters()
{
Messages = messages,
- MaxTokens = 256,
- Model = settings.Version, // AnthropicModels.Claude3Haiku
+ MaxTokens = maxToken,
+ Model = settings.Name,
Stream = false,
- Temperature = 0m,
+ Temperature = temperature,
SystemMessage = instruction,
Tools = new List() { }
};
diff --git a/src/Plugins/BotSharp.Plugin.KnowledgeBase/BotSharp.Plugin.KnowledgeBase.csproj b/src/Plugins/BotSharp.Plugin.KnowledgeBase/BotSharp.Plugin.KnowledgeBase.csproj
index bdb0c2304..27cd4c788 100644
--- a/src/Plugins/BotSharp.Plugin.KnowledgeBase/BotSharp.Plugin.KnowledgeBase.csproj
+++ b/src/Plugins/BotSharp.Plugin.KnowledgeBase/BotSharp.Plugin.KnowledgeBase.csproj
@@ -16,6 +16,31 @@
+
+
+
+
+
+
+
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+
@@ -23,6 +48,7 @@
+
diff --git a/src/Plugins/BotSharp.Plugin.KnowledgeBase/Enum/UtilityName.cs b/src/Plugins/BotSharp.Plugin.KnowledgeBase/Enum/UtilityName.cs
new file mode 100644
index 000000000..18a28c91f
--- /dev/null
+++ b/src/Plugins/BotSharp.Plugin.KnowledgeBase/Enum/UtilityName.cs
@@ -0,0 +1,6 @@
+namespace BotSharp.Plugin.KnowledgeBase.Enum;
+
+public class UtilityName
+{
+ public const string KnowledgeRetrieval = "knowledge-retrieval";
+}
diff --git a/src/Plugins/BotSharp.Plugin.KnowledgeBase/Functions/KnowledgeRetrievalFn.cs b/src/Plugins/BotSharp.Plugin.KnowledgeBase/Functions/KnowledgeRetrievalFn.cs
new file mode 100644
index 000000000..19a0c97f4
--- /dev/null
+++ b/src/Plugins/BotSharp.Plugin.KnowledgeBase/Functions/KnowledgeRetrievalFn.cs
@@ -0,0 +1,40 @@
+using BotSharp.Abstraction.Functions;
+using BotSharp.Core.Infrastructures;
+
+namespace BotSharp.Plugin.KnowledgeBase.Functions;
+
+public class KnowledgeRetrievalFn : IFunctionCallback
+{
+ public string Name => "knowledge_retrieval";
+
+ private readonly IServiceProvider _services;
+ private readonly KnowledgeBaseSettings _settings;
+
+ public KnowledgeRetrievalFn(IServiceProvider services, KnowledgeBaseSettings settings)
+ {
+ _services = services;
+ _settings = settings;
+ }
+
+ public async Task Execute(RoleDialogModel message)
+ {
+ var args = JsonSerializer.Deserialize(message.FunctionArgs ?? "{}");
+
+ var embedding = _services.GetServices()
+ .FirstOrDefault(x => x.GetType().FullName.EndsWith(_settings.TextEmbedding));
+
+ var vector = await embedding.GetVectorsAsync(new List
+ {
+ args.Question
+ });
+
+ var vectorDb = _services.GetRequiredService();
+
+ var id = Utilities.HashTextMd5(args.Question);
+ var knowledges = await vectorDb.Search("lessen", vector[0], "answer");
+
+ message.Content = string.Join("\r\n\r\n=====\r\n", knowledges);
+
+ return true;
+ }
+}
diff --git a/src/Plugins/BotSharp.Plugin.KnowledgeBase/Functions/MemorizeKnowledgeFn.cs b/src/Plugins/BotSharp.Plugin.KnowledgeBase/Functions/MemorizeKnowledgeFn.cs
new file mode 100644
index 000000000..2a20f0f02
--- /dev/null
+++ b/src/Plugins/BotSharp.Plugin.KnowledgeBase/Functions/MemorizeKnowledgeFn.cs
@@ -0,0 +1,47 @@
+using BotSharp.Abstraction.Functions;
+using BotSharp.Core.Infrastructures;
+
+namespace BotSharp.Plugin.KnowledgeBase.Functions;
+
+public class MemorizeKnowledgeFn : IFunctionCallback
+{
+ public string Name => "memorize_knowledge";
+
+ private readonly IServiceProvider _services;
+ private readonly KnowledgeBaseSettings _settings;
+
+ public MemorizeKnowledgeFn(IServiceProvider services, KnowledgeBaseSettings settings)
+ {
+ _services = services;
+ _settings = settings;
+ }
+
+ public async Task Execute(RoleDialogModel message)
+ {
+ var args = JsonSerializer.Deserialize(message.FunctionArgs ?? "{}");
+
+ var embedding = _services.GetServices()
+ .First(x => x.GetType().FullName.EndsWith(_settings.TextEmbedding));
+
+ var vector = await embedding.GetVectorsAsync(new List
+ {
+ args.Question
+ });
+
+ var vectorDb = _services.GetRequiredService();
+
+ await vectorDb.CreateCollection("lessen", vector[0].Length);
+
+ var id = Utilities.HashTextMd5(args.Question);
+ var result = await vectorDb.Upsert("lessen", id, vector[0],
+ args.Question,
+ new Dictionary
+ {
+ { "answer", args.Answer }
+ });
+
+ message.Content = $"Save result: {(result ? "success" : "failed")}";
+
+ return true;
+ }
+}
diff --git a/src/Plugins/BotSharp.Plugin.KnowledgeBase/Hooks/KnowledgeBaseAgentHook.cs b/src/Plugins/BotSharp.Plugin.KnowledgeBase/Hooks/KnowledgeBaseAgentHook.cs
new file mode 100644
index 000000000..2eebf75c5
--- /dev/null
+++ b/src/Plugins/BotSharp.Plugin.KnowledgeBase/Hooks/KnowledgeBaseAgentHook.cs
@@ -0,0 +1,66 @@
+using BotSharp.Abstraction.Agents.Enums;
+using BotSharp.Abstraction.Agents.Models;
+using BotSharp.Abstraction.Functions.Models;
+using BotSharp.Abstraction.Repositories;
+using BotSharp.Plugin.KnowledgeBase.Enum;
+
+namespace BotSharp.Plugin.KnowledgeBase.Hooks;
+
+public class KnowledgeBaseAgentHook : AgentHookBase, IAgentHook
+{
+ public override string SelfId => string.Empty;
+ public KnowledgeBaseAgentHook(IServiceProvider services, AgentSettings settings) : base(services, settings)
+ {
+
+ }
+
+ public override void OnAgentLoaded(Agent agent)
+ {
+ var conv = _services.GetRequiredService();
+ var isConvMode = conv.IsConversationMode();
+
+ if (isConvMode)
+ {
+ AddUtility(agent, UtilityName.KnowledgeRetrieval, "knowledge_retrieval");
+ }
+
+ base.OnAgentLoaded(agent);
+ }
+
+ private void AddUtility(Agent agent, string utility, string functionName)
+ {
+ if (!IsEnableUtility(agent, utility)) return;
+
+ var (prompt, fn) = GetPromptAndFunction(functionName);
+ 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 { fn };
+ }
+ else
+ {
+ agent.Functions.Add(fn);
+ }
+ }
+ }
+
+ private bool IsEnableUtility(Agent agent, string utility)
+ {
+ return !agent.Utilities.IsNullOrEmpty() && agent.Utilities.Contains(utility);
+ }
+
+ private (string, FunctionDef?) GetPromptAndFunction(string functionName)
+ {
+ var db = _services.GetRequiredService();
+ var agent = db.GetAgent(BuiltInAgentId.UtilityAssistant);
+ var prompt = agent?.Templates?.FirstOrDefault(x => x.Name.IsEqualTo($"{functionName}.fn"))?.Content ?? string.Empty;
+ var fn = agent?.Functions?.FirstOrDefault(x => x.Name.IsEqualTo(functionName));
+ return (prompt, fn);
+ }
+}
diff --git a/src/Plugins/BotSharp.Plugin.KnowledgeBase/Hooks/KnowledgeBaseUtilityHook.cs b/src/Plugins/BotSharp.Plugin.KnowledgeBase/Hooks/KnowledgeBaseUtilityHook.cs
new file mode 100644
index 000000000..fd163cbf2
--- /dev/null
+++ b/src/Plugins/BotSharp.Plugin.KnowledgeBase/Hooks/KnowledgeBaseUtilityHook.cs
@@ -0,0 +1,11 @@
+using BotSharp.Plugin.KnowledgeBase.Enum;
+
+namespace BotSharp.Plugin.KnowledgeBase.Hooks;
+
+public class KnowledgeBaseUtilityHook : IAgentUtilityHook
+{
+ public void AddUtilities(List utilities)
+ {
+ utilities.Add(UtilityName.KnowledgeRetrieval);
+ }
+}
diff --git a/src/Plugins/BotSharp.Plugin.KnowledgeBase/KnowledgeBasePlugin.cs b/src/Plugins/BotSharp.Plugin.KnowledgeBase/KnowledgeBasePlugin.cs
index 60fb0e8a8..51c390bf5 100644
--- a/src/Plugins/BotSharp.Plugin.KnowledgeBase/KnowledgeBasePlugin.cs
+++ b/src/Plugins/BotSharp.Plugin.KnowledgeBase/KnowledgeBasePlugin.cs
@@ -1,5 +1,6 @@
using BotSharp.Abstraction.Plugins.Models;
using BotSharp.Abstraction.Settings;
+using BotSharp.Plugin.KnowledgeBase.Hooks;
using Microsoft.Extensions.Configuration;
namespace BotSharp.Plugin.KnowledgeBase;
@@ -24,6 +25,8 @@ public void RegisterDI(IServiceCollection services, IConfiguration config)
services.AddScoped();
services.AddScoped();
services.AddSingleton();
+ services.AddScoped();
+ services.AddScoped();
}
public bool AttachMenu(List menu)
diff --git a/src/Plugins/BotSharp.Plugin.KnowledgeBase/MemVecDb/MemVectorDatabase.cs b/src/Plugins/BotSharp.Plugin.KnowledgeBase/MemVecDb/MemVectorDatabase.cs
index a595c5da3..c46ccdf5a 100644
--- a/src/Plugins/BotSharp.Plugin.KnowledgeBase/MemVecDb/MemVectorDatabase.cs
+++ b/src/Plugins/BotSharp.Plugin.KnowledgeBase/MemVecDb/MemVectorDatabase.cs
@@ -18,7 +18,7 @@ public async Task> GetCollections()
return _collections.Select(x => x.Key).ToList();
}
- public async Task> Search(string collectionName, float[] vector, int limit = 5)
+ public async Task> Search(string collectionName, float[] vector, string returnFieldName, int limit = 5, float confidence = 0.5f)
{
if (!_vectors.ContainsKey(collectionName))
{
@@ -37,7 +37,7 @@ public async Task> Search(string collectionName, float[] vector, in
return texts;
}
- public async Task Upsert(string collectionName, string id, float[] vector, string text, Dictionary? payload = null)
+ public async Task Upsert(string collectionName, string id, float[] vector, string text, Dictionary? payload = null)
{
_vectors[collectionName].Add(new VecRecord
{
@@ -45,6 +45,8 @@ public async Task Upsert(string collectionName, string id, float[] vector, strin
Vector = vector,
Text = text
});
+
+ return true;
}
private float[] CalEuclideanDistance(float[] vec, List records)
diff --git a/src/Plugins/BotSharp.Plugin.KnowledgeBase/Services/KnowledgeService.cs b/src/Plugins/BotSharp.Plugin.KnowledgeBase/Services/KnowledgeService.cs
index bd4cf6f47..7ac5cf4c1 100644
--- a/src/Plugins/BotSharp.Plugin.KnowledgeBase/Services/KnowledgeService.cs
+++ b/src/Plugins/BotSharp.Plugin.KnowledgeBase/Services/KnowledgeService.cs
@@ -68,7 +68,7 @@ public async Task GetKnowledges(KnowledgeRetrievalModel retrievalModel)
// Vector search
var db = GetVectorDb();
- var result = await db.Search("shared", vector, limit: 10);
+ var result = await db.Search("shared", vector, "answer", limit: 10);
// Restore
return string.Join("\n\n", result.Select((x, i) => $"### Paragraph {i + 1} ###\n{x.Trim()}"));
diff --git a/src/Plugins/BotSharp.Plugin.KnowledgeBase/data/agents/01acc3e5-0af7-49e6-ad7a-a760bd12dc40/agent.json b/src/Plugins/BotSharp.Plugin.KnowledgeBase/data/agents/01acc3e5-0af7-49e6-ad7a-a760bd12dc40/agent.json
new file mode 100644
index 000000000..79310ecc7
--- /dev/null
+++ b/src/Plugins/BotSharp.Plugin.KnowledgeBase/data/agents/01acc3e5-0af7-49e6-ad7a-a760bd12dc40/agent.json
@@ -0,0 +1,16 @@
+{
+ "id": "01acc3e5-0af7-49e6-ad7a-a760bd12dc40",
+ "name": "Learner",
+ "description": "An avid learner who is eager to learn and acquire knowledge",
+ "iconUrl": "https://cdn-icons-png.flaticon.com/512/4578/4578413.png",
+ "type": "task",
+ "createdDateTime": "2024-07-17T00:00:00Z",
+ "updatedDateTime": "2024-07-17T00:00:00Z",
+ "disabled": false,
+ "isPublic": true,
+ "profiles": [ "tool" ],
+ "llmConfig": {
+ "provider": "anthropic",
+ "model": "claude-3-5-sonnet-20240620"
+ }
+}
\ No newline at end of file
diff --git a/src/Plugins/BotSharp.Plugin.KnowledgeBase/data/agents/01acc3e5-0af7-49e6-ad7a-a760bd12dc40/functions/memorize_knowledge.json b/src/Plugins/BotSharp.Plugin.KnowledgeBase/data/agents/01acc3e5-0af7-49e6-ad7a-a760bd12dc40/functions/memorize_knowledge.json
new file mode 100644
index 000000000..7ecaa37aa
--- /dev/null
+++ b/src/Plugins/BotSharp.Plugin.KnowledgeBase/data/agents/01acc3e5-0af7-49e6-ad7a-a760bd12dc40/functions/memorize_knowledge.json
@@ -0,0 +1,18 @@
+{
+ "name": "memorize_knowledge",
+ "description": "Retrieve related domain knowledge to handle user request",
+ "parameters": {
+ "type": "object",
+ "properties": {
+ "question": {
+ "type": "string",
+ "description": "User question with scenario detail"
+ },
+ "answer": {
+ "type": "string",
+ "description": "The answer to handle user question"
+ }
+ },
+ "required": [ "question", "answer" ]
+ }
+}
\ No newline at end of file
diff --git a/src/Plugins/BotSharp.Plugin.KnowledgeBase/data/agents/01acc3e5-0af7-49e6-ad7a-a760bd12dc40/instruction.liquid b/src/Plugins/BotSharp.Plugin.KnowledgeBase/data/agents/01acc3e5-0af7-49e6-ad7a-a760bd12dc40/instruction.liquid
new file mode 100644
index 000000000..7f6efa95e
--- /dev/null
+++ b/src/Plugins/BotSharp.Plugin.KnowledgeBase/data/agents/01acc3e5-0af7-49e6-ad7a-a760bd12dc40/instruction.liquid
@@ -0,0 +1,2 @@
+You an avid learner who is eager to learn and acquire knowledge from the conversation.
+You're good at learning useful domain knowledge and experience by interacting with user.
\ No newline at end of file
diff --git a/src/Plugins/BotSharp.Plugin.KnowledgeBase/data/agents/6745151e-6d46-4a02-8de4-1c4f21c7da95/functions/knowledge_retrieval.json b/src/Plugins/BotSharp.Plugin.KnowledgeBase/data/agents/6745151e-6d46-4a02-8de4-1c4f21c7da95/functions/knowledge_retrieval.json
new file mode 100644
index 000000000..b292d7d97
--- /dev/null
+++ b/src/Plugins/BotSharp.Plugin.KnowledgeBase/data/agents/6745151e-6d46-4a02-8de4-1c4f21c7da95/functions/knowledge_retrieval.json
@@ -0,0 +1,14 @@
+{
+ "name": "knowledge_retrieval",
+ "description": "Retrieve related domain knowledge to handle user request",
+ "parameters": {
+ "type": "object",
+ "properties": {
+ "question": {
+ "type": "string",
+ "description": "Knowledge topic with scenario detail"
+ }
+ },
+ "required": [ "question" ]
+ }
+}
\ No newline at end of file
diff --git a/src/Plugins/BotSharp.Plugin.KnowledgeBase/data/agents/6745151e-6d46-4a02-8de4-1c4f21c7da95/templates/knowledge_retrieval.fn.liquid b/src/Plugins/BotSharp.Plugin.KnowledgeBase/data/agents/6745151e-6d46-4a02-8de4-1c4f21c7da95/templates/knowledge_retrieval.fn.liquid
new file mode 100644
index 000000000..da5e157b3
--- /dev/null
+++ b/src/Plugins/BotSharp.Plugin.KnowledgeBase/data/agents/6745151e-6d46-4a02-8de4-1c4f21c7da95/templates/knowledge_retrieval.fn.liquid
@@ -0,0 +1,3 @@
+Call function knowledge_retrieval to retrieve related domain knowledge to handle user request.
+You must retrieve existing KnowledgeBase to get prerequisite informations before you writing SQL query;
+You must retrieve existing API specification from KnowledgeBase before calling a Web API;
diff --git a/src/Plugins/BotSharp.Plugin.MetaAI/Providers/FaissDb.cs b/src/Plugins/BotSharp.Plugin.MetaAI/Providers/FaissDb.cs
index c74c86bbf..48e2be170 100644
--- a/src/Plugins/BotSharp.Plugin.MetaAI/Providers/FaissDb.cs
+++ b/src/Plugins/BotSharp.Plugin.MetaAI/Providers/FaissDb.cs
@@ -17,12 +17,12 @@ public Task> GetCollections()
throw new NotImplementedException();
}
- public Task> Search(string collectionName, float[] vector, int limit = 10)
+ public Task> Search(string collectionName, float[] vector, string returnFieldName, int limit = 10, float confidence = 0.5f)
{
throw new NotImplementedException();
}
- public Task Upsert(string collectionName, string id, float[] vector, string text, Dictionary? payload = null)
+ public Task Upsert(string collectionName, string id, float[] vector, string text, Dictionary? payload = null)
{
throw new NotImplementedException();
}
diff --git a/src/Plugins/BotSharp.Plugin.OpenAI/Providers/Embedding/TextEmbeddingProvider.cs b/src/Plugins/BotSharp.Plugin.OpenAI/Providers/Embedding/TextEmbeddingProvider.cs
index 2a84b61a3..578849bfa 100644
--- a/src/Plugins/BotSharp.Plugin.OpenAI/Providers/Embedding/TextEmbeddingProvider.cs
+++ b/src/Plugins/BotSharp.Plugin.OpenAI/Providers/Embedding/TextEmbeddingProvider.cs
@@ -9,7 +9,7 @@ public class TextEmbeddingProvider : ITextEmbedding
protected readonly ILogger _logger;
private const int DEFAULT_DIMENSION = 1536;
- protected string _model;
+ protected string _model = "text-embedding-3-small";
public virtual string Provider => "openai";
diff --git a/src/Plugins/BotSharp.Plugin.Qdrant/QdrantDb.cs b/src/Plugins/BotSharp.Plugin.Qdrant/QdrantDb.cs
index c571fba10..e698d5e3f 100644
--- a/src/Plugins/BotSharp.Plugin.Qdrant/QdrantDb.cs
+++ b/src/Plugins/BotSharp.Plugin.Qdrant/QdrantDb.cs
@@ -67,7 +67,7 @@ public async Task CreateCollection(string collectionName, int dim)
}
}
- public async Task Upsert(string collectionName, string id, float[] vector, string text, Dictionary? payload = null)
+ public async Task Upsert(string collectionName, string id, float[] vector, string text, Dictionary? payload = null)
{
// Insert vectors
var point = new PointStruct()
@@ -78,29 +78,37 @@ public async Task Upsert(string collectionName, string id, float[] vector, strin
},
Vectors = vector,
- Payload = { }
+ Payload =
+ {
+ { "text", text }
+ }
};
- foreach (var item in payload)
+ if (payload != null)
{
- point.Payload.Add(item.Key, item.Value);
+ foreach (var item in payload)
+ {
+ point.Payload.Add(item.Key, item.Value);
+ }
}
- var result = await GetClient().UpsertAsync(collectionName, points: new List
+ var client = GetClient();
+
+ var result = await client.UpsertAsync(collectionName, points: new List
{
point
});
+
+ return result.Status == UpdateStatus.Completed;
}
- public async Task> Search(string collectionName, float[] vector, int limit = 5)
+ public async Task> Search(string collectionName, float[] vector, string returnFieldName, int limit = 5, float confidence = 0.5f)
{
- var result = await GetClient().SearchAsync(collectionName, vector, limit: (ulong)limit);
-
- var agentService = _services.GetRequiredService();
- var agentDataDir = agentService.GetAgentDataDir(collectionName);
- var knowledgePath = Path.Combine(agentDataDir, "knowledge.txt");
- var texts = File.ReadAllLines(knowledgePath);
+ var client = GetClient();
+ var points = await client.SearchAsync(collectionName, vector,
+ limit: (ulong)limit,
+ scoreThreshold: confidence);
- return result.Select(x => texts[x.Id.Num]).ToList();
+ return points.Select(x => x.Payload[returnFieldName].StringValue).ToList();
}
}
diff --git a/src/Plugins/BotSharp.Plugin.SqlDriver/data/agents/6745151e-6d46-4a02-8de4-1c4f21c7da95/templates/sql_executor.fn.liquid b/src/Plugins/BotSharp.Plugin.SqlDriver/data/agents/6745151e-6d46-4a02-8de4-1c4f21c7da95/templates/sql_executor.fn.liquid
index e8ac2a14e..30fa8124a 100644
--- a/src/Plugins/BotSharp.Plugin.SqlDriver/data/agents/6745151e-6d46-4a02-8de4-1c4f21c7da95/templates/sql_executor.fn.liquid
+++ b/src/Plugins/BotSharp.Plugin.SqlDriver/data/agents/6745151e-6d46-4a02-8de4-1c4f21c7da95/templates/sql_executor.fn.liquid
@@ -2,4 +2,5 @@ You are connecting to {{ db_type }} database. Please generate SQL statements fol
Please call function sql_select if user wants to get or retrieve data from data tables.
If there are any parameters, please add them in the WHERE clause, each of which starts with "@".
-For example, SELECT * FROM table WHERE Id=@Id AND Name=@Name
+Avoid returning the entire record and only return the fields you need.
+For example, SELECT Id FROM table WHERE Id=@Id AND Name=@Name