XIUNOX AIService 核心文档 [Copy Link]

三级用户组

AIService 核心文档

适用项目:XIUNOX(XIUNO BBS X重构版) 源文件:xiunobbs-master/lib/AIService.php 最后更新:2026-07-03

一、概述

AIService 是 XIUNOX 的 AI 调用中台,统一管理所有 AI 功能的调用入口。核心职责:

  1. 多 provider 调用:支持 failover/round_robin/random/concurrent 四种模式

  2. 健康检查:kv 持久化 provider 在线/离线状态,自动故障转移

  3. 功能注册:插件通过 registerFeature() 注册新 AI 功能

  4. 内容后处理:插件通过 registerPostFilter() 注册回调过滤 AI 返回内容

  5. 配置解析:按 mode(global/user_key/both)合并全局与用户配置

二、配置结构

2.1 全局配置 conf.ai(conf/conf.php)

'ai' => array (
    // 全局提供商库(管理员维护,含 api_key)
    'providers' => array (
        array(
            'name'    => 'openai',           // 唯一标识
            'type'    => 'text',             // text/image/video/audio/transcription
            'url'     => 'https://api.openai.com',
            'api_key' => 'sk-xxx',
            'models'  => array(              // 模型列表
                array('name' => 'gpt-4o', 'enabled' => 1),
                array('name' => 'gpt-4o-mini', 'enabled' => 1),
            ),
        ),
    ),
    // 功能配置(每个 AI 功能一项)
    'features' => array (
        'editor' => array (
            'name'             => 'AIeditor',
            'type'             => 'text',
            'mode'             => 'user_key',   // global/user_key/both
            'call_method'      => 'frontend',   // frontend/proxy
            'default_provider' => '',
            'default_model'    => '',
            'allowed_providers' => array('openai', 'deepseek'),
        ),
    ),
    // 编辑器专属配置(可选)
    'promptContinue' => '请根据上下文续写内容',
    'promptImprove'  => '请优化以下文本的表达',
),

2.2 用户配置 user.ai_config

// 存储在 user 表 ai_config 字段(JSON)
// 新版结构:{featureKey: {apiKey, model, url, provider_name}}
array(
    'editor' => array(
        'apiKey'        => 'sk-xxx',
        'model'         => 'gpt-4o-mini',
        'url'           => 'https://api.openai.com',
        'provider_name' => 'openai',
    ),
)

2.3 健康状态(kv 持久化)

  • kv 键:ai_provider_health

  • 结构:{provider_name: {online: bool, last_check: int}}

  • 写入时机:仅状态变化时写 kv(减少写开销)

  • 读取:请求内 static 缓存,避免重复读 kv

2.4 轮询状态(kv 持久化)

  • kv 键:ai_roundrobin_last_{feature}

  • 作用:round_robin 模式记录上次使用的 provider,下次从下一个开始

三、API 参考

3.1 静态方法(功能注册)

registerFeature($key, $config)

注册新 AI 功能。插件应在 model_inc_start.php 钩子中调用,先注册者胜(已注册不覆盖)。

AIService::registerFeature('xnx_ai_reply', array(
    'name'             => 'AI 自动回复',
    'type'             => 'text',
    'mode'             => 'global',
    'call_method'      => 'proxy',
    'default_provider' => '',
    'default_model'    => '',
    'allowed_providers' => array(),
));

字段

类型

必填

说明

name

string

是

功能名称(显示用)

type

string

是

provider 类型:text/image/video/audio/transcription

mode

string

是

global(用全局配置)/ user_key(用用户配置)/ both(优先用户,回退全局)

call_method

string

是

frontend(前端直连)/ proxy(服务端代理)

default_provider

string

否

默认 provider 名

default_model

string

否

默认模型名

allowed_providers

array

否

允许的 provider 名数组

registerPostFilter($key, $callback)

注册内容后处理过滤器。call() 和 callWithFailover() 成功后会自动调用。

AIService::registerPostFilter('xnx_ai_reply', function($content, $context) {
    // $context = ['key', 'messages', 'provider_name', 'options']
    return trim($content);
});

getRegisteredFeatures()

返回所有已注册功能(核心 editor + 插件注册的)。

3.2 实例方法(配置解析)

getFeatureConfig($key)

返回功能配置(合并注册默认值 + conf.ai.features.$key,conf 覆盖注册默认值)。

getEffectiveConfig($key, $uid = null)

按 mode 合并全局/用户配置,返回最终生效配置。配置不完整时返回空数组。

$ai = new AIService($db, $conf);
$config = $ai->getEffectiveConfig('editor', $uid);
// 返回:['apiKey', 'model', 'url', 'provider_name', 'promptContinue'(可选), 'promptImprove'(可选)]

3.3 实例方法(AI 调用)

