Skip to content

northwindlight/satori-client-cpp

Repository files navigation

satori-client-cpp

Satori 协议 的 C++ 客户端实现。配合 Satori 服务端(LLBot 等)使用,可接入 QQ、Telegram、Discord 等聊天平台。

C++20,依赖 ixwebsocket


当前实现状态

Satori 资源结构:已完整实现解析(Event、Message、Channel、User、Guild、GuildMember 等)

Satori 标准元素:已基本实现解析和封装( <at><sharp><file><img><video> 等)

Satori API:已完整实现所有标准 API(message / channel / guild / guild.member / guild.role / user / friend / login / reaction)

LLMClient:可选功能。鉴于 AI 热潮,目前也是主要支持方向。


示例

不使用 LLMClient

#include "satori_client.h"
#include <ixwebsocket/IXNetSystem.h>

namespace se = satori::event;
namespace sel = satori::element;

int main()
{
    ix::initNetSystem();

    Bot bot("127.0.0.1:5600", "YOUR_TOKEN", "QQ", "YOUR_BOT_QQ");

    bot.addOnMessageCallback([&bot](const se::Event& event)
    {
        if (!event.message || !event.channel) return;
        sel::Elements elems = sel::parse(event.message->content.value_or(""));
        bot.message.create(event.channel->id, "收到:" + elems.plainText);
    });

    bot.launch();
    // bot.launchAsync() 异步执行
    ix::uninitNetSystem();
}

使用 LLMClient

#include "satori_client.h"
#include "LLMClient/LLMClient.h"
#include "LLMClient/LLMAgent.h"
#include <ixwebsocket/IXNetSystem.h>

namespace se = satori::event;
namespace sel = satori::element;

int main()
{
    ix::initNetSystem();

    LLMClient llm(
        "https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions",
        "sk-xxxxx",
        "qwen3-14b"
    );

    Bot bot("127.0.0.1:5600", "YOUR_TOKEN", "QQ", "YOUR_BOT_QQ");

    bot.addOnMessageCallback([&bot, &llm](const se::Event& event)
    {
        if (!event.message || !event.channel) return;

        sel::Elements elems = sel::parse(event.message->content.value_or(""));
        auto agent = LLMAgent::create(llm,
            "你是服务器管理助手,名字叫小小北风。\n\n"
        );
        agent->ask(elems.plainText, [&bot, event](const std::string& llmreply)
        {
            auto reply = sel::Builder()
                .img("weburl")
                .text(llmreply)
                .build();
            bot.message.create(event.channel->id, reply);
        });
    });

    bot.launch();
    ix::uninitNetSystem();
}

更多示例请参照demo.cpp

使用 LLMClient + Tool(函数调用)

LLMAgent 支持 LLM 函数调用(tool calling)。通过注册工具,让 LLM 在需要时自动调用你定义的函数并获取结果。

#include "satori_client.h"
#include "LLMClient/LLMClient.h"
#include "LLMClient/LLMAgent.h"
#include "LLMClient/tool.hpp"
#include <ixwebsocket/IXNetSystem.h>

namespace se = satori::event;
namespace sel = satori::element;

