BotSharp 入门教程-第03章-快速启动

克隆 BotSharp 项目

学习目标

完成本节学习后,你将能够:

  • 使用 Git 成功克隆 BotSharp 项目

  • 选择合适的项目存放位置

  • 解决常见的克隆问题

前置知识

  • 已安装 Git(参考第 01 章)

  • 了解基本的命令行操作

  • 有稳定的网络连接

为什么要克隆项目?

克隆项目就像是把 GitHub 上的代码"复制"到你的电脑上。想象一下,GitHub 就像一个图书馆,克隆就是把你需要的书借回家。这样你就可以在本地查看代码、运行项目、进行修改了。

第一步:选择项目存放位置

在克隆项目之前,我们需要选择一个合适的位置来存放代码。

推荐的存放位置

Windows 系统:

复制代码
C:\Projects\BotSharp
或
D:\Code\BotSharp

Mac/Linux 系统:

复制代码
~/Projects/BotSharp
或
~/Code/BotSharp

选择建议

  1. 避免中文路径:路径中不要包含中文字符,可能会导致一些工具出错

  2. 避免空格:路径中尽量不要有空格

  3. 不要太深:路径层级不要太深,方便访问

  4. 有足够空间:确保磁盘有至少 2GB 的可用空间

创建项目目录

打开命令行工具(Windows 用 PowerShell 或 CMD,Mac/Linux 用 Terminal),执行以下命令:

Windows:

复制代码
# 创建项目目录
mkdir C:\Projects
cd C:\Projects

Mac/Linux:

复制代码
# 创建项目目录
mkdir -p ~/Projects
cd ~/Projects

第二步:克隆 BotSharp 主项目

现在我们开始克隆 BotSharp 的主项目。

克隆命令

复制代码
git clone https://github.com/dotnetcore/BotSharp.git

命令说明

  • git clone:Git 的克隆命令

  • https://github.com/dotnetcore/BotSharp.git:BotSharp 项目的 GitHub 地址

执行过程

执行命令后,你会看到类似这样的输出:

复制代码
Cloning into 'BotSharp'...
remote: Enumerating objects: 15234, done.
remote: Counting objects: 100% (1523/1523), done.
remote: Compressing objects: 100% (856/856), done.
remote: Total 15234 (delta 789), reused 1234 (delta 567), pack-reused 13711
Receiving objects: 100% (15234/15234), 12.34 MiB | 2.56 MiB/s, done.
Resolving deltas: 100% (9876/9876), done.

这个过程可能需要几分钟,取决于你的网络速度。

验证克隆成功

克隆完成后,进入项目目录:

复制代码
cd BotSharp

查看项目文件:

Windows:

复制代码
dir

Mac/Linux:

复制代码
ls -la

你应该能看到以下主要文件和文件夹:

  • src/ - 源代码目录

  • tests/ - 测试代码目录

  • docs/ - 文档目录

  • README.md - 项目说明文件

  • BotSharp.sln - Visual Studio 解决方案文件

第三步:克隆 UI 项目(可选)

BotSharp 有一个独立的 UI 项目,如果你想使用图形界面,可以克隆它。

返回上级目录

复制代码
cd ..

克隆 UI 项目

复制代码
git clone https://github.com/SciSharp/BotSharp-UI.git

项目结构

克隆完成后,你的项目目录结构应该是这样的:

复制代码
Projects/
├── BotSharp/          # 后端项目
└── BotSharp-UI/       # 前端项目(可选)

常见克隆问题及解决方案

问题 1:网络连接超时

错误信息:

复制代码
fatal: unable to access 'https://github.com/...': Failed to connect to github.com

解决方案:

  1. 检查网络连接:确保你的电脑能访问 GitHub

  2. 使用代理 (如果你有):

    复制代码
    git config --global http.proxy http://127.0.0.1:7890
    git config --global https.proxy http://127.0.0.1:7890
  3. 使用 Gitee 镜像 (国内用户推荐):

    复制代码
    git clone https://gitee.com/dotnetchina/BotSharp.git

问题 2:克隆速度很慢

解决方案:

  1. 使用浅克隆(只克隆最新版本,不包含完整历史):

    复制代码
    git clone --depth 1 https://github.com/dotnetcore/BotSharp.git
  2. 使用 SSH 方式(需要先配置 SSH 密钥):

    复制代码
    git clone git@github.com:dotnetcore/BotSharp.git

问题 3:权限被拒绝

错误信息:

复制代码
Permission denied (publickey)

解决方案:

这通常发生在使用 SSH 方式克隆时。改用 HTTPS 方式:

复制代码
git clone https://github.com/dotnetcore/BotSharp.git

问题 4:磁盘空间不足

错误信息:

复制代码
error: unable to write file: No space left on device

解决方案:

  1. 清理磁盘空间

  2. 选择另一个有足够空间的磁盘

  3. 使用浅克隆减少空间占用

问题 5:文件名太长(Windows)

错误信息:

复制代码
error: unable to create file: Filename too long

解决方案:

启用 Windows 长路径支持:

复制代码
git config --system core.longpaths true

验证克隆结果

检查项目完整性

进入 BotSharp 目录,检查关键文件是否存在:

复制代码
cd BotSharp

检查解决方案文件:

复制代码
# Windows
dir BotSharp.sln

# Mac/Linux
ls -l BotSharp.sln

检查源代码目录:

复制代码
# Windows
dir src

# Mac/Linux
ls -l src

查看项目信息

查看当前分支:

复制代码
git branch

应该显示:

复制代码
* master

查看最新提交:

复制代码
git log -1

会显示最新的提交信息,包括作者、日期和提交说明。

小结

恭喜你!你已经成功克隆了 BotSharp 项目。让我们回顾一下本节的重点:

选择合适的项目位置 :避免中文路径和空格 ✅ 使用 Git 克隆命令git clone 加上项目地址 ✅ 验证克隆成功 :检查关键文件和目录 ✅ 解决常见问题:网络、权限、空间等问题

下一步

现在你已经有了 BotSharp 的代码,接下来我们将学习如何运行 PizzaBot 示例项目。

常见问题

Q: 我需要 GitHub 账号才能克隆项目吗? A: 不需要。克隆公开项目不需要 GitHub 账号,只有在你想要贡献代码时才需要。

Q: 克隆后的代码可以修改吗? A: 可以!克隆到本地的代码完全属于你,你可以随意修改和实验。

Q: 如何更新到最新版本? A: 在项目目录中执行 git pull 命令即可获取最新更新。

Q: 克隆失败了怎么办? A: 首先检查网络连接,然后尝试使用浅克隆或 Gitee 镜像。如果还是不行,可以直接从 GitHub 下载 ZIP 文件。

Q: 可以直接下载 ZIP 而不用 Git 吗? A: 可以,但不推荐。使用 Git 克隆可以方便地更新代码和查看历史记录。

练习

  1. 在你的电脑上选择一个合适的位置,克隆 BotSharp 项目

  2. 验证克隆是否成功,检查关键文件是否存在

  3. 尝试查看项目的提交历史(使用 git log 命令)

  4. (可选)克隆 BotSharp-UI 项目

完成这些练习后,你就可以继续学习如何运行项目了!

运行 PizzaBot 示例

学习目标

完成本节学习后,你将能够:

  • 成功启动 BotSharp 项目

  • 运行 PizzaBot 示例

  • 理解启动参数的含义

  • 识别启动成功的标志

  • 解决常见的启动错误

前置知识

  • 已完成环境准备(第 01 章)

  • 已克隆 BotSharp 项目(上一节)

  • 已安装 .NET SDK 8.0 或更高版本

什么是 PizzaBot?

PizzaBot 是 BotSharp 提供的一个示例项目,就像学习做菜时的"第一道菜"。它是一个简单的披萨订购机器人,可以帮助你:

  • 理解 BotSharp 的基本工作流程

  • 学习如何配置 Agent

  • 体验对话式 AI 的交互

通过运行 PizzaBot,你可以快速看到 BotSharp 的实际效果,而不需要从零开始编写代码。

第一步:打开项目

使用 Visual Studio(推荐)

  1. 启动 Visual Studio

  2. 打开解决方案

    • 点击"文件" → "打开" → "项目/解决方案"

    • 导航到你克隆的 BotSharp 目录

    • 选择 BotSharp.sln 文件

    • 点击"打开"

  3. 等待项目加载

    • Visual Studio 会自动还原 NuGet 包

    • 这个过程可能需要几分钟

    • 你会在底部看到"正在还原..."的提示

使用 VS Code

  1. 启动 VS Code

  2. 打开文件夹

    • 点击"文件" → "打开文件夹"

    • 选择 BotSharp 目录

    • 点击"选择文件夹"

  3. 安装推荐扩展

    • VS Code 会提示安装 C# 扩展

    • 点击"安装"按钮

第二步:配置 LLM 提供商

在运行 PizzaBot 之前,我们需要配置一个 LLM(大语言模型)提供商。BotSharp 支持多种提供商,这里我们以 OpenAI 为例。

找到配置文件

配置文件位于:

复制代码
src/WebStarter/appsettings.json

配置 OpenAI

打开 appsettings.json,找到 LLM 配置部分:

复制代码
{
  "LlmProviders": [
    {
      "Provider": "openai",
      "Models": [
        {
          "Name": "gpt-4",
          "Type": "chat",
          "ApiKey": "your-api-key-here"
        }
      ]
    }
  ]
}

替换 API Key

your-api-key-here 替换为你的实际 API Key:

复制代码
"ApiKey": "sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

其他 LLM 提供商

如果你没有 OpenAI API Key,也可以使用其他提供商:

Azure OpenAI:

复制代码
{
  "Provider": "azure-openai",
  "Models": [
    {
      "Name": "gpt-4",
      "Type": "chat",
      "Endpoint": "https://your-resource.openai.azure.com/",
      "ApiKey": "your-azure-key"
    }
  ]
}

本地模型(LLamaSharp):

复制代码
{
  "Provider": "llama-sharp",
  "Models": [
    {
      "Name": "llama-2-7b",
      "Type": "chat",
      "ModelPath": "path/to/your/model.gguf"
    }
  ]
}

第三步:启动项目

方法 1:使用 Visual Studio

  1. 设置启动项目

    • 在解决方案资源管理器中

    • 右键点击 WebStarter 项目

    • 选择"设为启动项目"

  2. 选择启动配置

    • 在顶部工具栏找到启动按钮旁边的下拉菜单

    • 选择 httphttps

  3. 点击启动按钮

    • 点击绿色的"▶ WebStarter"按钮

    • 或按 F5

方法 2:使用命令行

打开命令行工具,进入 WebStarter 目录:

复制代码
cd src/WebStarter

运行项目:

复制代码
dotnet run

启动参数说明

你可以使用不同的参数来启动项目:

指定端口:

复制代码
dotnet run --urls "http://localhost:5000"

使用 HTTPS:

复制代码
dotnet run --urls "https://localhost:5001"

同时监听多个端口:

复制代码
dotnet run --urls "http://localhost:5000;https://localhost:5001"

指定环境:

复制代码
dotnet run --environment Development

第四步:验证启动成功

启动成功的标志

当项目成功启动后,你会在控制台看到类似这样的输出:

复制代码
info: Microsoft.Hosting.Lifetime[14]
      Now listening on: http://localhost:5000
info: Microsoft.Hosting.Lifetime[14]
      Now listening on: https://localhost:5001
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
      Content root path: C:\Projects\BotSharp\src\WebStarter

关键信息:

  • Now listening on: http://localhost:5000 - 服务正在监听

  • Application started - 应用已启动

  • ✅ 没有红色的错误信息

访问 Swagger UI

打开浏览器,访问:

复制代码
http://localhost:5000/swagger

或(如果使用 HTTPS):

复制代码
https://localhost:5001/swagger

