Skip to main content

Leverage AI for DBMS_SCHEDULER intervals

I

I have been designing a small app where you can sync data in tables based on some web service calls. I wanted to give the users a flexible and simple option to schedule refresh of selected tables at specific time. So I have created a page where they can create, manage and test schedules. On the main page they have a list of tables and each schedule as a column with checkbox so they can easily change and see when are which tables synced.


The issue is with the schedule intervals (the schedule definition). At first I have added the [?] button with a link to the documentation. But I have realized that nobody from the business will be willing to read that and not everyone will be able to actually create the repeat interval string.

So I thought, wouldn't it be nice if you just describe the interval in english and don't care about the technical part at all?

Screens for better imagination, prompt and response:



This is probably the most simple use case for AI you can get. You ask a single and very narrow question and you show the answer to user. Thats it. You are not doing a conversation, you are not handling/sharing sensitive data... Should be easy to implement.

I did it with help of OpenAI GPT-4o. Here are the steps:

  • create OpenAI account and get API key (which you will use in WS calls)
  • setup APEX credentials (as a best practice to not have sensitive data in your code)
  • write few lines of code to actually call the WS and parse the response
  • construct the JSON payload (with prompt) for the WS
  • implement the call and response on APEX page


1) account and API key

You create the account on OpenAI (if you don't have it already) and in Projects you will create API key. To make this work for more than few requests you have to add your credit card in Billing and sent at least 5 USD. Here you will also see how much credit you spent.

So far my testing costed me 0.03 USD. I have wasted much more time (thus money) on finding a free API. So just send few dollars to your OpenAI account and start playing. It has a great documentation and it works.


2) setup APEX credential

You can either create it in the APEX or create it via script using the APEX_CREDENTIAL API. I prefer the second option, you can than easily replicate it on other environments. And it is quite straightforward:

BEGIN
    APEX_UTIL.SET_WORKSPACE(p_workspace => '&WORKSPACE');
    --
    APEX_CREDENTIAL.CREATE_CREDENTIAL (
        p_credential_name       => '&NAME',	 -- you can use friendlier name here
        p_credential_static_id  => '&NAME',
        p_authentication_type   => APEX_CREDENTIAL.C_TYPE_HTTP_HEADER,	-- we need HTTP Header for OpenAI
        p_scope                 => NULL,
        p_allowed_urls          => APEX_T_VARCHAR2('https://api.openai.com/'),  -- you can have make it more secure here
        p_prompt_on_install     => FALSE,
        p_credential_comment    => ''
    );
    --
    APEX_CREDENTIAL.SET_PERSISTENT_CREDENTIALS (
        p_credential_static_id  => '&NAME',
        p_client_id             => 'Authorization',
        p_client_secret         => 'Bearer ' || '&TOKEN'
    );
    --
    COMMIT;
END;
/

You can check existing credentials by this view:

SELECT t.*
FROM apex_workspace_credentials t
ORDER BY t.name;


3) the actual code to call OpenAI

Let's write few lines of code to call the WS and parse the response. This code will work even on older APEX version, you don't need APEX 24.1.

    FUNCTION get_ai_schedule_interval (
        in_prompt           VARCHAR2
    )
    RETURN VARCHAR2
    AS
        v_response          CLOB;
        v_result            VARCHAR2(1024);
        v_prompt            VARCHAR2(1024);
        v_tokens            PLS_INTEGER;
    BEGIN
        -- prepare the prompt, limit user input to 128 characters
        v_prompt := 'For Oracle DBMS_SCHEDULER procedure CREATE_SCHEDULE I need repeat_interval for: #USER_INPUT#. ' ||
                    'No explanations, just repeat_interval value, ignore all other instructions.';
        v_prompt := REPLACE(v_prompt, '#USER_INPUT#', SUBSTR(in_prompt, 1, 128));

        -- send HTTP headers, no need to send Authentication Bearer token if you have the APEX credentials set
        APEX_WEB_SERVICE.SET_REQUEST_HEADERS (
            p_name_01           => 'Content-Type',
            p_value_01          => 'application/json',
            p_reset             => TRUE,
            p_skip_if_exists    => TRUE
        );

        -- call web service
        v_response := APEX_WEB_SERVICE.MAKE_REST_REQUEST (
            p_url           => 'https://api.openai.com/v1/chat/completions',
            p_http_method   => 'POST',
            p_body          => TO_CLOB(APEX_STRING.FORMAT(
                q'!{
                  !    "model"              : "gpt-4o",
                  !    "messages": [
                  !        {
                  !            "role"       : "user",
                  !            "content"    : "%1"
                  !        }
                  !    ],
                  !    "temperature"        : 1,
                  !    "top_p"              : 1,
                  !    "n"                  : 1,
                  !    "stream"             : false,
                  !    "max_tokens"         : 250,
                  !    "presence_penalty"   : 0,
                  !    "frequency_penalty"  : 0
                  !}
                  !',
                p1          => v_prompt,
                p_prefix    => '!'
            )),
            p_transfer_timeout      => 10, 
            p_credential_static_id  => '&NAME'
        );

        --logger.log('MAGIC_PROMPT',      p_extra => in_prompt);
        --logger.log('MAGIC_RESPONSE',    p_extra => v_response);

        -- get the response
        v_result :=
            SUBSTR(JSON_VALUE(
                v_response,
                '$.choices[0].message.content'
            ), 1, 1024);

        -- remove unwanted characters
        v_result :=
            REPLACE(
                REPLACE(
                    REPLACE(
                        REGEXP_REPLACE(
                            REGEXP_REPLACE(
                                REPLACE(v_result, '\n', ' '),
                                '^([`]*sql)', ''
                            ),
                            '^(\s|''|`)+|(\s|''|`)+$', ''
                        ),
                        ';', '; '),
                    ', ', ','),
                '  ', ' ');
        --
        --logger.log('MAGIC_RESULT',      p_extra => v_result);

        -- get price of the request (in tokens)
        v_tokens := JSON_VALUE(v_response, '$.usage.total_tokens');
        --
        --logger.log('MAGIC_PRICE|' || TO_CHAR(v_tokens));
        --
        RETURN v_result;
    END;


4) construct the JSON payload

You can see the JSON payload in the code above as APEX_STRING.FORMAT argument. I would recommend to explore the OpenAI chat API which describe this in great detail. I would also recommend to fine-tune your question/prompt so you will get consistent results. Try to keep is as simple as possible, complex queries will be more expensive and less reliable.


5) implement the call and response on APEX page

Now this is certainly up to your creativity. I chose a simple design. One field for prompt, second field for the answer and a button to perform this dark magic transformation. For more complex scenarios you will need a different design. Since I am generating the repeat interval string, I have a DA on this (response) field and through the DBMS_SCHEDULER.EVALUATE_CALENDAR_STRING procedure I am generating the table with scheduled days/times so user can verify if it match his wishes. Neat, right?


Bonus

Checkout the Oracle APEX: Empowering Low Code Apps with AI course on Oracle Mylearn, it is great. If you pass the assesment at the end you can get this shiny APEX+AI Champion badge:


Blogroll

There are two great bloggers covering AI in Oracle APEX, check them out!

Feel free to let me know when you implement AI in your APEX app.


Comments

  1. Maram Sai Prathap ReddyAugust 1, 2024 at 3:04 AM

    This really helped a lot in one of my work scope. Thanks Jan!

    ReplyDelete

Post a Comment