|
|
using System.Collections.Generic;
|
|
|
using System.ComponentModel;
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
|
namespace AI.KnowledgeBase
|
|
|
{
|
|
|
/// <summary>
|
|
|
/// 简单知识库实现
|
|
|
/// </summary>
|
|
|
public class SimpleKnowledgeBase : IKnowledgeBase
|
|
|
{
|
|
|
private static readonly Dictionary<string, string> QueryAliasToTopic = new(StringComparer.OrdinalIgnoreCase)
|
|
|
{
|
|
|
// 常用中文/英文说法归一到知识条目 key
|
|
|
{ "网格化", "成图" },
|
|
|
{ "网格化流程", "成图" },
|
|
|
{ "成图流程", "成图" },
|
|
|
{ "gridding", "成图" },
|
|
|
{ "grid", "成图" },
|
|
|
{ "gridding workflow", "成图" },
|
|
|
};
|
|
|
|
|
|
/// <summary>
|
|
|
/// 每个主题对应的知识条目 Id 与版本号,便于在会话存储或日志中引用和比对。
|
|
|
/// </summary>
|
|
|
private static readonly Dictionary<string, (string Id, string Version)> TopicMeta = new(StringComparer.OrdinalIgnoreCase)
|
|
|
{
|
|
|
{ "open file", (Id: "open-file", Version: "1") },
|
|
|
{ "close file", (Id: "close-file", Version: "1") },
|
|
|
{ "validate excel", (Id: "validate-excel", Version: "1") },
|
|
|
{ "成图", (Id: "gridding-flow", Version: "3") },
|
|
|
};
|
|
|
|
|
|
private readonly Dictionary<string, string> knowledge = new()
|
|
|
{
|
|
|
{ "open file", "Use the OpenFile tool to open a file." },
|
|
|
{ "close file", "Use the CloseFile tool to close a file." },
|
|
|
{ "validate excel", "Use the ValidExcelFile tool to validate an Excel file." },
|
|
|
{ "成图", @"
|
|
|
你是一名智能的网格化助手,负责引导用户完成以下两步流程:
|
|
|
|
|
|
1. 散点文件加载卡片:调用 ShowForm(""gridding-load-xyz""),界面会弹出「加载散点文件」综合卡片。
|
|
|
该卡片自动完成:选择文件 → 数据预览 → 列头匹配,无需你介入。
|
|
|
用户点击「确认匹配」后,系统会向你发送包含文件信息与列头匹配结果的摘要消息。
|
|
|
|
|
|
2. 成图参数卡片:调用 ShowForm(""gridding-parameters""),界面会弹出「网格化参数设置」综合卡片。
|
|
|
卡片会自动加载当前参数,用户可在卡片中查看、编辑参数,点击「生成」按钮后由卡片内部完成参数设置与成图,无需你再调用获取/设置参数或成图函数。
|
|
|
调用后只需一句话告知用户参数卡片已展示、可在卡片中修改并点击生成即可。"
|
|
|
},
|
|
|
};
|
|
|
|
|
|
/// <inheritdoc/>
|
|
|
public Task<string> SearchKnowledgeAsync(string query)
|
|
|
{
|
|
|
if (string.IsNullOrWhiteSpace(query))
|
|
|
{
|
|
|
return Task.FromResult(BuildNotFoundMessage());
|
|
|
}
|
|
|
|
|
|
var normalized = query.Trim().ToLowerInvariant();
|
|
|
|
|
|
// 先做别名归一(精确)
|
|
|
if (QueryAliasToTopic.TryGetValue(normalized, out var topic))
|
|
|
{
|
|
|
normalized = topic.ToLowerInvariant();
|
|
|
}
|
|
|
|
|
|
// 精确命中
|
|
|
if (knowledge.TryGetValue(normalized, out var result))
|
|
|
{
|
|
|
return Task.FromResult(FormatResult(normalized, result));
|
|
|
}
|
|
|
|
|
|
// 别名归一(包含匹配):比如"我要进行网格化"也能映射到"成图"
|
|
|
foreach (var kv in QueryAliasToTopic)
|
|
|
{
|
|
|
if (normalized.Contains(kv.Key.ToLowerInvariant()))
|
|
|
{
|
|
|
var key = kv.Value.ToLowerInvariant();
|
|
|
if (knowledge.TryGetValue(key, out result))
|
|
|
{
|
|
|
return Task.FromResult(FormatResult(key, result));
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 兜底:包含匹配(选最长 key,避免过于宽泛)
|
|
|
string? bestKey = null;
|
|
|
foreach (var key in knowledge.Keys)
|
|
|
{
|
|
|
var k = key.ToLowerInvariant();
|
|
|
if (normalized.Contains(k) || k.Contains(normalized))
|
|
|
{
|
|
|
if (bestKey == null || k.Length > bestKey.Length)
|
|
|
{
|
|
|
bestKey = key;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if (bestKey != null && knowledge.TryGetValue(bestKey, out result))
|
|
|
{
|
|
|
return Task.FromResult(FormatResult(bestKey, result));
|
|
|
}
|
|
|
|
|
|
return Task.FromResult(BuildNotFoundMessage(query));
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 按主题 key 为知识正文加上 [KB-ID; Version] 头部,便于回放与引用。
|
|
|
/// </summary>
|
|
|
private static string FormatResult(string topicKey, string content)
|
|
|
{
|
|
|
if (!TopicMeta.TryGetValue(topicKey, out var meta))
|
|
|
{
|
|
|
return content;
|
|
|
}
|
|
|
|
|
|
return $"[KB-ID: {meta.Id}; Version: {meta.Version}]{System.Environment.NewLine}{content}";
|
|
|
}
|
|
|
|
|
|
private string BuildNotFoundMessage(string? query = null)
|
|
|
{
|
|
|
var topics = string.Join("、", knowledge.Keys);
|
|
|
if (string.IsNullOrWhiteSpace(query))
|
|
|
return $"未找到相关知识。可用主题:{topics}";
|
|
|
return $"未找到与「{query}」相关的知识。可用主题:{topics}";
|
|
|
}
|
|
|
}
|
|
|
}
|