mirror of
https://gh.wpcy.net/https://github.com/thomas-deep/freescoutAI.git
synced 2026-05-24 07:42:04 +08:00
- Added MistralProvider, OllamaProvider, OpenAIProvider, and OpenRouterProvider classes for AI functionalities. - Created DefaultPrompts service for managing standard prompts for email prioritization, response suggestions, text modifications, and summarization. - Developed a user interface for customizing prompts within FreeScout settings. - Established a comprehensive test plan covering installation, configuration, email prioritization, response suggestions, text modifications, and performance. - Included module metadata in module.json and routing setup in start.php.
312 lines
12 KiB
PHP
312 lines
12 KiB
PHP
<?php
|
|
|
|
namespace Modules\FreeScoutAI\Http\Controllers;
|
|
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Http\Response;
|
|
use Illuminate\Routing\Controller;
|
|
use App\Mailbox;
|
|
use App\Thread;
|
|
use App\Conversation;
|
|
use Modules\FreeScoutAI\Entities\AISettings;
|
|
use Modules\FreeScoutAI\Entities\AIPriority;
|
|
use Modules\FreeScoutAI\Entities\AISuggestion;
|
|
use Modules\FreeScoutAI\Services\DefaultPrompts;
|
|
|
|
class FreeScoutAIController extends Controller
|
|
{
|
|
/**
|
|
* Display the settings page.
|
|
*
|
|
* @param int $mailbox_id
|
|
* @return Response
|
|
*/
|
|
public function settings($mailbox_id)
|
|
{
|
|
$mailbox = Mailbox::findOrFail($mailbox_id);
|
|
$settings = AISettings::find($mailbox_id);
|
|
|
|
if (empty($settings)) {
|
|
$settings = new AISettings();
|
|
$settings->mailbox_id = $mailbox_id;
|
|
$settings->enabled = false;
|
|
$settings->provider = '';
|
|
$settings->api_key = '';
|
|
$settings->model = '';
|
|
$settings->priority_enabled = false;
|
|
$settings->suggestions_enabled = false;
|
|
$settings->modifications_enabled = false;
|
|
$settings->summary_enabled = false;
|
|
$settings->ollama_url = 'http://localhost:11434';
|
|
$settings->data_privacy_acknowledged = false;
|
|
|
|
// Set default prompts
|
|
$settings->priority_prompt = DefaultPrompts::getPriorityPrompt();
|
|
$settings->suggestion_prompt = DefaultPrompts::getSuggestionPrompt();
|
|
$settings->shorten_prompt = DefaultPrompts::getShortenPrompt();
|
|
$settings->expand_prompt = DefaultPrompts::getExpandPrompt();
|
|
$settings->formal_prompt = DefaultPrompts::getFormalPrompt();
|
|
$settings->personal_prompt = DefaultPrompts::getPersonalPrompt();
|
|
$settings->summary_prompt = DefaultPrompts::getSummaryPrompt();
|
|
}
|
|
|
|
// Load default prompts for reference
|
|
$defaultPrompts = [
|
|
'priority_prompt' => DefaultPrompts::getPriorityPrompt(),
|
|
'suggestion_prompt' => DefaultPrompts::getSuggestionPrompt(),
|
|
'shorten_prompt' => DefaultPrompts::getShortenPrompt(),
|
|
'expand_prompt' => DefaultPrompts::getExpandPrompt(),
|
|
'formal_prompt' => DefaultPrompts::getFormalPrompt(),
|
|
'personal_prompt' => DefaultPrompts::getPersonalPrompt(),
|
|
'summary_prompt' => DefaultPrompts::getSummaryPrompt()
|
|
];
|
|
|
|
return view('freescoutai::settings', [
|
|
'mailbox' => $mailbox,
|
|
'settings' => $settings,
|
|
'defaultPrompts' => $defaultPrompts
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Save settings.
|
|
*
|
|
* @param int $mailbox_id
|
|
* @param Request $request
|
|
* @return Response
|
|
*/
|
|
public function saveSettings($mailbox_id, Request $request)
|
|
{
|
|
$provider = $request->get('provider');
|
|
$data_privacy_required = in_array($provider, ['openai', 'anthropic', 'mistral', 'openrouter']);
|
|
|
|
if ($data_privacy_required && !$request->has('data_privacy_acknowledged')) {
|
|
\Session::flash('flash_error_floating', __('Bitte bestätigen Sie den Datenschutzhinweis für Online-KI-Dienste'));
|
|
return redirect()->route('freescoutai.settings', ['mailbox_id' => $mailbox_id]);
|
|
}
|
|
|
|
AISettings::updateOrCreate(
|
|
['mailbox_id' => $mailbox_id],
|
|
[
|
|
'enabled' => $request->has('enabled'),
|
|
'provider' => $provider,
|
|
'api_key' => $request->get('api_key'),
|
|
'model' => $request->get('model'),
|
|
'priority_enabled' => $request->has('priority_enabled'),
|
|
'suggestions_enabled' => $request->has('suggestions_enabled'),
|
|
'modifications_enabled' => $request->has('modifications_enabled'),
|
|
'summary_enabled' => $request->has('summary_enabled'),
|
|
'ollama_url' => $request->get('ollama_url'),
|
|
'data_privacy_acknowledged' => $request->has('data_privacy_acknowledged'),
|
|
'priority_prompt' => $request->get('priority_prompt'),
|
|
'suggestion_prompt' => $request->get('suggestion_prompt'),
|
|
'shorten_prompt' => $request->get('shorten_prompt'),
|
|
'expand_prompt' => $request->get('expand_prompt'),
|
|
'formal_prompt' => $request->get('formal_prompt'),
|
|
'personal_prompt' => $request->get('personal_prompt'),
|
|
'summary_prompt' => $request->get('summary_prompt')
|
|
]
|
|
);
|
|
|
|
\Session::flash('flash_success_floating', __('Einstellungen gespeichert'));
|
|
return redirect()->route('freescoutai.settings', ['mailbox_id' => $mailbox_id]);
|
|
}
|
|
|
|
/**
|
|
* Get available models for the selected provider.
|
|
*
|
|
* @param Request $request
|
|
* @return Response
|
|
*/
|
|
public function getModels(Request $request)
|
|
{
|
|
$provider = $request->get('provider');
|
|
$api_key = $request->get('api_key');
|
|
$ollama_url = $request->get('ollama_url');
|
|
|
|
$models = [];
|
|
|
|
switch ($provider) {
|
|
case 'ollama':
|
|
// For Ollama, we need to query the local server
|
|
if (!empty($ollama_url)) {
|
|
try {
|
|
$client = new \GuzzleHttp\Client();
|
|
$response = $client->get($ollama_url . '/api/tags');
|
|
$data = json_decode($response->getBody(), true);
|
|
|
|
if (isset($data['models'])) {
|
|
foreach ($data['models'] as $model) {
|
|
$models[] = [
|
|
'id' => $model['name'],
|
|
'name' => $model['name']
|
|
];
|
|
}
|
|
}
|
|
} catch (\Exception $e) {
|
|
return response()->json(['error' => 'Fehler beim Abrufen der Ollama-Modelle: ' . $e->getMessage()], 400);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 'openai':
|
|
// OpenAI models
|
|
if (!empty($api_key)) {
|
|
$models = [
|
|
['id' => 'gpt-3.5-turbo', 'name' => 'GPT-3.5 Turbo'],
|
|
['id' => 'gpt-3.5-turbo-16k', 'name' => 'GPT-3.5 Turbo 16K'],
|
|
['id' => 'gpt-4', 'name' => 'GPT-4'],
|
|
['id' => 'gpt-4-turbo', 'name' => 'GPT-4 Turbo'],
|
|
['id' => 'gpt-4-32k', 'name' => 'GPT-4 32K']
|
|
];
|
|
}
|
|
break;
|
|
|
|
case 'anthropic':
|
|
// Anthropic models
|
|
if (!empty($api_key)) {
|
|
$models = [
|
|
['id' => 'claude-3-opus-20240229', 'name' => 'Claude 3 Opus'],
|
|
['id' => 'claude-3-sonnet-20240229', 'name' => 'Claude 3 Sonnet'],
|
|
['id' => 'claude-3-haiku-20240307', 'name' => 'Claude 3 Haiku'],
|
|
['id' => 'claude-2.1', 'name' => 'Claude 2.1'],
|
|
['id' => 'claude-2.0', 'name' => 'Claude 2.0']
|
|
];
|
|
}
|
|
break;
|
|
|
|
case 'mistral':
|
|
// Mistral models
|
|
if (!empty($api_key)) {
|
|
$models = [
|
|
['id' => 'mistral-tiny', 'name' => 'Mistral Tiny'],
|
|
['id' => 'mistral-small', 'name' => 'Mistral Small'],
|
|
['id' => 'mistral-medium', 'name' => 'Mistral Medium'],
|
|
['id' => 'mistral-large', 'name' => 'Mistral Large']
|
|
];
|
|
}
|
|
break;
|
|
|
|
case 'openrouter':
|
|
// OpenRouter models (simplified list)
|
|
if (!empty($api_key)) {
|
|
$models = [
|
|
['id' => 'openai/gpt-4-turbo', 'name' => 'OpenAI GPT-4 Turbo'],
|
|
['id' => 'anthropic/claude-3-opus', 'name' => 'Anthropic Claude 3 Opus'],
|
|
['id' => 'anthropic/claude-3-sonnet', 'name' => 'Anthropic Claude 3 Sonnet'],
|
|
['id' => 'meta-llama/llama-3-70b-instruct', 'name' => 'Meta Llama 3 70B'],
|
|
['id' => 'mistral/mistral-large', 'name' => 'Mistral Large']
|
|
];
|
|
}
|
|
break;
|
|
}
|
|
|
|
return response()->json(['models' => $models]);
|
|
}
|
|
|
|
/**
|
|
* Check if the module is enabled for the mailbox.
|
|
*
|
|
* @param Request $request
|
|
* @return Response
|
|
*/
|
|
public function checkEnabled(Request $request)
|
|
{
|
|
$mailbox_id = $request->query('mailbox_id');
|
|
$settings = AISettings::find($mailbox_id);
|
|
|
|
if (empty($settings)) {
|
|
return response()->json(['enabled' => false]);
|
|
}
|
|
|
|
return response()->json([
|
|
'enabled' => $settings->enabled,
|
|
'priority_enabled' => $settings->priority_enabled,
|
|
'suggestions_enabled' => $settings->suggestions_enabled,
|
|
'modifications_enabled' => $settings->modifications_enabled,
|
|
'summary_enabled' => $settings->summary_enabled
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Prioritize a conversation.
|
|
*
|
|
* @param Request $request
|
|
* @return Response
|
|
*/
|
|
public function prioritize(Request $request)
|
|
{
|
|
$conversation_id = $request->get('conversation_id');
|
|
|
|
if (!$conversation_id) {
|
|
return response()->json(['success' => false, 'error' => 'Conversation ID is required'], 400);
|
|
}
|
|
|
|
$priorityService = new \Modules\FreeScoutAI\Services\AIFunctions\PriorityService();
|
|
$result = $priorityService->prioritizeConversation($conversation_id);
|
|
|
|
return response()->json($result);
|
|
}
|
|
|
|
/**
|
|
* Generate a response suggestion.
|
|
*
|
|
* @param Request $request
|
|
* @return Response
|
|
*/
|
|
public function suggest(Request $request)
|
|
{
|
|
$thread_id = $request->get('thread_id');
|
|
|
|
if (!$thread_id) {
|
|
return response()->json(['success' => false, 'error' => 'Thread ID is required'], 400);
|
|
}
|
|
|
|
$suggestionService = new \Modules\FreeScoutAI\Services\AIFunctions\SuggestionService();
|
|
$result = $suggestionService->generateSuggestion($thread_id);
|
|
|
|
return response()->json($result);
|
|
}
|
|
|
|
/**
|
|
* Modify text.
|
|
*
|
|
* @param Request $request
|
|
* @return Response
|
|
*/
|
|
public function modify(Request $request)
|
|
{
|
|
$mailbox_id = $request->get('mailbox_id');
|
|
$text = $request->get('text');
|
|
$mode = $request->get('mode');
|
|
|
|
if (!$mailbox_id || !$text || !$mode) {
|
|
return response()->json(['success' => false, 'error' => 'Mailbox ID, text, and mode are required'], 400);
|
|
}
|
|
|
|
$modificationService = new \Modules\FreeScoutAI\Services\AIFunctions\ModificationService();
|
|
$result = $modificationService->modifyText($mailbox_id, $text, $mode);
|
|
|
|
return response()->json($result);
|
|
}
|
|
|
|
/**
|
|
* Summarize a conversation.
|
|
*
|
|
* @param Request $request
|
|
* @return Response
|
|
*/
|
|
public function summarize(Request $request)
|
|
{
|
|
$conversation_id = $request->get('conversation_id');
|
|
|
|
if (!$conversation_id) {
|
|
return response()->json(['success' => false, 'error' => 'Conversation ID is required'], 400);
|
|
}
|
|
|
|
$summaryService = new \Modules\FreeScoutAI\Services\AIFunctions\SummaryService();
|
|
$result = $summaryService->summarizeConversation($conversation_id);
|
|
|
|
return response()->json($result);
|
|
}
|
|
}
|