You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kev/Drawer/AI/KnowledgeBase/SimpleKnowledgeBase.cs

131 lines
5.2 KiB
C#

1 month ago
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}";
}
}
}