In earlier posts, I showed how to call the Oracle Private AI Services Container from PL/SQL to generate vector embeddings. Those examples used the container’s embedding endpoint and demonstrated how Oracle AI Database 26ai can send text to the container and receive a vector back.

In this post, we’ll use a similar approach, but instead of generating vector embeddings, we’ll call the Oracle Private AI Services Container LLM Service to generate a text response with an LLM.

The main objective is to allow developers to invoke LLM text generation directly from the database.

The package function DBMS_VECTOR_CHAIN.UTL_TO_GENERATE_TEXT is a native Oracle AI Database 26ai feature designed to interact with Large Language Models. It allows a user to send a prompt from the database to an AI model, such as the Oracle Private AI Services Container LLM Service, and receive a generated text response.

A similar text-generation API is also available in the lighter-weight DBMS_VECTOR package through DBMS_VECTOR.UTL_TO_GENERATE_TEXT.

We’ll ask an LLM a simple question:

input := 'What is SQL?';

For this example, Oracle AI Database 26ai communicates with the Oracle Private Services Container over HTTP. This keeps the setup simple and is useful for development, testing, or internal proof-of-concept environments. For production deployments, you should use HTTP/SSL so that traffic between Oracle AI Database 26ai and the Oracle Private AI Services Container is encrypted and authenticated.

It is also good practice to run the Oracle Private AI Services Container on a separate host from Oracle AI Database 26ai. LLM inference can require significant CPU, memory, or GPU resources. Running the service separately helps keep database workloads isolated from model inference workloads.

To get a quick overview about the topics covered, the post is divided into the following sections:

Let’s get started.

Accessing the Oracle Private AI Services Container LLM Service

Prerequisite – A running Oracle Private AI Services Container

I’m going to assume that the Oracle Private AI Services Container is already installed, configured, and running.

Please refer to the Oracle Private AI Services Container User Guide for download, setup, and installation instructions.

For this blog post, the container exposes the LLM Service over HTTP on port 8080.

In this example, I use the container image private-ai:large-gpu-infer-26.2.1.0.0. This image includes vLLM and GPU support, which allows the Oracle Private AI Services Container LLM Service to serve the Ministral-3-3B-Reasoning-2512 model through the chat completions endpoint exposed on the server “your-fully-qualified-hostname”.

This model is included in the container, so no additional download is required. You can also use other models; those will need to be downloaded separately.

Step 1. Verify the HTTP endpoint

Before calling the service from the database, verify that the endpoint is reachable.

Run the following command from a machine that has network access to the container host:

curl -i http://your-fully-qualified-hostname:8080/health

A successful response looks similar to this:

HTTP/1.1 200 OK
date: Thu, 23 Jun 2026 12:14:11 GMT
x-ratelimit-limit-requests: 60
x-ratelimit-remaining-requests: 59
x-ratelimit-reset-requests: 1
x-server-id: 3c66bfe8-b586-4b8f-b258-a93d058ce074
content-length: 0

The 200 OK status confirms that the container is available.

After verifying that the container is running, you can query the models endpoint to see which models are currently available through the Oracle Private AI Services Container LLM Service.

Run the following command:

curl http://your-fully-qualified-hostname:8080/v1/models | jq

The jq utility formats the JSON response for easier reading.

On Oracle Linux, you can install jq with: 

sudo dnf install –y jq 

On Ubuntu Linux, use: 

sudo apt install –y jq 

The response should include the available models, including the Ministral-3-3B-Reasoning-2512 model.