你应该能看到 BotSharp 的 API 文档页面,这是一个交互式的 API 测试界面。

检查 PizzaBot Agent

在 Swagger UI 中:

  1. 找到 Agent 相关的 API

  2. 展开 GET /api/agent 接口

  3. 点击"Try it out"按钮

  4. 点击"Execute"按钮

你应该能在响应中看到 PizzaBot Agent 的信息。

常见启动错误及解决方案

错误 1:端口被占用

错误信息:

复制代码
Failed to bind to address http://127.0.0.1:5000: address already in use.

原因: 端口 5000 已经被其他程序占用。

解决方案:

  1. 更换端口:

    复制代码
    dotnet run --urls "http://localhost:5005"
  2. 找到并关闭占用端口的程序:

    Windows:

    复制代码
    # 查找占用端口的进程
    netstat -ano | findstr :5000
    
    # 结束进程(替换 PID 为实际的进程 ID)
    taskkill /PID <PID> /F

    Mac/Linux:

    复制代码
    # 查找占用端口的进程
    lsof -i :5000
    
    # 结束进程
    kill -9 <PID>

错误 2:.NET SDK 版本不匹配

错误信息:

复制代码
The current .NET SDK does not support targeting .NET 8.0.

原因: 你的 .NET SDK 版本太低。

解决方案:

  1. 检查当前版本:

    复制代码
    dotnet --version
  2. 下载并安装 .NET 8.0 SDK:

错误 3:NuGet 包还原失败

错误信息:

复制代码
error NU1101: Unable to find package...

原因: 无法从 NuGet 服务器下载依赖包。

解决方案:

  1. 清理并重新还原:

    复制代码
    dotnet clean
    dotnet restore
  2. 检查 NuGet 源:

    复制代码
    dotnet nuget list source
  3. 添加官方 NuGet 源:

    复制代码
    dotnet nuget add source https://api.nuget.org/v3/index.json -n nuget.org

错误 4:缺少 API Key

错误信息:

复制代码
OpenAI API key is not configured

原因: 没有配置 LLM 提供商的 API Key。

解决方案:

  1. 打开 appsettings.json

  2. 添加你的 API Key(参考第二步)

  3. 保存文件并重新启动项目

错误 5:数据库连接失败

错误信息:

复制代码
Unable to connect to database

原因: 如果配置了外部数据库(如 MongoDB),但数据库服务未启动。

解决方案:

  1. 使用内存存储(开发环境推荐):

    appsettings.json 中:

    复制代码
    {
      "Database": {
        "Provider": "InMemory"
      }
    }
  2. 启动数据库服务:

    如果使用 MongoDB:

    复制代码
    # Windows
    net start MongoDB
    
    # Mac/Linux
    sudo systemctl start mongod

错误 6:编译错误

错误信息:

复制代码
Build FAILED.

原因: 代码有语法错误或依赖问题。

解决方案:

  1. 查看详细错误信息:

    复制代码
    dotnet build
  2. 清理并重新构建:

    复制代码
    dotnet clean
    dotnet build
  3. 检查是否有未提交的更改:

    复制代码
    git status
  4. 重置到最新版本:

    复制代码
    git reset --hard origin/master

启动后的基本操作

查看日志

启动后,控制台会持续输出日志信息:

复制代码
info: BotSharp.Core[0]
      Loading plugins...
info: BotSharp.Core[0]
      Plugin loaded: PizzaBotPlugin
info: BotSharp.Core[0]
      Agent initialized: PizzaBot

这些日志可以帮助你了解系统的运行状态。

停止服务

在 Visual Studio 中:

  • 点击红色的"停止"按钮

  • 或按 Shift + F5

在命令行中:

  • Ctrl + C

重新启动

修改配置文件后,需要重新启动服务才能生效:

  1. 停止当前运行的服务

  2. 保存配置文件

  3. 重新启动服务

性能优化建议

开发环境优化

  1. 使用 Development 环境:

    复制代码
    dotnet run --environment Development

    这会启用详细的错误信息和热重载功能。

  2. 启用热重载:

    复制代码
    dotnet watch run

    修改代码后会自动重新编译和启动。

  3. 减少日志输出:

    appsettings.Development.json 中:

    复制代码
    {
      "Logging": {
        "LogLevel": {
          "Default": "Information",
          "Microsoft": "Warning"
        }
      }
    }

小结

恭喜你!你已经成功启动了 BotSharp 项目和 PizzaBot 示例。让我们回顾一下本节的重点:

打开项目 :使用 Visual Studio 或 VS Code ✅ 配置 LLM :设置 API Key ✅ 启动项目 :使用 IDE 或命令行 ✅ 验证成功 :检查控制台输出和 Swagger UI ✅ 解决错误:处理常见的启动问题

下一步

现在项目已经成功运行,接下来我们将学习如何测试 PizzaBot 的功能,包括创建对话和发送消息。

常见问题

Q: 启动需要多长时间? A: 首次启动可能需要 1-2 分钟(需要还原 NuGet 包),之后的启动通常在 10-30 秒内完成。

Q: 可以同时运行多个实例吗? A: 可以,但需要使用不同的端口。

Q: 修改代码后需要重新启动吗? A: 是的,除非使用 dotnet watch run 启用热重载。

Q: 如何查看更详细的日志? A: 在 appsettings.json 中将日志级别设置为 DebugTrace

Q: 启动失败了怎么办? A: 首先查看控制台的错误信息,然后参考本节的"常见启动错误"部分。如果还是无法解决,可以在社区寻求帮助。

练习

  1. 使用 Visual Studio 启动 BotSharp 项目

  2. 访问 Swagger UI,浏览可用的 API

  3. 尝试使用不同的端口启动项目

  4. 故意制造一个错误(如删除 API Key),观察错误信息

  5. 使用 dotnet watch run 启动项目,修改一个文件,观察热重载效果

完成这些练习后,你就可以继续学习如何测试 PizzaBot 的功能了!

测试 PizzaBot 功能

学习目标

完成本节学习后,你将能够:

  • 使用 Postman 测试 BotSharp API

  • 使用 curl 命令测试 API

  • 创建对话并发送消息

  • 理解 API 的请求和响应格式

  • 验证 PizzaBot 的功能是否正常

前置知识

  • 已成功启动 BotSharp 项目(上一节)

  • 了解基本的 HTTP 请求概念

  • 了解 JSON 数据格式

什么是 API 测试?

API 测试就像是给机器人发送指令,然后检查它的回应是否正确。想象一下,你在餐厅点餐:

  • 你说:"我要一份披萨"(发送请求)

  • 服务员回答:"好的,您要什么口味?"(返回响应)

API 测试就是这样一个过程,只不过是通过代码来完成的。

测试工具介绍

Postman(推荐新手使用)

Postman 是一个图形化的 API 测试工具,就像一个友好的界面,让你不用写代码就能测试 API。

优点:

  • 界面友好,容易上手

  • 可以保存请求历史

  • 支持导入导出

  • 有详细的响应展示

下载地址: https://www.postman.com/downloads/

curl(命令行工具)

curl 是一个命令行工具,适合喜欢使用命令行的开发者。

优点:

  • 无需安装额外软件

  • 可以写成脚本自动化

  • 跨平台支持

方法 1:使用 Postman 测试

第一步:导入 BotSharp 集合

BotSharp 提供了一个 Postman 集合,包含了所有常用的 API 请求。

  1. 打开 Postman

  2. 导入集合

    • 点击左上角的"Import"按钮

    • 选择"Link"标签

    • 输入集合地址:

      复制代码
      https://www.postman.com/orange-flare-634868/workspace/botsharp
    • 点击"Continue"

    • 点击"Import"

  3. 查看集合

    • 在左侧边栏找到"BotSharp"集合

    • 展开可以看到所有的 API 请求

第二步:配置环境变量

  1. 创建环境

    • 点击右上角的"Environments"

    • 点击"+"创建新环境

    • 命名为"BotSharp Local"

  2. 添加变量

    添加以下变量:

    变量名 初始值 当前值
    baseUrl http://localhost:5000 http://localhost:5000
    conversationId
    agentId
  3. 保存环境

    • 点击"Save"按钮

    • 在右上角选择"BotSharp Local"环境

第三步:获取 Agent 列表

  1. 选择请求

    • 在集合中找到"Get Agents"请求

    • 点击打开

  2. 发送请求

    • 点击"Send"按钮
  3. 查看响应

    你应该能看到类似这样的响应:

    复制代码
    {
      "items": [
        {
          "id": "01234567-89ab-cdef-0123-456789abcdef",
          "name": "PizzaBot",
          "description": "A pizza ordering assistant",
          "isPublic": true,
          "disabled": false
        }
      ],
      "count": 1
    }
  4. 保存 Agent ID

    • 复制 PizzaBot 的 id

    • 在环境变量中设置 agentId 为这个值

第四步:创建对话

  1. 选择请求

    • 找到"Create Conversation"请求
  2. 修改请求体

    请求体应该是这样的:

    复制代码
    {
      "agentId": "{{agentId}}",
      "channel": "postman",
      "userId": "test-user"
    }
  3. 发送请求

    • 点击"Send"按钮
  4. 查看响应

    响应示例:

    复制代码
    {
      "conversationId": "conv-12345678-1234-1234-1234-123456789abc",
      "agentId": "01234567-89ab-cdef-0123-456789abcdef",
      "status": "active",
      "createdAt": "2024-01-09T10:30:00Z"
    }
  5. 保存 Conversation ID

    • 复制 conversationId 的值

    • 在环境变量中设置 conversationId 为这个值

第五步:发送消息

  1. 选择请求

    • 找到"Send Message"请求
  2. 修改请求体

    复制代码
    {
      "conversationId": "{{conversationId}}",
      "text": "我想订一份披萨",
      "postback": null
    }
  3. 发送请求

    • 点击"Send"按钮
  4. 查看响应

    PizzaBot 应该会回复类似这样的消息:

    复制代码
    {
      "conversationId": "conv-12345678-1234-1234-1234-123456789abc",
      "messageId": "msg-87654321-4321-4321-4321-210987654321",
      "text": "好的!我可以帮您订购披萨。请问您想要什么尺寸的披萨?我们有小号、中号和大号。",
      "richContent": null,
      "createdAt": "2024-01-09T10:31:00Z"
    }

第六步:继续对话

继续发送消息来完成订单:

消息 2:

复制代码
{
  "conversationId": "{{conversationId}}",
  "text": "大号的"
}

预期响应:

复制代码
太好了!大号披萨。请问您想要什么口味?我们有:
- 玛格丽特(经典番茄芝士)
- 意大利辣香肠
- 夏威夷(菠萝火腿)
- 四季披萨

消息 3:

复制代码
{
  "conversationId": "{{conversationId}}",
  "text": "意大利辣香肠"
}

预期响应:

复制代码
好的!一份大号意大利辣香肠披萨。请问需要添加额外的配料吗?

方法 2:使用 curl 测试

第一步:获取 Agent 列表

打开命令行工具,执行:

复制代码
curl -X GET "http://localhost:5000/api/agent" \
  -H "accept: application/json"

Windows PowerShell:

复制代码
curl.exe -X GET "http://localhost:5000/api/agent" `
  -H "accept: application/json"

预期响应:

复制代码
{
  "items": [
    {
      "id": "01234567-89ab-cdef-0123-456789abcdef",
      "name": "PizzaBot",
      "description": "A pizza ordering assistant"
    }
  ]
}

第二步:创建对话

复制代码
curl -X POST "http://localhost:5000/api/conversation" \
  -H "accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
    "agentId": "01234567-89ab-cdef-0123-456789abcdef",
    "channel": "curl",
    "userId": "test-user"
  }'

Windows PowerShell:

复制代码
$body = @{
    agentId = "01234567-89ab-cdef-0123-456789abcdef"
    channel = "curl"
    userId = "test-user"
} | ConvertTo-Json

Invoke-RestMethod -Uri "http://localhost:5000/api/conversation" `
  -Method Post `
  -ContentType "application/json" `
  -Body $body

