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_pathorsource_file_annotation_key, as for RAG collections), the models (text_model, and optionallyvision_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_itemsof the schema. - A form is one layout of one issuer:
markersfind it in the text of a document,field_patternscheck single values, andline_patternwithline_columnscan 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.
Check expressions
Section titled “Check expressions”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.
Functions and Procedures
Section titled “Functions and Procedures”create_profile
Section titled “create_profile”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
update_profile
Section titled “update_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 |
delete_profile
Section titled “delete_profile”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 |
get_profile_id
Section titled “get_profile_id”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
get_profile_config
Section titled “get_profile_config”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
create_doc_type
Section titled “create_doc_type”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
update_doc_type
Section titled “update_doc_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 |
delete_doc_type
Section titled “delete_doc_type”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 |
get_doc_type_id
Section titled “get_doc_type_id”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
get_doc_type_config
Section titled “get_doc_type_config”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
create_form
Section titled “create_form”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
update_form
Section titled “update_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 |
delete_form
Section titled “delete_form”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 |
get_form_id
Section titled “get_form_id”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
get_form_config
Section titled “get_form_config”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
get_schema_fields
Section titled “get_schema_fields”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
get_line_regex
Section titled “get_line_regex”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
validate_expression
Section titled “validate_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
check_result
Section titled “check_result”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