# 课程访问 cpp.show

# 夏曹俊老师微信 cppxcj

# xai_agent 安装与运行文档

> 视频课程版本：20260905；核对日期：2026-09-05。
> 配套阅读：[设计文档](设计文档.md) · [HTML 版](installation.html) · [文档首页](index.html)

## 1. 选择安装方式

| 目标 | 使用入口 | 是否编译 |
| --- | --- | --- |
| 直接体验现有桌面程序 | 本目录的 `rel/xai_agent.exe` | 否，使用课程包自带文件 |
| 修改或学习 Qt 桌面源码 | 根 `CMakeLists.txt` | 编译 xai_agent 与 xllm，使用已有 llama SDK |
| 单独学习 llmclass | `third_party/llmclass/CMakeLists.txt` | 编译 xllm 与两个控制台示例 |
| 自行更换 CPU/CUDA/Vulkan 后端 | 同版本 llama.cpp 源码或完整配套 SDK | 可重建上游依赖，属可选步骤 |

原始源码位置是 `C:\code\xai_agent视频课程版本20260905整理\xai_agent`。下文 PowerShell 命令中的 `$src` 与 `$qt` 可以换为自己的实际路径，带空格或中文的路径必须保留引号。源码含 `u8` 字符串，按 C++17 构建；不要直接改为 C++20 后期待字符串类型完全一致。

## 2. 环境与依赖

| 项目 | 要求/选择依据 | 本机核验配置 |
| --- | --- | --- |
| 系统 | 本教程主要覆盖 Windows x64 | Windows 11，构建检测版本 `10.0.22621` |
| 编译器 | MSVC x64，安装“使用 C++ 的桌面开发”和 Windows SDK | MSVC `19.51.36248`，Windows SDK `10.0.26100.0` |
| 生成器 | 使用本机已安装 VS 对应的 CMake 生成器 | `Visual Studio 18 2026` |
| Qt | 源码声明 Qt 6.5+，Core、Widgets，使用 MSVC x64 Kit | `C:\Qt\6.11.1\msvc2022_64` |
| CMake | 项目与子项目合并要求至少 3.22，实际还需满足所选 Qt/VS | 本机已有 `4.4.0-rc2`，不要求安装此预览版本 |
| llama SDK | 同套 include、lib、bin 和 CMake 配置 | 根目录 `lib/`，CPU 动态后端 |
| 模型 | 与该 SDK 兼容的 GGUF | `Qwen3.5-0.8B-Q4_K_M.gguf`，527502816 字节 |
| Python | 仅重新生成 HTML 文档需要 | Python 3 标准库，无第三方包 |

Qt 的 MinGW Kit 不能与本目录的 MSVC `.lib` 混用。`BUILD_SHARED_LIBS=OFF` 只让自有 xllm 静态链接，不会把现有 llama DLL 或 Qt DLL 自动变成静态库。

