aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio_22/Tango.Portal.Chat.Web/Services
diff options
context:
space:
mode:
authorRoy Ben Shabat <roy.mail.net@gmail.com>2025-09-03 00:06:46 +0300
committerRoy Ben Shabat <roy.mail.net@gmail.com>2025-09-03 00:06:46 +0300
commite91dd4d23647947b2c14787605b55400a405cff3 (patch)
treec1bb8fd60eb3923376573b63f8870e74f9828f5c /Software/Visual_Studio_22/Tango.Portal.Chat.Web/Services
parent12184412615b52ae98cba57921a7586e6970c436 (diff)
downloadTango-e91dd4d23647947b2c14787605b55400a405cff3.tar.gz
Tango-e91dd4d23647947b2c14787605b55400a405cff3.zip
Twine AI.
Diffstat (limited to 'Software/Visual_Studio_22/Tango.Portal.Chat.Web/Services')
-rw-r--r--Software/Visual_Studio_22/Tango.Portal.Chat.Web/Services/KqlGuard.cs2
-rw-r--r--Software/Visual_Studio_22/Tango.Portal.Chat.Web/Services/KustoQueryService.cs2
-rw-r--r--Software/Visual_Studio_22/Tango.Portal.Chat.Web/Services/LlmClient.cs32
-rw-r--r--Software/Visual_Studio_22/Tango.Portal.Chat.Web/Services/SchemaRegistry.cs13
4 files changed, 21 insertions, 28 deletions
diff --git a/Software/Visual_Studio_22/Tango.Portal.Chat.Web/Services/KqlGuard.cs b/Software/Visual_Studio_22/Tango.Portal.Chat.Web/Services/KqlGuard.cs
index 6ce4e44c9..b248fb502 100644
--- a/Software/Visual_Studio_22/Tango.Portal.Chat.Web/Services/KqlGuard.cs
+++ b/Software/Visual_Studio_22/Tango.Portal.Chat.Web/Services/KqlGuard.cs
@@ -1,6 +1,6 @@
using System.Text.RegularExpressions;
-namespace ChatADX.Web.Services
+namespace Tango.Portal.Chat.Web.Services
{
public sealed class KqlGuard
{
diff --git a/Software/Visual_Studio_22/Tango.Portal.Chat.Web/Services/KustoQueryService.cs b/Software/Visual_Studio_22/Tango.Portal.Chat.Web/Services/KustoQueryService.cs
index ecb89fcd6..8766eacd5 100644
--- a/Software/Visual_Studio_22/Tango.Portal.Chat.Web/Services/KustoQueryService.cs
+++ b/Software/Visual_Studio_22/Tango.Portal.Chat.Web/Services/KustoQueryService.cs
@@ -6,7 +6,7 @@ using Kusto.Data.Net.Client;
using Microsoft.Extensions.Options;
using System.Data;
-namespace ChatADX.Web.Services
+namespace Tango.Portal.Chat.Web.Services
{
public sealed class KustoQueryService
{
diff --git a/Software/Visual_Studio_22/Tango.Portal.Chat.Web/Services/LlmClient.cs b/Software/Visual_Studio_22/Tango.Portal.Chat.Web/Services/LlmClient.cs
index fb2226fb8..1577b7e08 100644
--- a/Software/Visual_Studio_22/Tango.Portal.Chat.Web/Services/LlmClient.cs
+++ b/Software/Visual_Studio_22/Tango.Portal.Chat.Web/Services/LlmClient.cs
@@ -3,10 +3,10 @@ using System.Text;
using System.Text.Json;
using System.Text.Json.Nodes;
using Microsoft.Extensions.Options;
-using ChatADX.Web.Models;
+using Tango.Portal.Chat.Web.Models;
using System.Text.RegularExpressions;
-namespace ChatADX.Web.Services
+namespace Tango.Portal.Chat.Web.Services
{
public sealed class LlmClient
{
@@ -44,7 +44,8 @@ namespace ChatADX.Web.Services
"Output raw JSON ONLY (no code fences).",
@"Classify the user's question into exactly one of:
- ""data"": requires querying telemetry via KQL (numbers, trends, counts, rates, top-N, timelines).
- - ""docs"": architectural/how-to/design/definitions/“what is/how do we” that do not require live data. place data or docs in the assistant field you return.",
+ - ""docs"": architectural/how-to/design/definitions/“what is/how do we” that do not require live data. place data or docs in the assistant field you return.
+ - ""none"": conversational content like Thank you/Hi/How are you. Or questions about why did you chose to execute the previouse KQL query the way you did and maybe ask for correction. In this case answer nicely and try to have a good conversation without going out of context.",
"If the question is classified as 'docs', set kql to an empty string and parameters to an empty object.",
@@ -125,34 +126,15 @@ namespace ChatADX.Web.Services
};
}
- public async Task<ProposeKqlResult> ProposeKqlAsync(
+ public async Task<ProposeKqlResult> ProposeKqlAsync(String plannerPrompt,
string question, string schemaJson, IEnumerable<ChatMessage>? history, CancellationToken ct = default)
{
- var system = string.Join("\n", new[] {
- "You are a Kusto (KQL) assistant for Azure Data Explorer.",
- "Use ONLY the tables/columns provided in the SCHEMA JSON that follows.",
- "ALWAYS follow upper case column names when specified by the schema.",
- "ALWAYS try to query for the least amount of data neccessary to answer the question.",
- "Return a JSON object with fields: assistant, kql, parameters, parameterTypes (optional), assumptions, why.",
- "When asked to query by months ago, convert number of months to days (e.g last to months = StartTime >= ago(60d))",
- "When joining tables, this example for correct syntax: EventsTable | join kind=inner (EventTypesTable) on $left.EventTypeGuid == $right.GUID.",
- "If you are joining and want to project two columns with the same name append '1' to the end of the second table name. (e.g: SitesTable | join kind=inner (OrganizationsTable) on $left.ORGANIZATION_GUID == $right.GUID | project Site = NAME, Organization = NAME1).",
- "When joining tables, make sure to also join by environment (e.g: SitesTable | join kind=inner (OrganizationsTable) on $left.ORGANIZATION_GUID == $right.GUID and $left.ENVIRONMENT == $right.ENVIRONMENT)).",
- "Output raw JSON ONLY (no code fences).",
- // 👇 tiny but important instruction for routing:
- @"Use conversational context from prior turns. If the current question refers to a previous result (e.g., 'that', 'those', 'the same one'),
- keep the same 'assistant' classification as the previous turn unless the user clearly asks for documentation.",
- @"Classify into exactly one of:
- - ""data"": requires querying telemetry via KQL (numbers, trends, counts, rates, top-N, timelines).
- - ""docs"": architectural/how-to/design/definitions not requiring live data."
- });
-
- var messages = new List<object> { new { role = "system", content = system } };
+ var messages = new List<object> { new { role = "system", content = plannerPrompt } };
if (history != null)
{
foreach (var m in history.TakeLast(6))
- messages.Add(new { role = m.Role, content = m.Content });
+ messages.Add(new { role = m.Role, content = m.Content, usedKql = m.UsedKql });
}
var schemaBlock = $"SCHEMA:\n{schemaJson}";
diff --git a/Software/Visual_Studio_22/Tango.Portal.Chat.Web/Services/SchemaRegistry.cs b/Software/Visual_Studio_22/Tango.Portal.Chat.Web/Services/SchemaRegistry.cs
index da6868bc5..3ba6ad0c5 100644
--- a/Software/Visual_Studio_22/Tango.Portal.Chat.Web/Services/SchemaRegistry.cs
+++ b/Software/Visual_Studio_22/Tango.Portal.Chat.Web/Services/SchemaRegistry.cs
@@ -1,6 +1,6 @@
using System.Text.Json;
-namespace ChatADX.Web.Services
+namespace Tango.Portal.Chat.Web.Services
{
public sealed class SchemaRegistry
{
@@ -28,5 +28,16 @@ namespace ChatADX.Web.Services
JsonDocument.Parse(_cached);
return _cached!;
}
+
+ public string GetPlannerPrompt()
+ {
+ var path = Path.Combine(_env.ContentRootPath, "Data", "planner_prompt.txt");
+ if (!File.Exists(path))
+ {
+ _log.LogWarning("Planner prompt file not found at {Path}. Returning empty prompt.", path);
+ return string.Empty;
+ }
+ return File.ReadAllText(path);
+ }
}
}