int main()
{
    ix::initNetSystem();

    LLMClient llm(
        "https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions",
        "sk-xxxxx",
        "qwen3-14b"
    );

    Tool tool;
    tool.toolRegister(
        "get_time",
        "获取当前系统时间",
        {},
        [](const nlohmann::json&) -> std::string {
            auto now = std::chrono::system_clock::now();
            auto t   = std::chrono::system_clock::to_time_t(now);
            return std::ctime(&t);
        }
    );

    tool.toolRegister(
        "echo",
        "回显输入内容",
        {{"text", "string", "要回显的文本", true}},
        [](const nlohmann::json& args) -> std::string {
            return "你说的是: " + args.value("text", "");
        }
    );

    auto agent = LLMAgent::create(llm, "你是智能助手", tool);

    agent->setToolHook([](const Tool::Call& call, const std::string& output) {
        if (call.name == "fortune") {
            // 工具执行后额外处理
        }
    });

    Bot bot("127.0.0.1:5600", "YOUR_TOKEN", "QQ", "YOUR_BOT_QQ");

    bot.addOnMessageCallback([&bot, agent](const se::Event& event)
    {
        if (!event.message || !event.channel) return;

        sel::Elements elems = sel::parse(event.message->content.value_or(""));

        if (event.user.has_value())
            agent->setSystemPrompt("当前用户:" + event.user->id);

        agent->ask(elems.plainText, [&bot, event](const std::string& reply)
        {
            bot.message.create(event.channel->id, reply);
        });
    });

    bot.launch();
    ix::uninitNetSystem();
}

更多示例请参照 demo_toolcall.cpp

注册工具 API

tool.toolRegister(
    "tool_name",          // 工具名称,LLM 通过此名调用
    "工具描述",            // 告诉 LLM 何时调用
    {                     // 参数定义,可为空
        {"param_name", "string", "参数描述", true /* 是否必填 */}
    },
    handler               // 回调:接收 JSON args,返回 string 结果
);

ToolHook

通过 agent->setToolHook(callback) 注册钩子,在每个工具执行完成后触发,可用于:

  • 根据工具结果向消息缓冲区追加图片、@ 等元素
  • 日志记录或额外副作用

钩子回调签名:void(const Tool::Call& call, const std::string& output)


多会话管理(SessionManager)

上面的示例所有用户共用同一个 LLMAgent,对话历史会互相串台。SessionManager 为每个会话(频道 / 私聊 / 用户)维护一个独立的 LLMAgent,按 key 复用、线程安全, 适合多人同时使用的机器人。

#include "satori_client.h"
#include "LLMClient/LLMClient.h"
#include "LLMClient/LLMAgent.h"
#include "LLMClient/tool.hpp"
#include "SessionManager.h"
#include <ixwebsocket/IXNetSystem.h>

namespace se  = satori::event;
namespace sel = satori::element;

int main()
{
    ix::initNetSystem();

    LLMClient llm(
        "https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions",
        "sk-xxxxx",
        "qwen3-14b"
    );

    Tool tool;               // 所有会话共享同一套工具定义
    SessionManager sessions; // 按 key 缓存各自的 LLMAgent

    Bot bot("127.0.0.1:5600", "YOUR_TOKEN", "QQ", "YOUR_BOT_QQ");

    bot.addOnMessageCallback([&bot, &llm, &tool, &sessions](const se::Event& event)
    {
        if (!event.message || !event.channel) return;
        sel::Elements elems = sel::parse(event.message->content.value_or(""));

        // 以 channel id 为 key,取出(或首次创建)该会话专属的 agent
        auto agent = sessions.getOrCreate(
            event.channel->id, llm, "你是智能助手", tool);

        std::string channelId = event.channel->id;
        agent->ask(elems.plainText, [&bot, channelId](const std::string& reply)
        {
            bot.message.create(channelId, reply);
        });
    });

    bot.launch();
    ix::uninitNetSystem();
}

getOrCreate(key, llm, systemPrompt, tool):key 已存在则返回已有 agent(保留历史), 否则用给定参数创建一个新 agent 并缓存。完整示例见 demo_session.cpp


依赖

依赖 说明
ixwebsocket WebSocket + HTTP,外部库,需要启用TLS支持
nlohmann/json JSON 解析,已内嵌
tinyxml2 XML 解析,已内嵌
# Ubuntu
sudo apt install libixwebsocket-dev

cmake -B build && cmake --build build

License

MIT License © 2026 Zhang Feng

About

用 C++20 写的satori客户端bot框架,内置 LLM 工具调用支持。C++ client for Satori protocol

Resources

License

Stars

1 star

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors