Qt接入大语言模型,实现一个Ai聊天机器人

在 Qt 桌面应用中接入大语言模型,最直接的落地方式是先实现一个 AI 聊天机器人:用户输入问题,程序把消息交给模型,模型以流式方式返回内容,界面实时显示回复。

如果完全从零开始,需要自己处理 HTTP 请求、流式 SSE 解析、错误处理、停止生成、聊天界面和模型配置。Qt-UI AgentKit 已经把这些基础能力封装成一组 Qt/C++ 接口,可以更快完成第一版聊天机器人。

本文基于 UIGearsAgentKit Demo 中的基础对话能力,说明如何使用 AgentKit 实现一个可运行的 AI Chat Bot。

image

 

一、AgentKit 提供了什么

AgentKit 当前基础对话相关接口位于命名空间:

UIGQtLib::QtAgent

常用类包括:

  • ModelConfig:模型配置,包含 provider、baseUrl、apiKey、model、temperature、maxTokens、timeoutMs、stream。
  • ChatRequest:聊天请求,负责保存 system/user/assistant 消息。
  • ChatModel:模型抽象基类。
  • MockChatModel:离线模拟模型,不需要网络和 API Key,适合 Demo 和本地验证。
  • OpenAICompatibleModel:OpenAI-compatible 接口实现。
  • ChatReply:一次模型回复对象,提供 delta、finished、failed、canceled 信号。
  • AgentChatPanel:可嵌入 Qt Widgets 的聊天面板,包含消息区、输入区、发送、停止和清空按钮。
  • ModelConfigWidget:模型配置控件,用于切换 Mock/OpenAI-compatible 并填写接口参数。

也就是说,一个基础聊天机器人并不需要直接写 QNetworkAccessManager,只需要组装 ChatRequest,选择一个 ChatModel,然后把 ChatReply 的信号连接到聊天面板即可。

二、最小工程接入

在 CMake 中链接 AgentKit 库:

target_link_libraries(MyQtChatBot PRIVATE
    UIGearsAgentKitLib
)

在代码中包含聚合头文件:

#include "QtAgentKit.h"

如果只使用基础对话,也可以只包含:

#include "QtAgentChatModel.h"
#include "QtAgentWidgets.h"

三、准备模型配置

AgentKit 的模型配置由 ModelConfig 表示。

UIGQtLib::QtAgent::ModelConfig config;
config.provider = QStringLiteral("openai");
config.baseUrl = QStringLiteral("https://api.openai.com/v1");
config.apiKey = qEnvironmentVariable("OPENAI_API_KEY");
config.model = QStringLiteral("gpt-4.1-mini");
config.temperature = 0.2;
config.maxTokens = 1024;
config.timeoutMs = 60000;
config.stream = true;

  

如果没有 API Key,可以先使用 Mock 模型:

UIGQtLib::QtAgent::ModelConfig config;
config.provider = QStringLiteral("mock");
config.model = QStringLiteral("mock");
config.stream = true;

 

AgentKit Demo 中还支持读取 agentkit.local.json

{
  "provider": "openai",
  "baseUrl": "https://api.openai.com/v1",
  "apiKey": "your-api-key",
  "model": "gpt-4.1-mini",
  "maxTokens": 1024,
  "timeoutMs": 60000,
  "stream": true
}

 

实际项目中建议使用本地配置文件或环境变量,不要把 API Key 提交到仓库。

四、创建聊天窗口

下面是一个基于 AgentKit 的最小聊天窗口。它包含:

  • 左侧模型配置面板。
  • 右侧聊天面板。
  • Mock 模型和 OpenAI-compatible 模型。
  • 发送消息、流式追加、完成、失败和停止生成处理。
#include "QtAgentKit.h"
#include <QtWidgets/QHBoxLayout>
#include <QtWidgets/QWidget>

class AgentChatBotWindow : public QWidget
{
    Q_OBJECT

public:
    explicit AgentChatBotWindow(QWidget* parent = nullptr)
        : QWidget(parent)
    {
        _mockModel = new UIGQtLib::QtAgent::MockChatModel(this);
        _openAiModel = new UIGQtLib::QtAgent::OpenAICompatibleModel(this);

        _configWidget = new UIGQtLib::QtAgent::ModelConfigWidget(this);
        _chatPanel = new UIGQtLib::QtAgent::AgentChatPanel(this);

        QHBoxLayout* layout = new QHBoxLayout(this);
        layout->setContentsMargins(12, 12, 12, 12);
        layout->setSpacing(12);
        layout->addWidget(_configWidget);
        layout->addWidget(_chatPanel, 1);

        initDefaultConfig();
        rebuildModels();

        _chatPanel->appendSystemMessage(
            QStringLiteral("请输入问题,AgentKit 会调用大语言模型生成回复。"));

        connect(_configWidget,
                &UIGQtLib::QtAgent::ModelConfigWidget::configChanged,
                this,
                &AgentChatBotWindow::rebuildModels);

        connect(_chatPanel,
                &UIGQtLib::QtAgent::AgentChatPanel::sendRequested,
                this,
                &AgentChatBotWindow::sendMessage);
    }

private slots:
    void rebuildModels()
    {
        const UIGQtLib::QtAgent::ModelConfig config = _configWidget->config();
        _mockModel->setConfig(config);
        _openAiModel->setConfig(config);
    }

    void sendMessage(const QString& text)
    {
        rebuildModels();

        _chatPanel->appendUserMessage(text);
        _chatPanel->beginAssistantMessage();
        _chatPanel->setRunning(true);

        UIGQtLib::QtAgent::ChatRequest request;
        request.addSystemMessage(QStringLiteral(
            "你是一个嵌入 Qt Widgets 程序中的 AI 助手,回答要简洁、准确。"));
        request.addUserMessage(text);

        UIGQtLib::QtAgent::ChatModel* model = currentModel();
        UIGQtLib::QtAgent::ChatReply* reply = model->chat(request, {}, this);

        connect(reply,
                &UIGQtLib::QtAgent::ChatReply::deltaReceived,
                _chatPanel,
                &UIGQtLib::QtAgent::AgentChatPanel::appendDelta);

        connect(reply,
                &UIGQtLib::QtAgent::ChatReply::finished,
                this,
                [this, reply](const QString&) {
                    _chatPanel->finishAssistantMessage();
                    _chatPanel->setRunning(false);
                    reply->deleteLater();
                });

        connect(reply,
                &UIGQtLib::QtAgent::ChatReply::failed,
                this,
                [this, reply](const QString& error) {
                    _chatPanel->appendSystemMessage(QStringLiteral("请求失败:") + error);
                    _chatPanel->setRunning(false);
                    reply->deleteLater();
                });

        connect(_chatPanel,
                &UIGQtLib::QtAgent::AgentChatPanel::stopRequested,
                reply,
                &UIGQtLib::QtAgent::ChatReply::cancel);
    }

private:
    UIGQtLib::QtAgent::ChatModel* currentModel() const
    {
        if (_configWidget->useOpenAI()) {
            return _openAiModel;
        }
        return _mockModel;
    }

    void initDefaultConfig()
    {
        UIGQtLib::QtAgent::ModelConfig config;

        const QString apiKey = qEnvironmentVariable("OPENAI_API_KEY");
        config.provider = apiKey.isEmpty()
            ? QStringLiteral("mock")
            : QStringLiteral("openai");
        config.apiKey = apiKey;
        config.baseUrl = qEnvironmentVariable("OPENAI_BASE_URL");
        config.model = qEnvironmentVariable("OPENAI_MODEL");

        if (config.baseUrl.isEmpty()) {
            config.baseUrl = QStringLiteral("https://api.openai.com/v1");
        }
        if (config.model.isEmpty()) {
            config.model = QStringLiteral("gpt-4.1-mini");
        }

        config.stream = true;
        config.maxTokens = 1024;
        config.timeoutMs = 60000;

        _configWidget->setConfig(config);
    }

private:
    UIGQtLib::QtAgent::ModelConfigWidget* _configWidget = nullptr;
    UIGQtLib::QtAgent::AgentChatPanel* _chatPanel = nullptr;
    UIGQtLib::QtAgent::MockChatModel* _mockModel = nullptr;
    UIGQtLib::QtAgent::OpenAICompatibleModel* _openAiModel = nullptr;
};

 

这段代码和 UIGearsAgentKit Demo 中的基础对话逻辑一致,核心流程来自 Demo 的 sendBasicMessage()

ChatRequest request;
request.addSystemMessage(...);
request.addUserMessage(text);

ChatReply* reply = model->chat(request, {}, this);
connect(reply, &ChatReply::deltaReceived, chatPanel, &AgentChatPanel::appendDelta);
connect(reply, &ChatReply::finished, ...);
connect(reply, &ChatReply::failed, ...);

 

五、main.cpp 示例

创建一个普通 Qt Widgets 程序即可运行。

#include <QtWidgets/QApplication>

int main(int argc, char* argv[])
{
    QApplication app(argc, argv);

    AgentChatBotWindow window;
    window.resize(1100, 720);
    window.show();

    return app.exec();
}

 

如果希望和 AgentKit Demo 一样使用深色样式,可以加载 UIGearsAgentKit/styles/dark.qss

QFile file("styles/dark.qss");
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
    app.setStyleSheet(QString::fromUtf8(file.readAll()));
}

 

六、ChatRequest 如何组织上下文

ChatRequest 是 AgentKit 对模型消息的封装。

UIGQtLib::QtAgent::ChatRequest request;
request.addSystemMessage("你是一个 Qt 开发助手。");
request.addUserMessage("如何在 Qt 中创建按钮?");

 

它会生成符合 OpenAI-compatible messages 格式的 JSON:

[
  {
    "role": "system",
    "content": "你是一个 Qt 开发助手。"
  },
  {
    "role": "user",
    "content": "如何在 Qt 中创建按钮?"
  }
]

 

