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#

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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}";
}
}
}