Skip to content

adm_ai_form_config_api

Configuration of the form extraction: profiles, document types and forms, and the checks that decide whether an extracted result can be used without a person looking at it.

The configuration has three levels. Each is a row with a JSON configuration that this package validates before it saves it:

  • A profile names the documents to extract (source_folder_path or source_file_annotation_key, as for RAG collections), the models (text_model, and optionally vision_model) and the rules for every form of the profile.
  • A document type defines the fields that every form of the type returns, as a JSON schema, and the checks on them. Line items are the array property line_items of the schema.
  • A form is one layout of one issuer: markers find it in the text of a document, field_patterns check single values, and line_pattern with line_columns can read the line table without a model.

Profile:

{
"source_folder_path": "/shared/inbox",
"text_model": {"provider": "ollama", "model": "qwen3:8b", "config": {"g_base_url": "..."}},
"vision_model": {"provider": "ollama", "model": "qwen2.5vl:7b"},
"review_tag": "extraction-review",
"min_text_chars": 20,
"max_text_chars": 40000,
"rules": ["Return dates as YYYY-MM-DD."],
"process_new_documents": true,
"max_documents_per_run": 20,
"max_file_bytes": 20971520,
"ocr_text_extraction": {"provider": "mistral",
"config": {"g_apex_web_credential": "MISTRAL_API_KEY"},
"apply_to": {"mime_types": ["application/pdf", "image/png"]}}
}

ocr_text_extraction is optional and has the keys and rules of the section of the same name of a RAG collection (provider, model, config, options, apply_to). The extraction reads a document with this OCR when the built-in filter finds fewer than min_text_chars characters and apply_to matches the document; an image that apply_to.mime_types names is read with OCR instead of the vision_model. The default of apply_to.mime_types is ["application/pdf"] and is written into the configuration. See adm_ai_form_extract_api.document_text.

min_text_chars is the least text a document needs, counted as characters that are not blank. A document with less is a scan without a text layer and goes to review without a model call. The default 20 is the default min_text_chars of the OCR fallback (adm_ai_ocr_fallback_api), so that every document with too little text for the profile is one that the fallback reads. Keep the value of a profile at or below the value of the fallback.

process_new_documents true lets the AI queue job extract the new documents of the profile without a call (see adm_ai_form_extract_api.documents_to_process); at most max_documents_per_run of them in one run of the job.

max_file_bytes (default 20971520, 20 MB) is the largest file that a form with model_input file sends to the vision_model. A larger file goes to review without a model call. The default stays below the limits of the providers for a file in a request.

Document type:

{
"json_schema": {"type": "object", "properties": {
"net_amount": {"type": "number"}, "vat_amount": {"type": "number"},
"total_amount": {"type": "number"},
"line_items": {"type": "array", "items": {"type": "object", "properties": {
"quantity": {"type": "number"}, "unit_price": {"type": "number"},
"amount": {"type": "number"}}}}}},
"annotation_fields": ["total_amount"],
"rules": ["The issuer of the invoice is never the customer."],
"line_checks": [{"name": "quantity x unit price = amount",
"expr": "abs(quantity * unit_price - amount) <= 0.01"}],
"checks": [{"name": "sum of lines = net amount", "expr": "abs(sum_amount - net_amount) <= 0.01"},
{"name": "net + VAT = total", "expr": "abs(net_amount + vat_amount - total_amount) <= 0.01"}]
}

A result without line items is the issue no line items, and the checks do not run. "allow_empty_line_items": true accepts an empty line_items array, for example a bank statement without transactions: the checks then run with line_count 0 and every sum_<column>, min_<column> and max_<column> null. The key needs line_items in the schema.

Form:

{
"markers": ["VAT ID DE 812 334 905", "^(INVOICE|CREDIT NOTE)$"],
"field_patterns": {"invoice_number": "^INV-[0-9]{4}-[0-9]{5}$",
"line_items.item_number": "^[A-Z]{3}-[A-Z0-9-]+$"},
"line_pattern": "^([0-9]{1,3})\\n([A-Z]{3}-[A-Z0-9-]+)\\n(.*)\\n([0-9,]+)\\n([0-9.]+,[0-9]{2})\\n(-?[0-9.]+,[0-9]{2})$",
"line_columns": {"item_number": 2, "quantity": 4, "unit_price": 5, "amount": 6},
"decimal_comma": true,
"model_input": "text",
"rules": ["Dates are printed as DD.MM.YYYY."]
}

