From 318eb6f234e99881ce66c56a25593697e2dbcec7 Mon Sep 17 00:00:00 2001 From: lkddi Date: Fri, 6 Mar 2026 03:29:13 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=EF=BC=9AAI=20=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=E8=BF=9E=E9=80=9A=E6=80=A7=E6=B5=8B=E8=AF=95=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=EF=BC=9B=E4=BF=AE=E5=A4=8D=EF=BC=9AOllama=20=E8=B6=85?= =?UTF-8?q?=E6=97=B6=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 后台 AI 厂商列表新增「⚡ 测试」按钮,实时验证接口连通性 - 显示响应耗时(含冷启动)和模型返回内容 - AiChatService 请求超时从 30s 调整为 120s(兼容 Ollama 本地冷启动) - 测试接口超时设为 60s --- .../Admin/AiProviderController.php | 61 +++++++++++++++++++ app/Services/AiChatService.php | 8 +-- .../views/admin/ai-providers/index.blade.php | 35 +++++++++++ routes/web.php | 1 + 4 files changed, 101 insertions(+), 4 deletions(-) diff --git a/app/Http/Controllers/Admin/AiProviderController.php b/app/Http/Controllers/Admin/AiProviderController.php index 82e16f3..c19e62d 100644 --- a/app/Http/Controllers/Admin/AiProviderController.php +++ b/app/Http/Controllers/Admin/AiProviderController.php @@ -200,6 +200,67 @@ class AiProviderController extends Controller ]); } + /** + * 测试指定 AI 厂商的接口连通性 + * + * 发送一条简短的测试消息,返回响应结果和耗时,用于验证配置是否正确。 + * + * @param int $id 厂商配置 ID + * @return JsonResponse 测试结果 + */ + public function testConnection(int $id): JsonResponse + { + $provider = AiProviderConfig::findOrFail($id); + + $apiKey = $provider->getDecryptedApiKey(); + $base = rtrim($provider->api_endpoint, '/'); + $endpoint = str_ends_with($base, '/v1') + ? $base.'/chat/completions' + : $base.'/v1/chat/completions'; + + $startTime = microtime(true); + + try { + $response = \Illuminate\Support\Facades\Http::withToken($apiKey) + ->timeout(60) // Ollama 本地模型冷启动较慢,给 60s + ->post($endpoint, [ + 'model' => $provider->model, + 'messages' => [ + ['role' => 'user', 'content' => '请用一句话介绍你自己。'], + ], + 'max_tokens' => 64, + ]); + + $ms = (int) ((microtime(true) - $startTime) * 1000); + $data = $response->json(); + + if (! $response->successful()) { + return response()->json([ + 'ok' => false, + 'message' => "HTTP {$response->status()}:{$response->body()}", + 'ms' => $ms, + ]); + } + + $reply = $data['choices'][0]['message']['content'] ?? '(无回复内容)'; + + return response()->json([ + 'ok' => true, + 'message' => trim($reply), + 'ms' => $ms, + 'model' => $data['model'] ?? $provider->model, + ]); + } catch (\Illuminate\Http\Client\ConnectionException $e) { + $ms = (int) ((microtime(true) - $startTime) * 1000); + + return response()->json([ + 'ok' => false, + 'message' => '连接失败:'.$e->getMessage(), + 'ms' => $ms, + ]); + } + } + /** * 删除 AI 厂商配置 * diff --git a/app/Services/AiChatService.php b/app/Services/AiChatService.php index dbaa7b4..d457732 100644 --- a/app/Services/AiChatService.php +++ b/app/Services/AiChatService.php @@ -32,7 +32,7 @@ class AiChatService /** * AI 请求超时时间(秒) */ - private const REQUEST_TIMEOUT = 30; + private const REQUEST_TIMEOUT = 120; // Ollama 本地模型冷启动较慢,给足时间 /** * Redis 上下文 key 前缀 @@ -54,7 +54,7 @@ class AiChatService $charmCross = Sysparam::getValue('charm_cross_sex', '2'); $charmSame = Sysparam::getValue('charm_same_sex', '1'); $charmLimit = Sysparam::getValue('charm_hourly_limit', '20'); - + $levelWarn = Sysparam::getValue('level_warn', '5'); $levelMute = Sysparam::getValue('level_mute', '8'); $levelKick = Sysparam::getValue('level_kick', '10'); @@ -123,8 +123,8 @@ PROMPT; // 将用户消息加入上下文(包含发送者信息) $context[] = [ - 'role' => 'user', - 'content' => "【当前发言人:{$username}】\n" . $message + 'role' => 'user', + 'content' => "【当前发言人:{$username}】\n".$message, ]; // 构建完整的 messages 数组(系统提示 + 对话上下文) diff --git a/resources/views/admin/ai-providers/index.blade.php b/resources/views/admin/ai-providers/index.blade.php index 285410d..4167b5e 100644 --- a/resources/views/admin/ai-providers/index.blade.php +++ b/resources/views/admin/ai-providers/index.blade.php @@ -148,6 +148,9 @@
+
prefix('admin')->name('ad Route::put('/ai-providers/{id}', [\App\Http\Controllers\Admin\AiProviderController::class, 'update'])->name('ai-providers.update'); Route::post('/ai-providers/{id}/toggle', [\App\Http\Controllers\Admin\AiProviderController::class, 'toggleEnabled'])->name('ai-providers.toggle'); Route::post('/ai-providers/{id}/default', [\App\Http\Controllers\Admin\AiProviderController::class, 'setDefault'])->name('ai-providers.default'); + Route::post('/ai-providers/{id}/test', [\App\Http\Controllers\Admin\AiProviderController::class, 'testConnection'])->name('ai-providers.test'); Route::post('/ai-providers/toggle-chatbot', [\App\Http\Controllers\Admin\AiProviderController::class, 'toggleChatBot'])->name('ai-providers.toggle-chatbot'); Route::delete('/ai-providers/{id}', [\App\Http\Controllers\Admin\AiProviderController::class, 'destroy'])->name('ai-providers.destroy');