{
  "data": [
    {
      "id": "Ministral-3-3B-Reasoning-2512",
      "modelDeployedTime": "2026-07-31T14:38:47.516225405Z",
      "modelSize": "7.20G",
      "modelCapabilities": [
        "TEXT_GENERATION"
      ]
...
}

Next, test the LLM Service endpoint directly with curl.

The text generation endpoint is:

/v1/chat/completions

Run the following command:

curl -i http://your-fully-qualified-hostname:8080/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
        "model": "Ministral-3-3B-Reasoning-2512",
        "messages": [
          {
            "role": "user",
            "content": "What is SQL?"
          }
        ],
        "max_tokens": 128,
        "temperature": 0
      }' 

If the service is configured correctly, the response payload should contain generated text for the question “What is SQL?”, for example:

SQL, or Structured Query Language, is a standard language used to manage and query data stored in relational databases. 
...

Testing the endpoint with curl before calling it from Oracle Database helps separate container or network issues from database configuration issues. 

Step 2. Grant network access from the database

Oracle Database controls outbound network access with network ACLs. Before a database user can call the Oracle Private AI Services Container LLM Service over HTTP, a DBA must grant the required network permission.

In this example, the database user is:

vectordb

The container host is:

your-fully-qualified-hostname

The HTTP port is:

8080

Run the following PL/SQL block as the PDB’s SYS or SYSTEM user:

BEGIN
  DBMS_NETWORK_ACL_ADMIN.APPEND_HOST_ACE(
    host       => 'your-fully-qualified-hostname',
    lower_port => 8080,
    upper_port => 8080,
    ace        => xs$ace_type(
                    privilege_list => xs$name_list('http'),
                    principal_name => 'vectordb',
                    principal_type => xs_acl.ptype_db));
END;
/

This grants the vectordb schema permission to make HTTP calls to the specified host and port.

The example uses the http privilege because we only need outbound HTTP access for this scenario. You could also grant connect, but that provides broader capabilities than required here.

Step 2.1 Verify the network ACL

Run the following command as user vectordb and check the ACL entry:

SELECT host, lower_port, upper_port, privilege, status
FROM user_host_aces;

The expected output should include a row similar to this:

HOST                          LOWER_PORT UPPER_PORT PRIVILEGE STATUS
----------------------------- ---------- ---------- --------- -------
your-fully-qualified-hostname 8080       8080       HTTP      GRANTED

This confirms that the current schema can call:

http://your-fully-qualified-hostname:8080/...

If the ACL is missing or incorrect, the PL/SQL call will fail. A common error is:

ORA-29273: HTTP request failed

To get more details, run:

SELECT UTL_HTTP.GET_DETAILED_SQLERRM;

A response looks similar to this:

GET_DETAILED_SQLERRM
--------------------------------------------------------------------------------
ORA-24247: network access denied by access control list (ACL)

This usually means that the ACL was not granted, was granted to the wrong user, or was created for the wrong host or port. Please see the Troubleshooting section of this post for steps to resolve the issue. 

Call the LLM Service and generate text from PL/SQL

We can now call the Oracle Private AI Services Container LLM Service from PL/SQL.

The following block sends the question “What is SQL?” to the model and prints the generated answer.

SET SERVEROUTPUT ON

DECLARE
  input  CLOB;
  params CLOB;
  output CLOB;
BEGIN
  input := 'What is SQL?';

  params := '
  {
    "provider": "privateai",
    "url": "http://your-fully-qualified-hostname:8080/v1/chat/completions",
    "host": "local",
    "model": "Ministral-3-3B-Reasoning-2512",
    "temperature": 0,
    "max_tokens": 256,
    "transfer_timeout: 30
  }';

  output := DBMS_VECTOR_CHAIN.UTL_TO_GENERATE_TEXT(
              input,
              json(params));

  DBMS_OUTPUT.PUT_LINE(output);

  IF output IS NOT NULL THEN
    DBMS_LOB.FREETEMPORARY(output);
  END IF;

EXCEPTION
  WHEN OTHERS THEN
    DBMS_OUTPUT.PUT_LINE(SQLERRM);
    DBMS_OUTPUT.PUT_LINE(SQLCODE);
END;
/

A typical response may look like this:

SQL, or Structured Query Language, is a standard language used to store, query, update, and manage data in relational databases.

Let’s look at the important parts of the JSON payload.

{
  "provider": "privateai",
  "url": "http://your-fully-qualified-hostname:8080/v1/chat/completions",
  "host": "local",
  "model": "Ministral-3-3B-Reasoning-2512",
  "temperature": 0,
  "max_tokens": 256,
  "transfer_timeout": 30
}

The parameters are:

  • provider: “privateai” – Identifies the Oracle Private AI Services LLM Service provider.
  • url: Points to the HTTP text generation endpoint. 
  • host: Uses the provider-specific “local” setting. So no database credential is required for HTTP. 
  • model: Identifies the model used to generate the response, for example “Ministral-3-3B-Reasoning-2512”. 
  • temperature: Controls the variability of the generated text. 
  • max_tokens: Sets the maximum response length. 
  • transfer_timeout: Maximum wait time before timeout.

DBMS_VECTOR_CHAIN.UTL_TO_GENERATE_TEXT sends the prompt and parameters to the configured LLM Service and returns the generated text response.

The first request to the model may take a little longer than later requests. This is expected because the model may need to be loaded into memory before it can generate a response. Once loaded, subsequent requests are usually faster.

Call the LLM Service and generate text from SQL

The same LLM Service can also be called directly from SQL.

First, define the parameter JSON as a SQL*Plus bind variable:

VAR params CLOB;

BEGIN
  :params := '{
    "provider": "privateai",
    "url": "http://your-fully-qualified-hostname:8080/v1/chat/completions",
    "host": "local",
    "model": "Ministral-3-3B-Reasoning-2512",
    "temperature": 0,
    "max_tokens": 256,
    "transfer_timeout": 30 
  }';
