Ben.SemanticKernel 5.3.1

dotnet add package Ben.SemanticKernel --version 5.3.1
                    
NuGet\Install-Package Ben.SemanticKernel -Version 5.3.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Ben.SemanticKernel" Version="5.3.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Ben.SemanticKernel" Version="5.3.1" />
                    
Directory.Packages.props
<PackageReference Include="Ben.SemanticKernel" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Ben.SemanticKernel --version 5.3.1
                    
#r "nuget: Ben.SemanticKernel, 5.3.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Ben.SemanticKernel@5.3.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Ben.SemanticKernel&version=5.3.1
                    
Install as a Cake Addin
#tool nuget:?package=Ben.SemanticKernel&version=5.3.1
                    
Install as a Cake Tool

Ben.SemanticKernel 完整指南

基于 Microsoft Semantic Kernel 的企业级 AI Agent 框架
版本: v3.0 (ReAct Agent)
更新时间: 2025-10-24
.NET 版本: 8.0


📑 目录

  1. 项目概览
  2. 快速开始
  3. 核心架构
  4. 功能特性
  5. 配置说明
  6. API 接口
  7. ReAct Agent 模式
  8. 联网搜索系统
  9. MCP 工具集成
  10. 知识库 RAG
  11. 测试指南
  12. 开发指南
  13. 部署指南
  14. 常见问题
  15. 性能优化

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:注册和风天气账号
  1. 访问 和风天气开发平台
  2. 注册并登录账号
  3. 进入 控制台 - 项目管理
步骤 2:获取项目 ID
  1. 项目管理页面,查看或创建一个项目
  2. 记录项目 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 凭据
  1. 控制台 → 项目管理中,点击你的项目
  2. 凭据区域点击"添加凭据"按钮
  3. 填写表单:
    • 凭据名称:自定义名称(如"生产环境JWT凭据")
    • 身份认证方式:选择 JSON Web Token
    • 公钥:复制 ed25519-public.pem 的全部内容(包括 BEGIN/END 标记)
  4. 点击"保存"
  5. 记录生成的凭据 ID(10位字符,用作 JWT 的 kid 字段)
    • 示例:ABCDE12345
步骤 5:查看自定义域名(重要)
  1. 在控制台 → 项目管理 → 点击你的项目
  2. 查看Host 配置API 域名
  3. 记录你的专属域名(每个项目都有独立的域名)
    • 示例: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 错误)

常见错误

  1. 使用了 API KEY 类型的凭据ID(不是 JWT 类型)
  2. 私钥格式不完整(缺少 BEGIN/END 标记)
  3. 私钥中的 \n 换行符丢失(JSON 中必须转义)
  4. 未配置 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"
}

预期流程:

  1. AI 调用 search_weather 获取天气信息
  2. AI 调用 MCP 工具 create_system_log 保存记录
  3. 返回完整结果

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 条结果 ⚠️

原因 & 解决:

  1. Playwright 未安装

    cd Ben.SemanticKernel
    .\install-playwright.ps1
    
  2. 验证安装

    playwright --version
    

Q2: 天气 API 调用失败?

症状 1:401 Unauthorized 或 404 Not Found
⚠️ 天气 API 调用失败: 401 Unauthorized
或
❌ 404 错误:API 端点不存在

解决方案:

  1. 检查 JWT 配置是否完整

    {
      "WeatherApi": {
        "QWeather": {
          "KeyId": "你的凭据ID",        // ← 必须配置(JWT类型)
          "ProjectId": "你的项目ID",    // ← 必须配置
          "PrivateKey": "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----",  // ← 必须包含完整PEM格式
          "ApiHost": "https://xxx.qweatherapi.com"  // ← 强烈推荐配置
        }
      }
    }
    
  2. 验证 JWT Token 是否有效

    • 启动应用,查看控制台输出的 JWT Token
    • 访问 https://dev.qweather.com/help/jwt
    • 粘贴 Token 并点击【验证】
    • ✅ 绿色勾 = 配置正确
    • ❌ 红色叉 = 需要检查配置
  3. 常见错误排查

    • ❌ KeyId 使用了 API KEY 类型(应该使用 JWT 类型)
    • ❌ PrivateKey 格式不完整(缺少 BEGIN/END 标记)
    • ❌ 未配置 ApiHost(每个项目有独立域名)
    • ❌ 私钥和公钥不匹配
  4. 查看详细日志

    [和风天气] ✅ 成功生成 JWT Token(有效期至 ...)
    [和风天气] ✅ 方式1 请求成功!
    [和风天气] ✅ 找到城市: 深圳 (ID: 101280601)
    
  5. 自动降级机制

    • 即使 API 失败,也会自动降级到 OpenWeatherMap
    • 如果 OpenWeatherMap 也失败,会降级到网页搜索

详细配置指南:参见 5.3 和风天气 JWT Token 配置指南

Q3: DeepSeek 不显示深度思考?

症状:

  • 启用 enableDeepThinking: true
  • 控制台无 reasoning_content 输出

原因 & 解决:

  1. 简单问题被优化

    • 系统判断为简单问题(如"你好"),不传递 tools
    • 这是正常的性能优化
  2. 检查模型配置

    • 确保使用 DeepSeek 模型
    • 确保 Provider 设置正确

Q4: Google 搜索失败(中国环境)?

症状:

✗ google 失败: Timeout

解决:

  1. 使用 Smart 策略(推荐)

    engine: "smart"  // 中文查询自动避开 Google
    
  2. 强制使用百度

    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:向量检索 + 知识图谱
  • 开发友好:详细日志、丰富示例、完整文档

现在,开始构建你的智能应用吧! 🚀


📚 相关资源


文档版本: v1.0
更新时间: 2025-10-24
维护者: Ben.SemanticKernel Team
许可证: MIT

Product 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

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.4 is deprecated because it is no longer maintained.
4.8.3 276 4/24/2025 4.8.3 is deprecated because it is no longer maintained and has critical bugs.
4.8.2 288 4/24/2025 4.8.2 is deprecated because it is no longer maintained and has critical bugs.
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