工具官方入口：[Visual Studio 下载](https://visualstudio.microsoft.com/downloads/)、[CMake 下载](https://cmake.org/download/)、[Qt CMake 文档](https://doc.qt.io/qt-6/cmake-manual.html)。构建参数以本课程源码和选定工具链为准，不要求追随最新版依赖。

模型文件约 503 MiB，但运行内存还包括模型映射、上下文状态、临时计算区和 GUI。不要用模型文件大小代替运行时内存需求；具体取决于模型、上下文、后端和量化设置。CPU 路径不要求 CUDA 或 Vulkan SDK。

## 3. 直接运行现成 rel 包

在 PowerShell 中执行：

```powershell
$src = 'C:\code\xai_agent视频课程版本20260905整理\xai_agent'
Set-Location -LiteralPath "$src\rel"
Test-Path '.\xai_agent.exe'
Test-Path '.\models\Qwen3.5-0.8B-Q4_K_M.gguf'
.\xai_agent.exe
```

两项检查都应为 `True`。应用先显示加载对话框，模型就绪后进入主窗口。输入简短问题，点击发送，或按 Enter；Shift+Enter 用于换行。为避开当前版本的并发显示限制，一次只发送一个问题，生成结束后再切换历史任务。

使用其他模型路径时，把模型作为第一个命令行参数：

```powershell
.\xai_agent.exe 'D:\models\your-model.gguf'
```

此处的文件必须真实存在且与模板/SDK 兼容。程序没有模型下载器，也不会自动寻找目录中的其他 GGUF。默认模型路径和 `./cache` 都以进程工作目录为基准；从终端或 IDE 启动时务必设置工作目录。

至少保留这些文件，并尽量保留整个部署目录：

```text
rel/
├─ xai_agent.exe
├─ Qt6Core.dll / Qt6Gui.dll / Qt6Widgets.dll
├─ llama.dll / ggml.dll / ggml-base.dll
├─ ggml-cpu-*.dll
├─ plugins/platforms/qwindows.dll
├─ qt.conf
├─ models/Qwen3.5-0.8B-Q4_K_M.gguf
└─ cache/                     运行后生成的个人会话数据
```

其他 Qt 插件与依赖也可能由部署工具复制，不建议只凭上表删除文件。复制运行包给另一台电脑时，保持 DLL、插件和模型的相对结构；如目标机缺少 MSVC 运行库，应安装微软官方运行库安装包。Qt 依赖收集与第三方库处理见 [Qt Windows 部署说明](https://doc.qt.io/qt-6/windows-deployment.html)。

## 4. 构建桌面程序

### 4.1 检查开发工具与 SDK

```powershell
$src = 'C:\code\xai_agent视频课程版本20260905整理\xai_agent'
$qt = 'C:\Qt\6.11.1\msvc2022_64'
Set-Location -LiteralPath $src
cmake --version
cmake --help
Test-Path "$qt\lib\cmake\Qt6\Qt6Config.cmake"
Test-Path '.\lib\lib\cmake\llama\llama-config.cmake'
Test-Path '.\lib\lib\llama.lib'
Test-Path '.\lib\bin\llama.dll'
Test-Path '.\lib\bin\models\Qwen3.5-0.8B-Q4_K_M.gguf'
```

在 `cmake --help` 的生成器列表中确认所选生成器。若安装 VS 2022，改用 `Visual Studio 17 2022`；本机验证使用 `Visual Studio 18 2026`。不同生成器需要不同 build 目录，不能复用其他机器或旧路径生成的 CMakeCache。

根工程会先查 Qt，再使用 `lib/` 查 llama；`lib/include`、`lib/lib` 和 `lib/bin` 必须来自同一兼容构建。打包安装时从 `lib/bin` 取 DLL、从 `lib/bin/models` 取 GGUF，不是从 `rel` 自动回填。

### 4.2 配置、编译与安装

以下命令安装到新的 `build-course/package`，不删除或覆盖原有 `rel` 和历史缓存。每一步失败立即停止，检查上一条错误后再继续。

```powershell
$generator = 'Visual Studio 18 2026'
cmake -S . -B build-course -G $generator -A x64 `
  "-DCMAKE_PREFIX_PATH=$qt" `
  -DCMAKE_CXX_STANDARD=17 `
  '-DCMAKE_CXX_FLAGS=/utf-8 /EHsc' `
  -DBUILD_SHARED_LIBS=OFF `
  "-DCMAKE_INSTALL_PREFIX=$src/build-course/package"
if ($LASTEXITCODE -ne 0) { throw 'CMake 配置失败' }

cmake --build build-course --config Release --parallel 8
if ($LASTEXITCODE -ne 0) { throw 'Release 编译失败' }

cmake --install build-course --config Release
if ($LASTEXITCODE -ne 0) { throw '安装失败' }
```

`/utf-8` 明确中文源码编码，`/EHsc` 保留标准 C++ 异常展开；通过 `CMAKE_CXX_FLAGS` 显式设置时一并提供。此参数是 MSVC 专用，不能原样传给 GCC/Clang。源码根目录没有完整声明所有 C++17 编译要求，所以命令显式指定标准。

编译产物通常位于 `build-course/Release/xai_agent.exe`；不要只复制该 exe 就认为安装完成。`cmake --install` 负责程序、Qt 部署脚本和本项目声明的 llama/模型复制规则。Qt 部署工具不替代第三方依赖部署，具体机制见 [Qt Windows 部署说明](https://doc.qt.io/qt-6/windows-deployment.html)。

### 4.3 检查安装包并运行

```powershell
$package = Join-Path $src 'build-course\package'
Test-Path "$package\xai_agent.exe"
Test-Path "$package\llama.dll"
Test-Path "$package\ggml-base.dll"
Test-Path "$package\models\Qwen3.5-0.8B-Q4_K_M.gguf"
Get-ChildItem -LiteralPath $package -Filter 'qwindows.dll' -Recurse
Set-Location -LiteralPath $package
.\xai_agent.exe
```

`file(GLOB ...)` 没有匹配到文件时未必会使 CMake 安装失败，所以必须检查 DLL 与模型。若 SDK 的 models 子目录缺失，但原 `rel` 的模型完好，可在保留原文件的前提下复制到新安装包：

```powershell
New-Item -ItemType Directory -Path "$package\models" -Force | Out-Null
Copy-Item -LiteralPath "$src\rel\models\Qwen3.5-0.8B-Q4_K_M.gguf" `
  -Destination "$package\models\Qwen3.5-0.8B-Q4_K_M.gguf"
```

若 Qt 部署阶段失败，应先检查 Qt Kit 和完整构建日志；确需手动补齐时，可对已编译的 Release exe 使用匹配 Kit 的 `windeployqt --release`，不要混用另一套 Qt。插件实际位置以生成的 `qt.conf` 和部署结果为准。

### 4.4 使用 Qt Creator

1. 打开根目录 `CMakeLists.txt`，选择 Qt 6 的 MSVC x64 Kit。
2. 使用新的构建目录，配置 `CMAKE_CXX_STANDARD=17`、`BUILD_SHARED_LIBS=OFF`，MSVC 编译选项包含 `/utf-8 /EHsc`。
3. 先构建 Release 并完成安装，再将运行目标设置为安装包中的 exe。
4. 把工作目录设置为安装包目录；模型参数留空使用默认文件，或显式传入模型绝对路径。

原 `install.cmd` 固定使用 `E:\QT6\6.11.1\msvc2022_64`，且会删除 `relbuild` 和 `rel`。`rel` 中包含模型和会话数据，不能在未备份前直接运行该脚本。本文采用新目录构建，实际未执行其删除步骤。

## 5. 单独构建 llmclass

此入口不依赖 Qt；需要相同架构的 MSVC、CMake，以及 `llm_sdk/msvc/cpu` 下的完整 SDK。默认示例开关全部关闭，不能只执行默认 cmake 就期待得到两个可执行文件。

```powershell
$src = 'C:\code\xai_agent视频课程版本20260905整理\xai_agent'
$llm = Join-Path $src 'third_party\llmclass'
Set-Location -LiteralPath $llm
cmake -S . -B build-course-cpu -G 'Visual Studio 18 2026' -A x64 `
  -DBUILD_LLAMA=OFF -DGGML_CUDA=OFF -DGGML_VULKAN=OFF `
  -DBUILD_XLLM=ON -DBUILD_TEST_XLLM=ON -DBUILD_TESTLLM=ON `
  -DBUILD_SHARED_LIBS=OFF '-DCMAKE_CXX_FLAGS=/utf-8 /EHsc'
if ($LASTEXITCODE -ne 0) { throw 'llmclass 配置失败' }

cmake --build build-course-cpu --config Release --parallel 8
if ($LASTEXITCODE -ne 0) { throw 'llmclass 编译失败' }

cmake --install build-course-cpu --config Release `
  --prefix "$llm/build-course-cpu/package"
if ($LASTEXITCODE -ne 0) { throw 'llmclass 安装失败' }
```

当前 `test_xllm` 的构建输出目录指向 `llm_sdk/msvc/cpu/bin`；安装后统一从新的 package 运行。原 CMake 的 DLL 复制使用了拼错的 `LLAMA_INSALL_DIR`，因此还要显式把匹配 CPU SDK 的 DLL 复制进测试包：

```powershell
$llmPackage = Join-Path $llm 'build-course-cpu\package'
Get-ChildItem -LiteralPath "$llm\llm_sdk\msvc\cpu\bin" -Filter '*.dll' |
  Copy-Item -Destination $llmPackage
Set-Location -LiteralPath $llmPackage
.\test_xllm.exe "$src\rel\models\Qwen3.5-0.8B-Q4_K_M.gguf"
```

`test_xllm` 未传参数时使用原作者的 `M:\llmclass\bin\models\...` 路径，其他机器必须显式传模型。它会尝试读取当前工作目录的历史缓存，否则执行固定的 C++ 示例问题；生成后 `getchar()` 等待 Enter。它不是带断言的自动测试，且目前部分错误返回值未检查。

直接 C API 性能示例：

```powershell
.\testllm.exe "$src\rel\models\Qwen3.5-0.8B-Q4_K_M.gguf"
```

该示例 `n_ctx=102400`、KV 类型 `Q4_0`、生成上限 512，和桌面 4096/F16 配置不同。模型结构或后端不支持相应 KV 类型时可能初始化失败；不能把失败直接归因于安装，也不能用它与桌面程序进行不加说明的性能对比。示例的总耗时只计算 prefill 与生成，不包含模型加载和分词。

## 6. 可选：重建 llama.cpp 后端

优先使用课程目录中配套版本，避免只更新一个 DLL。仅阅读/构建上游，不需要修改其源码。上游构建选项说明见 [llama.cpp 官方构建文档](https://github.com/ggml-org/llama.cpp/blob/master/docs/build.md)，命令中的开关应与本地版本核对。

为了避开 llmclass 根工程在配置阶段嵌套编译、未检查子进程退出码的问题，可直接分步构建。以下示例是 CPU SDK，输出到独立目录：

```powershell
$src = 'C:\code\xai_agent视频课程版本20260905整理\xai_agent'
$llm = Join-Path $src 'third_party\llmclass'
cmake -S "$llm/third_party/llama.cpp" -B "$llm/build-sdk-cpu" `
  -G 'Visual Studio 18 2026' -A x64 `
  -DLLAMA_BUILD_COMMON=OFF -DGGML_CCACHE=OFF `
  -DLLAMA_BUILD_TESTS=OFF -DLLAMA_BUILD_TOOLS=OFF `
  -DLLAMA_BUILD_EXAMPLES=OFF -DLLAMA_BUILD_SERVER=OFF `
  -DLLAMA_BUILD_APP=OFF -DLLAMA_BUILD_UI=OFF -DLLAMA_OPENSSL=OFF `
  -DBUILD_SHARED_LIBS=ON -DGGML_NATIVE=OFF `
  -DGGML_BACKEND_DL=ON -DGGML_CPU_ALL_VARIANTS=ON `
  -DGGML_CUDA=OFF -DGGML_VULKAN=OFF `
  "-DCMAKE_INSTALL_PREFIX=$llm/build-sdk-cpu/sdk"
if ($LASTEXITCODE -ne 0) { throw 'llama 配置失败' }
cmake --build "$llm/build-sdk-cpu" --config Release --parallel 8
if ($LASTEXITCODE -ne 0) { throw 'llama 编译失败' }
cmake --install "$llm/build-sdk-cpu" --config Release
if ($LASTEXITCODE -ne 0) { throw 'llama 安装失败' }
```

CUDA 需要匹配的 NVIDIA 设备、驱动和 CUDA Toolkit，改用新 build 目录并设置 `GGML_CUDA=ON`。Vulkan 需要合适驱动与 Vulkan SDK，设置 `GGML_VULKAN=ON`；不要同时启用两个选项。GPU 环境并非运行 CPU 版本的前置要求。

生成 SDK 后先在独立目录验证，再整体替换桌面 `lib` 对应的 `include/lib/bin` 或 llmclass 约定的 SDK 目录。替换前另存旧 SDK，保留模型，使用新的 build 目录重新配置；不要把不同构建的后端 DLL、导入库和头文件拼在一起。设置 `gpu_layer=-1` 只是请求 GPU 卸载，不能让 CPU 专用 SDK 获得 GPU 能力。

本次没有重建上游，也没有实测 CUDA、Vulkan、Linux 或 macOS。已有 Linux `.sh` 还包含 `LLAMA_INSALL_DIR` 关联路径问题和历史拼写 `build_vukan.sh`，不是已验证的一键安装方案。桌面还包含 Windows `.rc`、默认反斜杠路径，跨平台迁移需要单独处理。

## 7. 会话备份与版本管理

模型较大，可以单独备份；对话位于所用工作目录的 `cache`。退出程序后再复制整个 cache 目录，使 `cache_info.md`、`msg.md`、`kv.bin` 尽量保持配套。`msg.md` 是二进制数据，不要用 Markdown 编辑器修改。旧 KV 状态不保证跨模型或 SDK 兼容，升级后优先使用新的缓存工作目录。

本源码整理目录已建立本地 Git 仓库。Git 跟踪自有源码、资源、注释与文档；`.gitignore` 排除 build、rel、模型、SDK、会话缓存和上游 llama.cpp。Git 克隆/归档因此不是完整运行包，必须另外取得课程配套 SDK、模型及上游源码（仅在需要重建时）。原依赖目录在磁盘上保留，不因忽略规则而删除。

原始基线提交是 `97f3cc6`。源码目录没有配置远端，因此不能凭空推送到其他同名仓库；后续配置正确的远端再执行 `git push -u origin main`。HTML 网站副本在 cppwww 的独立 Git 仓库提交并使用该仓库已有远端。

## 8. 常见问题

| 现象 | 优先检查 | 处理方向 |
| --- | --- | --- |
| 找不到 Qt6Config.cmake | `$qt`、MSVC Kit、Qt 组件 | 指向实际 Qt 安装前缀，确认 Core/Widgets 已安装 |
| 找不到 llama 包/库 | `lib/lib/cmake`、`lib/include`、`.lib` | 补齐同版本 SDK，不要只复制 DLL |
| 生成器不匹配 | 旧 CMakeCache 与当前 VS | 使用新的 build 目录，不在旧缓存上切换生成器 |
| 中文乱码/`char8_t` 类型错误 | 编码与语言标准 | 使用 `/utf-8 /EHsc` 和 C++17，避免混入 C++20 |
| 缺少 Qt、llama、ggml DLL | 是否从安装目录运行 | 完成安装，检查匹配 DLL 和官方 MSVC 运行库 |
| `Could not find the Qt platform plugin` | `qwindows.dll`、qt.conf、Qt Kit | 用匹配 windeployqt 重新部署，必要时临时设 `QT_DEBUG_PLUGINS=1` 诊断 |
| 进度框不结束 | GGUF 路径、DLL、内存、加载错误日志 | 本版失败信号未接入 GUI；先修正模型路径和依赖，再重启 |
| 改了 qss 但无变化 | 是否重新构建 | 样式编译进 qrc，不读取安装目录的外置 app.qss |
| 运行后找不到历史 | 工作目录是否变化 | 在原工作目录运行，并保留同套 cache 文件 |
| 生成首字/中文片段异常 | 首 token 与 UTF-8 分片限制 | 属于设计文档 D04/D08，不能靠重新安装保证修复 |
| 多条消息混到同一气泡 | 是否连续快速发送 | 本版等待当前回答结束再发送，后续按消息 ID 修复 |
| 生成中切换历史卡顿/异常 | GUI 与工作线程共用上下文 | 先等推理完成；设计文档 D03 记录线程整改方向 |
| 上下文满或长输入失败 | 4096 容量、未实现分块 | 新建会话并缩短输入；增加容量要评估内存并改配置 |
| testllm 初始化失败 | 102400/Q4_0 配置与模型支持 | 该性能示例配置与桌面不同，检查具体底层错误 |
| llmclass 安装后缺 DLL | `LLAMA_INSALL_DIR` 拼写 | 按第 5 节显式复制匹配 SDK 的 DLL |

## 9. 文档生成与公开访问

源码内可直接打开 `docs/index.html` 离线阅读，设计和安装文档各有 Markdown 下载入口。所有样式为本地静态文件，未加载 CDN、统计脚本或登录组件。

```powershell
Set-Location -LiteralPath 'C:\code\xai_agent视频课程版本20260905整理\xai_agent'
python .\tools\build_docs.py
python .\tools\build_docs.py --site-root 'C:\code\cppwww'
```

公开副本位于 `C:\code\cppwww\www\articles\cpp-ai-course\xai-agent-20260905`；在本机已有 Web 服务下访问 [课程文档首页](http://localhost/articles/cpp-ai-course/xai-agent-20260905/index.html)。该专题已在 C++ AI 内容分类登记；登记不代表新增会员课程、数据库内容导入或权限模块实现。

以后修改 Markdown 后重新运行生成器，再对源码仓库和 cppwww 仓库分别验证、提交、推送。不要只编辑生成的 HTML，否则下次生成会覆盖手工修改。

## 10. 验收范围

本次核验使用同目录现有 CPU SDK 与模型，结果如下。测试产生的新程序与缓存保存在忽略的 build 目录，原 rel 与 SDK 文件保持不变。

| 检查 | 结果 | 范围 |
| --- | --- | --- |
| 注释前后等价 | 通过 | 43 个原有文本文件；27 个 C++ 文件按词法 token 比较，脚本与资源去除注释后比较 |
| 上游依赖保护 | 通过 | 2078 个 llama.cpp、lib、llm_sdk 文件 SHA-256 保持一致 |
| 桌面源码配置与 Release 编译 | 通过 | Qt 6.11.1/MSVC 19.51/C++17，静态 xllm，输出 build-doccheck |
| 桌面安装 | 通过，有工具环境提示 | cmake --install 完成，Qt/llama DLL、平台插件及模型已生成 |
| 独立 llmclass 编译 | 通过 | xllm、test_xllm、testllm 均成功；临时外层工程将输出重定向到 build-validation，避免改写原 SDK |
| CPU 短流程推理 | 通过 | 临时验证程序调用真实封装，512 上下文完成加载、模板、分词、prefill、8 token decode 与两条消息保存/恢复 |
| HTML 响应式与公开访问 | 通过 | Edge/Playwright，3 页 × 1440/980/560/375，共 12 组；匿名 HTTP 200、正文非空、无整页横向溢出 |
| HTML 交互 | 通过 | 首页卡片 → 设计页 → 缓存目录锚点 → 安装页 → Markdown 下载；离线打开与键盘跳到正文正常 |
| 页面控制台 | 通过 | 无页面运行错误；已避免默认 favicon 404 请求 |
| cppwww 内容与健康检查 | 通过 | 注册表校验、数据库 health、PHP 回归 26 项通过；两篇文档作为公开技术资料登记 |

Qt 部署工具提示 `VCINSTALLDIR is not set`，但安装命令返回成功且 Qt/插件文件存在；未在干净 Windows 机器验证 MSVC 运行库齐备性。部署到新电脑时仍需按第 3 节准备官方运行库。

页面截图已人工检查桌面正文、目录与移动版布局。Browser 插件不可用，使用本机已有 Edge 通过 Playwright 验证；未安装新的浏览器依赖。未进行完整 Qt 聊天界面交互回归、长对话压力测试、两个控制台示例的完整问答/性能运行，也未验证 CUDA、Vulkan、Linux、macOS。CPU 短流程结果不代表已消除设计文档中的课程代码限制。

人工体验建议依次检查：加载有效模型 → 发送短问题 → 等待完成 → 第二轮提问 → 新建任务 → 在空闲时恢复历史 → 退出后从同一工作目录重开。首 token、UTF-8 分片、错误处理、连续发送、缓存竞争等已知限制详见设计文档，编译通过不代表这些问题已修复。


第二轮注释细化仍保持相同的构建与运行步骤：覆盖 Qt Agent 与 llmclass 的全部 27 个 C++ 文件，补上接口参数、返回值、前置条件、成员所有权和关键步骤解释。与上一轮提交 `f736bad` 比较的 C++ 词法 token 完全一致；llama.cpp 与 SDK 的 2078 个原文件摘要保持一致。本轮重新通过 Qt Agent Release 编译、llmclass 与两个控制台示例编译、CPU 实际模型生成 8 个 token 及缓存保存/恢复短流程，并通过 3 个文档页面在 4 种宽度下的检查、目录与下载交互及站点内容校验；未重复运行未受影响的 PHP 回归。此次仅细化注释和文档，既有功能限制未作修复。