保存返回的 conversationId,后续步骤会用到。

第三步:发送消息

复制代码
curl -X POST "http://localhost:5000/api/conversation/message" \
  -H "accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
    "conversationId": "conv-12345678-1234-1234-1234-123456789abc",
    "text": "我想订一份披萨"
  }'

Windows PowerShell:

复制代码
$body = @{
    conversationId = "conv-12345678-1234-1234-1234-123456789abc"
    text = "我想订一份披萨"
} | ConvertTo-Json

Invoke-RestMethod -Uri "http://localhost:5000/api/conversation/message" `
  -Method Post `
  -ContentType "application/json" `
  -Body $body

方法 3:使用 Swagger UI 测试

Swagger UI 是最简单的测试方法,不需要安装任何额外工具。

第一步:打开 Swagger UI

在浏览器中访问:

复制代码
http://localhost:5000/swagger

第二步:测试 Get Agents API

  1. 找到 Agent 部分

    • 滚动页面找到"Agent"标签

    • 点击展开

  2. 选择 GET /api/agent

    • 点击展开这个接口
  3. 执行请求

    • 点击"Try it out"按钮

    • 点击"Execute"按钮

  4. 查看响应

    • 在下方的"Responses"部分查看结果

    • 复制 PizzaBot 的 ID

第三步:创建对话

  1. 找到 Conversation 部分

    • 找到"Conversation"标签
  2. 选择 POST /api/conversation

    • 点击展开
  3. 填写请求体

    • 点击"Try it out"

    • 在请求体中填写:

      复制代码
      {
        "agentId": "你复制的Agent ID",
        "channel": "swagger",
        "userId": "test-user"
      }
  4. 执行请求

    • 点击"Execute"

    • 复制返回的 conversationId

第四步:发送消息

  1. 选择 POST /api/conversation/message

  2. 填写请求体

    复制代码
    {
      "conversationId": "你复制的Conversation ID",
      "text": "我想订一份披萨"
    }
  3. 执行请求

    • 点击"Execute"

    • 查看 PizzaBot 的回复

完整的测试场景

场景 1:成功订购披萨

步骤:

  1. 创建对话

  2. 发送:"我想订一份披萨"

  3. 发送:"大号的"

  4. 发送:"意大利辣香肠"

  5. 发送:"不需要额外配料"

  6. 发送:"送到XX地址"

  7. 发送:"确认订单"

预期结果:

  • 每一步都能收到合理的回复

  • 最后能成功创建订单

场景 2:取消订单

步骤:

  1. 创建对话

  2. 发送:"我想订一份披萨"

  3. 发送:"取消订单"

预期结果:

  • 系统确认取消

  • 对话可以重新开始

场景 3:查询菜单

步骤:

  1. 创建对话

  2. 发送:"你们有什么披萨?"

预期结果:

  • 返回完整的披萨菜单

  • 包含价格和描述

验证测试结果

成功的标志

API 响应正常

  • HTTP 状态码为 200

  • 返回了预期的 JSON 数据

对话流程顺畅

  • 每条消息都能收到回复

  • 回复内容符合上下文

数据格式正确

  • conversationId 格式正确

  • messageId 格式正确

  • 时间戳格式正确

失败的标志

HTTP 错误

  • 400: 请求参数错误

  • 401: 未授权

  • 404: 资源不存在

  • 500: 服务器内部错误

响应异常

  • 返回空数据

  • 返回错误消息

  • 响应时间过长(超过 30 秒)

常见测试问题

问题 1:401 Unauthorized

原因: API 需要认证,但没有提供认证信息。

解决方案: 检查 appsettings.json 中的认证配置,或在请求头中添加认证信息。

问题 2:404 Not Found

原因:

  • API 路径错误

  • Agent 或 Conversation 不存在

解决方案:

  • 检查 URL 是否正确

  • 确认 Agent ID 和 Conversation ID 是否有效

问题 3:500 Internal Server Error

原因: 服务器内部错误,可能是:

  • LLM API Key 无效

  • 数据库连接失败

  • 代码逻辑错误

解决方案:

  • 查看服务器控制台的错误日志

  • 检查 LLM 配置

  • 检查数据库连接

问题 4:响应时间过长

原因:

  • LLM 响应慢

  • 网络延迟

  • 服务器负载高

解决方案:

  • 使用更快的 LLM 模型

  • 检查网络连接

  • 优化服务器配置

问题 5:对话上下文丢失

原因:

  • 使用了错误的 conversationId

  • 对话已过期

  • 使用了内存存储且服务重启

解决方案:

  • 确认使用正确的 conversationId

  • 创建新的对话

  • 使用持久化存储(如 MongoDB)

测试最佳实践

1. 保存测试数据

将常用的 ID 保存到文件中:

复制代码
{
  "agentId": "01234567-89ab-cdef-0123-456789abcdef",
  "conversationId": "conv-12345678-1234-1234-1234-123456789abc",
  "baseUrl": "http://localhost:5000"
}

2. 使用环境变量

在 Postman 中使用环境变量,方便切换不同环境(开发、测试、生产)。

3. 编写测试脚本

在 Postman 中可以编写测试脚本自动验证响应:

复制代码
// 验证状态码
pm.test("Status code is 200", function () {
    pm.response.to.have.status(200);
});

// 验证响应包含必要字段
pm.test("Response has conversationId", function () {
    var jsonData = pm.response.json();
    pm.expect(jsonData).to.have.property('conversationId');
});

// 保存 conversationId 到环境变量
var jsonData = pm.response.json();
pm.environment.set("conversationId", jsonData.conversationId);

4. 记录测试结果

创建测试记录表格:

测试场景 预期结果 实际结果 状态 备注
创建对话 返回 conversationId ✅ 成功 通过 -
发送消息 收到回复 ✅ 成功 通过 -
订购披萨 完成订单 ✅ 成功 通过 -

小结

恭喜你!你已经学会了如何测试 BotSharp 的 API。让我们回顾一下本节的重点:

三种测试方法 :Postman、curl、Swagger UI ✅ 完整测试流程 :获取 Agent → 创建对话 → 发送消息 ✅ 理解请求响应 :知道如何构造请求和解析响应 ✅ 解决常见问题 :处理各种测试错误 ✅ 测试最佳实践:保存数据、使用变量、编写脚本

下一步

现在你已经能够成功测试 PizzaBot 的功能,接下来我们将学习如何调试项目,包括查看日志和排查错误。

常见问题

Q: 哪种测试方法最好? A: 对于新手,推荐使用 Swagger UI 或 Postman。对于自动化测试,推荐使用 curl 或编程语言的 HTTP 客户端。

Q: 测试时需要重启服务吗? A: 通常不需要。只有修改了配置文件或代码时才需要重启。

Q: 如何测试流式响应? A: 流式响应需要使用支持 Server-Sent Events (SSE) 的客户端,Postman 和 curl 都支持。

Q: 可以同时创建多个对话吗? A: 可以,每个对话都有独立的 conversationId。

Q: 测试数据会保存吗? A: 如果使用内存存储,重启后数据会丢失。使用 MongoDB 等持久化存储可以保留数据。

练习

  1. 使用 Postman 完成一次完整的披萨订购流程

  2. 使用 curl 命令创建对话并发送消息

  3. 在 Swagger UI 中测试所有 Agent 相关的 API

  4. 尝试发送一些"刁难"的消息,看 PizzaBot 如何回应

  5. 记录一次完整的测试过程,包括请求和响应

完成这些练习后,你就可以继续学习如何调试项目了!

调试 BotSharp 项目

学习目标

完成本节学习后,你将能够:

  • 使用 Visual Studio 进行断点调试

  • 使用 VS Code 进行调试

  • 查看和分析日志信息

  • 排查常见的运行时错误

  • 使用调试工具定位问题

  • 理解调试的基本流程

前置知识

  • 已成功运行 BotSharp 项目

  • 了解基本的编程概念

  • 熟悉 Visual Studio 或 VS Code

什么是调试?

调试就像是"侦探工作",当程序出现问题时,我们需要找出问题在哪里。想象一下:

  • 你的汽车突然不能启动了(程序出错)

  • 你需要检查电池、油箱、发动机(查看日志、设置断点)

  • 找到问题后修复它(修改代码)

调试是每个开发者必备的技能,它能帮助你:

  • 理解代码的执行流程

  • 找出程序错误的原因

  • 验证代码是否按预期工作

  • 学习和理解复杂的代码

方法 1:使用 Visual Studio 调试

Visual Studio 是最强大的 C# 调试工具,提供了丰富的调试功能。

第一步:设置断点

断点就像是在代码中设置的"暂停标记",程序运行到这里时会自动停下来。

如何设置断点:

  1. 打开要调试的文件

    • 例如:src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.cs
  2. 点击行号左侧

    • 在你想暂停的代码行号左侧点击

    • 会出现一个红色的圆点,这就是断点

  3. 快捷键设置

    • 将光标放在要设置断点的行

    • F9

示例:在消息处理函数设置断点

复制代码
public async Task<RoleDialogModel> SendMessage(string conversationId, 
    RoleDialogModel message)
{
    // 在这一行设置断点,查看接收到的消息
    var conversation = await GetConversation(conversationId);
    
    // 在这一行设置断点,查看对话状态
    if (conversation == null)
    {
        throw new Exception("Conversation not found");
    }
    
    // 在这一行设置断点,查看消息处理过程
    var response = await ProcessMessage(conversation, message);
    
    return response;
}

第二步:启动调试

方法 1:使用调试按钮

  1. 确保 WebStarter 是启动项目

  2. 点击工具栏上的绿色"▶ WebStarter"按钮旁边的下拉箭头

  3. 选择"调试"模式

  4. 点击按钮启动

方法 2:使用快捷键

  • F5 键启动调试

方法 3:使用菜单

  • 点击"调试" → "开始调试"

第三步:触发断点

启动后,程序会正常运行,直到执行到断点位置。

触发断点的方法:

  1. 使用 Postman 发送请求

    • 创建对话

    • 发送消息

    • 程序会在断点处暂停

  2. 使用 Swagger UI

    • 访问 http://localhost:5000/swagger

    • 执行相应的 API

    • 程序会在断点处暂停

第四步:检查变量

当程序在断点处暂停时,你可以查看所有变量的值。

查看变量的方法:

  1. 鼠标悬停

    • 将鼠标悬停在变量名上

    • 会显示变量的当前值

  2. 使用"局部变量"窗口

    • 在底部找到"局部变量"标签

    • 显示当前作用域内的所有变量

  3. 使用"监视"窗口

    • 右键点击变量

    • 选择"添加监视"

    • 在"监视"窗口中查看

  4. 使用"即时窗口"

    • Ctrl + Alt + I 打开即时窗口

    • 输入变量名或表达式

    • 按回车查看结果

示例:检查对话对象

复制代码
// 当程序暂停在这一行时
var conversation = await GetConversation(conversationId);

// 你可以查看:
// - conversationId 的值
// - conversation 对象的所有属性
// - conversation.Messages 列表的内容

第五步:单步执行

断点暂停后,你可以一行一行地执行代码。

单步执行的快捷键:

快捷键 功能 说明
F10 逐过程 执行当前行,不进入函数内部
F11 逐语句 执行当前行,进入函数内部
Shift + F11 跳出 跳出当前函数
F5 继续 继续运行到下一个断点
Shift + F5 停止调试 停止调试会话

使用场景:

  • F10(逐过程):当你不关心函数内部实现时使用

    复制代码
    var result = CalculateTotal(items); // 按 F10,直接得到结果
  • F11(逐语句):当你想深入了解函数内部时使用

    复制代码
    var result = CalculateTotal(items); // 按 F11,进入函数内部

第六步:条件断点

有时候你只想在特定条件下暂停程序。

设置条件断点:

  1. 右键点击断点

    • 右键点击红色断点圆点

    • 选择"条件..."

  2. 设置条件

    • 选择"条件表达式"

    • 输入条件,例如:conversationId == "特定ID"

    • 点击"关闭"

  3. 设置命中次数

    • 选择"命中次数"

    • 设置断点触发的次数

示例:只在特定用户时暂停

复制代码
public async Task<RoleDialogModel> SendMessage(string conversationId, 
    RoleDialogModel message)
{
    // 设置条件:message.UserId == "test-user"
    // 只有当用户ID是"test-user"时才会暂停
    var conversation = await GetConversation(conversationId);
    
    return await ProcessMessage(conversation, message);
}

第七步:查看调用堆栈

调用堆栈显示了程序是如何一步步执行到当前位置的。

查看调用堆栈:

  1. 打开"调用堆栈"窗口

    • 在调试时,底部会显示"调用堆栈"标签

    • 或按 Ctrl + Alt + C

  2. 理解调用堆栈

    复制代码
    BotSharp.Core.dll!ConversationService.SendMessage() 第 45 行
    BotSharp.OpenAPI.dll!ConversationController.SendMessage() 第 78 行
    Microsoft.AspNetCore.Mvc.Core.dll!ControllerActionInvoker.InvokeActionMethodAsync()

    这表示:

    • 最上面是当前位置

    • 往下是调用链

    • 可以双击任意一行跳转到那个位置

第八步:修改变量值

在调试过程中,你可以临时修改变量的值来测试不同的情况。

修改变量:

  1. 在"局部变量"窗口中

    • 找到要修改的变量

    • 双击值

    • 输入新值

    • 按回车

  2. 在"即时窗口"中

    • 输入:conversationId = "new-id"

    • 按回车

注意: 这只是临时修改,不会改变源代码。

方法 2:使用 VS Code 调试

VS Code 也提供了强大的调试功能,虽然界面不同,但原理相同。

第一步:配置调试

  1. 打开调试面板

    • 点击左侧的"运行和调试"图标

    • 或按 Ctrl + Shift + D

  2. 创建 launch.json

    • 点击"创建 launch.json 文件"

    • 选择".NET Core"

  3. 配置内容

    复制代码
    {
      "version": "0.2.0",
      "configurations": [
        {
          "name": ".NET Core Launch (web)",
          "type": "coreclr",
          "request": "launch",
          "preLaunchTask": "build",
          "program": "${workspaceFolder}/src/WebStarter/bin/Debug/net8.0/WebStarter.dll",
          "args": [],
          "cwd": "${workspaceFolder}/src/WebStarter",
          "stopAtEntry": false,
          "serverReadyAction": {
            "action": "openExternally",
            "pattern": "\\bNow listening on:\\s+(https?://\\S+)"
          },
          "env": {
            "ASPNETCORE_ENVIRONMENT": "Development"
          },
          "sourceFileMap": {
            "/Views": "${workspaceFolder}/Views"
          }
        }
      ]
    }

第二步:设置断点

在 VS Code 中设置断点:

  1. 点击行号左侧

    • 会出现红色圆点
  2. 快捷键

    • F9 切换断点

第三步:启动调试

  1. 选择配置

    • 在调试面板顶部选择".NET Core Launch (web)"
  2. 启动

    • 点击绿色的播放按钮

    • 或按 F5

第四步:使用调试功能

VS Code 的调试快捷键与 Visual Studio 相同:

快捷键 功能
F5 继续
F10 逐过程
F11 逐语句
Shift + F11 跳出
Shift + F5 停止

方法 3:查看和分析日志

日志是调试的重要工具,它记录了程序运行的详细信息。

日志级别

BotSharp 使用标准的日志级别:

级别 用途 示例
Trace 最详细的信息 函数进入/退出
Debug 调试信息 变量值、中间结果
Information 一般信息 请求处理、操作完成
Warning 警告信息 可恢复的错误
Error 错误信息 异常、失败操作
Critical 严重错误 系统崩溃

配置日志级别

appsettings.Development.json 中配置:

复制代码
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information",
      "BotSharp": "Debug"
    }
  }
}

配置说明:

  • Default: 默认日志级别

  • Microsoft: Microsoft 相关组件的日志级别

  • BotSharp: BotSharp 相关组件的日志级别

查看控制台日志

启动项目后,控制台会显示日志:

复制代码
info: BotSharp.Core.Conversations.Services.ConversationService[0]
      Creating new conversation for agent: PizzaBot
info: BotSharp.Core.Conversations.Services.ConversationService[0]
      Conversation created: conv-12345678-1234-1234-1234-123456789abc
dbug: BotSharp.Core.Agents.Services.AgentService[0]
      Loading agent profile: PizzaBot
dbug: BotSharp.Core.Plugins.PluginLoader[0]
      Loading plugin: PizzaBotPlugin

日志格式:

复制代码
[级别]: [命名空间][事件ID]
        [消息内容]

添加自定义日志

在代码中添加日志:

复制代码
public class ConversationService
{
    private readonly ILogger<ConversationService> _logger;
    
    public ConversationService(ILogger<ConversationService> logger)
    {
        _logger = logger;
    }
    
    public async Task<RoleDialogModel> SendMessage(string conversationId, 
        RoleDialogModel message)
    {
        // 记录信息日志
        _logger.LogInformation("Sending message to conversation: {ConversationId}", 
            conversationId);
        
        // 记录调试日志
        _logger.LogDebug("Message content: {Content}", message.Content);
        
        try
        {
            var result = await ProcessMessage(conversationId, message);
            
            // 记录成功信息
            _logger.LogInformation("Message sent successfully");
            
            return result;
        }
        catch (Exception ex)
        {
            // 记录错误日志
            _logger.LogError(ex, "Failed to send message to conversation: {ConversationId}", 
                conversationId);
            throw;
        }
    }
}

日志文件

默认情况下,日志只输出到控制台。如果需要保存到文件,可以配置日志提供程序。

使用 Serilog(推荐):

  1. 安装 NuGet 包

    复制代码
    dotnet add package Serilog.AspNetCore
    dotnet add package Serilog.Sinks.File
  2. 配置 Program.cs

    复制代码
    using Serilog;
    
    Log.Logger = new LoggerConfiguration()
        .WriteTo.Console()
        .WriteTo.File("logs/botsharp-.txt", rollingInterval: RollingInterval.Day)
        .CreateLogger();
    
    builder.Host.UseSerilog();
  3. 日志文件位置

    • 日志会保存在 logs/ 目录

    • 每天创建一个新文件

    • 文件名格式:botsharp-20240109.txt

常见错误排查

错误 1:NullReferenceException

错误信息:

复制代码
System.NullReferenceException: Object reference not set to an instance of an object.

原因: 尝试访问一个 null 对象的属性或方法。

排查步骤:

  1. 查看堆栈跟踪

    复制代码
    at BotSharp.Core.Conversations.Services.ConversationService.SendMessage() 
       in ConversationService.cs:line 45
  2. 在出错行设置断点

    • 打开 ConversationService.cs

    • 在第 45 行设置断点

  3. 检查变量

    • 运行到断点

    • 检查哪个变量是 null

    • 找出为什么是 null

  4. 修复代码

    复制代码
    // 修复前
    var result = conversation.Messages.Last();
    
    // 修复后
    if (conversation?.Messages?.Any() == true)
    {
        var result = conversation.Messages.Last();
    }
    else
    {
        _logger.LogWarning("No messages found in conversation");
    }

错误 2:InvalidOperationException

错误信息:

复制代码
System.InvalidOperationException: Sequence contains no elements

原因: 对空集合调用了 First()Single() 等方法。

排查步骤:

  1. 找到出错位置

    • 查看堆栈跟踪
  2. 检查集合

    • 在断点处查看集合是否为空
  3. 修复代码

    复制代码
    // 修复前
    var agent = agents.First(a => a.Name == "PizzaBot");
    
    // 修复后
    var agent = agents.FirstOrDefault(a => a.Name == "PizzaBot");
    if (agent == null)
    {
        throw new Exception("PizzaBot agent not found");
    }

错误 3:ArgumentException

错误信息:

复制代码
System.ArgumentException: Value cannot be null or empty. (Parameter 'conversationId')

原因: 传入了无效的参数。

排查步骤:

  1. 检查参数来源

    • 在函数入口设置断点

    • 查看参数值

  2. 添加参数验证

    复制代码
    public async Task<RoleDialogModel> SendMessage(string conversationId, 
        RoleDialogModel message)
    {
        // 添加参数验证
        if (string.IsNullOrEmpty(conversationId))
        {
            throw new ArgumentException("Conversation ID cannot be null or empty", 
                nameof(conversationId));
        }
        
        if (message == null)
        {
            throw new ArgumentNullException(nameof(message));
        }
        
        // 继续处理...
    }

错误 4:TimeoutException

错误信息:

复制代码
System.TimeoutException: The operation has timed out.

原因:

  • LLM API 响应超时

  • 数据库查询超时

  • 网络连接超时

排查步骤:

  1. 检查日志

    • 查看超时前的最后一条日志

    • 确定是哪个操作超时

  2. 增加超时时间

    复制代码
    // 配置 HTTP 客户端超时
    services.AddHttpClient("OpenAI", client =>
    {
        client.Timeout = TimeSpan.FromSeconds(120); // 增加到 120 秒
    });
  3. 添加重试机制

    复制代码
    int maxRetries = 3;
    for (int i = 0; i < maxRetries; i++)
    {
        try
        {
            var result = await CallLLMApi();
            return result;
        }
        catch (TimeoutException) when (i < maxRetries - 1)
        {
            _logger.LogWarning("API call timed out, retrying... ({Attempt}/{MaxRetries})", 
                i + 1, maxRetries);
            await Task.Delay(1000 * (i + 1)); // 递增延迟
        }
    }

错误 5:JsonException

错误信息:

复制代码
System.Text.Json.JsonException: The JSON value could not be converted to...

原因: JSON 反序列化失败。

排查步骤:

  1. 查看原始 JSON

    • 在日志中记录原始 JSON 字符串

      _logger.LogDebug("Received JSON: {Json}", jsonString);

  2. 检查数据类型

    • 确认 JSON 结构与 C# 类匹配
  3. 添加错误处理

    复制代码
    try
    {
        var obj = JsonSerializer.Deserialize<MyClass>(jsonString);
    }
    catch (JsonException ex)
    {
        _logger.LogError(ex, "Failed to deserialize JSON: {Json}", jsonString);
        throw;
    }

调试技巧和最佳实践

技巧 1:使用日志而不是断点

在某些情况下,日志比断点更有用:

适合使用日志的场景:

  • 生产环境问题

  • 性能测试

  • 长时间运行的操作

  • 异步操作

示例:

复制代码
_logger.LogDebug("Processing message {MessageId} at {Timestamp}", 
    message.Id, DateTime.UtcNow);

技巧 2:使用条件编译

在调试代码中使用条件编译:

复制代码
#if DEBUG
    _logger.LogDebug("Debug mode: Variable value = {Value}", value);
    System.Diagnostics.Debugger.Break(); // 自动触发断点
#endif

技巧 3:使用 Debug.Assert

在开发时验证假设:

复制代码
Debug.Assert(conversation != null, "Conversation should not be null");
Debug.Assert(messages.Count > 0, "Messages list should not be empty");

技巧 4:使用性能分析器

Visual Studio 提供了性能分析工具:

  1. 启动性能分析器

    • 点击"调试" → "性能探查器"

    • 选择"CPU 使用率"或"内存使用率"

    • 点击"开始"

  2. 分析结果

    • 查看哪些函数占用最多时间

    • 查看内存分配情况

    • 找出性能瓶颈

技巧 5:使用远程调试

调试部署在服务器上的应用:

  1. 在服务器上安装远程调试器

    • 下载 Remote Tools for Visual Studio
  2. 配置防火墙

    • 允许远程调试器端口
  3. 在 Visual Studio 中连接

    • 点击"调试" → "附加到进程"

    • 选择"远程(无身份验证)"

    • 输入服务器地址

    • 选择进程并附加

调试工作流程

标准调试流程

  1. 重现问题

    • 确保能稳定重现错误

    • 记录重现步骤

  2. 收集信息

    • 查看错误消息

    • 查看堆栈跟踪

    • 查看日志

  3. 形成假设

    • 根据信息推测问题原因

    • 列出可能的原因

  4. 验证假设

    • 设置断点

    • 检查变量

    • 单步执行

  5. 修复问题

    • 修改代码

    • 测试修复

  6. 验证修复

    • 重新测试

    • 确保问题解决

    • 确保没有引入新问题

调试检查清单

在开始调试前,检查以下项目:

  • \] 是否使用最新的代码?

  • \] 配置文件是否正确?

  • \] 数据库连接是否正常?

  • \] 日志级别是否设置为 Debug?

恭喜你!你已经掌握了调试 BotSharp 项目的各种方法。让我们回顾一下本节的重点:

Visual Studio 调试 :断点、单步执行、查看变量 ✅ VS Code 调试 :配置和使用调试功能 ✅ 日志分析 :查看和配置日志 ✅ 错误排查 :常见错误的排查方法 ✅ 调试技巧 :提高调试效率的技巧 ✅ 调试流程:系统化的调试方法

下一步

现在你已经掌握了环境准备、项目结构、快速启动和调试的知识,接下来我们将深入学习 BotSharp 的核心概念,包括 Agent、Plugin、LLM 集成等。

常见问题

Q: 断点不起作用怎么办? A: 检查是否在 Debug 模式下运行,确保代码已重新编译,确保断点设置在可执行的代码行上。

Q: 如何调试异步代码? A: 异步代码的调试与同步代码相同,但要注意查看"任务"窗口了解异步操作的状态。

Q: 调试时程序很慢怎么办? A: 这是正常的,因为调试器需要额外的开销。可以减少断点数量,或使用日志代替断点。

Q: 如何调试第三方库的代码? A: 在 Visual Studio 中,取消勾选"工具" → "选项" → "调试" → "启用仅我的代码",然后可以单步进入第三方库。

Q: 生产环境出现问题如何调试? A: 不要在生产环境使用断点调试。应该:

  1. 查看日志文件

  2. 启用详细日志

  3. 使用应用程序监控工具

  4. 在开发环境重现问题

Q: 如何调试性能问题? A: 使用性能分析器,查看 CPU 和内存使用情况,找出性能瓶颈。

练习

  1. ConversationService.SendMessage 方法中设置断点,发送一条消息,观察执行流程

  2. 修改日志级别为 Debug,观察更详细的日志输出

  3. 故意制造一个 NullReferenceException,使用调试器找出原因

  4. 使用条件断点,只在特定条件下暂停程序

  5. 查看一次完整的 API 调用的调用堆栈

  6. 在调试过程中修改一个变量的值,观察程序行为的变化

  7. 配置 Serilog,将日志保存到文件

完成这些练习后,你就完全掌握了 BotSharp 的调试技能!现在可以继续学习第 04 章:核心概念了。

第 03 章 - 快速启动实践

练习题

说明

本练习题旨在帮助你巩固第 03 章学到的知识。题目分为三个难度等级:

  • ⭐ 基础题:测试基本操作能力

  • ⭐⭐ 进阶题:测试问题排查能力

  • ⭐⭐⭐ 挑战题:测试综合应用能力

本章重点是实践操作,建议在实际环境中完成练习。每道题都有详细的参考答案和解析。


一、项目克隆实践题

题目 1:基础克隆操作 ⭐

问题:请完成以下操作并回答问题:

  1. 在你的电脑上选择一个合适的位置

  2. 使用 Git 克隆 BotSharp 项目

  3. 验证克隆是否成功

要求

  • 记录你选择的项目路径

  • 记录克隆命令

  • 记录克隆所用时间

  • 列出项目根目录下的主要文件和文件夹

参考答案

1. 选择项目路径

复制代码
Windows: C:\Projects\BotSharp
Mac/Linux: ~/Projects/BotSharp

2. 克隆命令

复制代码
# 创建项目目录
mkdir -p ~/Projects
cd ~/Projects

# 克隆项目
git clone https://github.com/dotnetcore/BotSharp.git

3. 验证成功

复制代码
cd BotSharp
ls -la

4. 主要文件和文件夹

复制代码
BotSharp/
├── src/                    # 源代码目录
├── tests/                  # 测试代码目录
├── docs/                   # 文档目录
├── dockerfiles/            # Docker 配置
├── BotSharp.sln           # 解决方案文件
├── README.md              # 项目说明
├── LICENSE                # 许可证
└── .gitignore             # Git 忽略文件

评分标准

  • 路径选择合理(避免中文、空格):2 分

  • 克隆命令正确:3 分

  • 能够验证成功:3 分

  • 正确列出主要文件:2 分


题目 2:克隆问题排查 ⭐⭐

问题:在克隆过程中可能遇到以下错误,请说明原因和解决方案:

错误 A

复制代码
fatal: unable to access 'https://github.com/...': Failed to connect to github.com

错误 B

复制代码
error: unable to create file: Filename too long

错误 C

复制代码
Cloning into 'BotSharp'...
remote: Enumerating objects: 15234, done.
remote: Total 15234 (delta 0), reused 0 (delta 0), pack-reused 15234
Receiving objects:  45% (6855/15234), 5.23 MiB | 12.00 KiB/s

(速度很慢,长时间卡住)

参考答案

错误 A:网络连接失败

原因

  • 无法访问 GitHub

  • 网络防火墙阻止

  • DNS 解析问题

解决方案

  1. 检查网络连接

    复制代码
    ping github.com
  2. 使用代理(如果有):

    复制代码
    git config --global http.proxy http://127.0.0.1:7890
    git config --global https.proxy http://127.0.0.1:7890
  3. 使用 Gitee 镜像(国内用户):

    复制代码
    git clone https://gitee.com/dotnetchina/BotSharp.git
  4. 使用 SSH 方式

    复制代码
    git clone git@github.com:dotnetcore/BotSharp.git

错误 B:文件名太长(Windows)

原因

  • Windows 默认路径长度限制为 260 字符

  • 项目中有些文件路径较深

解决方案

  1. 启用长路径支持

    复制代码
    # 以管理员身份运行
    git config --system core.longpaths true
  2. 修改注册表(Windows 10 1607+):

    • 打开注册表编辑器

    • 导航到:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem

    • LongPathsEnabled 设置为 1

  3. 选择更短的路径

    复制代码
    # 不好:C:\Users\YourName\Documents\Projects\BotSharp
    # 更好:C:\Projects\BotSharp

错误 C:克隆速度很慢

原因

  • 网络带宽限制

  • GitHub 服务器距离远

  • 项目历史记录很大

解决方案

  1. 使用浅克隆(只克隆最新版本):

    复制代码
    git clone --depth 1 https://github.com/dotnetcore/BotSharp.git
  2. 使用镜像站点

    复制代码
    git clone https://gitee.com/dotnetchina/BotSharp.git
  3. 使用下载工具

    • 使用 GitHub Desktop

    • 使用迅雷等下载工具下载 ZIP

  4. 等待或稍后重试

    • 有时是 GitHub 服务器繁忙

    • 换个时间段尝试

评分标准

  • 正确识别错误原因:3 分

  • 提供有效解决方案:5 分

  • 提供多种解决方案:2 分


题目 3:Git 操作实践 ⭐⭐

问题:完成以下 Git 操作:

  1. 查看当前分支

  2. 查看最近 5 次提交记录

  3. 查看项目的远程仓库地址

  4. 切换到一个特定的标签(tag)版本

参考答案

1. 查看当前分支

复制代码
git branch
# 输出:* master(当前分支前有 * 号)

2. 查看最近 5 次提交

复制代码
git log -5

# 或者查看简洁版本
git log -5 --oneline

# 输出示例:
# a1b2c3d Update README
# e4f5g6h Fix bug in conversation service
# i7j8k9l Add new plugin

3. 查看远程仓库地址

复制代码
git remote -v

# 输出:
# origin  https://github.com/dotnetcore/BotSharp.git (fetch)
# origin  https://github.com/dotnetcore/BotSharp.git (push)

4. 切换到特定标签

复制代码
# 查看所有标签
git tag

# 切换到特定标签(例如 v1.0.0)
git checkout v1.0.0

# 返回最新版本
git checkout master

评分标准

  • 每个命令正确:2.5 分

  • 能够解释输出结果:额外 2 分


二、项目启动实践题

题目 4:配置 LLM 提供商 ⭐

问题:请完成以下配置任务:

  1. 打开 appsettings.json 文件

  2. 找到 LLM 配置部分

  3. 配置 OpenAI 提供商(使用测试 API Key)

  4. 说明每个配置项的作用

参考答案

配置示例

复制代码
{
  "LlmProviders": [
    {
      "Provider": "openai",
      "Models": [
        {
          "Name": "gpt-4",
          "Type": "chat",
          "ApiKey": "sk-test-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
          "Endpoint": "https://api.openai.com/v1",
          "Temperature": 0.7,
          "MaxTokens": 2000
        }
      ]
    }
  ]
}

配置项说明

配置项 作用 示例值
Provider LLM 提供商名称 "openai"
Name 模型名称 "gpt-4"
Type 模型类型 "chat"
ApiKey API 密钥 "sk-xxx..."
Endpoint API 端点 "https://api.openai.com/v1"
Temperature 随机性(0-1) 0.7
MaxTokens 最大令牌数 2000

Temperature 说明

  • 0.0:输出确定性强,适合事实性任务

  • 0.7:平衡创造性和准确性(推荐)

  • 1.0:输出更有创造性,但可能不太准确

MaxTokens 说明

  • 控制回复的最大长度

  • 1 token ≈ 0.75 个英文单词

  • 1 token ≈ 0.5 个中文字符

评分标准

  • 正确找到配置文件:2 分

  • 配置格式正确:3 分

  • 能够解释配置项:5 分


题目 5:启动错误排查 ⭐⭐

问题:在启动项目时遇到以下错误,请分析原因并提供解决方案:

错误 A

复制代码
Failed to bind to address http://127.0.0.1:5000: address already in use.

错误 B

复制代码
The current .NET SDK does not support targeting .NET 8.0.

错误 C

复制代码
error NU1101: Unable to find package BotSharp.Abstraction

错误 D

复制代码
OpenAI API key is not configured

参考答案

错误 A:端口被占用

原因:端口 5000 已被其他程序使用

解决方案

  1. 更换端口

    复制代码
    dotnet run --urls "http://localhost:5005"
  2. 找到并关闭占用端口的程序

    Windows

    复制代码
    # 查找占用端口的进程
    netstat -ano | findstr :5000
    
    # 结束进程(替换 PID)
    taskkill /PID 12345 /F

    Mac/Linux

    复制代码
    # 查找占用端口的进程
    lsof -i :5000
    
    # 结束进程
    kill -9 12345

错误 B:.NET SDK 版本不匹配

原因:系统安装的 .NET SDK 版本低于项目要求

解决方案

  1. 检查当前版本

    复制代码
    dotnet --version
  2. 下载并安装 .NET 8.0 SDK

  3. 验证安装

    复制代码
    dotnet --list-sdks
    # 应该能看到 8.0.xxx

错误 C:NuGet 包还原失败

原因

  • NuGet 源不可用

  • 网络连接问题

  • 包版本不存在

解决方案

  1. 清理并重新还原

    复制代码
    dotnet clean
    dotnet restore
  2. 检查 NuGet 源

    复制代码
    dotnet nuget list source
  3. 添加官方源

    复制代码
    dotnet nuget add source https://api.nuget.org/v3/index.json -n nuget.org
  4. 使用国内镜像(可选):

    复制代码
    dotnet nuget add source https://nuget.cdn.azure.cn/v3/index.json -n azure-cn

错误 D:缺少 API Key

原因:未配置 LLM 提供商的 API Key

解决方案

  1. 打开配置文件

    复制代码
    src/WebStarter/appsettings.json
  2. 添加 API Key

    复制代码
    {
      "LlmProviders": [
        {
          "Provider": "openai",
          "Models": [
            {
              "Name": "gpt-4",
              "ApiKey": "your-actual-api-key-here"
            }
          ]
        }
      ]
    }
  3. 保存并重启项目

评分标准

  • 正确识别每个错误原因:4 分

  • 提供有效解决方案:6 分


题目 6:启动验证 ⭐

问题:项目启动后,如何验证启动是否成功?请列出至少 3 种验证方法。

参考答案

方法 1:检查控制台输出

成功标志

复制代码
info: Microsoft.Hosting.Lifetime[14]
      Now listening on: http://localhost:5000
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.

关键信息

  • ✅ "Now listening on" - 服务正在监听

  • ✅ "Application started" - 应用已启动

  • ✅ 没有红色错误信息

方法 2:访问 Swagger UI

步骤

  1. 打开浏览器

  2. 访问:http://localhost:5000/swagger

  3. 应该能看到 API 文档页面

成功标志

  • 页面正常加载

  • 显示 BotSharp API 列表

  • 可以展开和测试 API

方法 3:调用健康检查 API

使用 curl

复制代码
curl http://localhost:5000/health

预期响应

复制代码
{
  "status": "Healthy",
  "totalDuration": "00:00:00.0123456"
}

方法 4:测试 Agent API

使用 Swagger UI

  1. 找到 GET /api/agent 接口

  2. 点击 "Try it out"

  3. 点击 "Execute"

预期响应

复制代码
{
  "items": [
    {
      "id": "...",
      "name": "PizzaBot",
      "description": "..."
    }
  ],
  "count": 1
}

方法 5:检查日志文件

查看日志

复制代码
# 如果配置了文件日志
cat logs/botsharp-20240109.txt

成功标志

  • 插件加载成功

  • Agent 初始化完成

  • 没有错误日志

评分标准

  • 列出 3 种方法:6 分

  • 说明验证步骤:2 分

  • 说明成功标志:2 分


三、API 测试实践题

题目 7:Postman 测试流程 ⭐⭐

问题:使用 Postman 完成以下测试流程:

  1. 获取 Agent 列表

  2. 创建一个新对话

  3. 发送消息:"你好"

  4. 发送消息:"我想订披萨"

  5. 记录每一步的请求和响应

参考答案

步骤 1:获取 Agent 列表

请求

复制代码
GET http://localhost:5000/api/agent
Headers:
  Accept: application/json

响应

复制代码
{
  "items": [
    {
      "id": "01234567-89ab-cdef-0123-456789abcdef",
      "name": "PizzaBot",
      "description": "A pizza ordering assistant"
    }
  ],
  "count": 1
}

记录 :保存 Agent ID = 01234567-89ab-cdef-0123-456789abcdef

步骤 2:创建对话

请求

复制代码
POST http://localhost:5000/api/conversation
Headers:
  Content-Type: application/json
  Accept: application/json
Body:
{
  "agentId": "01234567-89ab-cdef-0123-456789abcdef",
  "channel": "postman",
  "userId": "test-user"
}

响应

复制代码
{
  "conversationId": "conv-12345678-1234-1234-1234-123456789abc",
  "agentId": "01234567-89ab-cdef-0123-456789abcdef",
  "status": "active",
  "createdAt": "2024-01-09T10:30:00Z"
}

记录 :保存 Conversation ID = conv-12345678-1234-1234-1234-123456789abc

步骤 3:发送消息 "你好"

请求

复制代码
POST http://localhost:5000/api/conversation/message
Headers:
  Content-Type: application/json
  Accept: application/json
Body:
{
  "conversationId": "conv-12345678-1234-1234-1234-123456789abc",
  "text": "你好"
}

响应

复制代码
{
  "conversationId": "conv-12345678-1234-1234-1234-123456789abc",
  "messageId": "msg-11111111-1111-1111-1111-111111111111",
  "text": "你好!我是 PizzaBot,很高兴为您服务。我可以帮您订购美味的披萨。请问您需要什么帮助?",
  "createdAt": "2024-01-09T10:31:00Z"
}

步骤 4:发送消息 "我想订披萨"

请求

复制代码
POST http://localhost:5000/api/conversation/message
Headers:
  Content-Type: application/json
  Accept: application/json
Body:
{
  "conversationId": "conv-12345678-1234-1234-1234-123456789abc",
  "text": "我想订披萨"
}

响应

复制代码
{
  "conversationId": "conv-12345678-1234-1234-1234-123456789abc",
  "messageId": "msg-22222222-2222-2222-2222-222222222222",
  "text": "太好了!我可以帮您订购披萨。请问您想要什么尺寸的披萨?我们有小号、中号和大号。",
  "createdAt": "2024-01-09T10:32:00Z"
}

测试记录表

步骤 API 状态码 响应时间 结果
1 GET /api/agent 200 150ms ✅ 成功
2 POST /api/conversation 200 200ms ✅ 成功
3 POST /api/conversation/message 200 2500ms ✅ 成功
4 POST /api/conversation/message 200 2800ms ✅ 成功

评分标准

  • 正确完成每个步骤:2 分/步

  • 记录完整的请求响应:2 分


题目 8:curl 命令测试 ⭐⭐

问题:使用 curl 命令完成以下操作:

  1. 获取 Agent 列表

  2. 创建对话

  3. 发送一条消息

请写出完整的 curl 命令(包括 Windows 和 Mac/Linux 版本)。

参考答案

1. 获取 Agent 列表

Mac/Linux

复制代码
curl -X GET "http://localhost:5000/api/agent" \
  -H "accept: application/json"

Windows PowerShell

复制代码
curl.exe -X GET "http://localhost:5000/api/agent" `
  -H "accept: application/json"

