using System.Collections.Generic; using System.ComponentModel; using System.Threading.Tasks; namespace AI.KnowledgeBase { /// /// 简单知识库实现 /// public class SimpleKnowledgeBase : IKnowledgeBase { private static readonly Dictionary QueryAliasToTopic = new(StringComparer.OrdinalIgnoreCase) { // 常用中文/英文说法归一到知识条目 key { "网格化", "成图" }, { "网格化流程", "成图" }, { "成图流程", "成图" }, { "gridding", "成图" }, { "grid", "成图" }, { "gridding workflow", "成图" }, }; /// /// 每个主题对应的知识条目 Id 与版本号,便于在会话存储或日志中引用和比对。 /// private static readonly Dictionary 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 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""),界面会弹出「网格化参数设置」综合卡片。 卡片会自动加载当前参数,用户可在卡片中查看、编辑参数,点击「生成」按钮后由卡片内部完成参数设置与成图,无需你再调用获取/设置参数或成图函数。 调用后只需一句话告知用户参数卡片已展示、可在卡片中修改并点击生成即可。" }, }; /// public Task 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)); } /// /// 按主题 key 为知识正文加上 [KB-ID; Version] 头部,便于回放与引用。 /// 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}"; } } }