2026-02-26 21:30:07 +08:00
|
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 文件功能:AI 厂商配置模型
|
|
|
|
|
|
*
|
|
|
|
|
|
* 对应 ai_provider_configs 表,管理多个 AI 厂商的 API 配置。
|
|
|
|
|
|
* 支持多厂商切换、默认配置、自动故障转移等功能。
|
|
|
|
|
|
*
|
|
|
|
|
|
* @author ChatRoom Laravel
|
|
|
|
|
|
*
|
|
|
|
|
|
* @version 1.0.0
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
namespace App\Models;
|
|
|
|
|
|
|
|
|
|
|
|
use Illuminate\Database\Eloquent\Model;
|
|
|
|
|
|
use Illuminate\Support\Facades\Crypt;
|
|
|
|
|
|
|
|
|
|
|
|
class AiProviderConfig extends Model
|
|
|
|
|
|
{
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 关联的数据库表名
|
|
|
|
|
|
*
|
|
|
|
|
|
* @var string
|
|
|
|
|
|
*/
|
|
|
|
|
|
protected $table = 'ai_provider_configs';
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 可批量赋值的属性
|
|
|
|
|
|
*
|
|
|
|
|
|
* @var array<int, string>
|
|
|
|
|
|
*/
|
|
|
|
|
|
protected $fillable = [
|
|
|
|
|
|
'provider',
|
|
|
|
|
|
'name',
|
|
|
|
|
|
'api_key',
|
|
|
|
|
|
'api_endpoint',
|
|
|
|
|
|
'model',
|
|
|
|
|
|
'temperature',
|
|
|
|
|
|
'max_tokens',
|
|
|
|
|
|
'is_enabled',
|
|
|
|
|
|
'is_default',
|
|
|
|
|
|
'sort_order',
|
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 属性类型转换
|
|
|
|
|
|
*
|
|
|
|
|
|
* @return array<string, string>
|
|
|
|
|
|
*/
|
|
|
|
|
|
protected function casts(): array
|
|
|
|
|
|
{
|
|
|
|
|
|
return [
|
|
|
|
|
|
'temperature' => 'float',
|
|
|
|
|
|
'max_tokens' => 'integer',
|
|
|
|
|
|
'is_enabled' => 'boolean',
|
|
|
|
|
|
'is_default' => 'boolean',
|
|
|
|
|
|
'sort_order' => 'integer',
|
|
|
|
|
|
];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取解密后的 API Key
|
|
|
|
|
|
*
|
|
|
|
|
|
* @return string|null 解密后的 API Key
|
|
|
|
|
|
*/
|
|
|
|
|
|
public function getDecryptedApiKey(): ?string
|
|
|
|
|
|
{
|
|
|
|
|
|
if (empty($this->api_key)) {
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
return Crypt::decryptString($this->api_key);
|
|
|
|
|
|
} catch (\Exception) {
|
|
|
|
|
|
// 如果解密失败(可能是明文存储的旧数据),直接返回原值
|
|
|
|
|
|
return $this->api_key;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 设置加密存储的 API Key
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param string $value 原始 API Key
|
|
|
|
|
|
*/
|
|
|
|
|
|
public function setApiKeyEncrypted(string $value): void
|
|
|
|
|
|
{
|
|
|
|
|
|
$this->api_key = Crypt::encryptString($value);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取当前默认的 AI 配置
|
|
|
|
|
|
*
|
|
|
|
|
|
* 返回 is_default=1 且 is_enabled=1 的第一条配置。
|
|
|
|
|
|
* 如果没有设置默认,则返回第一条已启用的配置。
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static function getDefault(): ?self
|
|
|
|
|
|
{
|
|
|
|
|
|
// 优先获取标记为默认且已启用的
|
|
|
|
|
|
$default = static::where('is_default', true)
|
|
|
|
|
|
->where('is_enabled', true)
|
|
|
|
|
|
->first();
|
|
|
|
|
|
|
|
|
|
|
|
if ($default) {
|
|
|
|
|
|
return $default;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 退而求其次,取第一个已启用的
|
|
|
|
|
|
return static::where('is_enabled', true)
|
|
|
|
|
|
->orderBy('sort_order')
|
|
|
|
|
|
->first();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取所有已启用的 AI 厂商配置(按 sort_order 排序)
|
|
|
|
|
|
*
|
|
|
|
|
|
* 用于故障转移时依次尝试备用厂商。
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static function getEnabledProviders(): \Illuminate\Database\Eloquent\Collection
|
|
|
|
|
|
{
|
|
|
|
|
|
return static::where('is_enabled', true)
|
|
|
|
|
|
->orderBy('is_default', 'desc') // 默认的排最前面
|
|
|
|
|
|
->orderBy('sort_order')
|
|
|
|
|
|
->get();
|
|
|
|
|
|
}
|
2026-03-28 20:59:50 +08:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 按模型名称查找已启用的 AI 配置
|
|
|
|
|
|
*
|
|
|
|
|
|
* 用于特定业务场景(如百家乐预测)指定使用某款模型。
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param string $model 模型名称(完整匹配)
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static function findByModel(string $model): ?self
|
|
|
|
|
|
{
|
|
|
|
|
|
return static::where('is_enabled', true)
|
|
|
|
|
|
->where('model', $model)
|
|
|
|
|
|
->first();
|
|
|
|
|
|
}
|
2026-02-26 21:30:07 +08:00
|
|
|
|
}
|