或使用 PowerShell 原生命令

复制代码
Invoke-RestMethod -Uri "http://localhost:5000/api/agent" `
  -Method Get `
  -ContentType "application/json"

2. 创建对话

Mac/Linux

复制代码
curl -X POST "http://localhost:5000/api/conversation" \
  -H "accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
    "agentId": "01234567-89ab-cdef-0123-456789abcdef",
    "channel": "curl",
    "userId": "test-user"
  }'

Windows PowerShell

复制代码
$body = @{
    agentId = "01234567-89ab-cdef-0123-456789abcdef"
    channel = "curl"
    userId = "test-user"
} | ConvertTo-Json

Invoke-RestMethod -Uri "http://localhost:5000/api/conversation" `
  -Method Post `
  -ContentType "application/json" `
  -Body $body

3. 发送消息

Mac/Linux

复制代码
curl -X POST "http://localhost:5000/api/conversation/message" \
  -H "accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
    "conversationId": "conv-12345678-1234-1234-1234-123456789abc",
    "text": "我想订披萨"
  }'

Windows PowerShell

复制代码
$body = @{
    conversationId = "conv-12345678-1234-1234-1234-123456789abc"
    text = "我想订披萨"
} | ConvertTo-Json

Invoke-RestMethod -Uri "http://localhost:5000/api/conversation/message" `
  -Method Post `
  -ContentType "application/json" `
  -Body $body

命令说明

参数 说明
-X POST 指定 HTTP 方法
-H 添加请求头
-d 发送请求体数据
\ 行继续符(Mac/Linux)
````` 行继续符(PowerShell)

评分标准

  • 命令语法正确:3 分

  • 包含必要的请求头:2 分

  • 数据格式正确:3 分

  • 提供跨平台版本:2 分


题目 9:API 错误处理 ⭐⭐⭐

问题:在测试 API 时遇到以下错误响应,请分析原因并说明如何修复:

错误 A

复制代码
{
  "status": 400,
  "title": "Bad Request",
  "errors": {
    "agentId": ["The agentId field is required."]
  }
}

错误 B

复制代码
{
  "status": 404,
  "title": "Not Found",
  "detail": "Conversation not found"
}

错误 C

复制代码
{
  "status": 500,
  "title": "Internal Server Error",
  "detail": "An error occurred while processing your request."
}

参考答案

错误 A:400 Bad Request - 缺少必填字段

原因

  • 请求体中缺少 agentId 字段

  • 或者 agentId 为空

错误请求示例

复制代码
{
  "channel": "postman",
  "userId": "test-user"
  // 缺少 agentId
}

修复方法

复制代码
{
  "agentId": "01234567-89ab-cdef-0123-456789abcdef",
  "channel": "postman",
  "userId": "test-user"
}

验证步骤

  1. 检查请求体是否包含所有必填字段

  2. 检查字段名拼写是否正确

  3. 检查字段值是否为空

错误 B:404 Not Found - 资源不存在

原因

  • 使用了不存在的 conversationId

  • conversationId 拼写错误

  • 对话已过期或被删除

错误请求示例

复制代码
{
  "conversationId": "wrong-id",
  "text": "你好"
}

修复方法

  1. 重新创建对话

    复制代码
    # 创建新对话
    POST /api/conversation
    
    # 使用返回的 conversationId
  2. 检查 ID 格式

    复制代码
    正确格式:conv-12345678-1234-1234-1234-123456789abc
    错误格式:conv-123 或 12345678
  3. 验证对话是否存在

    复制代码
    GET /api/conversation/{conversationId}

错误 C:500 Internal Server Error - 服务器内部错误

可能原因

  1. LLM API 调用失败

  2. 数据库连接失败

  3. 代码逻辑错误

  4. 配置错误

排查步骤

  1. 查看服务器日志

    复制代码
    # 在运行项目的控制台查看错误信息
  2. 检查 LLM 配置

    复制代码
    {
      "LlmProviders": [
        {
          "Provider": "openai",
          "Models": [
            {
              "ApiKey": "检查是否有效"
            }
          ]
        }
      ]
    }
  3. 检查数据库连接

    复制代码
    {
      "Database": {
        "Provider": "InMemory"  // 或检查 MongoDB 连接
      }
    }
  4. 测试 LLM API

    复制代码
    # 使用 curl 测试 OpenAI API
    curl https://api.openai.com/v1/models \
      -H "Authorization: Bearer YOUR_API_KEY"

常见 500 错误场景

场景 原因 解决方案
LLM 超时 API 响应慢 增加超时时间
API Key 无效 Key 过期或错误 更新 API Key
数据库错误 连接失败 检查数据库配置
内存不足 对话历史太长 清理旧对话

评分标准

  • 正确识别错误类型:3 分

  • 分析错误原因:4 分

  • 提供有效解决方案:3 分


四、调试实践题

题目 10:断点调试基础 ⭐

问题:请完成以下调试操作:

  1. 在 Visual Studio 中打开 BotSharp 项目

  2. 找到 ConversationService.cs 文件

  3. SendMessage 方法的第一行设置断点

  4. 启动调试

  5. 使用 Postman 发送一条消息

  6. 观察程序在断点处暂停

  7. 查看 conversationIdmessage 参数的值

要求

  • 截图显示断点设置

  • 记录观察到的变量值

  • 说明如何继续执行

参考答案

步骤 1-3:设置断点

文件位置

复制代码
src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.cs

设置断点

  • 找到 SendMessage 方法

  • 在方法的第一行点击行号左侧

  • 出现红色圆点表示断点已设置

步骤 4:启动调试

方法 1:使用按钮

  • 点击工具栏的绿色 "▶ WebStarter" 按钮

方法 2:使用快捷键

  • F5

步骤 5-6:触发断点

使用 Postman 发送消息

复制代码
POST http://localhost:5000/api/conversation/message
{
  "conversationId": "conv-12345678-1234-1234-1234-123456789abc",
  "text": "你好"
}

程序暂停

  • Visual Studio 会自动切换到前台

  • 断点行会高亮显示

  • 程序执行暂停

步骤 7:查看变量

方法 1:鼠标悬停

  • 将鼠标悬停在 conversationId

  • 显示值:"conv-12345678-1234-1234-1234-123456789abc"

方法 2:局部变量窗口

  • 在底部找到"局部变量"标签

  • 查看所有参数:

    复制代码
    conversationId = "conv-12345678-1234-1234-1234-123456789abc"
    message = {
      Content = "你好",
      Role = "user",
      CreatedAt = {2024-01-09 10:30:00}
    }

继续执行

操作 快捷键 说明
继续运行 F5 运行到下一个断点
逐过程 F10 执行当前行,不进入函数
逐语句 F11 执行当前行,进入函数内部
跳出 Shift+F11 跳出当前函数
停止调试 Shift+F5 停止调试会话

评分标准

  • 正确设置断点:2 分

  • 成功触发断点:3 分

  • 正确查看变量:3 分

  • 了解继续执行方法:2 分


题目 11:日志分析 ⭐⭐

问题:以下是项目启动时的日志输出,请分析每一行的含义:

复制代码
info: Microsoft.Hosting.Lifetime[14]
      Now listening on: http://localhost:5000
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: BotSharp.Core.Plugins.PluginLoader[0]
      Loading plugins from configuration
info: BotSharp.Core.Plugins.PluginLoader[0]
      Loaded plugin: PizzaBotPlugin
info: BotSharp.Core.Agents.Services.AgentService[0]
      Initializing agent: PizzaBot
dbug: BotSharp.Core.Agents.Services.AgentService[0]
      Loading agent profile from: data/agents/pizza-bot.json
info: BotSharp.Core.Agents.Services.AgentService[0]
      Agent initialized successfully: PizzaBot

参考答案

日志格式说明

复制代码
[级别]: [命名空间][事件ID]
        [消息内容]

逐行分析

第 1-2 行:应用启动

复制代码
info: Microsoft.Hosting.Lifetime[14]
      Now listening on: http://localhost:5000
  • 级别:info(信息)

  • 来源:Microsoft.Hosting.Lifetime(ASP.NET Core 生命周期管理)

  • 含义:Web 服务器已启动,正在监听 5000 端口

  • 重要性:✅ 关键信息,表示服务可以接收请求

第 3-4 行:应用就绪

复制代码
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
  • 含义:应用程序已完全启动

  • 提示:按 Ctrl+C 可以停止服务

  • 重要性:✅ 表示启动成功

第 5-6 行:插件加载开始

复制代码
info: BotSharp.Core.Plugins.PluginLoader[0]
      Loading plugins from configuration
  • 来源:BotSharp.Core.Plugins.PluginLoader

  • 含义:开始从配置文件加载插件

  • 重要性:表示插件系统正在初始化

第 7-8 行:插件加载成功

复制代码
info: BotSharp.Core.Plugins.PluginLoader[0]
      Loaded plugin: PizzaBotPlugin
  • 含义:成功加载 PizzaBotPlugin 插件

  • 重要性:✅ 确认插件可用

第 9-10 行:Agent 初始化开始

复制代码
info: BotSharp.Core.Agents.Services.AgentService[0]
      Initializing agent: PizzaBot
  • 来源:AgentService

  • 含义:开始初始化 PizzaBot Agent

  • 重要性:表示 Agent 系统正在启动

第 11-12 行:加载 Agent 配置

复制代码
dbug: BotSharp.Core.Agents.Services.AgentService[0]
      Loading agent profile from: data/agents/pizza-bot.json
  • 级别:dbug(调试)

  • 含义:从 JSON 文件加载 Agent 配置

  • 文件路径:data/agents/pizza-bot.json

  • 重要性:调试信息,帮助定位配置文件

第 13-14 行:Agent 初始化完成

复制代码
info: BotSharp.Core.Agents.Services.AgentService[0]
      Agent initialized successfully: PizzaBot
  • 含义:PizzaBot Agent 初始化成功

  • 重要性:✅ 确认 Agent 可以使用

日志级别说明

级别 缩写 用途 示例
Trace trce 最详细的信息 函数进入/退出
Debug dbug 调试信息 变量值、配置路径
Information info 一般信息 启动、完成
Warning warn 警告信息 可恢复的错误
Error erro 错误信息 异常、失败
Critical crit 严重错误 系统崩溃

启动成功的标志

  • ✅ "Now listening on" 出现

  • ✅ "Application started" 出现

  • ✅ 所有插件加载成功

  • ✅ 所有 Agent 初始化成功

  • ✅ 没有 "erro" 或 "crit" 级别的日志

评分标准

  • 理解日志格式:2 分

  • 正确解释每行含义:6 分

  • 识别关键信息:2 分


题目 12:错误日志排查 ⭐⭐⭐

问题:在运行过程中出现以下错误日志,请分析问题并提供解决方案:

错误日志 A

复制代码
erro: BotSharp.Plugin.OpenAI.Providers.ChatCompletionProvider[0]
      Failed to call OpenAI API
      System.Net.Http.HttpRequestException: The SSL connection could not be established

错误日志 B

复制代码
erro: BotSharp.Core.Conversations.Services.ConversationService[0]
      Error processing message
      System.NullReferenceException: Object reference not set to an instance of an object.
         at BotSharp.Core.Conversations.Services.ConversationService.SendMessage()

错误日志 C

复制代码
warn: BotSharp.Core.Agents.Services.AgentService[0]
      Agent not found: customer-service
      Falling back to default agent

参考答案

错误 A:SSL 连接失败

问题分析

  • 无法建立 SSL 连接到 OpenAI API

  • 可能原因:

    1. 网络代理问题

    2. 防火墙阻止

    3. SSL 证书验证失败

    4. 网络不稳定

解决方案

  1. 检查网络连接

    复制代码
    ping api.openai.com
  2. 配置代理(如果使用代理):

    复制代码
    {
      "LlmProviders": [
        {
          "Provider": "openai",
          "Proxy": "http://127.0.0.1:7890"
        }
      ]
    }
  3. 禁用 SSL 验证(仅用于测试):

    复制代码
    // 在 Program.cs 中添加(不推荐用于生产环境)
    ServicePointManager.ServerCertificateValidationCallback = 
        (sender, cert, chain, sslPolicyErrors) => true;
  4. 使用备用 Endpoint

    复制代码
    {
      "Endpoint": "https://api.openai-proxy.com/v1"
    }
  5. 检查防火墙设置

错误 B:空引用异常

问题分析

  • 代码尝试访问 null 对象的属性或方法

  • 这是编程错误,需要修复代码

排查步骤

  1. 查看完整堆栈跟踪

    复制代码
    at BotSharp.Core.Conversations.Services.ConversationService.SendMessage() 
       in ConversationService.cs:line 45
  2. 在出错行设置断点

    • 打开 ConversationService.cs

    • 在第 45 行设置断点

    • 重现错误

  3. 检查变量

    • 查看哪个变量是 null

    • 追踪变量的来源

常见原因

复制代码
// 原因 1:对话不存在
var conversation = await GetConversation(conversationId);
var lastMessage = conversation.Messages.Last(); // conversation 是 null

// 原因 2:集合为空
var messages = conversation.Messages;
var lastMessage = messages.Last(); // messages 是空集合

// 原因 3:属性未初始化
var agent = conversation.Agent;
var agentName = agent.Name; // agent 是 null

修复方法

复制代码
// 修复 1:添加 null 检查
var conversation = await GetConversation(conversationId);
if (conversation == null)
{
    throw new Exception("Conversation not found");
}

// 修复 2:使用安全导航
var lastMessage = conversation?.Messages?.LastOrDefault();

// 修复 3:使用 null 合并
var agentName = conversation?.Agent?.Name ?? "Unknown";

错误 C:Agent 未找到(警告)

问题分析

  • 这是警告(warn),不是错误

  • 系统找不到指定的 Agent

  • 已自动回退到默认 Agent

  • 功能可以继续,但可能不是预期行为

可能原因

  1. Agent ID 拼写错误

  2. Agent 配置文件不存在

  3. Agent 未正确加载

  4. 路由配置错误

排查步骤

  1. 检查 Agent 是否存在

    复制代码
    GET /api/agent
    # 查看返回的 Agent 列表
  2. 检查 Agent 配置文件

    复制代码
    # 查看配置文件是否存在
    ls data/agents/customer-service.json
  3. 检查 Agent ID

    复制代码
    // 确保 ID 匹配
    {
      "id": "customer-service",  // 必须与请求中的 ID 一致
      "name": "Customer Service Bot"
    }
  4. 检查插件加载

    复制代码
    # 查看启动日志
    info: BotSharp.Core.Plugins.PluginLoader[0]
          Loaded plugin: CustomerServicePlugin

解决方案

  1. 修正 Agent ID

    复制代码
    // 请求中使用正确的 ID
    {
      "agentId": "pizza-bot"  // 而不是 "customer-service"
    }
  2. 创建缺失的 Agent

    • data/agents/ 目录创建配置文件

    • 重启服务

  3. 检查路由配置

    复制代码
    {
      "Routing": {
        "DefaultAgent": "pizza-bot",
        "FallbackAgent": "general-assistant"
      }
    }

评分标准

  • 正确识别错误类型:3 分

  • 分析错误原因:4 分

  • 提供有效解决方案:3 分


五、综合实战题

题目 13:完整订单流程测试 ⭐⭐⭐

问题:请完成一个完整的披萨订购流程测试,包括:

  1. 创建对话

  2. 选择披萨尺寸

  3. 选择披萨口味

  4. 添加配料

  5. 提供配送地址

  6. 确认订单

要求:

  • 记录每一步的请求和响应

  • 如果遇到错误,记录错误信息并解决

  • 最终成功完成订单

参考答案

完整测试流程

步骤 1:创建对话

复制代码
POST /api/conversation
{
  "agentId": "01234567-89ab-cdef-0123-456789abcdef",
  "channel": "test",
  "userId": "test-user-001"
}

响应:
{
  "conversationId": "conv-test-001",
  "status": "active"
}

步骤 2:开始订购

复制代码
POST /api/conversation/message
{
  "conversationId": "conv-test-001",
  "text": "我想订一份披萨"
}

响应:
{
  "text": "好的!请问您想要什么尺寸的披萨?我们有小号、中号和大号。"
}

步骤 3:选择尺寸

复制代码
POST /api/conversation/message
{
  "conversationId": "conv-test-001",
  "text": "大号的"
}

响应:
{
  "text": "太好了!大号披萨。请问您想要什么口味?我们有:\n- 玛格丽特\n- 意大利辣香肠\n- 夏威夷\n- 四季披萨"
}

步骤 4:选择口味

复制代码
POST /api/conversation/message
{
  "conversationId": "conv-test-001",
  "text": "意大利辣香肠"
}

响应:
{
  "text": "好的!一份大号意大利辣香肠披萨。请问需要添加额外的配料吗?"
}

步骤 5:添加配料

复制代码
POST /api/conversation/message
{
  "conversationId": "conv-test-001",
  "text": "加双倍芝士"
}

响应:
{
  "text": "好的,已添加双倍芝士。请提供您的配送地址。"
}

步骤 6:提供地址

复制代码
POST /api/conversation/message
{
  "conversationId": "conv-test-001",
  "text": "北京市朝阳区建国路 88 号"
}

响应:
{
  "text": "收到!配送地址:北京市朝阳区建国路 88 号。\n\n订单摘要:\n- 尺寸:大号\n- 口味:意大利辣香肠\n- 配料:双倍芝士\n- 地址:北京市朝阳区建国路 88 号\n\n请确认订单。"
}

步骤 7:确认订单

复制代码
POST /api/conversation/message
{
  "conversationId": "conv-test-001",
  "text": "确认"
}

响应:
{
  "text": "订单已确认!您的订单号是 #12345。预计 30-45 分钟送达。感谢您的订购!"
}

测试记录表

步骤 操作 状态 响应时间 备注
1 创建对话 200ms 成功
2 开始订购 2500ms LLM 响应
3 选择尺寸 2300ms 状态已更新
4 选择口味 2400ms 状态已更新
5 添加配料 2200ms 状态已更新
6 提供地址 2600ms 状态已更新
7 确认订单 2800ms 订单创建成功

可能遇到的问题

问题 1:对话状态丢失

  • 现象:Bot 忘记之前的选择

  • 原因:使用了内存存储且服务重启

  • 解决:使用持久化存储或不要重启服务

问题 2:响应不符合预期

  • 现象:Bot 的回复不按流程走

  • 原因:Agent 配置或 Prompt 不够明确

  • 解决:优化 Agent 的 instruction

问题 3:超时

  • 现象:请求超过 30 秒无响应

  • 原因:LLM API 响应慢

  • 解决:增加超时时间或使用更快的模型

评分标准

  • 完成完整流程:5 分

  • 记录详细:3 分

  • 处理错误:2 分


题目 14:问题诊断综合题 ⭐⭐⭐

问题:一个用户报告说"我的 BotSharp 项目无法启动",请设计一个完整的问题诊断流程。

要求

  1. 列出需要收集的信息

  2. 设计诊断步骤

  3. 列出可能的原因

  4. 提供解决方案

参考答案

第一步:收集基本信息

需要询问的问题

  1. 操作系统是什么?(Windows/Mac/Linux)

  2. .NET SDK 版本是多少?

  3. 如何启动的项目?(Visual Studio/命令行)

  4. 有什么错误信息?

  5. 之前能正常运行吗?

  6. 最近做了什么改动?

第二步:环境检查

检查清单

复制代码
# 1. 检查 .NET SDK
dotnet --version
# 应该是 8.0.x 或更高

# 2. 检查项目文件
cd BotSharp
ls BotSharp.sln
# 确认项目文件存在

# 3. 检查依赖包
dotnet restore
# 确认包还原成功

# 4. 检查编译
dotnet build
# 确认编译成功

第三步:诊断流程图

复制代码
开始
  ↓
能否编译?
  ├─ 否 → 检查 .NET SDK 版本
  │        ├─ 版本不对 → 安装正确版本
  │        └─ 版本正确 → 检查代码错误
  ↓
  是
  ↓
能否启动?
  ├─ 否 → 查看错误信息
  │        ├─ 端口占用 → 更换端口
  │        ├─ 配置错误 → 检查配置文件
  │        └─ 依赖问题 → 重新还原包
  ↓
  是
  ↓
能否访问 Swagger?
  ├─ 否 → 检查防火墙
  │        └─ 检查端口监听
  ↓
  是
  ↓
能否调用 API?
  ├─ 否 → 检查 LLM 配置
  │        └─ 检查数据库连接
  ↓
  是
  ↓
问题解决

第四步:常见问题及解决方案

问题类型 1:环境问题

症状 原因 解决方案
找不到 dotnet 命令 未安装 .NET SDK 安装 .NET 8.0 SDK
SDK 版本不匹配 版本太低 升级到 8.0+
编译失败 代码错误 查看错误信息修复

问题类型 2:配置问题

症状 原因 解决方案
缺少 API Key 未配置 LLM 添加 API Key
数据库连接失败 配置错误 使用 InMemory 存储
插件加载失败 配置路径错误 检查插件配置

问题类型 3:运行时问题

症状 原因 解决方案
端口被占用 其他程序占用 更换端口或关闭占用程序
内存不足 系统资源不足 增加内存或优化配置
网络超时 LLM API 慢 增加超时时间

第五步:标准诊断脚本

Windows PowerShell

复制代码
# BotSharp 诊断脚本
Write-Host "=== BotSharp 诊断工具 ===" -ForegroundColor Green

# 1. 检查 .NET SDK
Write-Host "`n1. 检查 .NET SDK..." -ForegroundColor Yellow
dotnet --version

# 2. 检查项目文件
Write-Host "`n2. 检查项目文件..." -ForegroundColor Yellow
if (Test-Path "BotSharp.sln") {
    Write-Host "✓ 项目文件存在" -ForegroundColor Green
} else {
    Write-Host "✗ 项目文件不存在" -ForegroundColor Red
}

# 3. 检查端口占用
Write-Host "`n3. 检查端口 5000..." -ForegroundColor Yellow
$port = netstat -ano | findstr :5000
if ($port) {
    Write-Host "✗ 端口 5000 已被占用" -ForegroundColor Red
    Write-Host $port
} else {
    Write-Host "✓ 端口 5000 可用" -ForegroundColor Green
}

# 4. 尝试编译
Write-Host "`n4. 尝试编译项目..." -ForegroundColor Yellow
dotnet build --no-restore

Write-Host "`n=== 诊断完成 ===" -ForegroundColor Green

Mac/Linux Bash

复制代码
#!/bin/bash
# BotSharp 诊断脚本

echo "=== BotSharp 诊断工具 ==="

# 1. 检查 .NET SDK
echo -e "\n1. 检查 .NET SDK..."
dotnet --version

# 2. 检查项目文件
echo -e "\n2. 检查项目文件..."
if [ -f "BotSharp.sln" ]; then
    echo "✓ 项目文件存在"
