RT-Extension-AI

 view release on metacpan or  search on metacpan

html/Helpers/AISearch/GenerateTicketSQL  view on Meta::CPAN


    # Add Format grammar if available
    if ($format_grammar) {
        $full_prompt .= <<"END_FORMAT_GRAMMAR";

# Format Grammar Reference

$format_grammar

END_FORMAT_GRAMMAR
    }

    # The prompt for the expected response format is inline below because the
    # code expects a specific JSON structure. If set in the configuration file,
    # users might unintentionally change the response format and break the code
    # parsing the response.
    $full_prompt .= <<"END_REQUEST";

# User Request

$naturalLanguageQuery

# Response Format

You MUST respond with valid JSON in this exact format (no markdown, no explanation):
{"query": "YOUR_TICKETSQL_QUERY", "format": "YOUR_FORMAT_STRING", "message": "Brief explanation of what the search does"}

The "query" field contains the TicketSQL query.
The "format" field contains the Format string for displaying results. Use the Format Grammar Reference above to construct an appropriate format based on what the user wants to see. If the user doesn't specify display preferences, use a sensible defau...
The "message" field contains a brief (1-2 sentence) explanation of what tickets will be found and what columns will be displayed.
END_REQUEST

    # Initialize the AI provider
    my $provider_class = "RT::Extension::AI::Provider::" . $config->{name};
    my $provider_instance = $provider_class->new(config => $config);

    # Process the request
    my $response = $provider_instance->process_request(
        prompt       => $full_prompt,
        raw_text     => '',  # The query is in the prompt
        model_config => $config->{default_model},
    );

    if ($response->{success}) {
        my $ai_response = $response->{result};

        # Try to parse as JSON
        my $parsed;
        eval {
            # Remove markdown code blocks if present
            $ai_response =~ s/```json\s*//g;
            $ai_response =~ s/```\s*//g;
            $ai_response =~ s/^\s+|\s+$//g;

            RT->Logger->debug("AI response after cleanup: $ai_response");

            $parsed = JSON::decode_json($ai_response);
        };

        # Use default format when AI doesn't provide one
        my $user_prefs = $session{'CurrentUser'}->UserObj->Preferences("SearchDisplay") || {};
        my $default_search_format = $user_prefs->{'Format'}  || RT->Config->Get('DefaultSearchResultFormat');

        if ($@ || !$parsed) {
            RT->Logger->warning("AI response was not valid JSON, attempting to extract TicketSQL. Error: $@");
            RT->Logger->debug("Failed to parse as JSON, raw response was: $ai_response");

            # Fallback: try to extract TicketSQL the old way
            my $ticketsql = $ai_response;
            $ticketsql =~ s/```ticketsql\s*//g;
            $ticketsql =~ s/```\s*//g;
            $ticketsql =~ s/^\s+|\s+$//g;

            # If multiline, find the query line
            if ($ticketsql =~ /\n/) {
                my @lines = split /\n/, $ticketsql;
                for my $line (@lines) {
                    next if $line =~ /^\s*$/;
                    next if $line =~ /^(here|this|the|note|explanation|search)/i;
                    if ($line =~ /(Queue|Status|Owner|Priority|Subject|Created|Due|Requestor|Content)\s*[=!<>]|AND|OR/i) {
                        $ticketsql = $line;
                        last;
                    }
                }
            }

            $result->{success} = 1;
            $result->{query} = $ticketsql;
            $result->{format} = $default_search_format;
            $result->{message} = "Search generated (using default display format)";
        } else {
            $result->{success} = 1;
            $result->{query} = $parsed->{query} // '';
            $result->{format} = $parsed->{format} // $default_search_format;
            $result->{message} = $parsed->{message} // '';
        }
    } else {
        RT->Logger->error("AI request failed: " . $response->{error});
        $result->{message} = $response->{error} || "Unknown error";
    }
}

$output = JSON::encode_json($result);
</%INIT>



( run in 0.446 second using v1.01-cache-2.11-cpan-8f98c5d2c55 )