call($key, $messages, $options = [])

单 provider 调用(按功能 key 解析配置后调用)。

$result = $ai->call('editor', $messages, array(
    'uid'         => $uid,
    'temperature' => 0.7,
    'max_tokens'  => 1024,
    'timeout'     => 30,
    'source'      => 'core',
));

返回结构:

array(
    'code'    => 0,           // 0成功 / 1失败
    'message' => '',          // 错误信息
    'data'    => array(
        'content'       => 'AI 回复文本',
        'usage'         => array('prompt_tokens', 'completion_tokens', 'total_tokens'),
        'provider_name' => 'openai',
        'model'         => 'gpt-4o-mini',
        'time_ms'       => 1234,
    ),
)

callWithFailover($key, $messages, $options = []) ★

多 provider 调用,支持四种模式。插件复用此方法实现轮询、故障转移、并发竞速。

$result = $ai->callWithFailover('xnx_ai_reply', $messages, array(
    'mode'              => 'failover',   // failover/round_robin/random/concurrent
    'retry'             => 2,            // 每个 provider 重试次数
    'providers'         => array('openai', 'deepseek'),  // 可选,覆盖 feature.allowed_providers
    'uid'               => $uid,
    'temperature'       => 0.7,
    'max_tokens'        => 1024,
    'timeout'           => 30,
    'source'            => 'xnx_ai_reply',
    'recover_threshold' => 600,          // 离线恢复阈值秒数
));

provider 来源优先级:

  1. options.providers 显式指定

  2. feature.allowed_providers

  3. feature.default_provider

四种模式:

模式

行为

适用场景

failover

顺序故障转移,每个 provider retry 次后切下一个

默认,高可用

round_robin

轮询,从上次使用的下一个开始(kv 持久化)

负载均衡

random

shuffle 后顺序 fallback

随机分散

concurrent

curl_multi 前 3 个并发竞速,取最快返回

低延迟

健康检查逻辑:

  • 调用前过滤掉已离线未过 recover_threshold 的 provider

  • 调用成功后标记 provider online

  • 调用失败后标记 provider offline

  • 未知 provider(kv 无记录)视为健康

3.4 实例方法(健康状态)

markProviderOnline($name) / markProviderOffline($name)

标记 provider 在线/离线(仅状态变化时写 kv)。

isProviderHealthy($name, $recoverThreshold = 600)

判断 provider 是否健康。未知 provider 视为健康,离线超过阈值视为可恢复。

getProviderHealth($name = null)

返回单个或全部 provider 健康状态。

$all = $ai->getProviderHealth();
// 返回:['openai' => ['online' => true, 'last_check' => 1234567890], ...]

$one = $ai->getProviderHealth('openai');
// 返回:['online' => true, 'last_check' => 1234567890]

3.5 实例方法(测试)

testProvider($name)

测试 provider 连接(发送 ping 请求)。成功/失败后自动标记健康状态。

$result = $ai->testProvider('openai');
// 返回:['code' => 0/1, 'message' => ..., 'data' => ['time_ms' => ...]]

四、调用流程

4.1 单 provider 调用流程(call())

call($key, $messages, $options)
  ├─ getEffectiveConfig($key, $uid)  // 按 mode 解析配置
  ├─ callByConfig($config, $messages, $options, $logBase)  // 底层 curl 调用
  │   ├─ 构造请求体(model/messages/temperature/max_tokens)
  │   ├─ curl POST 到 {url}/chat/completions
  │   ├─ 解析响应(choices[0].message.content + usage)
  │   └─ writeLog()  // 写入 xnx_ai_call_log
  └─ applyPostFilters($key, $content, $context)  // 应用已注册的后处理过滤器

4.2 多 provider 调用流程(callWithFailover())

callWithFailover($key, $messages, $options)
  ├─ 解析 providerNames(options.providers > feature.allowed_providers > feature.default_provider)
  ├─ 构建 configs 列表(过滤掉配置不完整和已离线未恢复的)
  ├─ 按模式调用:
  │   ├─ concurrent: callConcurrent()  // curl_multi 前 3 个并发竞速
  │   ├─ random:     callRandom()      // shuffle 后顺序 fallback
  │   ├─ round_robin: callRoundRobin() // 从上次下一个开始,kv 持久化
  │   └─ failover:   callFailover()    // 顺序故障转移 + retry
  │   每种模式内部都调用 callByConfig() 执行单次 curl
  └─ applyPostFilters($key, $content, $context)

五、插件接入指南

5.1 接入步骤

  1. 注册功能:在 hook/model_inc_start.php 调用 AIService::registerFeature()

  2. 配置功能:在 install.php 写入 conf.ai.features.{key}

  3. 调用 AI:在插件业务代码中调用 $ai->call() 或 $ai->callWithFailover()

  4. (可选)注册后处理:通过 registerPostFilter() 注册内容过滤器