model_input decides what the model reads once the markers have found the form: text (the default, written into the configuration) sends the text to the text_model; file sends the file of the document (a PDF or an image) to the vision_model, which keeps the layout that the text loses, such as empty cells of a table and the label next to a check box. A form with file cannot have line_pattern or line_columns, and its profile needs a vision_model whose provider can read a file: one of c_file_providers (openai, anthropic, google, oci, mistral, responses_api; not ollama, which reads images only). update_profile refuses a change of the vision_model that a form with file cannot use, active or not, and names the form: change the form to text first.

A check is a SQL condition. It passes when it is true; false or null is an issue named after the check. line_checks run once for each line and see the columns of a line item; checks run once and see the scalar fields of the document and the aggregates of the line items: line_count, and sum_<column>, min_<column> and max_<column> for each numeric column.

The expressions run as dynamic SQL with the rights of the schema owner, so only these tokens are allowed: the field names above, numbers, strings in single quotes without a quote inside, the operators + - * / ( ) , = <> != < <= > >=, the keywords and or not is null between in, and the functions abs round trunc sign nvl coalesce greatest least mod. Everything else is refused when the document type is saved, and again before every evaluation. Never write config_json of the tables directly.

Every management call needs an administrator.

Creates a profile. Validates the configuration and stores it with its defaults (review_tag, min_text_chars, process_new_documents, max_documents_per_run, max_file_bytes) written out.

Signature:

function create_profile (
p_profile_name in varchar2,
p_description in varchar2 default null,
p_config_json in clob
) return number;

Parameters:

Name Direction Type Description
p_profile_name in varchar2 Unique name: lower case letters, digits, underscore and hyphen
p_description in varchar2 default null Description of the profile
p_config_json in clob The profile configuration

Returns: number - The id of the new profile


Changes a profile. A null parameter keeps the stored value. A new configuration replaces the stored one completely; keys that it leaves out get their defaults again. A new configuration whose vision_model is missing, or has a provider that cannot read a file, is refused while a form of the profile (active or not) has model_input file; the error names the form.

Signature:

procedure update_profile (
p_profile_id in number,
p_profile_name in varchar2 default null,
p_description in varchar2 default null,
p_config_json in clob default null
);

Parameters:

Name Direction Type Description
p_profile_id in number The profile
p_profile_name in varchar2 default null New name
p_description in varchar2 default null New description
p_config_json in clob default null New configuration

Deletes a profile with its document types, forms, extraction results, test set and measurements.

Signature:

procedure delete_profile (
p_profile_id in number
);

Parameters:

Name Direction Type Description
p_profile_id in number The profile

The id of a profile.

Signature:

function get_profile_id (
p_profile_name in varchar2
) return number;

Parameters:

Name Direction Type Description
p_profile_name in varchar2 Name of the profile

Returns: number - The profile id


The stored configuration of a profile, with its defaults written out. Read it, change it with json_object_t, and pass the whole of it to update_profile, which replaces the stored configuration.

Signature:

function get_profile_config (
p_profile_id in number
) return clob;

Parameters:

Name Direction Type Description
p_profile_id in number The profile

Returns: clob - The configuration as JSON


Creates a document type in a profile. Validates the JSON schema and compiles every check expression against it.

Signature:

function create_doc_type (
p_profile_id in number,
p_doc_type in varchar2,
p_config_json in clob
) return number;

Parameters:

Name Direction Type Description
p_profile_id in number The profile
p_doc_type in varchar2 Code, unique in the profile: lower case letters, digits and underscore
p_config_json in clob The document type configuration

Returns: number - The id of the new document type


Changes a document type. A null parameter keeps the stored value. A new configuration is validated, and so is every form of the document type against it: a schema change that removes a field a form still uses is refused and names the form.

Signature:

procedure update_doc_type (
p_doc_type_id in number,
p_doc_type in varchar2 default null,
p_config_json in clob default null
);

Parameters:

Name Direction Type Description
p_doc_type_id in number The document type
p_doc_type in varchar2 default null New code
p_config_json in clob default null New configuration

Deletes a document type. Refused while forms use it.

Signature:

procedure delete_doc_type (
p_doc_type_id in number
);

Parameters:

Name Direction Type Description
p_doc_type_id in number The document type

The id of a document type.

Signature:

function get_doc_type_id (
p_profile_id in number,
p_doc_type in varchar2
) return number;

Parameters:

Name Direction Type Description
p_profile_id in number The profile
p_doc_type in varchar2 Code of the document type

Returns: number - The document type id


The stored configuration of a document type. Read it, change it with json_object_t, and pass the whole of it to update_doc_type.

Signature:

function get_doc_type_config (
p_doc_type_id in number
) return clob;

Parameters:

Name Direction Type Description
p_doc_type_id in number The document type

Returns: clob - The configuration as JSON


Creates a form. Compiles every regular expression and checks every field and column name against the JSON schema of the document type. decimal_comma defaults to false, model_input to text. A form with model_input file needs a vision_model in the profile whose provider is one of c_file_providers.

