Ben.SemanticKernel
5.3.1
dotnet add package Ben.SemanticKernel --version 5.3.1
NuGet\Install-Package Ben.SemanticKernel -Version 5.3.1
<PackageReference Include="Ben.SemanticKernel" Version="5.3.1" />
<PackageVersion Include="Ben.SemanticKernel" Version="5.3.1" />
<PackageReference Include="Ben.SemanticKernel" />
paket add Ben.SemanticKernel --version 5.3.1
#r "nuget: Ben.SemanticKernel, 5.3.1"
#:package Ben.SemanticKernel@5.3.1
#addin nuget:?package=Ben.SemanticKernel&version=5.3.1
#tool nuget:?package=Ben.SemanticKernel&version=5.3.1
Ben.SemanticKernel 完整指南
基于 Microsoft Semantic Kernel 的企业级 AI Agent 框架
版本: v3.0 (ReAct Agent)
更新时间: 2025-10-24
.NET 版本: 8.0
📑 目录
1. 项目概览
1.1 项目简介
Ben.SemanticKernel 是一个生产级的 .NET AI Agent 框架,提供完整的 ReAct(Reasoning + Acting)模式实现、智能联网搜索、知识库管理和企业工具集成能力。
核心亮点:
- ✅ ReAct Agent 模式:完整的 Planning → Action → Observation 循环
- ✅ 深度思考可见:捕获 DeepSeek/OpenAI o1 的 reasoning_content
- ✅ 智能分支选择:自动判断简单/复杂问题,优化执行策略
- ✅ 企业级搜索:多引擎聚合(百度/Bing/Google)+ 语义重排
- ✅ 专业 API 集成:天气(和风/OpenWeatherMap)、可扩展股票/新闻
- ✅ MCP 工具支持:Model Context Protocol 企业工具集成
- ✅ 知识库 RAG:向量检索(Qdrant/PgVector)+ 知识图谱
1.2 技术栈
| 组件 | 技术 | 版本 |
|---|---|---|
| 框架 | Microsoft Semantic Kernel | 1.66.0 |
| 运行时 | .NET | 8.0 |
| AI 模型 | DeepSeek / OpenAI / Ollama | - |
| 向量数据库 | Qdrant / PostgreSQL (pgvector) | - |
| 浏览器自动化 | Playwright | 1.x |
| 弹性策略 | Polly | 8.x |
1.3 架构演进
v1.0 预检索 RAG (2024 Q1)
├─ 用户问题 → 系统强制搜索 → 注入结果 → LLM 生成
└─ ❌ 总是搜索,浪费资源;无深度思考
v2.0 简单 Agent RAG (2024 Q3)
├─ 用户问题 → LLM 自主决策 → 自动执行工具 → 返回结果
└─ ✅ LLM 自主决策 ❌ 思考不可见,无迭代
v3.0 ReAct Agent (2025 Q1) ⭐ 当前版本
├─ Planning → Action → Observation → Planning → ...
├─ ✅ 深度思考完全可见 (reasoning_content)
├─ ✅ 决策链透明 (planning/action/observation)
├─ ✅ 多轮迭代支持 (最多10次)
└─ ✅ 智能分支选择 (简单问题快速响应)
2. 快速开始 (10分钟)
2.1 环境要求
- ✅ .NET 8.0 SDK 或更高版本
- ✅ AI 服务 API Key (DeepSeek/OpenAI/Ollama)
- ⚡ 可选:Playwright(联网搜索)
- ⚡ 可选:Qdrant/PostgreSQL(知识库)
2.2 三步启动
步骤 1:安装 Playwright(可选,用于联网搜索)
cd Ben.SemanticKernel
.\install-playwright.ps1
步骤 2:配置 appsettings.json
{
"BEN_SK": {
"AIConfig": {
"TextInfo": {
"ApiKey": "sk-your-api-key",
"Model": "deepseek-chat",
"BaseUri": "https://api.deepseek.com",
"Provider": "openai"
},
"EmbeddingInfo": {
"ApiKey": "sk-your-api-key",
"Model": "text-embedding-3-small",
"BaseUri": "https://api.openai.com/v1",
"Provider": "openai",
"VectorSize": 1536,
"Index": "default"
}
}
}
}
步骤 3:运行示例项目
# 编译项目
dotnet build -c Release
# 启动 Web 服务
cd Ben.Examples
dotnet run
预期输出:
Now listening on: http://localhost:5000
Application started. Press Ctrl+C to shut down.
2.3 快速测试
使用 REST Client 或 curl 测试:
POST http://localhost:5000/api/Chat/Chat
Content-Type: application/json
{
"sessionId": 1,
"text": "今天深圳天气怎么样?",
"networking": true
}
预期响应(SSE 流式):
data: {"type":"thinking","data":"用户询问今天深圳天气,需要使用工具..."}
data: {"type":"planning","data":{"name":"search_weather",...}}
data: {"type":"action","data":"执行中..."}
data: {"type":"observation","data":"【深圳天气预报】..."}
data: {"type":"chat","data":"根据最新天气预报[1],深圳今天..."}
data: {"type":"times","data":4850}
data: {"type":"done","data":"done"}
3. 核心架构
3.1 整体架构图
graph TB
User[用户请求] --> Controller[ChatController]
Controller --> ChatService[ChatService<br/>核心编排器]
ChatService --> Branch{智能分支选择}
Branch -->|简单问题| Simple[简单模式<br/>快速响应 < 1s]
Branch -->|复杂问题| ReAct[ReAct 模式<br/>完整循环]
ReAct --> Loop{迭代循环}
Loop --> Planning[💭 Planning<br/>决策阶段]
Planning --> Action[⚡ Action<br/>执行工具]
Action --> Observation[👁️ Observation<br/>获取结果]
Observation --> Check{是否需要<br/>继续迭代?}
Check -->|是| Loop
Check -->|否| Answer[📢 Final Answer]
Action --> Tools[工具层]
Tools --> WebSearch[联网搜索]
Tools --> Weather[天气 API]
Tools --> MCP[MCP 工具]
Tools --> KMS[知识库]
WebSearch --> Aggregator[SearchAggregator<br/>多引擎聚合]
Aggregator --> Baidu[百度]
Aggregator --> Bing[Bing]
Aggregator --> Google[Google]
Aggregator --> Reranker[SemanticReranker<br/>语义重排]
Answer --> SSE[SSE 流式输出]
SSE --> User
3.2 目录结构
Ben.SemanticKernel/
├── AI/ # AI 核心
│ ├── KernelFactory.cs # Kernel 工厂(缓存、多提供商)
│ ├── KernelFactory.WebSearch.cs # 联网搜索工具注册
│ ├── KernelFactory.Mcp.cs # MCP 工具注册
│ └── MemoryKernelFactory.cs # 向量检索
│
├── Services/
│ ├── ChatService/
│ │ ├── ChatService.cs # 🔥 核心对话编排(1768行)
│ │ ├── WebSearchPlugin.cs # Kernel 插件
│ │ └── ChatServiceExtension.cs # DI 注册
│ │
│ ├── Common/
│ │ ├── SearchAggregator.cs # 多引擎聚合
│ │ ├── SemanticReranker.cs # 语义重排
│ │ ├── WeatherApiService.cs # 天气 API(三层降级)
│ │ ├── BingScraper.cs # 搜索引擎抓取
│ │ ├── ContentExtractor.cs # 网页正文提取
│ │ └── QueryClassifier.cs # 查询分类(6大类)
│ │
│ ├── TextMemory/ # 向量存储
│ ├── KnowledgeGraph/ # 知识图谱
│ ├── Mcp/ # MCP 服务
│ └── Tools/ # 工具服务
│
├── Models/ # 数据模型
├── Prompts/ # 提示词模板
└── Utils/ # 工具类
Ben.Examples/ # 示例 Web 项目
├── Controllers/
│ ├── ChatController.cs # 🔥 ReAct Agent API
│ ├── McpController.cs # MCP 测试 API
│ └── KnowledgeController.cs # 知识库管理
├── appsettings.json # 配置文件
└── Program.cs # 启动入口
3.3 数据流
HTTP 请求 (POST /api/Chat/Chat)
↓
ChatController 接收
↓
构建系统提示词 + 历史消息
↓
ChatService.ChatAsync()
├─ IsLikelyNeedingTools("今天深圳天气") → true
├─ 用户启用工具 (networking=true) → true
└─ 选择 ReAct 模式
↓
创建 Kernel + 注册 WebSearchPlugin
├─ search_web
├─ search_weather
└─ search_news
↓
ReAct 循环 - 迭代 1
├─ 💭 Planning(非流式调用)
│ └─ 捕获 reasoning_content → yield "thinking" 事件
├─ 检测 FunctionCallContent → search_weather("深圳", 1)
└─ ⚡ Action:手动执行工具
↓
WebSearchPlugin.SearchWeatherAsync()
├─ 优先:WeatherApiService.GetWeatherAsync()
│ ├─ 和风天气 API → 成功 ✅
│ └─ 失败 → OpenWeatherMap → 失败 → 网页搜索
└─ 降级:SearchWebAsync(..., extractFullContent: true)
↓
网页搜索流程(降级时)
├─ SearchAggregator.AggregateAsync()
│ ├─ 智能引擎选择:百度 + Bing(并行)
│ ├─ 合并去重:URL 归一化
│ └─ ContentExtractor 抓取完整正文(Top 5)
└─ SemanticReranker.RerankAsync()
└─ Score = 余弦相似度 + 新鲜度 + 质量
↓
👁️ Observation:工具结果添加到历史
↓
ReAct 循环 - 迭代 2
├─ 💭 Planning(再次非流式调用)
│ └─ 捕获 reasoning_content: "已获取信息,可以回答…"
├─ 无 FunctionCall → 最终答案阶段
└─ 使用 chatResult.Content 伪流式输出(逐字符 3ms)
↓
输出完成
├─ yield "times" 事件(总耗时)
├─ yield "done" 事件
└─ 触发 onCompletion 回调
4. 功能特性
4.1 ReAct Agent 模式
Planning → Action → Observation 完整循环
// 自动进入 ReAct 模式(系统智能判断)
await chatService.ChatAsync(
input: "今天深圳天气",
assistantPrompt: systemPrompt,
aiOptions: options,
_history: null,
netWork: true, // 启用联网搜索
serviceProvider: serviceProvider, // 必须传递(工具注册)
enableDeepThinking: true, // 捕获深度思考
maxIterations: 10 // 最大迭代次数
);
控制台输出示例:
================================================================================
🧠 ReAct Agent 模式 - Planning → Action → Observation
================================================================================
📝 用户问题: 今天深圳天气怎么样?
💭 深度思考: 已启用(DeepSeek 兼容)
--------------------------------------------------------------------------------
[智能分支选择]
- 系统判断需要工具: True
- 用户启用工具: True
- 系统自动选择: ReAct 模式(复杂问题)
💭 [Thinking] 用户询问今天深圳的天气,这是实时信息查询...
📋 [Planning] 决定调用工具: search_weather
参数: {"location":"深圳","days":1}
⚡ [Action] 执行中...
✅ 天气 API 调用成功,返回 1 天预报
【深圳天气预报】来源: 和风天气
📅 10月24日(周四)
天气: 多云 转 晴
温度: 25°C ~ 31°C
风向: 东南风 2级
👁️ [Observation] 工具执行成功
🔄 迭代 2/10
💭 [Thinking] 已获取天气信息,可以回答了...
📢 AI回答: 根据最新天气预报[1],深圳今天(10月24日)天气多云转晴...
⏱️ 耗时: 4850ms (4.85秒)
================================================================================
4.2 智能分支选择
自动判断简单/复杂问题,优化执行策略
| 场景 | 判断 | 模式 | 响应时间 | 特点 |
|---|---|---|---|---|
| "你好" | 简单问题 | 简单模式 | < 1秒 | 不传 tools,真流式,极速响应 |
| "1+1=?" | 简单问题 | 简单模式 | < 1秒 | 直接回答,无工具调用 |
| "今天深圳天气" | 复杂问题 | ReAct 模式 | 4-8秒 | 完整流程,思考可见 |
| "特斯拉股价" | 复杂问题 | ReAct 模式 | 8-12秒 | 多引擎搜索 + 分析 |
判断规则(IsLikelyNeedingTools):
// ✅ 明确需要工具
if (input.Contains("天气") || input.Contains("新闻") || input.Contains("股票"))
return true;
// ❌ 明确不需要工具
if (input.Matches(@"^\s*\d+\s*[\+\-\*/]\s*\d+")) // 简单数学
return false;
if (input.Matches(@"^(你好|hello|hi)")) // 打招呼
return false;
// 🤔 启发式判断
if (input.Length > 50) // 长问题可能需要工具
return true;
return input.Length >= 10; // 保守策略
4.3 联网搜索系统
多引擎聚合 + 语义重排 + 全文抓取
搜索引擎策略
| 策略 | 引擎组合 | 适用场景 |
|---|---|---|
smart (推荐) |
智能选择 | 中文→百度+Bing;英文→Google+Bing |
baidu |
仅百度 | 中文查询、中国本地信息 |
bing |
仅 Bing | 国际信息、平衡搜索 |
google |
仅 Google | 学术研究、技术文档 |
all |
三引擎全开 | 需要最全面结果(较慢) |
查询分类(6大类)
public enum QueryCategory
{
Stock, // 股票财经 → 东方财富、雪球
News, // 新闻资讯 → 全文抓取 + 时间优先
Weather, // 天气查询 → 优先天气 API
Technical, // 技术问题 → 增加 Google
Academic, // 学术研究 → Google + Bing
General // 通用查询 → 智能引擎
}
语义重排算法
最终分数 = 基础分 + 加权分
基础分 = Cosine(查询向量, 结果向量) // 0.0-1.0
加权分 =
+ 标题匹配 × 0.05 // 标题包含关键词
+ 时间新鲜度 × 0.15 // 越新越好(时间敏感查询)
+ 内容质量 × 0.10 // 有 FullContent 优先
内容质量分 =
+ 有 FullContent: 0.5
+ 长度适中 (500-5000字): 0.2
+ ContentQuality 分数: 0.3
4.4 天气 API(三层降级)
search_weather("深圳", 7)
↓
① 和风天气 API(推荐)
├─ JWT Token 认证(EdDSA 签名)
├─ 自动生成 Token + 缓存(15分钟)
├─ Gzip 自动解压缩
├─ 成功 → 返回详细数据 ✅ (1-2秒)
└─ 失败 ↓
② OpenWeatherMap API
├─ 成功 → 返回详细数据 ✅ (2-3秒)
└─ 失败 ↓
③ 网页搜索(extractFullContent: true)
└─ 返回网页抓取内容 ⚠️ (25-30秒)
配置示例:
{
"WeatherApi": {
"QWeather": {
"KeyId": "ABCDE12345", // JWT 凭据ID
"ProjectId": "HE2408041234567", // 项目ID
"PrivateKey": "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----",
"ApiHost": "https://xxx.qweatherapi.com", // 自定义域名
"Enabled": true
},
"OpenWeather": {
"ApiKey": "your-openweather-api-key",
"Enabled": true
}
}
}
技术特性:
- ✅ JWT Token:自动生成并缓存(Ed25519 签名)
- ✅ 安全性高:私钥本地保管,无法伪造
- ✅ 自动降级:和风 → OpenWeather → 网页搜索
- ✅ Gzip 压缩:自动解压缩响应数据
- ✅ 详细日志:完整的调试信息输出
详细配置:参见 5.3 和风天气 JWT Token 配置指南
4.5 深度思考捕获
兼容 DeepSeek / OpenAI o1 的 reasoning_content
// 自动捕获并输出
var jsonContent = JsonNode.Parse(ModelReaderWriter.Write(chatResult.InnerContent));
var reasoningNode = jsonContent["choices"]?[0]?["message"]?["reasoning_content"];
if (reasoningNode != null)
{
var thought = reasoningNode.ToString();
yield return JsonSerializer.Serialize(new
{
data = thought,
type = "thinking", // ReAct 模式用 "thinking"
});
}
SSE 事件流:
{"type":"thinking","data":"用户询问今天深圳天气,这是实时信息查询..."}
{"type":"planning","data":{"name":"search_weather",...}}
{"type":"action","data":"执行中..."}
{"type":"observation","data":"【深圳天气预报】..."}
{"type":"chat","data":"根据最新天气预报[1]..."}
{"type":"times","data":4850}
{"type":"done","data":"done"}
5. 配置说明
5.1 完整配置文件(appsettings.json)
{
"BEN_SK": {
"AIConfig": {
// 🔥 文本生成模型(必需)
"TextInfo": {
"ApiKey": "sk-112e82a5f6fa4be89ed223fbf955b565",
"Model": "deepseek-chat",
"BaseUri": "https://api.deepseek.com",
"Provider": "openai" // openai/deepseek/ollama/azure/grok
},
// 🔥 向量嵌入模型(知识库必需)
"EmbeddingInfo": {
"ApiKey": "sk-112e82a5f6fa4be89ed223fbf955b565",
"Model": "bge-m3:latest",
"BaseUri": "http://localhost:11434",
"Provider": "ollama",
"VectorSize": 1024,
"Index": "MES-V002-test",
// 向量数据库连接
"KmsPoint": "Host=localhost;Port=5432;Username=postgres;Password=admin;Database=mes_vector",
"VertorType": "pgsql", // qdrant/pgsql/sqlite
// 检索配置
"SearchOption": {
"SearchMinRelevance": 0.5,
"SearchLimit": 3,
"NodeDepth": 3,
"MaxNodes": 300,
"MaxTokens": 32000
}
},
// ⚡ 知识图谱(可选)
"Neo4j": {
"Uri": "neo4j://localhost:7687",
"User": "neo4j",
"Password": "strongpassword"
}
},
// 🔥 MCP 配置(可选)
"McpConfig": {
"Enabled": true,
"DefaultTimeoutSeconds": 30,
"RetryCount": 3,
"EnableDebugLogging": true,
"Servers": [
{
"Name": "mes-mcp-server",
"Type": "http",
"Url": "http://localhost:5278/api/mcp",
"Description": "MES系统MCP服务器",
"Enabled": true,
"TimeoutSeconds": 60
}
]
}
},
// 🔥 天气 API 配置(可选,提升天气查询质量)
// 推荐使用和风天气 JWT Token 认证(更安全、更稳定)
"WeatherApi": {
"QWeather": {
// JWT Token 认证(推荐)- 需要配置三个参数
// 步骤1:在控制台 → 项目管理 → 查看项目ID
"KeyId": "your-credential-id", // 凭据ID(kid),在控制台获取
// 步骤2:在控制台 → 项目管理 → 创建凭据(选择 JSON Web Token)
"ProjectId": "your-project-id", // 项目ID(sub),在控制台获取
// 步骤3:使用 OpenSSL 生成 Ed25519 密钥对(参考文档)
// 命令:openssl genpkey -algorithm ED25519 -out ed25519-private.pem
// 将生成的私钥文件内容(包含 BEGIN/END 标记)粘贴到下方
"PrivateKey": "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----", // Ed25519 私钥(PEM格式)
// "-----BEGIN PRIVATE KEY-----\nMC4CAQAwBQYDK2VwBCIEIOoH...\n-----END PRIVATE KEY-----"
// 注意:
// - PrivateKey 必须包含完整的 PEM 格式(包括 -----BEGIN PRIVATE KEY----- 和 -----END PRIVATE KEY-----)
// - 公钥需要在控制台上传,私钥由你自己保管
// - JWT 有效期默认 15 分钟,自动缓存重用
// ⚠️ 如果遇到 404 错误,请检查控制台的自定义域名配置
// 在控制台 → 项目管理 → 查看【Host】或【API 域名】
// 如果有自定义域名(如 xxx.qweatherapi.com),请在此配置:
"ApiHost": "https://xxx.qweatherapi.com", // 自定义域名(可选),在控制台查看
"Enabled": true
},
"OpenWeather": {
// OpenWeatherMap 备用(降级使用)
"ApiKey": "your-openweather-api-key",
"Enabled": true
}
},
// 🔥 内容抓取配置(可选)
"ContentExtraction": {
"Enabled": true,
"MaxConcurrent": 3,
"TimeoutSeconds": 10,
"MaxContentLength": 5000
}
}
5.2 支持的 AI 模型提供商
DeepSeek(推荐,支持深度思考)
{
"TextInfo": {
"ApiKey": "sk-xxx",
"Model": "deepseek-chat",
"BaseUri": "https://api.deepseek.com",
"Provider": "openai"
}
}
优势:
- ✅ 支持
reasoning_content(深度思考) - ✅ 支持 Function Calling
- ✅ 价格低廉(1元/百万token)
- ✅ 完美适配 ReAct 模式
OpenAI GPT-4
{
"TextInfo": {
"ApiKey": "sk-xxx",
"Model": "gpt-4",
"BaseUri": "https://api.openai.com/v1",
"Provider": "openai"
}
}
Ollama(本地模型)
{
"TextInfo": {
"ApiKey": "not-needed",
"Model": "qwen2.5:7b",
"BaseUri": "http://localhost:11434",
"Provider": "ollama"
}
}
安装:
# 下载 Ollama: https://ollama.ai/download
# 启动模型
ollama pull qwen2.5:7b
ollama pull nomic-embed-text
5.3 和风天气 JWT Token 配置指南
和风天气 API 使用 JWT (JSON Web Token) 认证方式,基于 Ed25519 非对称加密算法,提供更高的安全性。
为什么使用 JWT 认证?
| 特性 | API Key | JWT Token |
|---|---|---|
| 安全性 | ⚠️ 中等(Key 可能泄露) | ✅ 高(私钥本地保管) |
| 防伪造 | ⚠️ Key 泄露后可被伪造 | ✅ 无法伪造(非对称加密) |
| 长期支持 | ❌ SDK 5+ 不再支持 | ✅ 官方推荐方式 |
| 有效期 | 永久有效 | 15分钟(自动续期) |
配置步骤(5步完成)
步骤 1:注册和风天气账号
- 访问 和风天气开发平台
- 注册并登录账号
- 进入 控制台 - 项目管理
步骤 2:获取项目 ID
- 在项目管理页面,查看或创建一个项目
- 记录项目 ID(10位字符,用作 JWT 的
sub字段)- 示例:
HE2408041234567
- 示例:
步骤 3:生成 Ed25519 密钥对
使用 OpenSSL 生成 Ed25519 密钥对(推荐 OpenSSL 3.0.1+):
# Windows(使用 PowerShell 或 Git Bash)
# 安装 OpenSSL: winget install --id=OpenSSL.OpenSSL -e
# Linux / macOS
openssl genpkey -algorithm ED25519 -out ed25519-private.pem \
&& openssl pkey -pubout -in ed25519-private.pem > ed25519-public.pem
这将生成两个文件:
ed25519-private.pem:私钥(⚠️ 请妥善保管,不要泄露)ed25519-public.pem:公钥(需要上传到和风天气控制台)
私钥示例(ed25519-private.pem):
-----BEGIN PRIVATE KEY-----
MC4CAQAwBQYDK2VwBCIEIOoHhOGko015veaBJKAueX90eC3YoxhKi3qaZktu1Dke
-----END PRIVATE KEY-----
公钥示例(ed25519-public.pem):
-----BEGIN PUBLIC KEY-----
MCowBQYDK2VwAyEAARbeZ5AhklFG4gg1Gx5g5bWxMMdsUd6b2MC4wV0/M9Q=
-----END PUBLIC KEY-----
步骤 4:在控制台创建 JWT 凭据
- 在控制台 → 项目管理中,点击你的项目
- 在凭据区域点击"添加凭据"按钮
- 填写表单:
- 凭据名称:自定义名称(如"生产环境JWT凭据")
- 身份认证方式:选择 JSON Web Token
- 公钥:复制
ed25519-public.pem的全部内容(包括BEGIN/END标记)
- 点击"保存"
- 记录生成的凭据 ID(10位字符,用作 JWT 的
kid字段)- 示例:
ABCDE12345
- 示例:
步骤 5:查看自定义域名(重要)
- 在控制台 → 项目管理 → 点击你的项目
- 查看Host 配置或API 域名
- 记录你的专属域名(每个项目都有独立的域名)
- 示例:
https://nm4ewt2hfu.re.qweatherapi.com - ⚠️ 不是统一的
devapi.qweather.com
- 示例:
完整配置示例
{
"WeatherApi": {
"QWeather": {
"KeyId": "ABCDE12345", // 步骤4 中的凭据ID
"ProjectId": "HE2408041234567", // 步骤2 中的项目ID
"PrivateKey": "-----BEGIN PRIVATE KEY-----\nMC4CAQAwBQYDK2VwBCIEIOoHhOGko015veaBJKAueX90eC3YoxhKi3qaZktu1Dke\n-----END PRIVATE KEY-----", // 步骤3 中的私钥
"ApiHost": "https://nm4ewt2hfu.re.qweatherapi.com", // 步骤5 中的自定义域名
"Enabled": true
},
"OpenWeather": {
"ApiKey": "your-openweather-api-key", // 备用选项
"Enabled": false
}
}
}
配置要点
✅ 必须配置:
KeyId:JWT 类型的凭据ID(不是 API KEY 类型)ProjectId:项目ID(在项目管理页面顶部显示)PrivateKey:完整的 Ed25519 私钥(包含BEGIN/END标记)
⚡ 强烈推荐:
ApiHost:自定义域名(避免 404 错误)
❌ 常见错误:
- 使用了 API KEY 类型的凭据ID(不是 JWT 类型)
- 私钥格式不完整(缺少
BEGIN/END标记) - 私钥中的
\n换行符丢失(JSON 中必须转义) - 未配置
ApiHost,使用默认域名导致 404
验证配置
启动应用后,查看控制台输出:
[和风天气] ✅ 成功生成 JWT Token(有效期至 2025-10-27 09:25:12 UTC)
[和风天气] 🔍 方式1:https://nm4ewt2hfu.re.qweatherapi.com + Authorization Header
(使用自定义域名配置)
[和风天气] ✅ 方式1 请求成功!
[和风天气] ✅ JSON 解析成功!
[和风天气] ✅ 找到城市: 深圳 (ID: 101280601)
[和风天气] ✅ 成功解析 3 天的天气预报
在线验证工具
如果遇到问题,可以使用和风天气官方 JWT 验证工具:
粘贴生成的 JWT Token,点击【验证】:
- ✅ 绿色勾 = JWT 正确
- ❌ 红色叉 = JWT 错误(检查配置)
技术细节
JWT Token 结构:
eyJhbGciOiJFZERTQSIsImtpZCI6IktLQjMyUjQ5VFQifQ.eyJzdWIiOiI0TURXTkE5Rk1RIiwiaWF0IjoxNzYxNTU2MjEyLCJleHAiOjE3NjE1NTcxMTJ9.lwfWmqZlVxy7UzKVai3Rn7EL4oAIjjdl7hofjhm_XvAbP0GX0GXtf2Td9w7n4lyGdP_TiHyFVLouMa45IkQxAg
Header(Base64Url 编码):
{
"alg": "EdDSA",
"kid": "KKB32R49TT"
}
Payload(Base64Url 编码):
{
"sub": "4MDWNA9FMQ",
"iat": 1761556212,
"exp": 1761557112
}
Signature(Ed25519 签名,Base64Url 编码)
自动功能:
- ✅ JWT Token 自动生成(Ed25519 签名)
- ✅ Token 缓存(15分钟有效期内重用)
- ✅ Gzip 响应自动解压缩
- ✅ 多端点自动降级(自定义域名 → devapi → geoapi)
相关文档
6. API 接口
6.1 接口清单
| 接口 | 路由 | 方法 | 说明 | 响应格式 |
|---|---|---|---|---|
| 通用对话 | /api/Chat/Chat |
POST | ReAct Agent 模式(详细流程) | SSE |
| MCP 对话 | /api/Chat/ChatWithMcp |
POST | 支持 MCP 工具 + 联网 | SSE |
| 知识库对话 | /api/Chat/KmsChatCompleteAsync |
POST | 基于向量库的 RAG 对话 | SSE |
6.2 通用对话接口(ReAct Agent)
请求:
POST /api/Chat/Chat
Content-Type: application/json
{
"sessionId": 123,
"parentId": null,
"assistantMessageId": 456,
"text": "今天深圳天气怎么样?",
"functionCalls": [],
"networking": true
}
响应事件类型:
| 事件类型 | 说明 | 示例 |
|---|---|---|
thinking |
💭 深度思考(DeepSeek reasoning_content) | "用户询问天气,需要工具..." |
planning |
📋 规划阶段(决定调用哪个工具) | {"name":"search_weather",...} |
action |
⚡ 行动阶段(执行工具) | "执行中..." |
observation |
👁️ 观察阶段(工具结果) | "【深圳天气预报】..." |
iteration |
🔄 迭代信息 | "迭代 2/10" |
chat |
💬 最终回答(逐 token 流式) | "根据最新天气预报[1]..." |
times |
⏱️ 耗时统计(毫秒) | 4850 |
done |
✅ 完成标记 | "done" |
error |
❌ 错误信息 | {"message":"..."} |
响应示例(SSE):
data: {"type":"thinking","data":"用户询问今天深圳天气..."}
data: {"type":"planning","data":{"name":"search_weather","arguments":"..."}}
data: {"type":"action","data":"执行中..."}
data: {"type":"observation","data":"【深圳天气预报】来源: 和风天气\n..."}
data: {"type":"chat","data":"根"}
data: {"type":"chat","data":"据"}
data: {"type":"chat","data":"最"}
data: {"type":"chat","data":"新"}
data: {"type":"times","data":4850}
data: {"type":"done","data":"done"}
6.3 MCP 对话接口
请求:
POST /api/Chat/ChatWithMcp
Content-Type: application/json
{
"message": "查询编号为 WO-2025-001 的生产工单信息",
"enableMcp": true,
"enableNetwork": false,
"searchEngine": "smart",
"siteFilters": null,
"systemPrompt": "你是MES系统助手,可以查询生产数据..."
}
适用场景:
- 需要调用企业内部系统(MES/ERP/数据库)
- 同时需要联网搜索补充信息
- 混合使用内外部工具
6.4 前端集成示例
JavaScript (EventSource)
const eventSource = new EventSource('/api/Chat/Chat');
eventSource.onmessage = (event) => {
const data = JSON.parse(event.data);
switch (data.type) {
case 'thinking':
displayThinking(data.data); // 显示思考过程
break;
case 'chat':
appendChatContent(data.data); // 追加回答内容
break;
case 'times':
showElapsedTime(data.data); // 显示耗时
break;
case 'done':
eventSource.close();
enableInput(); // 启用输入框
break;
case 'error':
showError(data.data);
break;
}
};
eventSource.onerror = (error) => {
console.error('SSE 连接错误:', error);
eventSource.close();
};
Python (requests)
import requests
import json
def chat_stream(message):
url = "http://localhost:5000/api/Chat/Chat"
response = requests.post(url, json={"text": message}, stream=True)
for line in response.iter_lines():
if line and line.startswith(b'data: '):
data = json.loads(line[6:].decode('utf-8'))
if data['type'] == 'thinking':
print(f"💭 {data['data']}")
elif data['type'] == 'chat':
print(data['data'], end='', flush=True)
elif data['type'] == 'done':
print("\n✅ 完成")
break
# 使用
chat_stream("今天深圳天气怎么样?")
7. ReAct Agent 模式
7.1 什么是 ReAct?
ReAct (Reasoning + Acting) 是一种 AI Agent 模式,结合了推理和行动:
Planning (思考)
↓
Action (行动)
↓
Observation (观察)
↓
Planning (再次思考)
↓
... (循环)
↓
Final Answer (最终答案)
7.2 实现细节
ToolCallBehavior 策略
if (useReActLoop)
{
if (enableDeepThinking)
{
// 🔥 手动执行工具,保留完整思考过程
toolBehavior = ToolCallBehavior.EnableKernelFunctions;
}
else
{
// ⚡ 自动执行工具,快速响应
toolBehavior = ToolCallBehavior.AutoInvokeKernelFunctions;
}
}
else
{
// 简单问题:不传 tools,性能最优
toolBehavior = null;
}
循环控制
for (int iteration = 1; iteration <= maxIterations; iteration++)
{
Console.WriteLine($"🔄 迭代 {iteration}/{maxIterations}");
// 1. Planning(非流式调用)
var chatResult = await chat.GetChatMessageContentAsync(history, settings, kernel);
// 2. 捕获深度思考
var reasoning = ExtractReasoningContent(chatResult);
if (!string.IsNullOrEmpty(reasoning))
{
yield return JsonSerializer.Serialize(new { type = "thinking", data = reasoning });
}
// 3. 检测工具调用
if (chatResult.Items.Any(item => item is FunctionCallContent))
{
// 4. Action: 手动执行工具
var functionResult = await ExecuteFunction(functionCall);
// 5. Observation: 添加结果到历史
history.Add(new ChatMessageContent
{
Role = AuthorRole.Tool,
Content = functionResult
});
continue; // 下一轮迭代
}
else
{
// 6. Final Answer: 伪流式输出
foreach (char c in chatResult.Content)
{
yield return JsonSerializer.Serialize(new { type = "chat", data = c.ToString() });
await Task.Delay(3);
}
break;
}
}
7.3 对比:三种模式
| 特性 | 简单模式 | AutoInvoke | ReAct (手动执行) |
|---|---|---|---|
| 工具调用 | ❌ 不支持 | ✅ 自动 | ✅ 手动 |
| 深度思考 | ⚡ 可能有 | ❌ 不可见 | ✅ 完全可见 |
| 迭代循环 | ❌ 无 | ❌ 无 | ✅ 支持 |
| 响应速度 | ⭐⭐⭐⭐⭐ < 1s | ⭐⭐⭐⭐ 4-6s | ⭐⭐⭐ 4-8s |
| 流程透明 | ❌ 无流程 | ⚠️ 部分可见 | ✅ 完全透明 |
| 适用场景 | 简单问答 | 中等复杂 | 复杂任务 |
8. 联网搜索系统
8.1 搜索流程
用户输入: "分析寒武纪2025/10/10股价走势"
↓
QueryClassifier.Classify() → Stock
↓
生成查询变体(移除日期,简化关键词):
[1] 寒武纪 股价
[2] 寒武纪 股票
[3] 寒武纪 行情
[4] 寒武纪 最新消息
↓
SearchAggregator.AggregateAsync()
├─ 智能引擎选择: 百度 + Bing
├─ 并行搜索(5个变体 × 2个引擎)
└─ 合并去重: 18条 → 13条(URL归一化)
↓
ContentExtractor.ExtractBatchAsync()(可选)
└─ 抓取 Top 5 完整网页内容(并发 3)
↓
SemanticReranker.RerankAsync()
├─ 计算相似度分数
├─ 时间新鲜度加权
├─ 内容质量加权
└─ 选出 Top 8 结果
↓
返回搜索结果 JSON
8.2 查询优化示例
股票查询
输入: "分析寒武纪2025/10/10股价走势"
ExtractCoreEntity():
- 移除: "分析|股价|走势|2025/10/10|并给出|策略"
- 结果: "寒武纪"
BuildStockQueryVariants():
[1] 寒武纪 股价
[2] 寒武纪 股票
[3] 寒武纪 行情
[4] 寒武纪 最新消息
推荐站点: eastmoney.com, xueqiu.com, finance.sina.com.cn
时间范围: 最近 30 天
天气查询
输入: "深圳近7天天气预报"
ExtractCoreEntity():
- 移除: "天气|预报|近7天|一周"
- 结果: "深圳"
BuildWeatherQueryVariants():
[1] 深圳天气
[2] 深圳天气预报
[3] 深圳7天天气预报
[4] 深圳一周天气预报
优先: 天气 API (和风/OpenWeatherMap)
降级: 网页搜索 + 全文抓取
8.3 内容提取器
智能识别网页类型并提取关键信息
public enum PageType
{
Weather, // 天气网站 → 提取温度、湿度、风向
News, // 新闻网站 → 提取正文、发布时间
Encyclopedia, // 百科网站 → 提取定义、描述
Forum, // 论坛网站 → 提取问题、回答
Stock, // 股票网站 → 提取价格、涨跌
General // 通用网站 → 智能提取 <main>/<article>
}
内容质量评分:
int score = 50; // 基础分
// 长度适中(+20分)
if (length > 500 && length < 5000) score += 20;
// 包含数字(+10分)- 数据类查询
if (Regex.Matches(content, @"\d+").Count > 5) score += 10;
// 包含日期(+10分)- 新鲜度
if (Regex.IsMatch(content, @"\d{4}[年\-/]\d{1,2}")) score += 10;
// 特定类型(+10分)
if (pageType == PageType.Weather) score += 10;
9. MCP 工具集成
9.1 什么是 MCP?
Model Context Protocol (MCP) 是 Anthropic 推出的企业工具集成标准,允许 AI 模型调用外部工具和服务。
9.2 配置 MCP 服务器
appsettings.json:
{
"BEN_SK": {
"McpConfig": {
"Enabled": true,
"DefaultTimeoutSeconds": 30,
"RetryCount": 3,
"Servers": [
{
"Name": "mes-mcp-server",
"Type": "http",
"Url": "http://localhost:5278/api/mcp",
"Description": "MES系统MCP服务器",
"Enabled": true,
"TimeoutSeconds": 60
}
]
}
}
}
9.3 使用 MCP 工具
Program.cs:
var builder = WebApplication.CreateBuilder(args);
// 注册所有服务(包括 MCP)
builder.Services.AddBenSKAllService(builder.Configuration);
var app = builder.Build();
// 🔥 初始化 MCP 服务(重要!)
app.Services.InitializeMcpServices();
app.Run();
调用示例:
POST /api/Chat/ChatWithMcp
Content-Type: application/json
{
"message": "查询编号为 WO-2025-001 的生产工单信息",
"enableMcp": true,
"enableNetwork": false
}
9.4 MCP 工具清单
根据 MES MCP 服务器,可用的工具包括:
| 工具 | 参数 | 说明 |
|---|---|---|
query_production_orders |
orderId, status, pageSize | 查询生产订单 |
query_material_inventory |
materialCode, materialName | 查询物料库存 |
query_bom_info |
productCode, version | 查询BOM信息 |
generate_production_report |
reportType, startDate, endDate | 生成生产报表 |
9.5 混合使用(MCP + 联网)
POST /api/Chat/ChatWithMcp
Content-Type: application/json
{
"message": "搜索深圳今天的天气情况,并记录到系统日志",
"enableMcp": true, // 启用 MCP 工具
"enableNetwork": true, // 同时启用联网搜索
"searchEngine": "smart"
}
预期流程:
- AI 调用
search_weather获取天气信息 - AI 调用 MCP 工具
create_system_log保存记录 - 返回完整结果
10. 知识库 RAG
10.1 向量数据库配置
使用 Qdrant
docker run -p 6333:6333 qdrant/qdrant
{
"EmbeddingInfo": {
"KmsPoint": "http://localhost:6333",
"VertorType": "qdrant",
"Index": "my-knowledge-base"
}
}
使用 PostgreSQL (pgvector)
docker run -p 5432:5432 -e POSTGRES_PASSWORD=password pgvector/pgvector:pg16
{
"EmbeddingInfo": {
"KmsPoint": "Host=localhost;Port=5432;Database=vectors;Username=postgres;Password=password",
"VertorType": "pgsql",
"Index": "my-knowledge-base"
}
}
10.2 导入文档
POST /api/Knowledge/ImportDocument
Content-Type: multipart/form-data
file: document.pdf
indexName: my-knowledge-base
10.3 知识库对话
POST /api/Chat/KmsChatCompleteAsync
Content-Type: application/json
{
"sessionId": 123,
"text": "生产车间的工单流程是什么?",
"networking": false
}
流程:
用户问题: "生产车间的工单流程是什么?"
↓
向量检索 (SearchMinRelevance: 0.5, SearchLimit: 3)
↓
找到相关文档片段:
[1] 工单管理流程.pdf - 第3页 (相似度: 0.87)
[2] 生产作业指导书.docx - 第2章 (相似度: 0.76)
[3] MES系统操作手册.pdf - 第15页 (相似度: 0.68)
↓
拼接文档内容注入提示词
↓
LLM 生成回答(基于检索到的内容)
↓
返回答案 + 来源标注 [1][2][3]
11. 测试指南
11.1 测试用例(6大类)
1. 股票财经 📈
POST /api/Chat/Chat
Content-Type: application/json
{"text": "分析寒武纪2025/10/10股价走势", "networking": true}
预期:
- 分类: Stock
- 引擎: 百度 + Bing
- 结果: 15-25条(东方财富、雪球、新浪财经)
- 回答: 包含具体数据(价格、涨跌幅)
2. 新闻资讯 📰
POST /api/Chat/Chat
Content-Type: application/json
{"text": "最近一周AI芯片行业新闻", "networking": true}
预期:
- 自动识别为新闻类查询
- 启用全文抓取
- 语义重排优先最新内容
- 回答包含多个来源 [1][2][3]
3. 技术问题 💻
POST /api/Chat/Chat
Content-Type: application/json
{"text": "如何使用C# Semantic Kernel实现RAG", "networking": true}
预期:
- 分类: Technical
- 引擎: 百度 + Bing + Google
- 结果: 技术文档、Stack Overflow、GitHub
4. 学术研究 🎓
POST /api/Chat/Chat
Content-Type: application/json
{"text": "Transformer模型最新研究论文", "networking": true}
预期:
- 引擎: Google + Bing
- 结果: Google Scholar、arXiv
5. 天气查询 ⛅
POST /api/Chat/Chat
Content-Type: application/json
{"text": "今天北京天气", "networking": true}
预期:
- 优先: 和风天气 API(1-2秒)
- 降级: 网页搜索 + 完整内容抓取
- 结果: 包含温度、湿度、风向、降水
6. 通用查询 🔍
POST /api/Chat/Chat
Content-Type: application/json
{"text": "什么是量子计算机", "networking": true}
预期:
- 分类: General
- 引擎: 百度 + Bing
- 结果: 百科、技术博客
11.2 性能基准
| 场景 | 目标时间 | 实际时间 | 状态 |
|---|---|---|---|
| 简单问题("你好") | < 1秒 | 0.5-0.8秒 | ✅ |
| 天气查询(API) | < 10秒 | 4-8秒 | ✅ |
| 天气查询(网页) | < 35秒 | 25-30秒 | ✅ |
| 新闻查询(全文) | < 35秒 | 28-32秒 | ✅ |
| 股票查询 | < 15秒 | 8-12秒 | ✅ |
| 通用搜索 | < 15秒 | 6-10秒 | ✅ |
11.3 HTTP 测试文件
Ben.Examples/ChatService_AgentRAG测试示例.http
包含完整的测试用例和预期输出示例,涵盖:
- 天气查询(完整 ReAct 流程)
- 简单计算(不需要工具)
- 复杂查询(多次迭代)
- 股票分析(深度思考)
- 禁用联网(对比测试)
12. 开发指南
12.1 依赖注入注册
Program.cs:
using Ben.SemanticKernel.Services;
using Ben.SemanticKernel.Services.ChatService;
using Ben.SemanticKernel.Services.Mcp;
var builder = WebApplication.CreateBuilder(args);
// 🔥 一行注册所有核心服务
builder.Services.AddBenSKAllService(builder.Configuration);
// 或分别注册
// builder.Services.AddChatService(builder.Configuration); // 对话服务
// builder.Services.AddGraphRagNetService(builder.Configuration); // 知识图谱
// builder.Services.AddMcpServices(builder.Configuration); // MCP 服务
builder.Services.AddControllers();
builder.Services.AddHttpContextAccessor();
var app = builder.Build();
// 初始化 MCP 服务(可选但推荐)
app.Services.InitializeMcpServices();
app.MapControllers();
app.Run();
12.2 创建自定义 Kernel 工具
1. 创建插件类:
public class CustomToolPlugin
{
private readonly IHttpClientFactory _httpClientFactory;
private readonly ILogger<CustomToolPlugin> _logger;
public CustomToolPlugin(
IHttpClientFactory httpClientFactory,
ILogger<CustomToolPlugin> logger)
{
_httpClientFactory = httpClientFactory;
_logger = logger;
}
[KernelFunction("custom_tool")]
[Description(@"自定义工具的描述,告诉 LLM 何时使用。
用途:具体用途
示例:custom_tool(param='value')")]
public async Task<string> CustomToolAsync(
[Description("参数描述")] string param1,
[Description("可选参数")] string param2 = "default",
CancellationToken cancellationToken = default)
{
try
{
_logger.LogDebug($"🔧 LLM 调用自定义工具 - 参数: {param1}");
// 实现工具逻辑
var result = await DoSomethingAsync(param1, param2, cancellationToken);
_logger.LogDebug($"✅ 工具执行成功");
return result;
}
catch (Exception ex)
{
_logger.LogError(ex, $"工具执行失败: {param1}");
return $"工具执行失败: {ex.Message}";
}
}
}
2. 注册到 DI 容器:
// ChatServiceExtension.cs
services.AddScoped<CustomToolPlugin>();
3. 注册到 Kernel:
// KernelFactory.CustomTools.cs
public static Kernel CreateKernelWithCustomTools(
AIOptions aiOptions,
IServiceProvider serviceProvider)
{
var kernel = CreateKernel(aiOptions);
var customToolPlugin = serviceProvider.GetRequiredService<CustomToolPlugin>();
kernel.Plugins.AddFromObject(customToolPlugin, "CustomTools");
return kernel;
}
12.3 添加新的搜索引擎
扩展 BingScraper.cs:
private string BuildSearchUrl(string query, string engine, ...)
{
return engine.ToLower() switch
{
"baidu" => BuildBaiduUrl(query, ...),
"bing" => BuildBingUrl(query, ...),
"google" => BuildGoogleUrl(query, ...),
"duckduckgo" => BuildDuckDuckGoUrl(query, ...), // 🆕
_ => BuildBaiduUrl(query, ...)
};
}
private string BuildDuckDuckGoUrl(string query, ...)
{
var encodedQuery = Uri.EscapeDataString(query);
return $"https://duckduckgo.com/?q={encodedQuery}&t=h_&ia=web";
}
private List<SearchResultDto> ParseDuckDuckGoResults(string html)
{
// 使用 XPath/CSS 选择器解析
var results = new List<SearchResultDto>();
// ...
return results;
}
12.4 自定义查询分类
编辑 ChatService.cs 的 IsLikelyNeedingTools:
// 添加业务规则
if (Regex.IsMatch(trimmedInput, @"(工单|订单|生产|库存|MES)", RegexOptions.IgnoreCase))
return true; // MES 系统查询必须使用工具
if (trimmedInput.Contains("公司制度") || trimmedInput.Contains("内部文档"))
return false; // 内部文档不需要联网
13. 部署指南
13.1 Docker 容器化
Dockerfile:
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
WORKDIR /app
EXPOSE 80
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src
COPY ["Ben.SemanticKernel/Ben.SemanticKernel.csproj", "Ben.SemanticKernel/"]
COPY ["Ben.Examples/Ben.Examples.csproj", "Ben.Examples/"]
RUN dotnet restore "Ben.Examples/Ben.Examples.csproj"
COPY . .
WORKDIR "/src/Ben.Examples"
RUN dotnet build "Ben.Examples.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "Ben.Examples.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
# 安装 Playwright 浏览器(可选)
RUN apt-get update && apt-get install -y wget \
&& playwright install chromium \
&& apt-get clean
ENTRYPOINT ["dotnet", "Ben.Examples.dll"]
docker-compose.yml:
version: '3.8'
services:
app:
build: .
ports:
- "5000:80"
environment:
- BEN_SK__AIConfig__TextInfo__ApiKey=sk-xxx
- BEN_SK__AIConfig__TextInfo__Model=deepseek-chat
- BEN_SK__AIConfig__TextInfo__BaseUri=https://api.deepseek.com
depends_on:
- qdrant
qdrant:
image: qdrant/qdrant
ports:
- "6333:6333"
volumes:
- qdrant_data:/qdrant/storage
volumes:
qdrant_data:
13.2 生产环境配置
环境变量:
# AI 配置
BEN_SK__AIConfig__TextInfo__ApiKey=sk-xxx
BEN_SK__AIConfig__TextInfo__Model=deepseek-chat
BEN_SK__AIConfig__TextInfo__BaseUri=https://api.deepseek.com
# 天气 API
WeatherApi__QWeather__ApiKey=your-key
# 日志级别
Logging__LogLevel__Default=Information
Logging__LogLevel__Ben.SemanticKernel=Warning
13.3 横向扩展
无状态设计:
- ✅ ChatService 无状态(历史由调用方管理)
- ✅ Kernel 缓存共享(ConcurrentDictionary 线程安全)
- ✅ PlaywrightHelper Singleton(跨请求共享)
负载均衡:
- 使用 Nginx/Traefik 负载均衡
- Session Sticky 不需要(无状态)
- 数据库连接池(向量库)需要配置
14. 常见问题
Q1: 所有查询返回 0 结果?
症状:
⏳ 开始并行搜索...
查询 [1] 返回 0 条结果 ⚠️
查询 [2] 返回 0 条结果 ⚠️
原因 & 解决:
Playwright 未安装
cd Ben.SemanticKernel .\install-playwright.ps1验证安装
playwright --version
Q2: 天气 API 调用失败?
症状 1:401 Unauthorized 或 404 Not Found
⚠️ 天气 API 调用失败: 401 Unauthorized
或
❌ 404 错误:API 端点不存在
解决方案:
检查 JWT 配置是否完整
{ "WeatherApi": { "QWeather": { "KeyId": "你的凭据ID", // ← 必须配置(JWT类型) "ProjectId": "你的项目ID", // ← 必须配置 "PrivateKey": "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----", // ← 必须包含完整PEM格式 "ApiHost": "https://xxx.qweatherapi.com" // ← 强烈推荐配置 } } }验证 JWT Token 是否有效
- 启动应用,查看控制台输出的 JWT Token
- 访问 https://dev.qweather.com/help/jwt
- 粘贴 Token 并点击【验证】
- ✅ 绿色勾 = 配置正确
- ❌ 红色叉 = 需要检查配置
常见错误排查
- ❌ KeyId 使用了 API KEY 类型(应该使用 JWT 类型)
- ❌ PrivateKey 格式不完整(缺少 BEGIN/END 标记)
- ❌ 未配置 ApiHost(每个项目有独立域名)
- ❌ 私钥和公钥不匹配
查看详细日志
[和风天气] ✅ 成功生成 JWT Token(有效期至 ...) [和风天气] ✅ 方式1 请求成功! [和风天气] ✅ 找到城市: 深圳 (ID: 101280601)自动降级机制
- 即使 API 失败,也会自动降级到 OpenWeatherMap
- 如果 OpenWeatherMap 也失败,会降级到网页搜索
详细配置指南:参见 5.3 和风天气 JWT Token 配置指南
Q3: DeepSeek 不显示深度思考?
症状:
- 启用
enableDeepThinking: true - 控制台无
reasoning_content输出
原因 & 解决:
简单问题被优化
- 系统判断为简单问题(如"你好"),不传递 tools
- 这是正常的性能优化
检查模型配置
- 确保使用 DeepSeek 模型
- 确保
Provider设置正确
Q4: Google 搜索失败(中国环境)?
症状:
✗ google 失败: Timeout
解决:
使用 Smart 策略(推荐)
engine: "smart" // 中文查询自动避开 Google强制使用百度
engine: "baidu"
Q5: MCP 工具调用失败?
检查清单:
- MCP 服务器已启动 (
http://localhost:5278/api/mcp) -
appsettings.json配置正确 - 已调用
app.Services.InitializeMcpServices() - 查看日志获取详细错误信息
15. 性能优化
15.1 Kernel 缓存
当前实现:
private static readonly ConcurrentDictionary<string, Lazy<Kernel>> Kernels = new();
// 缓存键:Model + Provider + BaseUri + ApiKey(哈希)
var key = $"{textConfig.Model}_{textConfig.BaseUri}_{textConfig.ApiKey}_{textConfig.Provider}";
return Kernels.GetOrAdd(key, _ => new Lazy<Kernel>(() => CreateNewKernel(...))).Value;
优势:
- ✅ 避免重复创建 Kernel(节省 200-500ms)
- ✅ 线程安全(ConcurrentDictionary)
- ✅ 懒加载(Lazy<T>)
15.2 并行搜索
// 查询变体并行(5个查询同时搜索)
var variantTasks = variants.Select(v => SearchSingleVariantAsync(v, engine));
await Task.WhenAll(variantTasks);
// 引擎并行(多个搜索引擎同时抓取)
var engineTasks = engines.Select(e => SearchEngineAsync(query, e));
await Task.WhenAll(engineTasks);
// 全文抓取并发(最多 3 个网页同时抓取)
var semaphore = new SemaphoreSlim(3);
var contentTasks = urls.Select(async url => {
await semaphore.WaitAsync();
try { return await ExtractAsync(url); }
finally { semaphore.Release(); }
});
15.3 智能降级
| 场景 | 降级策略 |
|---|---|
| 引擎失败 | 使用其他引擎的结果 |
| 语义重排失败 | 使用原始排序 |
| 搜索完全失败 | 基于 AI 知识回答 |
| 天气 API 失败 | 降级网页搜索(全文抓取) |
15.4 资源管理
| 服务 | 生命周期 | 原因 |
|---|---|---|
| PlaywrightHelper | Singleton | 避免 ReAct 多轮迭代中释放 |
| BingScraper | Scoped | 每次请求新实例 |
| ChatService | Scoped | 每次请求新实例 |
| HttpClient | 池化管理 | 使用 IHttpClientFactory |
🎉 总结
Ben.SemanticKernel 提供了一个生产级的 AI Agent 框架:
- ✅ 10分钟快速开始:简单配置即可运行
- ✅ ReAct Agent 模式:完整的 Planning → Action → Observation 循环
- ✅ 深度思考可见:捕获 DeepSeek/OpenAI o1 的 reasoning_content
- ✅ 智能分支选择:简单问题 < 1秒,复杂问题完整流程
- ✅ 企业级搜索:多引擎聚合 + 语义重排 + 全文抓取
- ✅ 专业 API 集成:天气、股票、新闻等垂直领域
- ✅ MCP 工具支持:企业系统无缝集成
- ✅ 知识库 RAG:向量检索 + 知识图谱
- ✅ 开发友好:详细日志、丰富示例、完整文档
现在,开始构建你的智能应用吧! 🚀
📚 相关资源
- GitHub: microsoft/semantic-kernel
- 官方文档: Microsoft Learn - Semantic Kernel
- DeepSeek: api.deepseek.com
- 和风天气: dev.qweather.com
- Playwright: playwright.dev
文档版本: v1.0
更新时间: 2025-10-24
维护者: Ben.SemanticKernel Team
许可证: MIT
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.0
- BouncyCastle.Cryptography (>= 2.6.2)
- Google.Protobuf (>= 3.30.0)
- HtmlAgilityPack (>= 1.12.1)
- itext7 (>= 9.1.0)
- Microsoft.AspNetCore.Http (>= 2.3.0)
- Microsoft.Data.SqlClient (>= 6.1.0-preview1.25120.4)
- Microsoft.Extensions.Http.Polly (>= 9.0.4)
- Microsoft.KernelMemory.AI.Ollama (>= 0.98.250508.3)
- Microsoft.KernelMemory.AI.OpenAI (>= 0.98.250508.3)
- Microsoft.KernelMemory.Core (>= 0.98.250508.3)
- Microsoft.KernelMemory.MemoryDb.Postgres (>= 0.98.250508.3)
- Microsoft.KernelMemory.MemoryDb.Qdrant (>= 0.98.250508.3)
- Microsoft.Playwright (>= 1.52.0)
- Microsoft.Playwright.NUnit (>= 1.52.0)
- Microsoft.SemanticKernel (>= 1.54.0)
- Microsoft.SemanticKernel.Connectors.Ollama (>= 1.54.0-alpha)
- Microsoft.SemanticKernel.Connectors.PgVector (>= 1.54.0-preview)
- Microsoft.SemanticKernel.Connectors.Qdrant (>= 1.54.0-preview)
- Microsoft.SemanticKernel.Connectors.SqliteVec (>= 1.54.0-preview)
- MySql.Data (>= 9.3.0)
- Polly (>= 8.5.2)
- Polly.Extensions.Http (>= 3.0.0)
- pythonnet (>= 3.1.0-preview2024-09-06)
- Selenium.Support (>= 4.31.0)
- Selenium.WebDriver (>= 4.31.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated | |
|---|---|---|---|
| 5.3.1 | 30 | 10/28/2025 | |
| 5.3.0 | 38 | 10/28/2025 | |
| 5.2.29 | 95 | 10/24/2025 | |
| 5.2.28 | 113 | 10/24/2025 | |
| 5.2.27 | 114 | 10/22/2025 | |
| 5.2.26 | 115 | 10/22/2025 | |
| 5.2.25 | 122 | 10/21/2025 | |
| 5.2.24 | 116 | 10/21/2025 | |
| 5.2.23 | 119 | 10/21/2025 | |
| 5.2.22 | 113 | 10/21/2025 | |
| 5.2.21 | 122 | 10/21/2025 | |
| 5.2.20 | 119 | 10/20/2025 | |
| 5.2.19 | 111 | 10/19/2025 | |
| 5.2.18 | 127 | 10/14/2025 | |
| 5.2.17 | 124 | 10/14/2025 | |
| 5.2.16 | 127 | 10/13/2025 | |
| 5.2.15 | 120 | 10/13/2025 | |
| 5.2.13 | 124 | 10/13/2025 | |
| 5.2.12 | 122 | 10/13/2025 | |
| 5.2.11 | 121 | 10/13/2025 | |
| 5.2.10 | 63 | 10/11/2025 | |
| 5.2.9 | 122 | 10/7/2025 | |
| 5.2.8 | 121 | 10/7/2025 | |
| 5.2.7 | 123 | 10/7/2025 | |
| 5.2.6 | 307 | 6/10/2025 | |
| 5.2.5 | 265 | 6/10/2025 | |
| 5.2.4 | 263 | 6/10/2025 | |
| 5.2.3 | 219 | 6/9/2025 | |
| 5.2.2 | 212 | 6/9/2025 | |
| 5.2.1 | 213 | 6/9/2025 | |
| 5.2.0 | 222 | 6/9/2025 | |
| 5.1.9 | 189 | 6/9/2025 | |
| 5.1.8 | 76 | 6/7/2025 | |
| 5.1.7 | 64 | 6/7/2025 | |
| 5.1.6 | 112 | 6/6/2025 | |
| 5.1.5 | 138 | 6/5/2025 | |
| 5.1.4 | 140 | 6/5/2025 | |
| 5.1.3 | 133 | 6/4/2025 | |
| 5.1.2 | 129 | 6/4/2025 | |
| 5.1.1 | 140 | 6/2/2025 | |
| 5.0.1 | 166 | 5/28/2025 | |
| 4.10.3 | 96 | 5/24/2025 | |
| 4.10.2 | 103 | 5/24/2025 | |
| 4.10.1 | 118 | 5/24/2025 | |
| 4.9.15 | 189 | 5/22/2025 | |
| 4.9.14 | 175 | 5/21/2025 | |
| 4.9.13 | 182 | 5/21/2025 | |
| 4.9.12 | 189 | 5/19/2025 | |
| 4.9.11 | 255 | 5/15/2025 | |
| 4.9.10 | 258 | 5/15/2025 | |
| 4.9.9 | 256 | 5/15/2025 | |
| 4.9.8 | 259 | 5/15/2025 | |
| 4.9.7 | 274 | 5/15/2025 | |
| 4.9.6 | 275 | 5/15/2025 | |
| 4.9.5 | 251 | 5/12/2025 | |
| 4.9.4 | 220 | 5/12/2025 | |
| 4.9.3 | 152 | 5/9/2025 | |
| 4.9.2 | 198 | 5/9/2025 | |
| 4.9.1 | 177 | 5/9/2025 | |
| 4.8.5 | 459 | 4/25/2025 | |
| 4.8.4 | 262 | 4/25/2025 | |
| 4.8.3 | 276 | 4/24/2025 | |
| 4.8.2 | 288 | 4/24/2025 | |
| 4.8.1 | 213 | 4/24/2025 | |
| 4.7.10 | 199 | 4/23/2025 | |
| 4.7.9 | 221 | 4/15/2025 | |
| 4.7.8 | 214 | 4/14/2025 | |
| 4.7.7 | 226 | 4/14/2025 | |
| 4.7.6 | 237 | 4/14/2025 | |
| 4.7.5 | 213 | 4/14/2025 | |
| 4.7.4 | 222 | 4/14/2025 | |
| 4.7.3 | 224 | 4/14/2025 | |
| 4.7.2 | 215 | 4/14/2025 | |
| 4.7.1 | 221 | 4/14/2025 | |
| 4.6.1 | 192 | 4/9/2025 | |
| 4.6.0 | 199 | 4/9/2025 | |
| 4.5.9 | 188 | 4/8/2025 | |
| 4.5.8 | 189 | 4/8/2025 | |
| 4.5.7 | 195 | 4/7/2025 | |
| 4.5.6 | 230 | 4/7/2025 | |
| 4.5.5 | 205 | 4/7/2025 | |
| 4.5.4 | 191 | 4/7/2025 | |
| 4.5.3 | 221 | 4/7/2025 | |
| 4.5.2 | 182 | 4/7/2025 | |
| 4.5.1 | 197 | 4/7/2025 | |
| 4.5.0 | 200 | 4/7/2025 | |
| 4.3.0 | 208 | 4/2/2025 | |
| 4.2.1 | 181 | 4/2/2025 | |
| 4.2.0 | 196 | 4/2/2025 | |
| 4.1.0 | 191 | 4/1/2025 | |
| 4.0.0 | 216 | 4/1/2025 | |
| 3.2.1 | 521 | 3/25/2025 | |
| 3.2.0 | 515 | 3/25/2025 | |
| 3.1.0 | 114 | 3/22/2025 | |
| 3.0.0 | 148 | 3/21/2025 | |
| 2.0.0 | 195 | 3/20/2025 | |
| 1.5.0 | 161 | 3/20/2025 | |
| 1.4.0 | 179 | 3/20/2025 | |
| 1.3.0 | 186 | 3/20/2025 | |
| 1.2.0 | 115 | 3/15/2025 | |
| 1.1.0 | 113 | 3/15/2025 | |
| 1.0.0 | 107 | 3/15/2025 |