END;
/

Configure the SQL*Plus output:

SET LONG 100000
SET LONGCHUNKSIZE 100000
SET LINESIZE 200
SET PAGESIZE 0
SET HEADING OFF
SET FEEDBACK OFF
SET TRIMSPOOL ON

Run the follwowing query:

SELECT DBMS_VECTOR_CHAIN.UTL_TO_GENERATE_TEXT
          ('What is SQL?', 
          JSON(:params)
       ) AS generated_text;

The generated output should be similar to this:

SQL, or Structured Query Language, is a standard language used to manage and query data stored in relational databases.
...

This SQL pattern is useful when you want to integrate text generation into SQL-driven workflows, demos, or application logic.

Increasing the transfer timeout

LLM requests can take longer than embedding requests. This is especially true when the model is loaded for the first time or when the prompt asks for a longer answer.

If the request fails with:

ORA-29276: transfer timeout

increase transfer_timeout in the parameter JSON:

"transfer_timeout": 120 

The value is specified in seconds. In this example, the database waits up to 120 seconds for the service to return a response.

You can also reduce max_tokens if you want the model to return a shorter answer

"max_tokens": 128

In this case, we reduce max_tokens from 256 to 128.

Troubleshooting

  • ORA-29273 / ORA-24247: Network ACL missing or incorrect. Verify with SELECT host, lower_port, upper_port, privilege, status FROM user_host_aces; 
  • ORA-29276: Model cold-start or slow inference. Increase transfer_timeout or reduce max_tokens. 
  • Other Checks: Is the hostname correct? Is port 8080 open? Does the firewall allows traffic? Is the container listening on expected interface? Is the model loaded? Does the container have sufficient CPU, GPU, and memory? 

Summary

In this post, you called the Oracle Private AI Services Container LLM Service from Oracle AI Database 26ai over HTTP.

You verified that the container was running, tested the REST endpoint, checked the available models, granted the required network ACL, and then generated text from both PL/SQL and SQL using DBMS_VECTOR_CHAIN.UTL_TO_GENERATE_TEXT.

The example used the Ministral-3-3B-Reasoning-2512 model and the simple question:

input := 'What is SQL?';

HTTP is convenient for development and internal testing. For production deployments, use HTTP/SSL so that requests are encrypted and authenticated.

Resources