feat: Integrate OpenAI API for email task parsing and update configuration
This commit is contained in:
@@ -88,8 +88,34 @@ class MailToTaskImporter
|
||||
try
|
||||
{
|
||||
$content = $this -> extractMessageContent( $imap, $message_no );
|
||||
$task_name = trim( $subject ) !== '' ? trim( $subject ) : '(bez tematu)';
|
||||
$task_text = $this -> prepareImportedTaskText( $content['text'] );
|
||||
|
||||
// Sprawdź czy użyć AI do parsowania
|
||||
global $settings;
|
||||
$use_ai = isset( $settings['openai_parse_emails'] ) && $settings['openai_parse_emails'] === true;
|
||||
$api_key = isset( $settings['openai_api_key'] ) ? trim( (string)$settings['openai_api_key'] ) : '';
|
||||
|
||||
if ( $use_ai && $api_key !== '' )
|
||||
{
|
||||
$model = isset( $settings['openai_model'] ) ? trim( (string)$settings['openai_model'] ) : 'gpt-3.5-turbo';
|
||||
$ai_result = $this -> parseWithAI( $api_key, $model, $subject, $content['text'] );
|
||||
if ( $ai_result !== null )
|
||||
{
|
||||
$task_name = $ai_result['task_name'];
|
||||
$task_text = $ai_result['task_text'];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Fallback do normalnego parsowania jeśli AI nie zadziała
|
||||
$task_name = trim( $subject ) !== '' ? trim( $subject ) : '(bez tematu)';
|
||||
$task_text = $this -> prepareImportedTaskText( $content['text'] );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Normalne parsowanie
|
||||
$task_name = trim( $subject ) !== '' ? trim( $subject ) : '(bez tematu)';
|
||||
$task_text = $this -> prepareImportedTaskText( $content['text'] );
|
||||
}
|
||||
$client_id = $this -> resolveClientIdBySenderDomain( $sender );
|
||||
|
||||
$task_id = \factory\Tasks::task_save(
|
||||
@@ -648,4 +674,96 @@ class MailToTaskImporter
|
||||
$value = trim( $value, '<>' );
|
||||
return strtolower( $value );
|
||||
}
|
||||
|
||||
private function parseWithAI( $api_key, $model, $subject, $raw_content )
|
||||
{
|
||||
$subject = trim( (string)$subject );
|
||||
$raw_content = trim( (string)$raw_content );
|
||||
$model = trim( (string)$model );
|
||||
|
||||
if ( $model === '' )
|
||||
$model = 'gpt-3.5-turbo';
|
||||
|
||||
// Przygotuj treść do analizy (usuń HTML jesli jest)
|
||||
if ( preg_match( '/<\s*[a-z][^>]*>/i', $raw_content ) )
|
||||
{
|
||||
$raw_content = $this -> htmlToText( $raw_content );
|
||||
$raw_content = $this -> cleanBodyText( $raw_content );
|
||||
}
|
||||
|
||||
$prompt = "Jesteś asystentem do przetwarzania emaili na zadania w systemie CRM. " .
|
||||
"Na podstawie poniższego tematu i treści emaila, wygeneruj:\n" .
|
||||
"1. Zwięzły, konkretny temat zadania (max 100 znaków)\n" .
|
||||
"2. Czytelny opis zadania zawierający najważniejsze informacje\n\n" .
|
||||
"Temat emaila: " . $subject . "\n\n" .
|
||||
"Treść emaila:\n" . mb_substr( $raw_content, 0, 2000 ) . "\n\n" .
|
||||
"Odpowiedz TYLKO w formacie JSON bez żadnych dodatkowych wyjaśnień:\n" .
|
||||
'{"task_name": "temat zadania", "task_text": "opis zadania"}';
|
||||
|
||||
$payload = [
|
||||
'model' => $model,
|
||||
'messages' => [
|
||||
[
|
||||
'role' => 'system',
|
||||
'content' => 'Jesteś asystentem do przetwarzania emaili. Odpowiadasz TYLKO w formacie JSON.'
|
||||
],
|
||||
[
|
||||
'role' => 'user',
|
||||
'content' => $prompt
|
||||
]
|
||||
],
|
||||
'temperature' => 0.3,
|
||||
'max_tokens' => 500
|
||||
];
|
||||
|
||||
$ch = curl_init( 'https://api.openai.com/v1/chat/completions' );
|
||||
curl_setopt_array( $ch, [
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_POST => true,
|
||||
CURLOPT_POSTFIELDS => json_encode( $payload ),
|
||||
CURLOPT_HTTPHEADER => [
|
||||
'Content-Type: application/json',
|
||||
'Authorization: Bearer ' . $api_key
|
||||
],
|
||||
CURLOPT_TIMEOUT => 30
|
||||
] );
|
||||
|
||||
$response = curl_exec( $ch );
|
||||
$http_code = curl_getinfo( $ch, CURLINFO_HTTP_CODE );
|
||||
curl_close( $ch );
|
||||
|
||||
if ( $http_code !== 200 || !$response )
|
||||
return null;
|
||||
|
||||
$data = json_decode( $response, true );
|
||||
if ( !isset( $data['choices'][0]['message']['content'] ) )
|
||||
return null;
|
||||
|
||||
$content = trim( $data['choices'][0]['message']['content'] );
|
||||
|
||||
// Usuń markdown code block jeśli jest
|
||||
$content = preg_replace( '/```json\s*|\s*```/', '', $content );
|
||||
$content = trim( $content );
|
||||
|
||||
$parsed = json_decode( $content, true );
|
||||
if ( !is_array( $parsed ) || !isset( $parsed['task_name'] ) || !isset( $parsed['task_text'] ) )
|
||||
return null;
|
||||
|
||||
$task_name = trim( (string)$parsed['task_name'] );
|
||||
$task_text = trim( (string)$parsed['task_text'] );
|
||||
|
||||
if ( $task_name === '' )
|
||||
$task_name = '(bez tematu)';
|
||||
|
||||
if ( $task_text === '' )
|
||||
$task_text = '(brak treści)';
|
||||
|
||||
// Formatuj treść zadania z nl2br
|
||||
$task_text = nl2br( $task_text );
|
||||
|
||||
return [
|
||||
'task_name' => $task_name,
|
||||
'task_text' => $task_text
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user