llmbackend/app/Http/Controllers/Api/Admin/LlmProviderController.php
2024-12-04 16:41:43 +08:00

300 lines
9.5 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Http\Controllers\Api\Admin;
use App\Constants\ErrorCode;
use App\Http\Controllers\Controller;
use App\Models\Admin;
use App\Models\LlmProvider;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Validation\ValidationException;
class LlmProviderController extends Controller
{
/**
* @var Admin
*/
private readonly Admin $admin;
public function __construct(Request $request)
{
$admin = $request->admin;
if (!$admin instanceof Admin) {
throw new \RuntimeException('管理員信息未找到。');
}
$this->admin = $admin;
}
/**
* 獲取 LLM 提供商列表
*
* @return JsonResponse
*/
public function index(): JsonResponse
{
try {
/** @var \Illuminate\Database\Eloquent\Builder $providers */
$providers = LlmProvider::select([
'id',
'name',
'service_name',
'api_url',
'status',
'created_at',
]);
// 如果不是超級管理員,只能看到自己管理的提供商
if (!$this->admin->isSuperAdmin()) {
$providers->whereHas('clients', function ($query) {
$query->whereHas('admins', function ($query) {
$query->where('admin_id', $this->admin->id);
});
});
}
/** @var \Illuminate\Database\Eloquent\Collection $providerList */
$providerList = $providers->get();
return response()->json([
'items' => $providerList->map(fn($provider) => [
'id' => $provider->id,
'name' => $provider->name,
'service_name' => $provider->service_name,
'api_url' => $provider->api_url,
'status' => $provider->status,
'created_at' => $provider->created_at->toIso8601String(),
])
]);
} catch (\Exception $e) {
Log::error('Error fetching LLM providers', [
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString(),
]);
return response()->json([
'error' => ErrorCode::SERVER_ERROR,
'message' => ErrorCode::getMessage(ErrorCode::SERVER_ERROR)
]);
}
}
/**
* 新增 LLM 提供商
*
* @param Request $request
* @return JsonResponse
* @throws ValidationException
*/
public function store(Request $request): JsonResponse
{
try {
// 只有超級管理員可以新增提供商
if (!$this->admin->isSuperAdmin()) {
return response()->json([
'error' => ErrorCode::FORBIDDEN,
'message' => '只有超級管理員可以新增 LLM 提供商。'
]);
}
/** @var array{
* name: string,
* service_name: string,
* api_url: string,
* api_token: string
* } $validated */
$validated = $request->validate([
'name' => [
'required',
'string',
'max:100',
'unique:llm_providers',
],
'service_name' => [
'required',
'string',
'max:100',
],
'api_url' => [
'required',
'string',
'url',
'max:255',
],
'api_token' => [
'required',
'string',
'max:255',
],
]);
$validated['status'] = LlmProvider::STATUS_ACTIVE;
/** @var LlmProvider $provider */
$provider = LlmProvider::create($validated);
return response()->json([
'id' => $provider->id,
'name' => $provider->name,
'service_name' => $provider->service_name,
'api_url' => $provider->api_url,
'api_token' => $provider->api_token,
'created_at' => $provider->created_at->toIso8601String(),
]);
} catch (ValidationException $e) {
return response()->json([
'error' => ErrorCode::VALIDATION_ERROR,
'message' => ErrorCode::getMessage(ErrorCode::VALIDATION_ERROR),
'errors' => $e->errors()
]);
} catch (\Exception $e) {
Log::error('Error creating LLM provider', [
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString(),
'request_data' => $request->except(['api_token']),
]);
return response()->json([
'error' => ErrorCode::SERVER_ERROR,
'message' => ErrorCode::getMessage(ErrorCode::SERVER_ERROR)
]);
}
}
/**
* 修改 LLM 提供商
*/
public function update(Request $request, int $id): JsonResponse
{
try {
$provider = LlmProvider::findOrFail($id);
if (!$this->admin->canManageLlmProvider($provider->id)) {
return response()->json([
'error' => ErrorCode::FORBIDDEN,
'message' => '您無權管理該 LLM 提供商。'
]);
}
$validated = $request->validate([
'name' => [
'required',
'string',
'max:100',
"unique:llm_providers,name,{$id}",
],
'service_name' => [
'required',
'string',
'max:100',
],
'api_url' => [
'required',
'string',
'url',
'max:255',
],
'api_token' => [
'required',
'string',
'max:255',
],
'status' => [
'required',
'string',
'in:active,inactive',
],
]);
// 如果要停用提供商,檢查是否有客戶在使用
if ($validated['status'] === LlmProvider::STATUS_INACTIVE &&
$provider->status === LlmProvider::STATUS_ACTIVE) {
if ($provider->clients()->exists()) {
return response()->json([
'error' => ErrorCode::RESOURCE_IN_USE,
'message' => '該提供商正在被客戶使用,無法停用。'
]);
}
}
$provider->update($validated);
return response()->json([
'id' => $provider->id,
'name' => $provider->name,
'service_name' => $provider->service_name,
'api_url' => $provider->api_url,
'api_token' => $provider->api_token,
'updated_at' => $provider->updated_at->toIso8601String(),
]);
} catch (ValidationException $e) {
return response()->json([
'error' => ErrorCode::VALIDATION_ERROR,
'message' => ErrorCode::getMessage(ErrorCode::VALIDATION_ERROR),
'errors' => $e->errors()
]);
} catch (\Exception $e) {
Log::error('Error updating LLM provider', [
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString(),
'provider_id' => $id,
'request_data' => $request->except(['api_token']),
]);
return response()->json([
'error' => ErrorCode::SERVER_ERROR,
'message' => ErrorCode::getMessage(ErrorCode::SERVER_ERROR)
]);
}
}
/**
* 刪除 LLM 提供商
*/
public function destroy(int $id): JsonResponse
{
try {
$provider = LlmProvider::findOrFail($id);
if (!$this->admin->canManageLlmProvider($provider->id)) {
return response()->json([
'error' => ErrorCode::FORBIDDEN,
'message' => '您無權管理該 LLM 提供商。'
]);
}
// 檢查是否有客戶在使用
if ($provider->clients()->exists()) {
return response()->json([
'error' => ErrorCode::RESOURCE_IN_USE,
'message' => '該提供商正在被客戶使用,無法刪除。'
]);
}
$providerName = $provider->name;
$provider->delete();
return response()->json([
'message' => 'LLM 提供商已刪除。'
]);
} catch (\Exception $e) {
Log::error('Error deleting LLM provider', [
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString(),
'provider_id' => $id,
]);
return response()->json([
'error' => ErrorCode::SERVER_ERROR,
'message' => ErrorCode::getMessage(ErrorCode::SERVER_ERROR)
]);
}
}
}