160 lines
5.0 KiB
PHP
Executable File
160 lines
5.0 KiB
PHP
Executable File
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
use App\Http\Validation\ContentFilterRule;
|
|
use App\Models\ChatMessage;
|
|
use App\Models\TokenUsage;
|
|
use App\Services\AIService;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\Auth;
|
|
use Illuminate\Validation\Rule as ValidationRule;
|
|
use Illuminate\View\View;
|
|
|
|
/**
|
|
* Controller for the AI Chat feature.
|
|
* Allows users to chat with registered AI models.
|
|
*/
|
|
class ChatController extends Controller
|
|
{
|
|
/**
|
|
* Display the AI chat interface.
|
|
*/
|
|
public function index(): View
|
|
{
|
|
/** @var \App\Models\User $user */
|
|
$user = Auth::user();
|
|
|
|
// Get available AI providers from config
|
|
$providers = config('services.ai.providers', []);
|
|
|
|
// Get user's chat history
|
|
$chatHistory = ChatMessage::where('user_id', $user->id)
|
|
->orderBy('created_at', 'asc')
|
|
->take(50)
|
|
->get();
|
|
|
|
// Get chat default provider/model from DB, fallback to config
|
|
$defaultProvider = \App\Models\Setting::where('key', 'chat_default_provider')->value('value');
|
|
$defaultModel = \App\Models\Setting::where('key', 'chat_default_model')->value('value');
|
|
|
|
if (!$defaultProvider) {
|
|
$defaultProvider = config('services.ai.default_provider', 'openrouter');
|
|
}
|
|
|
|
if (!$defaultModel) {
|
|
$defaultModel = config('services.ai.providers.'.$defaultProvider.'.model', 'inclusionai/ling-3.0-tiny:free');
|
|
}
|
|
|
|
return view('dashboard.chat', compact(
|
|
'providers',
|
|
'chatHistory',
|
|
'defaultProvider',
|
|
'defaultModel'
|
|
));
|
|
}
|
|
|
|
/**
|
|
* Send a message to the AI and get a response.
|
|
*/
|
|
public function store(Request $request): \Illuminate\Http\RedirectResponse
|
|
{
|
|
/** @var \App\Models\User $user */
|
|
$user = Auth::user();
|
|
|
|
$validated = $request->validate([
|
|
'message' => ['required', 'string', 'max:4000', new ContentFilterRule()],
|
|
]);
|
|
|
|
$message = trim($validated['message']);
|
|
|
|
// Use chat default provider/model from DB
|
|
$defaultProvider = \App\Models\Setting::where('key', 'chat_default_provider')->value('value');
|
|
$defaultModel = \App\Models\Setting::where('key', 'chat_default_model')->value('value');
|
|
|
|
if (!$defaultProvider) {
|
|
$defaultProvider = config('services.ai.default_provider', 'openrouter');
|
|
}
|
|
|
|
if (!$defaultModel) {
|
|
$defaultModel = config('services.ai.providers.'.$defaultProvider.'.model', 'inclusionai/ling-3.0-tiny:free');
|
|
}
|
|
|
|
// Build conversation history for context
|
|
$recentMessages = ChatMessage::where('user_id', $user->id)
|
|
->orderByDesc('created_at')
|
|
->take(10)
|
|
->get()
|
|
->reverse()
|
|
->values();
|
|
|
|
$messages = [];
|
|
foreach ($recentMessages as $chat) {
|
|
$messages[] = ['role' => 'user', 'content' => $chat->message];
|
|
if ($chat->response) {
|
|
$messages[] = ['role' => 'assistant', 'content' => $chat->response];
|
|
}
|
|
}
|
|
$messages[] = ['role' => 'user', 'content' => $message];
|
|
|
|
// Initialize AI service with selected provider and model
|
|
$aiService = new AIService($defaultProvider, $defaultModel);
|
|
|
|
// Use the chat completion endpoint directly
|
|
$result = $aiService->chat($messages);
|
|
|
|
if (!$result['success']) {
|
|
return back()->with('error', __('Failed to get response: :error', [
|
|
'error' => $result['error'] ?? __('Unknown error'),
|
|
]));
|
|
}
|
|
|
|
$response = $result['content'];
|
|
$inputTokens = $result['input_tokens'] ?? 0;
|
|
$outputTokens = $result['output_tokens'] ?? 0;
|
|
$model = $defaultModel;
|
|
$provider = $defaultProvider;
|
|
|
|
// Save chat message
|
|
ChatMessage::create([
|
|
'user_id' => $user->id,
|
|
'message' => $message,
|
|
'response' => $response,
|
|
'provider' => $provider,
|
|
'model' => $model,
|
|
'input_tokens' => $inputTokens,
|
|
'output_tokens' => $outputTokens,
|
|
'sent_at' => now(),
|
|
]);
|
|
|
|
// Track token usage
|
|
if ($inputTokens > 0 || $outputTokens > 0) {
|
|
TokenUsage::create([
|
|
'user_id' => $user->id,
|
|
'input_tokens' => $inputTokens,
|
|
'output_tokens' => $outputTokens,
|
|
'total_tokens' => $inputTokens + $outputTokens,
|
|
'model' => $model,
|
|
'provider' => $provider,
|
|
]);
|
|
}
|
|
|
|
return back()->with('success', __('Message sent successfully!'));
|
|
}
|
|
|
|
/**
|
|
* Clear chat history.
|
|
*/
|
|
public function destroy(Request $request): \Illuminate\Http\RedirectResponse
|
|
{
|
|
/** @var \App\Models\User $user */
|
|
$user = Auth::user();
|
|
|
|
ChatMessage::where('user_id', $user->id)->delete();
|
|
|
|
return back()->with('success', __('Chat history cleared.'));
|
|
}
|
|
}
|