5.2 接入示例(xnx_ai_reply 插件)

步骤 1:注册功能(hook/model_inc_start.php)

if (class_exists('AIService') && method_exists('AIService', 'registerFeature')) {
    AIService::registerFeature('xnx_ai_reply', array(
        'name'             => 'AI 自动回复',
        'type'             => 'text',
        'mode'             => 'global',
        'call_method'      => 'proxy',
        'allowed_providers' => array(),
    ));
}

步骤 2:调用 AI(插件 Service 类)

$ai = new AIService($db, $conf);
$result = $ai->callWithFailover('xnx_ai_reply', $messages, array(
    'mode'              => 'failover',
    'retry'             => 2,
    'temperature'       => 0.7,
    'recover_threshold' => 600,
    'source'            => 'xnx_ai_reply',
));

if ($result['code'] === 0) {
    $content = $result['data']['content'];
    $provider_name = $result['data']['provider_name'];
    $usage = $result['data']['usage'];  // prompt_tokens/completion_tokens/total_tokens
}

5.3 接入注意事项

  1. 类加载守卫:生产环境(DEBUG=0)走 tmp/model.min.php 合并加载,类加载顺序不可预测。调用 AIService 前必须:

    if (!class_exists('AIService')) {
        include_once APP_PATH . 'lib/AIService.php';
    }
    
  2. provider 来源:插件不应自建 provider 表,统一用核心 conf.ai.providers。用户在后台「AI - 全局提供商」页面配置。

  3. 健康状态:核心用 kv 持久化(ai_provider_health),插件不要自建健康检查逻辑,直接调用 isProviderHealthy() 或 getProviderHealth()。

  4. 日志写入:call() 和 callWithFailover() 内部已自动写入核心日志表 xnx_ai_call_log,插件如需自有日志表可双写(参考 xnx_ai_reply 的 AiLogService)。

  5. 流式调用:call() 和 callWithFailover() 是非流式调用。流式调用(SSE)由 route/ai.php 的 /ai-chat 端点处理,插件如需流式需自行实现。

六、相关文件

文件

职责

lib/AIService.php

核心 AI 调用中台(本文档)

lib/AILogService.php

统一 AI 调用日志接口(写入 xnx_ai_call_log)

route/ai.php

前台 AI 代理路由(/ai-chat,流式 SSE)

admin/route/ai.php

后台 AI 配置路由(providers/features)

admin/view/htm/ai_providers.htm

后台全局提供商配置页

admin/view/htm/ai_features.htm

后台功能配置页

admin/view/htm/ai_logs.htm

后台 AI 调用日志页

view/htm/my_ai.htm

前台「我的 AI」配置页

conf/conf.default.php

默认配置(含预置 5 个 AI 厂商)

七、数据库表

7.1 xnx_ai_call_log(核心统一日志表)

字段

类型

说明

id

int unsigned

主键

uid

int unsigned

用户ID

feature

varchar(32)

功能标识(editor/xnx_ai_reply/…)

source

varchar(32)

来源标识(core/xnx_ai_reply/…)

provider_name

varchar(64)

provider 名

model

varchar(64)

模型名

mode

varchar(16)

模式(global/user_key/both)

prompt_tokens

int

输入 token 数

completion_tokens

int

输出 token 数

total_tokens

int

总 token 数

response_time

int

响应时间(ms)

status

tinyint

1成功 / 0失败

error_msg

varchar(500)

错误信息

request_summary

varchar(500)

请求摘要

response_summary

varchar(500)

响应摘要

create_time

int unsigned

创建时间

7.2 kv 表

键

说明

ai_provider_health

provider 健康状态(name => {online, last_check})

ai_roundrobin_last_{feature}

round_robin 模式上次使用的 provider 名

八、错误码

code

含义

说明

0

成功

data 含 content/usage/provider_name/model/time_ms

1

失败

message 含错误信息

常见错误信息:

  • AI 配置不完整:apiKey/url/model 为空

  • 无可用 provider:allowed_providers 为空且无 default_provider

  • 无可用 provider 配置(可能全部离线或配置不完整):所有 provider 都离线或配置缺失

  • curl error: ...:curl 调用失败

  • HTTP 4xx/5xx: ...:provider 返回错误状态码

  • empty content:provider 返回空内容


New Post

Please log in to reply Login

uid:4 三级用户组
Follow
Posts 64
Comments 1
Followers 0
Following 0
Publish
Table of Contents
XIUNOX AIService 核心文档
This Ad Slot Available
This Ad Slot Available
This Ad Slot Available
Ad Available
Ad Available
Ad Available
Ad Available
Ad Available
Ad Available