克隆 BotSharp 项目
学习目标
完成本节学习后,你将能够:
-
使用 Git 成功克隆 BotSharp 项目
-
选择合适的项目存放位置
-
解决常见的克隆问题
前置知识
-
已安装 Git(参考第 01 章)
-
了解基本的命令行操作
-
有稳定的网络连接
为什么要克隆项目?
克隆项目就像是把 GitHub 上的代码"复制"到你的电脑上。想象一下,GitHub 就像一个图书馆,克隆就是把你需要的书借回家。这样你就可以在本地查看代码、运行项目、进行修改了。
第一步:选择项目存放位置
在克隆项目之前,我们需要选择一个合适的位置来存放代码。
推荐的存放位置
Windows 系统:
C:\Projects\BotSharp
或
D:\Code\BotSharp
Mac/Linux 系统:
~/Projects/BotSharp
或
~/Code/BotSharp
选择建议
-
避免中文路径:路径中不要包含中文字符,可能会导致一些工具出错
-
避免空格:路径中尽量不要有空格
-
不要太深:路径层级不要太深,方便访问
-
有足够空间:确保磁盘有至少 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
解决方案:
-
检查网络连接:确保你的电脑能访问 GitHub
-
使用代理 (如果你有):
git config --global http.proxy http://127.0.0.1:7890 git config --global https.proxy http://127.0.0.1:7890 -
使用 Gitee 镜像 (国内用户推荐):
git clone https://gitee.com/dotnetchina/BotSharp.git
问题 2:克隆速度很慢
解决方案:
-
使用浅克隆(只克隆最新版本,不包含完整历史):
git clone --depth 1 https://github.com/dotnetcore/BotSharp.git -
使用 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
解决方案:
-
清理磁盘空间
-
选择另一个有足够空间的磁盘
-
使用浅克隆减少空间占用
问题 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 克隆可以方便地更新代码和查看历史记录。
练习
-
在你的电脑上选择一个合适的位置,克隆 BotSharp 项目
-
验证克隆是否成功,检查关键文件是否存在
-
尝试查看项目的提交历史(使用
git log命令) -
(可选)克隆 BotSharp-UI 项目
完成这些练习后,你就可以继续学习如何运行项目了!
运行 PizzaBot 示例
学习目标
完成本节学习后,你将能够:
-
成功启动 BotSharp 项目
-
运行 PizzaBot 示例
-
理解启动参数的含义
-
识别启动成功的标志
-
解决常见的启动错误
前置知识
-
已完成环境准备(第 01 章)
-
已克隆 BotSharp 项目(上一节)
-
已安装 .NET SDK 8.0 或更高版本
什么是 PizzaBot?
PizzaBot 是 BotSharp 提供的一个示例项目,就像学习做菜时的"第一道菜"。它是一个简单的披萨订购机器人,可以帮助你:
-
理解 BotSharp 的基本工作流程
-
学习如何配置 Agent
-
体验对话式 AI 的交互
通过运行 PizzaBot,你可以快速看到 BotSharp 的实际效果,而不需要从零开始编写代码。
第一步:打开项目
使用 Visual Studio(推荐)
-
启动 Visual Studio
-
打开解决方案
-
点击"文件" → "打开" → "项目/解决方案"
-
导航到你克隆的 BotSharp 目录
-
选择
BotSharp.sln文件 -
点击"打开"
-
-
等待项目加载
-
Visual Studio 会自动还原 NuGet 包
-
这个过程可能需要几分钟
-
你会在底部看到"正在还原..."的提示
-
使用 VS Code
-
启动 VS Code
-
打开文件夹
-
点击"文件" → "打开文件夹"
-
选择 BotSharp 目录
-
点击"选择文件夹"
-
-
安装推荐扩展
-
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
-
设置启动项目
-
在解决方案资源管理器中
-
右键点击
WebStarter项目 -
选择"设为启动项目"
-
-
选择启动配置
-
在顶部工具栏找到启动按钮旁边的下拉菜单
-
选择
http或https
-
-
点击启动按钮
-
点击绿色的"▶ 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 中:
-
找到
Agent相关的 API -
展开
GET /api/agent接口 -
点击"Try it out"按钮
-
点击"Execute"按钮
你应该能在响应中看到 PizzaBot Agent 的信息。
常见启动错误及解决方案
错误 1:端口被占用
错误信息:
Failed to bind to address http://127.0.0.1:5000: address already in use.
原因: 端口 5000 已经被其他程序占用。
解决方案:
-
更换端口:
dotnet run --urls "http://localhost:5005" -
找到并关闭占用端口的程序:
Windows:
# 查找占用端口的进程 netstat -ano | findstr :5000 # 结束进程(替换 PID 为实际的进程 ID) taskkill /PID <PID> /FMac/Linux:
# 查找占用端口的进程 lsof -i :5000 # 结束进程 kill -9 <PID>
错误 2:.NET SDK 版本不匹配
错误信息:
The current .NET SDK does not support targeting .NET 8.0.
原因: 你的 .NET SDK 版本太低。
解决方案:
-
检查当前版本:
dotnet --version -
下载并安装 .NET 8.0 SDK:
-
下载 .NET 8.0 SDK
-
安装后重启命令行
错误 3:NuGet 包还原失败
错误信息:
error NU1101: Unable to find package...
原因: 无法从 NuGet 服务器下载依赖包。
解决方案:
-
清理并重新还原:
dotnet clean dotnet restore -
检查 NuGet 源:
dotnet nuget list source -
添加官方 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。
解决方案:
-
打开
appsettings.json -
添加你的 API Key(参考第二步)
-
保存文件并重新启动项目
错误 5:数据库连接失败
错误信息:
Unable to connect to database
原因: 如果配置了外部数据库(如 MongoDB),但数据库服务未启动。
解决方案:
-
使用内存存储(开发环境推荐):
在
appsettings.json中:{ "Database": { "Provider": "InMemory" } } -
启动数据库服务:
如果使用 MongoDB:
# Windows net start MongoDB # Mac/Linux sudo systemctl start mongod
错误 6:编译错误
错误信息:
Build FAILED.
原因: 代码有语法错误或依赖问题。
解决方案:
-
查看详细错误信息:
dotnet build -
清理并重新构建:
dotnet clean dotnet build -
检查是否有未提交的更改:
git status -
重置到最新版本:
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
重新启动
修改配置文件后,需要重新启动服务才能生效:
-
停止当前运行的服务
-
保存配置文件
-
重新启动服务
性能优化建议
开发环境优化
-
使用 Development 环境:
dotnet run --environment Development这会启用详细的错误信息和热重载功能。
-
启用热重载:
dotnet watch run修改代码后会自动重新编译和启动。
-
减少日志输出:
在
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 中将日志级别设置为 Debug 或 Trace。
Q: 启动失败了怎么办? A: 首先查看控制台的错误信息,然后参考本节的"常见启动错误"部分。如果还是无法解决,可以在社区寻求帮助。
练习
-
使用 Visual Studio 启动 BotSharp 项目
-
访问 Swagger UI,浏览可用的 API
-
尝试使用不同的端口启动项目
-
故意制造一个错误(如删除 API Key),观察错误信息
-
使用
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 请求。
-
打开 Postman
-
导入集合
-
点击左上角的"Import"按钮
-
选择"Link"标签
-
输入集合地址:
https://www.postman.com/orange-flare-634868/workspace/botsharp -
点击"Continue"
-
点击"Import"
-
-
查看集合
-
在左侧边栏找到"BotSharp"集合
-
展开可以看到所有的 API 请求
-
第二步:配置环境变量
-
创建环境
-
点击右上角的"Environments"
-
点击"+"创建新环境
-
命名为"BotSharp Local"
-
-
添加变量
添加以下变量:
变量名 初始值 当前值 baseUrl http://localhost:5000 http://localhost:5000 conversationId agentId -
保存环境
-
点击"Save"按钮
-
在右上角选择"BotSharp Local"环境
-
第三步:获取 Agent 列表
-
选择请求
-
在集合中找到"Get Agents"请求
-
点击打开
-
-
发送请求
- 点击"Send"按钮
-
查看响应
你应该能看到类似这样的响应:
{ "items": [ { "id": "01234567-89ab-cdef-0123-456789abcdef", "name": "PizzaBot", "description": "A pizza ordering assistant", "isPublic": true, "disabled": false } ], "count": 1 } -
保存 Agent ID
-
复制 PizzaBot 的
id值 -
在环境变量中设置
agentId为这个值
-
第四步:创建对话
-
选择请求
- 找到"Create Conversation"请求
-
修改请求体
请求体应该是这样的:
{ "agentId": "{{agentId}}", "channel": "postman", "userId": "test-user" } -
发送请求
- 点击"Send"按钮
-
查看响应
响应示例:
{ "conversationId": "conv-12345678-1234-1234-1234-123456789abc", "agentId": "01234567-89ab-cdef-0123-456789abcdef", "status": "active", "createdAt": "2024-01-09T10:30:00Z" } -
保存 Conversation ID
-
复制
conversationId的值 -
在环境变量中设置
conversationId为这个值
-
第五步:发送消息
-
选择请求
- 找到"Send Message"请求
-
修改请求体
{ "conversationId": "{{conversationId}}", "text": "我想订一份披萨", "postback": null } -
发送请求
- 点击"Send"按钮
-
查看响应
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
-
找到 Agent 部分
-
滚动页面找到"Agent"标签
-
点击展开
-
-
选择 GET /api/agent
- 点击展开这个接口
-
执行请求
-
点击"Try it out"按钮
-
点击"Execute"按钮
-
-
查看响应
-
在下方的"Responses"部分查看结果
-
复制 PizzaBot 的 ID
-
第三步:创建对话
-
找到 Conversation 部分
- 找到"Conversation"标签
-
选择 POST /api/conversation
- 点击展开
-
填写请求体
-
点击"Try it out"
-
在请求体中填写:
{ "agentId": "你复制的Agent ID", "channel": "swagger", "userId": "test-user" }
-
-
执行请求
-
点击"Execute"
-
复制返回的 conversationId
-
第四步:发送消息
-
选择 POST /api/conversation/message
-
填写请求体
{ "conversationId": "你复制的Conversation ID", "text": "我想订一份披萨" } -
执行请求
-
点击"Execute"
-
查看 PizzaBot 的回复
-
完整的测试场景
场景 1:成功订购披萨
步骤:
-
创建对话
-
发送:"我想订一份披萨"
-
发送:"大号的"
-
发送:"意大利辣香肠"
-
发送:"不需要额外配料"
-
发送:"送到XX地址"
-
发送:"确认订单"
预期结果:
-
每一步都能收到合理的回复
-
最后能成功创建订单
场景 2:取消订单
步骤:
-
创建对话
-
发送:"我想订一份披萨"
-
发送:"取消订单"
预期结果:
-
系统确认取消
-
对话可以重新开始
场景 3:查询菜单
步骤:
-
创建对话
-
发送:"你们有什么披萨?"
预期结果:
-
返回完整的披萨菜单
-
包含价格和描述
验证测试结果
成功的标志
✅ 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 等持久化存储可以保留数据。
练习
-
使用 Postman 完成一次完整的披萨订购流程
-
使用 curl 命令创建对话并发送消息
-
在 Swagger UI 中测试所有 Agent 相关的 API
-
尝试发送一些"刁难"的消息,看 PizzaBot 如何回应
-
记录一次完整的测试过程,包括请求和响应
完成这些练习后,你就可以继续学习如何调试项目了!
调试 BotSharp 项目
学习目标
完成本节学习后,你将能够:
-
使用 Visual Studio 进行断点调试
-
使用 VS Code 进行调试
-
查看和分析日志信息
-
排查常见的运行时错误
-
使用调试工具定位问题
-
理解调试的基本流程
前置知识
-
已成功运行 BotSharp 项目
-
了解基本的编程概念
-
熟悉 Visual Studio 或 VS Code
什么是调试?
调试就像是"侦探工作",当程序出现问题时,我们需要找出问题在哪里。想象一下:
-
你的汽车突然不能启动了(程序出错)
-
你需要检查电池、油箱、发动机(查看日志、设置断点)
-
找到问题后修复它(修改代码)
调试是每个开发者必备的技能,它能帮助你:
-
理解代码的执行流程
-
找出程序错误的原因
-
验证代码是否按预期工作
-
学习和理解复杂的代码
方法 1:使用 Visual Studio 调试
Visual Studio 是最强大的 C# 调试工具,提供了丰富的调试功能。
第一步:设置断点
断点就像是在代码中设置的"暂停标记",程序运行到这里时会自动停下来。
如何设置断点:
-
打开要调试的文件
- 例如:
src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.cs
- 例如:
-
点击行号左侧
-
在你想暂停的代码行号左侧点击
-
会出现一个红色的圆点,这就是断点
-
-
快捷键设置
-
将光标放在要设置断点的行
-
按
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:使用调试按钮
-
确保
WebStarter是启动项目 -
点击工具栏上的绿色"▶ WebStarter"按钮旁边的下拉箭头
-
选择"调试"模式
-
点击按钮启动
方法 2:使用快捷键
- 按
F5键启动调试
方法 3:使用菜单
- 点击"调试" → "开始调试"
第三步:触发断点
启动后,程序会正常运行,直到执行到断点位置。
触发断点的方法:
-
使用 Postman 发送请求
-
创建对话
-
发送消息
-
程序会在断点处暂停
-
-
使用 Swagger UI
-
访问
http://localhost:5000/swagger -
执行相应的 API
-
程序会在断点处暂停
-
第四步:检查变量
当程序在断点处暂停时,你可以查看所有变量的值。
查看变量的方法:
-
鼠标悬停
-
将鼠标悬停在变量名上
-
会显示变量的当前值
-
-
使用"局部变量"窗口
-
在底部找到"局部变量"标签
-
显示当前作用域内的所有变量
-
-
使用"监视"窗口
-
右键点击变量
-
选择"添加监视"
-
在"监视"窗口中查看
-
-
使用"即时窗口"
-
按
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,进入函数内部
第六步:条件断点
有时候你只想在特定条件下暂停程序。
设置条件断点:
-
右键点击断点
-
右键点击红色断点圆点
-
选择"条件..."
-
-
设置条件
-
选择"条件表达式"
-
输入条件,例如:
conversationId == "特定ID" -
点击"关闭"
-
-
设置命中次数
-
选择"命中次数"
-
设置断点触发的次数
-
示例:只在特定用户时暂停
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);
}
第七步:查看调用堆栈
调用堆栈显示了程序是如何一步步执行到当前位置的。
查看调用堆栈:
-
打开"调用堆栈"窗口
-
在调试时,底部会显示"调用堆栈"标签
-
或按
Ctrl + Alt + C
-
-
理解调用堆栈
BotSharp.Core.dll!ConversationService.SendMessage() 第 45 行 BotSharp.OpenAPI.dll!ConversationController.SendMessage() 第 78 行 Microsoft.AspNetCore.Mvc.Core.dll!ControllerActionInvoker.InvokeActionMethodAsync()这表示:
-
最上面是当前位置
-
往下是调用链
-
可以双击任意一行跳转到那个位置
-
第八步:修改变量值
在调试过程中,你可以临时修改变量的值来测试不同的情况。
修改变量:
-
在"局部变量"窗口中
-
找到要修改的变量
-
双击值
-
输入新值
-
按回车
-
-
在"即时窗口"中
-
输入:
conversationId = "new-id" -
按回车
-
注意: 这只是临时修改,不会改变源代码。
方法 2:使用 VS Code 调试
VS Code 也提供了强大的调试功能,虽然界面不同,但原理相同。
第一步:配置调试
-
打开调试面板
-
点击左侧的"运行和调试"图标
-
或按
Ctrl + Shift + D
-
-
创建 launch.json
-
点击"创建 launch.json 文件"
-
选择".NET Core"
-
-
配置内容
{ "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 中设置断点:
-
点击行号左侧
- 会出现红色圆点
-
快捷键
- 按
F9切换断点
- 按
第三步:启动调试
-
选择配置
- 在调试面板顶部选择".NET Core Launch (web)"
-
启动
-
点击绿色的播放按钮
-
或按
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(推荐):
-
安装 NuGet 包
dotnet add package Serilog.AspNetCore dotnet add package Serilog.Sinks.File -
配置 Program.cs
using Serilog; Log.Logger = new LoggerConfiguration() .WriteTo.Console() .WriteTo.File("logs/botsharp-.txt", rollingInterval: RollingInterval.Day) .CreateLogger(); builder.Host.UseSerilog(); -
日志文件位置
-
日志会保存在
logs/目录 -
每天创建一个新文件
-
文件名格式:
botsharp-20240109.txt
-
常见错误排查
错误 1:NullReferenceException
错误信息:
System.NullReferenceException: Object reference not set to an instance of an object.
原因: 尝试访问一个 null 对象的属性或方法。
排查步骤:
-
查看堆栈跟踪
at BotSharp.Core.Conversations.Services.ConversationService.SendMessage() in ConversationService.cs:line 45 -
在出错行设置断点
-
打开
ConversationService.cs -
在第 45 行设置断点
-
-
检查变量
-
运行到断点
-
检查哪个变量是 null
-
找出为什么是 null
-
-
修复代码
// 修复前 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() 等方法。
排查步骤:
-
找到出错位置
- 查看堆栈跟踪
-
检查集合
- 在断点处查看集合是否为空
-
修复代码
// 修复前 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')
原因: 传入了无效的参数。
排查步骤:
-
检查参数来源
-
在函数入口设置断点
-
查看参数值
-
-
添加参数验证
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 响应超时
-
数据库查询超时
-
网络连接超时
排查步骤:
-
检查日志
-
查看超时前的最后一条日志
-
确定是哪个操作超时
-
-
增加超时时间
// 配置 HTTP 客户端超时 services.AddHttpClient("OpenAI", client => { client.Timeout = TimeSpan.FromSeconds(120); // 增加到 120 秒 }); -
添加重试机制
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 反序列化失败。
排查步骤:
-
查看原始 JSON
-
在日志中记录原始 JSON 字符串
_logger.LogDebug("Received JSON: {Json}", jsonString);
-
-
检查数据类型
- 确认 JSON 结构与 C# 类匹配
-
添加错误处理
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 提供了性能分析工具:
-
启动性能分析器
-
点击"调试" → "性能探查器"
-
选择"CPU 使用率"或"内存使用率"
-
点击"开始"
-
-
分析结果
-
查看哪些函数占用最多时间
-
查看内存分配情况
-
找出性能瓶颈
-
技巧 5:使用远程调试
调试部署在服务器上的应用:
-
在服务器上安装远程调试器
- 下载 Remote Tools for Visual Studio
-
配置防火墙
- 允许远程调试器端口
-
在 Visual Studio 中连接
-
点击"调试" → "附加到进程"
-
选择"远程(无身份验证)"
-
输入服务器地址
-
选择进程并附加
-
调试工作流程
标准调试流程
-
重现问题
-
确保能稳定重现错误
-
记录重现步骤
-
-
收集信息
-
查看错误消息
-
查看堆栈跟踪
-
查看日志
-
-
形成假设
-
根据信息推测问题原因
-
列出可能的原因
-
-
验证假设
-
设置断点
-
检查变量
-
单步执行
-
-
修复问题
-
修改代码
-
测试修复
-
-
验证修复
-
重新测试
-
确保问题解决
-
确保没有引入新问题
-
调试检查清单
在开始调试前,检查以下项目:
-
\] 是否使用最新的代码?
-
\] 配置文件是否正确?
-
\] 数据库连接是否正常?
-
\] 日志级别是否设置为 Debug?
恭喜你!你已经掌握了调试 BotSharp 项目的各种方法。让我们回顾一下本节的重点:
✅ Visual Studio 调试 :断点、单步执行、查看变量 ✅ VS Code 调试 :配置和使用调试功能 ✅ 日志分析 :查看和配置日志 ✅ 错误排查 :常见错误的排查方法 ✅ 调试技巧 :提高调试效率的技巧 ✅ 调试流程:系统化的调试方法
下一步
现在你已经掌握了环境准备、项目结构、快速启动和调试的知识,接下来我们将深入学习 BotSharp 的核心概念,包括 Agent、Plugin、LLM 集成等。
常见问题
Q: 断点不起作用怎么办? A: 检查是否在 Debug 模式下运行,确保代码已重新编译,确保断点设置在可执行的代码行上。
Q: 如何调试异步代码? A: 异步代码的调试与同步代码相同,但要注意查看"任务"窗口了解异步操作的状态。
Q: 调试时程序很慢怎么办? A: 这是正常的,因为调试器需要额外的开销。可以减少断点数量,或使用日志代替断点。
Q: 如何调试第三方库的代码? A: 在 Visual Studio 中,取消勾选"工具" → "选项" → "调试" → "启用仅我的代码",然后可以单步进入第三方库。
Q: 生产环境出现问题如何调试? A: 不要在生产环境使用断点调试。应该:
-
查看日志文件
-
启用详细日志
-
使用应用程序监控工具
-
在开发环境重现问题
Q: 如何调试性能问题? A: 使用性能分析器,查看 CPU 和内存使用情况,找出性能瓶颈。
练习
-
在
ConversationService.SendMessage方法中设置断点,发送一条消息,观察执行流程 -
修改日志级别为 Debug,观察更详细的日志输出
-
故意制造一个 NullReferenceException,使用调试器找出原因
-
使用条件断点,只在特定条件下暂停程序
-
查看一次完整的 API 调用的调用堆栈
-
在调试过程中修改一个变量的值,观察程序行为的变化
-
配置 Serilog,将日志保存到文件
完成这些练习后,你就完全掌握了 BotSharp 的调试技能!现在可以继续学习第 04 章:核心概念了。
第 03 章 - 快速启动实践
练习题
说明
本练习题旨在帮助你巩固第 03 章学到的知识。题目分为三个难度等级:
-
⭐ 基础题:测试基本操作能力
-
⭐⭐ 进阶题:测试问题排查能力
-
⭐⭐⭐ 挑战题:测试综合应用能力
本章重点是实践操作,建议在实际环境中完成练习。每道题都有详细的参考答案和解析。
一、项目克隆实践题
题目 1:基础克隆操作 ⭐
问题:请完成以下操作并回答问题:
-
在你的电脑上选择一个合适的位置
-
使用 Git 克隆 BotSharp 项目
-
验证克隆是否成功
要求:
-
记录你选择的项目路径
-
记录克隆命令
-
记录克隆所用时间
-
列出项目根目录下的主要文件和文件夹
参考答案:
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 解析问题
解决方案:
-
检查网络连接:
ping github.com -
使用代理(如果有):
git config --global http.proxy http://127.0.0.1:7890 git config --global https.proxy http://127.0.0.1:7890 -
使用 Gitee 镜像(国内用户):
git clone https://gitee.com/dotnetchina/BotSharp.git -
使用 SSH 方式:
git clone git@github.com:dotnetcore/BotSharp.git
错误 B:文件名太长(Windows)
原因:
-
Windows 默认路径长度限制为 260 字符
-
项目中有些文件路径较深
解决方案:
-
启用长路径支持:
# 以管理员身份运行 git config --system core.longpaths true -
修改注册表(Windows 10 1607+):
-
打开注册表编辑器
-
导航到:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem -
将
LongPathsEnabled设置为 1
-
-
选择更短的路径:
# 不好:C:\Users\YourName\Documents\Projects\BotSharp # 更好:C:\Projects\BotSharp
错误 C:克隆速度很慢
原因:
-
网络带宽限制
-
GitHub 服务器距离远
-
项目历史记录很大
解决方案:
-
使用浅克隆(只克隆最新版本):
git clone --depth 1 https://github.com/dotnetcore/BotSharp.git -
使用镜像站点:
git clone https://gitee.com/dotnetchina/BotSharp.git -
使用下载工具:
-
使用 GitHub Desktop
-
使用迅雷等下载工具下载 ZIP
-
-
等待或稍后重试:
-
有时是 GitHub 服务器繁忙
-
换个时间段尝试
-
评分标准:
-
正确识别错误原因:3 分
-
提供有效解决方案:5 分
-
提供多种解决方案:2 分
题目 3:Git 操作实践 ⭐⭐
问题:完成以下 Git 操作:
-
查看当前分支
-
查看最近 5 次提交记录
-
查看项目的远程仓库地址
-
切换到一个特定的标签(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 提供商 ⭐
问题:请完成以下配置任务:
-
打开
appsettings.json文件 -
找到 LLM 配置部分
-
配置 OpenAI 提供商(使用测试 API Key)
-
说明每个配置项的作用
参考答案:
配置示例:
{
"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 已被其他程序使用
解决方案:
-
更换端口:
dotnet run --urls "http://localhost:5005" -
找到并关闭占用端口的程序:
Windows:
# 查找占用端口的进程 netstat -ano | findstr :5000 # 结束进程(替换 PID) taskkill /PID 12345 /FMac/Linux:
# 查找占用端口的进程 lsof -i :5000 # 结束进程 kill -9 12345
错误 B:.NET SDK 版本不匹配
原因:系统安装的 .NET SDK 版本低于项目要求
解决方案:
-
检查当前版本:
dotnet --version -
下载并安装 .NET 8.0 SDK:
-
下载 .NET 8.0 SDK
-
安装后重启命令行
-
验证安装:
dotnet --list-sdks # 应该能看到 8.0.xxx
错误 C:NuGet 包还原失败
原因:
-
NuGet 源不可用
-
网络连接问题
-
包版本不存在
解决方案:
-
清理并重新还原:
dotnet clean dotnet restore -
检查 NuGet 源:
dotnet nuget list source -
添加官方源:
dotnet nuget add source https://api.nuget.org/v3/index.json -n nuget.org -
使用国内镜像(可选):
dotnet nuget add source https://nuget.cdn.azure.cn/v3/index.json -n azure-cn
错误 D:缺少 API Key
原因:未配置 LLM 提供商的 API Key
解决方案:
-
打开配置文件:
src/WebStarter/appsettings.json -
添加 API Key:
{ "LlmProviders": [ { "Provider": "openai", "Models": [ { "Name": "gpt-4", "ApiKey": "your-actual-api-key-here" } ] } ] } -
保存并重启项目
评分标准:
-
正确识别每个错误原因: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
步骤:
-
打开浏览器
-
访问:
http://localhost:5000/swagger -
应该能看到 API 文档页面
成功标志:
-
页面正常加载
-
显示 BotSharp API 列表
-
可以展开和测试 API
方法 3:调用健康检查 API
使用 curl:
curl http://localhost:5000/health
预期响应:
{
"status": "Healthy",
"totalDuration": "00:00:00.0123456"
}
方法 4:测试 Agent API
使用 Swagger UI:
-
找到
GET /api/agent接口 -
点击 "Try it out"
-
点击 "Execute"
预期响应:
{
"items": [
{
"id": "...",
"name": "PizzaBot",
"description": "..."
}
],
"count": 1
}
方法 5:检查日志文件
查看日志:
# 如果配置了文件日志
cat logs/botsharp-20240109.txt
成功标志:
-
插件加载成功
-
Agent 初始化完成
-
没有错误日志
评分标准:
-
列出 3 种方法:6 分
-
说明验证步骤:2 分
-
说明成功标志:2 分
三、API 测试实践题
题目 7:Postman 测试流程 ⭐⭐
问题:使用 Postman 完成以下测试流程:
-
获取 Agent 列表
-
创建一个新对话
-
发送消息:"你好"
-
发送消息:"我想订披萨"
-
记录每一步的请求和响应
参考答案:
步骤 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 命令完成以下操作:
-
获取 Agent 列表
-
创建对话
-
发送一条消息
请写出完整的 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"
}
验证步骤:
-
检查请求体是否包含所有必填字段
-
检查字段名拼写是否正确
-
检查字段值是否为空
错误 B:404 Not Found - 资源不存在
原因:
-
使用了不存在的
conversationId -
conversationId拼写错误 -
对话已过期或被删除
错误请求示例:
{
"conversationId": "wrong-id",
"text": "你好"
}
修复方法:
-
重新创建对话:
# 创建新对话 POST /api/conversation # 使用返回的 conversationId -
检查 ID 格式:
正确格式:conv-12345678-1234-1234-1234-123456789abc 错误格式:conv-123 或 12345678 -
验证对话是否存在:
GET /api/conversation/{conversationId}
错误 C:500 Internal Server Error - 服务器内部错误
可能原因:
-
LLM API 调用失败
-
数据库连接失败
-
代码逻辑错误
-
配置错误
排查步骤:
-
查看服务器日志:
# 在运行项目的控制台查看错误信息 -
检查 LLM 配置:
{ "LlmProviders": [ { "Provider": "openai", "Models": [ { "ApiKey": "检查是否有效" } ] } ] } -
检查数据库连接:
{ "Database": { "Provider": "InMemory" // 或检查 MongoDB 连接 } } -
测试 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:断点调试基础 ⭐
问题:请完成以下调试操作:
-
在 Visual Studio 中打开 BotSharp 项目
-
找到
ConversationService.cs文件 -
在
SendMessage方法的第一行设置断点 -
启动调试
-
使用 Postman 发送一条消息
-
观察程序在断点处暂停
-
查看
conversationId和message参数的值
要求:
-
截图显示断点设置
-
记录观察到的变量值
-
说明如何继续执行
参考答案:
步骤 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
-
可能原因:
-
网络代理问题
-
防火墙阻止
-
SSL 证书验证失败
-
网络不稳定
-
解决方案:
-
检查网络连接:
ping api.openai.com -
配置代理(如果使用代理):
{ "LlmProviders": [ { "Provider": "openai", "Proxy": "http://127.0.0.1:7890" } ] } -
禁用 SSL 验证(仅用于测试):
// 在 Program.cs 中添加(不推荐用于生产环境) ServicePointManager.ServerCertificateValidationCallback = (sender, cert, chain, sslPolicyErrors) => true; -
使用备用 Endpoint:
{ "Endpoint": "https://api.openai-proxy.com/v1" } -
检查防火墙设置:
-
确保允许访问 api.openai.com
-
端口 443 (HTTPS) 需要开放
-
错误 B:空引用异常
问题分析:
-
代码尝试访问 null 对象的属性或方法
-
这是编程错误,需要修复代码
排查步骤:
-
查看完整堆栈跟踪:
at BotSharp.Core.Conversations.Services.ConversationService.SendMessage() in ConversationService.cs:line 45 -
在出错行设置断点:
-
打开 ConversationService.cs
-
在第 45 行设置断点
-
重现错误
-
-
检查变量:
-
查看哪个变量是 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
-
功能可以继续,但可能不是预期行为
可能原因:
-
Agent ID 拼写错误
-
Agent 配置文件不存在
-
Agent 未正确加载
-
路由配置错误
排查步骤:
-
检查 Agent 是否存在:
GET /api/agent # 查看返回的 Agent 列表 -
检查 Agent 配置文件:
# 查看配置文件是否存在 ls data/agents/customer-service.json -
检查 Agent ID:
// 确保 ID 匹配 { "id": "customer-service", // 必须与请求中的 ID 一致 "name": "Customer Service Bot" } -
检查插件加载:
# 查看启动日志 info: BotSharp.Core.Plugins.PluginLoader[0] Loaded plugin: CustomerServicePlugin
解决方案:
-
修正 Agent ID:
// 请求中使用正确的 ID { "agentId": "pizza-bot" // 而不是 "customer-service" } -
创建缺失的 Agent:
-
在
data/agents/目录创建配置文件 -
重启服务
-
-
检查路由配置:
{ "Routing": { "DefaultAgent": "pizza-bot", "FallbackAgent": "general-assistant" } }
评分标准:
-
正确识别错误类型:3 分
-
分析错误原因:4 分
-
提供有效解决方案:3 分
五、综合实战题
题目 13:完整订单流程测试 ⭐⭐⭐
问题:请完成一个完整的披萨订购流程测试,包括:
-
创建对话
-
选择披萨尺寸
-
选择披萨口味
-
添加配料
-
提供配送地址
-
确认订单
要求:
-
记录每一步的请求和响应
-
如果遇到错误,记录错误信息并解决
-
最终成功完成订单
参考答案:
完整测试流程:
步骤 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 项目无法启动",请设计一个完整的问题诊断流程。
要求:
-
列出需要收集的信息
-
设计诊断步骤
-
列出可能的原因
-
提供解决方案
参考答案:
第一步:收集基本信息
需要询问的问题:
-
操作系统是什么?(Windows/Mac/Linux)
-
.NET SDK 版本是多少?
-
如何启动的项目?(Visual Studio/命令行)
-
有什么错误信息?
-
之前能正常运行吗?
-
最近做了什么改动?
第二步:环境检查
检查清单:
# 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
步骤:
-
克隆 BotSharp 项目
-
配置 LLM 提供商
-
启动项目
-
访问 Swagger UI
-
截图证明成功
提交:
-
启动成功的控制台截图
-
Swagger UI 页面截图
任务 2:API 测试 ⭐⭐
目标:使用 Postman 完成基本的 API 测试
步骤:
-
安装 Postman
-
创建一个新的 Collection
-
添加以下请求:
-
获取 Agent 列表
-
创建对话
-
发送消息
-
-
测试所有请求
-
导出 Collection
提交:
-
Postman Collection JSON 文件
-
测试结果截图
任务 3:调试实践 ⭐⭐⭐
目标:使用调试器追踪一次完整的消息处理流程
步骤:
-
在以下位置设置断点:
-
ConversationController.SendMessage
-
ConversationService.SendMessage
-
LLM Provider 的调用方法
-
-
发送一条消息
-
逐步执行,观察数据流转
-
记录关键变量的值
提交:
-
调试过程的截图
-
数据流转的文字说明
任务 4:问题排查 ⭐⭐⭐
目标:故意制造一个错误并解决它
步骤:
-
选择一个错误场景(例如:删除 API Key)
-
尝试运行项目
-
记录错误信息
-
分析错误原因
-
解决问题
-
验证修复
提交:
-
错误信息截图
-
问题分析报告
-
解决方案说明
八、总结
通过完成这些练习题,你应该已经:
-
✅ 掌握了项目的克隆和启动
-
✅ 学会了配置和测试 API
-
✅ 掌握了基本的调试技能
-
✅ 能够排查和解决常见问题
-
✅ 完成了完整的测试流程
学习成果:
-
🎯 能够独立搭建 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 的快速启动,接下来让我们深入学习核心概念!🚀