Signature:

function create_form (
p_profile_id in number,
p_form_code in varchar2,
p_doc_type_id in number,
p_description in varchar2,
p_config_json in clob,
p_active in varchar2 default 'Y'
) return number;

Parameters:

Name Direction Type Description
p_profile_id in number The profile
p_form_code in varchar2 Code, unique in the profile: upper case letters, digits and underscore
p_doc_type_id in number The document type, from the same profile
p_description in varchar2 What the document is; becomes part of the prompt
p_config_json in clob The form configuration
p_active in varchar2 default 'Y' Y: the form takes part in the extraction. N: it is ignored

Returns: number - The id of the new form


Changes a form. A null parameter keeps the stored value. The configuration, new or stored, is validated against the document type, new or stored.

Signature:

procedure update_form (
p_form_id in number,
p_form_code in varchar2 default null,
p_doc_type_id in number default null,
p_description in varchar2 default null,
p_config_json in clob default null,
p_active in varchar2 default null
);

Parameters:

Name Direction Type Description
p_form_id in number The form
p_form_code in varchar2 default null New code
p_doc_type_id in number default null New document type, from the same profile
p_description in varchar2 default null New description
p_config_json in clob default null New configuration
p_active in varchar2 default null Y or N

Deletes a form. Its extraction results stay without a form; its test cases are deleted.

Signature:

procedure delete_form (
p_form_id in number
);

Parameters:

Name Direction Type Description
p_form_id in number The form

The id of a form.

Signature:

function get_form_id (
p_profile_id in number,
p_form_code in varchar2
) return number;

Parameters:

Name Direction Type Description
p_profile_id in number The profile
p_form_code in varchar2 Code of the form

Returns: number - The form id


The stored configuration of a form. Read it, change it with json_object_t, and pass the whole of it to update_form.

Signature:

function get_form_config (
p_form_id in number
) return clob;

Parameters:

Name Direction Type Description
p_form_id in number The form

Returns: clob - The configuration as JSON


The scalar fields of a document type schema with their SQL type, as {"net_amount": "NUMBER", "invoice_number": "VARCHAR2"}. A property whose type is number or integer (null allowed besides) is NUMBER, every other scalar is VARCHAR2. Objects and arrays are left out.

Signature:

function get_schema_fields (
p_json_schema in clob,
p_level in varchar2 default c_level_document
) return json_object_t;

Parameters:

Name Direction Type Description
p_json_schema in clob The json_schema of a document type configuration
p_level in varchar2 default c_level_document c_level_document: the properties of the document.
c_level_line: the properties of a line item |

Returns: json_object_t - The fields and their types


The line pattern of a form as a regular expression: \n in the stored pattern stands for a line break. Use it with the match parameter ‘m’.

Signature:

function get_line_regex (
p_line_pattern in varchar2
) return varchar2;

Parameters:

Name Direction Type Description
p_line_pattern in varchar2 line_pattern of a form configuration

Returns: varchar2 - The regular expression


Validates a check expression against a document type schema and returns the SQL text that would run. Raises adm_ai_error.e_form_expression with the token that is not allowed, or when the expression is no valid SQL condition.

Signature:

function validate_expression (
p_json_schema in clob,
p_expression in varchar2,
p_level in varchar2 default c_level_document
) return varchar2;

Parameters:

Name Direction Type Description
p_json_schema in clob The json_schema of a document type configuration
p_expression in varchar2 The expression, for example abs(net_amount + vat_amount - total_amount) <= 0.01
p_level in varchar2 default c_level_document c_level_document (a check) or c_level_line (a line check)

Returns: varchar2 - The normalized SQL condition


Checks an extracted result against its form. It is the one check for a model result and for an approval. It checks, in this order:

  • the declared JSON schema, for the document and for every line item: a required property must not be missing, null or empty; a value must have one of the types (string, number, integer, boolean) and be one of the enum values. A property that is not required may be missing or null. Keys that the schema does not know, nested objects and arrays, and keywords such as format are not checked
  • the field patterns of the form
  • that line items are present (when the schema has line items)
  • the line checks and the checks of the document type. When there are no line items, they do not run. Every expression is validated again before it runs. A check that cannot run on a value of the wrong type is an issue too.

Signature:

function check_result (
p_form_id in number,
p_fields in json_object_t,
p_line_items in json_array_t
) return varchar2;

Parameters:

Name Direction Type Description
p_form_id in number The form
p_fields in json_object_t The extracted fields
p_line_items in json_array_t The extracted line items

Returns: varchar2 - Null when everything passes, otherwise one line for each issue, for example line 2: quantity x unit price = amount