else
    echo "✗ 项目文件不存在"
fi

# 3. 检查端口占用
echo -e "\n3. 检查端口 5000..."
if lsof -i :5000 > /dev/null; then
    echo "✗ 端口 5000 已被占用"
    lsof -i :5000
else
    echo "✓ 端口 5000 可用"
fi

# 4. 尝试编译
echo -e "\n4. 尝试编译项目..."
dotnet build --no-restore

echo -e "\n=== 诊断完成 ==="

评分标准

  • 诊断流程完整:4 分

  • 覆盖常见问题:3 分

  • 提供有效解决方案:3 分


六、学习检查清单

完成本章学习后,你应该能够:

项目克隆

  • \] 选择合适的项目存放位置

  • \] 验证克隆是否成功

项目启动

  • \] 使用 Visual Studio 打开项目

  • \] 启动项目(IDE 或命令行)

  • \] 解决常见的启动错误

  • \] 使用 Postman 测试 API

  • \] 使用 Swagger UI 测试 API

  • \] 理解请求和响应格式

调试技能

  • \] 在 Visual Studio 中设置断点

  • \] 查看变量值

  • \] 查看调用堆栈

  • \] 排查常见错误

  • \] 完成完整的测试流程

  • \] 记录测试结果


七、实践任务

任务 1:环境搭建 ⭐