基础 Demo 每次只发送当前用户问题。如果要实现多轮上下文,可以在窗口中保存历史消息:

_history.addUserMessage(text);

ChatRequest request;
request.addSystemMessage("你是一个 Qt 开发助手。");
for (const ChatMessage& message : _history.messages()) {
    request.addMessage(message);
}

也可以直接使用 AgentKit 的 ChatMemory 模块来管理多轮历史。对于真实产品,建议保留最近若干轮对话,并对更早的内容做摘要或检索。

七、为什么要保留 MockChatModel

AgentKit Demo 默认可以离线运行,这是因为它内置了 MockChatModel

Mock 模型的价值很实际:

  • 没有 API Key 时也能展示 UI。
  • 没有网络时也能验证聊天流程。
  • 可以测试流式输出、停止生成、按钮状态和消息追加。
  • 方便演示软件能力,而不依赖外部服务稳定性。

所以在产品中建议保留 provider 切换:

ChatModel* model = configWidget->useOpenAI()
    ? static_cast<ChatModel*>(openAiModel)
    : static_cast<ChatModel*>(mockModel);

这样 Demo、测试环境和真实环境可以共用同一套 UI。

八、OpenAICompatibleModel 做了哪些事

使用 OpenAICompatibleModel 后,应用层不需要手写网络请求。AgentKit 内部会处理:

  • 拼接 {baseUrl}/chat/completions
  • 设置 Content-Type: application/json
  • 设置 Authorization: Bearer {apiKey}
  • 组装 model、messages、temperature、max_tokens、stream。
  • 非流式响应解析。
  • 流式 SSE 数据解析。
  • ChatReply::deltaReceived 增量输出。
  • ChatReply::finished 完成通知。
  • ChatReply::failed 错误通知。
  • ChatReply::cancel 取消请求。

业务代码只需要关心“用户输入什么”和“界面如何显示模型回复”。

九、从聊天机器人扩展到智能体

基础聊天机器人只是 AgentKit 的第一步。Demo 中还演示了设备分析场景,它把聊天、工具调用、审批和 Trace 组合在一起:

  • ToolRegistry 注册本地工具。
  • FunctionTool 把 C++ 函数暴露给模型。
  • AgentExecutor 负责模型循环、工具调用和最终回答。
  • ToolCallTraceView 显示工具调用过程。
  • ApprovalDialog 对文件写入等敏感操作进行确认。

例如 Demo 里注册了几个工具:

_toolRegistry->registerTool(new UIGQtLib::QtAgent::FunctionTool(
    "find_abnormal_devices",
    "查找预警或严重状态的演示设备。",
    objectSchema({}),
    UIGQtLib::QtAgent::ToolPermission::ReadOnly,
    [this](const QJsonObject& args) { return findAbnormalDevices(args); },
    _toolRegistry));

当用户输入“查找异常设备并导出报告”时,智能体可以先调用查询工具,再调用导出工具;如果导出涉及文件系统权限,会触发 Approval 确认。

这就是从 AI 聊天机器人升级为 AI Agent 的关键区别:

  • 聊天机器人只生成文本。
  • 智能体可以理解任务、调用工具、记录过程,并在必要时请求人工确认。

十、实现效果

如果你要在自己的 Qt 项目中接入 AgentKit,可以按这个顺序推进:

  1. 先接入 AgentChatPanel,跑通 Mock 模型。
  2. 加入 ModelConfigWidget,支持填写 baseUrl、apiKey、model。
  3. 切换到 OpenAICompatibleModel,测试真实模型。
  4. 把常用业务函数包装成 FunctionTool
  5. 对文件写入、网络访问、系统命令等操作增加 Approval。
  6. 使用 ToolCallTraceView 给开发和用户展示调用过程。
  7. 对产品文档、日志、知识库接入 RAG 检索。

这样可以从一个可演示的聊天窗口,逐步演进为能解决业务问题的 Qt 智能体应用。

使用 Qt-UI AgentKit 接入大语言模型,不需要从零处理 HTTP、流式解析和聊天 UI。基础聊天机器人可以由四个核心对象完成:

  • AgentChatPanel:负责聊天界面。
  • ModelConfigWidget:负责模型配置。
  • ChatRequest:负责组织 system/user 消息。
  • ChatModel + ChatReply:负责模型调用和流式返回。

这套接口已经在 UIGearsAgentKit Demo 中验证过:默认使用 Mock 模型离线运行,配置 API Key 后可以切换真实 OpenAI-compatible 模型。

当基础对话跑通后,再继续接入工具调用、审批、Trace、RAG 和状态工作流,就可以把 Qt 桌面程序从“有一个聊天框”升级为真正可用的 AI Agent 应用。

 

 

产品官网  www.qt-ui.com

 

Qt-UI C++Python界面开发工具 UI开发工具 qt解决方案 qt开源项目

posted on 2026-06-20 18:13  Qt-UI  阅读(82)  评论(0)    收藏  举报

导航