Add TwoStagePlanner.
This commit is contained in:
parent
32d5fc05bc
commit
2582ecd578
|
|
@ -4,5 +4,9 @@ namespace BotSharp.Abstraction.Knowledges;
|
|||
|
||||
public interface IKnowledgeHook
|
||||
{
|
||||
Task<List<KnowledgeChunk>> CollectChunkedKnowledge();
|
||||
Task<List<KnowledgeChunk>> CollectChunkedKnowledge()
|
||||
=> Task.FromResult(new List<KnowledgeChunk>());
|
||||
|
||||
Task<List<string>> GetRelevantKnowledges()
|
||||
=> Task.FromResult(new List<string>());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,6 +55,9 @@
|
|||
<None Remove="data\agents\01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a\templates\planner_prompt.naive.liquid" />
|
||||
<None Remove="data\agents\01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a\templates\planner_prompt.sequential.get_remaining_task.liquid" />
|
||||
<None Remove="data\agents\01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a\templates\planner_prompt.sequential.liquid" />
|
||||
<None Remove="data\agents\01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a\templates\planner_prompt.two_stage.1st.plan.liquid" />
|
||||
<None Remove="data\agents\01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a\templates\planner_prompt.two_stage.2nd.plan.liquid" />
|
||||
<None Remove="data\agents\01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a\templates\planner_prompt.two_stage.2nd.task.liquid" />
|
||||
<None Remove="data\agents\01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a\templates\response_with_function.liquid" />
|
||||
<None Remove="data\agents\dfd9b46d-d00c-40af-8a75-3fbdc2b89869\agent.json" />
|
||||
<None Remove="data\agents\dfd9b46d-d00c-40af-8a75-3fbdc2b89869\instruction.liquid" />
|
||||
|
|
@ -76,6 +79,15 @@
|
|||
<Content Include="data\agents\01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a\instruction.liquid">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="data\agents\01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a\templates\planner_prompt.two_stage.1st.plan.liquid">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="data\agents\01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a\templates\planner_prompt.two_stage.2nd.plan.liquid">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="data\agents\01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a\templates\planner_prompt.two_stage.2nd.task.liquid">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="data\agents\01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a\templates\planner_prompt.sequential.get_remaining_task.liquid">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,32 @@
|
|||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace BotSharp.Core.Routing.Planning;
|
||||
|
||||
public class FirstStagePlan
|
||||
{
|
||||
[JsonPropertyName("task_detail")]
|
||||
public string Task { get; set; } = "";
|
||||
|
||||
[JsonPropertyName("reason")]
|
||||
public string Reason { get; set; } = "";
|
||||
|
||||
[JsonPropertyName("step")]
|
||||
public int Step { get; set; } = -1;
|
||||
|
||||
[JsonPropertyName("contain_multiple_steps")]
|
||||
public bool ContainMultipleSteps { get; set; } = false;
|
||||
|
||||
[JsonPropertyName("related_tables")]
|
||||
public string[] Tables { get; set; } = new string[0];
|
||||
|
||||
[JsonPropertyName("input_args")]
|
||||
public JsonDocument[] Parameters { get; set; } = new JsonDocument[0];
|
||||
|
||||
[JsonPropertyName("output_results")]
|
||||
public string[] Results { get; set; } = new string[0];
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"STEP {Step}: {Task}";
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
using System.Text.Json.Serialization;
|
||||
|
||||
public class FirstStagePlanParameter
|
||||
{
|
||||
[JsonPropertyName("input_args")]
|
||||
public JsonDocument[] Parameters { get; set; } = new JsonDocument[0];
|
||||
|
||||
[JsonPropertyName("output_results")]
|
||||
public string[] Results { get; set; } = new string[0];
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"INPUTS:\r\n{JsonSerializer.Serialize(Parameters)}\r\n\r\nOUTPUTS:\r\n{JsonSerializer.Serialize(Results)}";
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace BotSharp.Core.Routing.Planning;
|
||||
|
||||
public class SecondStagePlan
|
||||
{
|
||||
[JsonPropertyName("related_tables")]
|
||||
public string[] Tables { get; set; } = new string[0];
|
||||
|
||||
[JsonPropertyName("description")]
|
||||
public string Description { get; set; } = "";
|
||||
|
||||
[JsonPropertyName("tool_name")]
|
||||
public string Tool { get; set; } = "";
|
||||
|
||||
[JsonPropertyName("input_args")]
|
||||
public JsonDocument[] Parameters { get; set; } = new JsonDocument[0];
|
||||
|
||||
[JsonPropertyName("output_results")]
|
||||
public string[] Results { get; set; } = new string[0];
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
public class SecondStagePlanParameter : FirstStagePlanParameter
|
||||
{
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
using BotSharp.Abstraction.Agents.Models;
|
||||
using BotSharp.Abstraction.MLTasks;
|
||||
using BotSharp.Abstraction.Templating;
|
||||
|
||||
namespace BotSharp.Core.Routing.Planning;
|
||||
|
||||
public partial class TwoStagePlanner
|
||||
{
|
||||
private async Task<FirstStagePlan[]> GetFirstStagePlanAsync(Agent router, string messageId, List<RoleDialogModel> dialogs)
|
||||
{
|
||||
var firstStagePlanPrompt = await GetFirstStagePlanPrompt(router);
|
||||
|
||||
var plan = new FirstStagePlan[0];
|
||||
|
||||
var llmProviderService = _services.GetRequiredService<ILlmProviderService>();
|
||||
var model = llmProviderService.GetProviderModel("azure-openai", "gpt-4");
|
||||
|
||||
// chat completion
|
||||
var completion = CompletionProvider.GetChatCompletion(_services,
|
||||
provider: "azure-openai",
|
||||
model: model.Name);
|
||||
|
||||
string text = string.Empty;
|
||||
|
||||
try
|
||||
{
|
||||
var response = await completion.GetChatCompletions(new Agent
|
||||
{
|
||||
Id = router.Id,
|
||||
Name = nameof(TwoStagePlanner),
|
||||
Instruction = firstStagePlanPrompt
|
||||
}, dialogs);
|
||||
|
||||
text = response.Content;
|
||||
plan = response.Content.JsonArrayContent<FirstStagePlan>();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError($"{ex.Message}: {text}");
|
||||
}
|
||||
|
||||
return plan;
|
||||
}
|
||||
|
||||
private async Task<string> GetFirstStagePlanPrompt(Agent router)
|
||||
{
|
||||
var template = router.Templates.First(x => x.Name == "planner_prompt.two_stage.1st.plan").Content;
|
||||
var responseFormat = JsonSerializer.Serialize(new FirstStagePlan
|
||||
{
|
||||
Parameters = new JsonDocument[]{ JsonDocument.Parse("{}") },
|
||||
Results = new string[] { "" }
|
||||
});
|
||||
|
||||
var relevantKnowledges = new List<string>();
|
||||
var hooks = _services.GetServices<IKnowledgeHook>();
|
||||
foreach (var hook in hooks)
|
||||
{
|
||||
var k = await hook.GetRelevantKnowledges();
|
||||
relevantKnowledges.AddRange(k);
|
||||
}
|
||||
|
||||
var render = _services.GetRequiredService<ITemplateRender>();
|
||||
return render.Render(template, new Dictionary<string, object>
|
||||
{
|
||||
{ "response_format", responseFormat },
|
||||
{ "relevant_knowledges", relevantKnowledges.ToArray() }
|
||||
});
|
||||
}
|
||||
|
||||
private string GetFirstStageNextPrompt(Agent router)
|
||||
{
|
||||
var template = router.Templates.First(x => x.Name == "planner_prompt.first_stage.next").Content;
|
||||
var responseFormat = JsonSerializer.Serialize(new FirstStagePlan
|
||||
{
|
||||
});
|
||||
var render = _services.GetRequiredService<ITemplateRender>();
|
||||
return render.Render(template, new Dictionary<string, object>
|
||||
{
|
||||
{ "response_format", responseFormat },
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
namespace BotSharp.Core.Routing.Planning;
|
||||
|
||||
public partial class TwoStagePlanner
|
||||
{
|
||||
public string GetContext()
|
||||
{
|
||||
var content = "";
|
||||
foreach (var c in _executionContext)
|
||||
{
|
||||
content += $"* {c}\r\n";
|
||||
}
|
||||
return content;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
using BotSharp.Abstraction.Agents.Models;
|
||||
using BotSharp.Abstraction.MLTasks;
|
||||
using BotSharp.Abstraction.Templating;
|
||||
|
||||
namespace BotSharp.Core.Routing.Planning;
|
||||
|
||||
public partial class TwoStagePlanner
|
||||
{
|
||||
private async Task<SecondStagePlan[]> GetSecondStagePlanAsync(Agent router, string messageId, FirstStagePlan plan1st, List<RoleDialogModel> dialogs)
|
||||
{
|
||||
var secondStagePrompt = GetSecondStagePlanPrompt(router, plan1st);
|
||||
var firstStageSystemPrompt = await GetFirstStagePlanPrompt(router);
|
||||
|
||||
var plan = new SecondStagePlan[0];
|
||||
|
||||
var llmProviderService = _services.GetRequiredService<ILlmProviderService>();
|
||||
var model = llmProviderService.GetProviderModel("azure-openai", "gpt-4");
|
||||
|
||||
// chat completion
|
||||
var completion = CompletionProvider.GetChatCompletion(_services,
|
||||
provider: "azure-openai",
|
||||
model: model.Name);
|
||||
|
||||
string text = string.Empty;
|
||||
|
||||
var conversations = dialogs.Where(x => x.Role != AgentRole.Function).ToList();
|
||||
conversations.Add(new RoleDialogModel(AgentRole.User, secondStagePrompt)
|
||||
{
|
||||
CurrentAgentId = router.Id,
|
||||
MessageId = messageId,
|
||||
});
|
||||
|
||||
try
|
||||
{
|
||||
var response = await completion.GetChatCompletions(new Agent
|
||||
{
|
||||
Id = router.Id,
|
||||
Name = nameof(TwoStagePlanner),
|
||||
Instruction = firstStageSystemPrompt
|
||||
}, conversations);
|
||||
|
||||
text = response.Content;
|
||||
plan = response.Content.JsonArrayContent<SecondStagePlan>();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError($"{ex.Message}: {text}");
|
||||
}
|
||||
|
||||
return plan;
|
||||
}
|
||||
|
||||
private string GetSecondStageTaskPrompt(Agent router, SecondStagePlan plan)
|
||||
{
|
||||
var template = router.Templates.First(x => x.Name == "planner_prompt.two_stage.2nd.task").Content;
|
||||
var render = _services.GetRequiredService<ITemplateRender>();
|
||||
return render.Render(template, new Dictionary<string, object>
|
||||
{
|
||||
{ "task_description", plan.Description },
|
||||
{ "related_tables", plan.Tables },
|
||||
{ "input_arguments", JsonSerializer.Serialize(plan.Parameters) },
|
||||
{ "output_results", JsonSerializer.Serialize(plan.Results) },
|
||||
});
|
||||
}
|
||||
|
||||
private string GetSecondStagePlanPrompt(Agent router, FirstStagePlan plan)
|
||||
{
|
||||
var template = router.Templates.First(x => x.Name == "planner_prompt.two_stage.2nd.plan").Content;
|
||||
var responseFormat = JsonSerializer.Serialize(new SecondStagePlan
|
||||
{
|
||||
Tool = "tool name if task solution provided",
|
||||
Parameters = new JsonDocument[] { JsonDocument.Parse("{}") },
|
||||
Results = new string[] { "" }
|
||||
});
|
||||
var context = GetContext();
|
||||
var render = _services.GetRequiredService<ITemplateRender>();
|
||||
return render.Render(template, new Dictionary<string, object>
|
||||
{
|
||||
{ "task_description", plan.Task },
|
||||
{ "response_format", responseFormat }
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,170 @@
|
|||
using BotSharp.Abstraction.Agents.Models;
|
||||
using BotSharp.Abstraction.Functions.Models;
|
||||
using BotSharp.Abstraction.Routing;
|
||||
using BotSharp.Abstraction.Routing.Models;
|
||||
using BotSharp.Abstraction.Routing.Planning;
|
||||
using System.IO;
|
||||
|
||||
namespace BotSharp.Core.Routing.Planning;
|
||||
|
||||
public partial class TwoStagePlanner : IPlaner
|
||||
{
|
||||
private readonly IServiceProvider _services;
|
||||
private readonly ILogger _logger;
|
||||
public int MaxLoopCount => 100;
|
||||
private bool _isTaskCompleted;
|
||||
private string _md5;
|
||||
|
||||
private Queue<FirstStagePlan> _plan1st = new Queue<FirstStagePlan>();
|
||||
private Queue<SecondStagePlan> _plan2nd = new Queue<SecondStagePlan>();
|
||||
|
||||
private List<string> _executionContext = new List<string>();
|
||||
|
||||
public TwoStagePlanner(IServiceProvider services, ILogger<TwoStagePlanner> logger)
|
||||
{
|
||||
_services = services;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public async Task<FunctionCallFromLlm> GetNextInstruction(Agent router, string messageId, List<RoleDialogModel> dialogs)
|
||||
{
|
||||
var tempDir = Path.Combine(Path.GetTempPath(), "botsharp", "cache");
|
||||
if (_plan1st.IsNullOrEmpty() && _plan2nd.IsNullOrEmpty())
|
||||
{
|
||||
Directory.CreateDirectory(tempDir);
|
||||
_md5 = Utilities.HashText(string.Join(".", dialogs.Where(x => x.Role == AgentRole.User)), "botsharp");
|
||||
var filePath = Path.Combine(tempDir, $"{_md5}-1st.json");
|
||||
FirstStagePlan[] items = new FirstStagePlan[0];
|
||||
if (File.Exists(filePath))
|
||||
{
|
||||
var cache = File.ReadAllText(filePath);
|
||||
items = JsonSerializer.Deserialize<FirstStagePlan[]>(cache);
|
||||
}
|
||||
else
|
||||
{
|
||||
items = await GetFirstStagePlanAsync(router, messageId, dialogs);
|
||||
|
||||
var cache = JsonSerializer.Serialize(items);
|
||||
File.WriteAllText(filePath, cache);
|
||||
}
|
||||
|
||||
foreach (var item in items)
|
||||
{
|
||||
_plan1st.Enqueue(item);
|
||||
};
|
||||
}
|
||||
|
||||
// Get Second Stage Plan
|
||||
if (_plan2nd.IsNullOrEmpty())
|
||||
{
|
||||
var plan1 = _plan1st.Dequeue();
|
||||
|
||||
if (plan1.ContainMultipleSteps)
|
||||
{
|
||||
var filePath = Path.Combine(tempDir, $"{_md5}-2nd-{plan1.Step}.json");
|
||||
SecondStagePlan[] items = new SecondStagePlan[0];
|
||||
if (File.Exists(filePath))
|
||||
{
|
||||
var cache = File.ReadAllText(filePath);
|
||||
items = JsonSerializer.Deserialize<SecondStagePlan[]>(cache);
|
||||
}
|
||||
else
|
||||
{
|
||||
items = await GetSecondStagePlanAsync(router, messageId, plan1, dialogs);
|
||||
|
||||
var cache = JsonSerializer.Serialize(items);
|
||||
File.WriteAllText(filePath, cache);
|
||||
}
|
||||
|
||||
foreach (var item in items)
|
||||
{
|
||||
_plan2nd.Enqueue(item);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_plan2nd.Enqueue(new SecondStagePlan
|
||||
{
|
||||
Description = plan1.Task,
|
||||
Tables = plan1.Tables,
|
||||
Parameters = plan1.Parameters,
|
||||
Results = plan1.Results,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
var plan2 = _plan2nd.Dequeue();
|
||||
|
||||
var secondStagePrompt = GetSecondStageTaskPrompt(router, plan2);
|
||||
var inst = new FunctionCallFromLlm
|
||||
{
|
||||
AgentName = "SQL Driver",
|
||||
Response = secondStagePrompt,
|
||||
Function = "route_to_agent"
|
||||
};
|
||||
|
||||
inst.HandleDialogsByPlanner = true;
|
||||
_isTaskCompleted = _plan1st.IsNullOrEmpty() && _plan2nd.IsNullOrEmpty();
|
||||
|
||||
return inst;
|
||||
}
|
||||
|
||||
public List<RoleDialogModel> BeforeHandleContext(FunctionCallFromLlm inst, RoleDialogModel message, List<RoleDialogModel> dialogs)
|
||||
{
|
||||
var question = inst.Response;
|
||||
if (_executionContext.Count > 0)
|
||||
{
|
||||
var content = GetContext();
|
||||
question = $"CONTEXT:\r\n{content}\r\n" + inst.Response;
|
||||
}
|
||||
else
|
||||
{
|
||||
question = $"CONTEXT:\r\n{question}";
|
||||
}
|
||||
|
||||
var taskAgentDialogs = new List<RoleDialogModel>
|
||||
{
|
||||
new RoleDialogModel(AgentRole.User, question)
|
||||
{
|
||||
MessageId = message.MessageId,
|
||||
}
|
||||
};
|
||||
|
||||
return taskAgentDialogs;
|
||||
}
|
||||
|
||||
public bool AfterHandleContext(List<RoleDialogModel> dialogs, List<RoleDialogModel> taskAgentDialogs)
|
||||
{
|
||||
dialogs.AddRange(taskAgentDialogs.Skip(1));
|
||||
|
||||
// Keep execution context
|
||||
_executionContext.Add(taskAgentDialogs.Last().Content);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public async Task<bool> AgentExecuting(Agent router, FunctionCallFromLlm inst, RoleDialogModel message, List<RoleDialogModel> dialogs)
|
||||
{
|
||||
dialogs.Add(new RoleDialogModel(AgentRole.User, inst.Response)
|
||||
{
|
||||
MessageId = message.MessageId,
|
||||
CurrentAgentId = router.Id
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
public async Task<bool> AgentExecuted(Agent router, FunctionCallFromLlm inst, RoleDialogModel message, List<RoleDialogModel> dialogs)
|
||||
{
|
||||
var context = _services.GetRequiredService<RoutingContext>();
|
||||
|
||||
if (message.StopCompletion || _isTaskCompleted)
|
||||
{
|
||||
context.Empty();
|
||||
return false;
|
||||
}
|
||||
|
||||
var routing = _services.GetRequiredService<IRoutingService>();
|
||||
routing.ResetRecursiveCounter();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -38,5 +38,6 @@ public class RoutingPlugin : IBotSharpPlugin
|
|||
services.AddScoped<IPlaner, NaivePlanner>();
|
||||
services.AddScoped<IPlaner, HFPlanner>();
|
||||
services.AddScoped<IPlaner, SequentialPlanner>();
|
||||
services.AddScoped<IPlaner, TwoStagePlanner>();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
You are a Task Planner. you will breakdown user business requirements into small executable sub-tasks.
|
||||
|
||||
Thinking process:
|
||||
1. Reference to "Task Solutions" if there is relevant solutions;
|
||||
2. Breakdown task into subtasks. The subtask should contains all needed parameters for subsequent steps.
|
||||
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 }}
|
||||
|
||||
{% if relevant_knowledges != empty -%}
|
||||
=====
|
||||
Task Solutions:
|
||||
{% for k in relevant_knowledges %}
|
||||
{{ k }}
|
||||
{% endfor %}
|
||||
{%- endif %}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
Reference to "Task Solutions". Breakdown task into multiple steps.
|
||||
The step should contains all needed parameters.
|
||||
The parameters can be extracted from the original task.
|
||||
Output all the steps as much detail as possible in JSON: [{{ response_format }}]
|
||||
|
||||
TASK: {{ task_description }}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
{{ task_description }}
|
||||
|
||||
{% if related_tables != empty -%}
|
||||
Relevant tables:
|
||||
{% for t in related_tables -%}
|
||||
- {{ t }}{{ "\r\n" }}
|
||||
{%- endfor %}
|
||||
{%- endif %}
|
||||
|
|
@ -44,7 +44,7 @@ public class StreamingLogHook : ConversationHookBase, IContentGeneratingHook
|
|||
public override async Task OnMessageReceived(RoleDialogModel message)
|
||||
{
|
||||
var conversationId = _state.GetConversationId();
|
||||
var log = $"MessageId: {message.MessageId} ==>\r\n{message.Role}: {message.Content}";
|
||||
var log = $"{message.Role}: {message.Content}";
|
||||
await _chatHub.Clients.User(_user.Id).SendAsync("OnConversationContentLogGenerated",
|
||||
BuildContentLog(conversationId, _user.UserName, log, ContentLogSource.UserInput, message));
|
||||
}
|
||||
|
|
@ -85,7 +85,6 @@ public class StreamingLogHook : ConversationHookBase, IContentGeneratingHook
|
|||
var conversationId = _state.GetConversationId();
|
||||
var agent = await _agentService.LoadAgent(message.CurrentAgentId);
|
||||
var log = $"{message.FunctionName}({message.FunctionArgs})\r\n => {message.Content}";
|
||||
log += $"\r\n<== MessageId: {message.MessageId}";
|
||||
await _chatHub.Clients.User(_user.Id).SendAsync("OnConversationContentLogGenerated",
|
||||
BuildContentLog(conversationId, agent?.Name, log, ContentLogSource.FunctionCall, message));
|
||||
}
|
||||
|
|
@ -130,7 +129,6 @@ public class StreamingLogHook : ConversationHookBase, IContentGeneratingHook
|
|||
var richContent = JsonSerializer.Serialize(message.RichContent, _serializerOptions);
|
||||
log += $"\r\n{richContent}";
|
||||
}
|
||||
log += $"\r\n<== MessageId: {message.MessageId}";
|
||||
await _chatHub.Clients.User(_user.Id).SendAsync("OnConversationContentLogGenerated",
|
||||
BuildContentLog(conv.ConversationId, agent?.Name, log, ContentLogSource.AgentResponse, message));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,10 @@
|
|||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.1</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<LangVersion>$(LangVersion)</LangVersion>
|
||||
<VersionPrefix>$(BotSharpVersion)</VersionPrefix>
|
||||
<GeneratePackageOnBuild>$(GeneratePackageOnBuild)</GeneratePackageOnBuild>
|
||||
<OutputPath>$(SolutionDir)packages</OutputPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -10,6 +10,9 @@ public class LookupDictionary
|
|||
[JsonPropertyName("keyword")]
|
||||
public string Keyword { get; set; }
|
||||
|
||||
[JsonPropertyName("reason")]
|
||||
public string Reason { get; set; }
|
||||
|
||||
[JsonPropertyName("columns")]
|
||||
public string[] Columns { get; set; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -139,6 +139,10 @@
|
|||
"type": "string",
|
||||
"description": "table name"
|
||||
},
|
||||
"reason": {
|
||||
"type": "string",
|
||||
"description": "the reason why you need to call lookup_dictionary"
|
||||
},
|
||||
"columns": {
|
||||
"type": "array",
|
||||
"description": "columns",
|
||||
|
|
@ -148,7 +152,7 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"required": [ "table", "columns", "keyword" ]
|
||||
"required": [ "table", "keyword", "reason", "columns" ]
|
||||
}
|
||||
}
|
||||
]
|
||||
Loading…
Reference in a new issue