目标:在你的电脑上成功运行 BotSharp

步骤

  1. 克隆 BotSharp 项目

  2. 配置 LLM 提供商

  3. 启动项目

  4. 访问 Swagger UI

  5. 截图证明成功

提交

  • 启动成功的控制台截图

  • Swagger UI 页面截图


任务 2:API 测试 ⭐⭐

目标:使用 Postman 完成基本的 API 测试

步骤

  1. 安装 Postman

  2. 创建一个新的 Collection

  3. 添加以下请求:

    • 获取 Agent 列表

    • 创建对话

    • 发送消息

  4. 测试所有请求

  5. 导出 Collection

提交

  • Postman Collection JSON 文件

  • 测试结果截图


任务 3:调试实践 ⭐⭐⭐

目标:使用调试器追踪一次完整的消息处理流程

步骤

  1. 在以下位置设置断点:

    • ConversationController.SendMessage

    • ConversationService.SendMessage

    • LLM Provider 的调用方法

  2. 发送一条消息

  3. 逐步执行,观察数据流转

  4. 记录关键变量的值

提交

  • 调试过程的截图

  • 数据流转的文字说明


任务 4:问题排查 ⭐⭐⭐

目标:故意制造一个错误并解决它

步骤

  1. 选择一个错误场景(例如:删除 API Key)

  2. 尝试运行项目

  3. 记录错误信息

  4. 分析错误原因

  5. 解决问题

  6. 验证修复

提交

  • 错误信息截图

  • 问题分析报告

  • 解决方案说明


八、总结

通过完成这些练习题,你应该已经:

  1. ✅ 掌握了项目的克隆和启动

  2. ✅ 学会了配置和测试 API

  3. ✅ 掌握了基本的调试技能

  4. ✅ 能够排查和解决常见问题

  5. ✅ 完成了完整的测试流程

学习成果

  • 🎯 能够独立搭建 BotSharp 开发环境

  • 🎯 能够使用多种工具测试 API

  • 🎯 能够使用调试器定位问题

  • 🎯 能够分析日志和错误信息

  • 🎯 能够完成基本的开发任务

下一步

  • 继续学习第 04 章:核心概念

  • 深入理解 Agent、Plugin、LLM 等概念

  • 学习如何开发自己的功能

学习建议

  • 📚 多动手实践,不要只看不做

  • 🔧 遇到错误不要慌,学会分析日志

  • 💭 理解每个步骤的原理,不要死记硬背

  • 🤝 遇到问题及时在社区寻求帮助

  • 📝 做好笔记,记录重要的命令和配置

常见问题汇总

问题 快速解决方案
克隆失败 使用 Gitee 镜像或浅克隆
编译失败 检查 .NET SDK 版本
启动失败 检查端口和配置文件
API 调用失败 检查 API Key 和网络
调试无效 确认使用 Debug 模式

技能自测

给自己打分(1-5 分):

  • \] 项目克隆和 Git 操作:___/5

  • \] API 测试能力:___/5

  • \] 问题排查能力:___/5

  • 20-25 分:优秀!可以继续下一章

  • 15-19 分:良好,建议多练习

  • 10-14 分:及格,需要加强实践

  • 10 分以下:建议重新学习本章

继续加油!你已经掌握了 BotSharp 的快速启动,接下来让我们深入学习核心概念!🚀

更多AIGC文章

RAG技术全解:从原理到实战的简明指南

更多VibeCoding文章

相关推荐
数字游民95272 小时前
2小时VibeCoding了一个看图猜词小程序:猜对了么
人工智能·ai·小程序·ai绘画·数字游民9527
每天学一点儿2 小时前
【SimpleITK】从 Python 闭包到空间几何
人工智能
心态与习惯3 小时前
深度学习中的 seq2seq 模型
人工智能·深度学习·seq2seq
Coder_Boy_3 小时前
基于SpringAI的在线考试系统-0到1全流程研发:DDD、TDD与CICD协同实践
java·人工智能·spring boot·架构·ddd·tdd
北京耐用通信3 小时前
耐达讯自动化Profibus总线光纤中继器:光伏逆变器通讯的“稳定纽带”
人工智能·物联网·网络协议·自动化·信息与通信
啊阿狸不会拉杆4 小时前
《数字图像处理》第 7 章 - 小波与多分辨率处理
图像处理·人工智能·算法·计算机视觉·数字图像处理
AI即插即用4 小时前
即插即用系列 | CVPR 2025 AmbiSSL:首个注释模糊感知的半监督医学图像分割框架
图像处理·人工智能·深度学习·计算机视觉·视觉检测
数说星榆1814 小时前
脑启发计算与类神经形态芯片的协同
人工智能
m0_650108244 小时前
AD-GS:面向自监督自动驾驶场景的目标感知 B 样条高斯 splatting 技术
论文阅读·人工智能·自动驾驶·基于高斯泼溅的自监督框架·高质量场景渲染