Logo
⚠️ Unsaved
[M]:

Prepare prompt

[1]:
type Mode = 'csv' | 'xlsx' | 'pdf';

/** CHANGE ME IF NEEDED */
const mode: Mode = 'pdf';
[2]:
const instruction = `
The provided OCR text (document) is most likely the customer Purchase Order (PO).
First verify if it is a PO. Criterias for verification of a PO - must contain list of SKUs, "LIEF.-ARTNR" and "GEBINDE" fields.
If not a PO - return 'ERR_AI_PO_INVALID' error.
Return the Requested Delivery Date from this PO document using the following algorithm:
Step 1. Locate the "Lieferdatum" field in the PO document. This field contains the Requested Delivery Date in the DD.MM.YYYY format. Example: 21.07.25 is July 21st, 2025. Make sure to ignore the "Datum" field that contains similar value that is not Requested Delivery Date.
Step 2. Return the Requested Delivery Date in the ISO 8601 format: YYYY-MM-DDTHH:MM:SSZ.
Return the Order ID using the following algorithm:
Step 1. Locate the "BESTELLUNG" field in the PO document. This field contains the customer's PO number. Example: - "BESTELLUNG 2263")
Step 2. Return the PO number indicated in the "BESTELLUNG" field. Example: "2263".
If you cannot find the order id, return error 'ERR_AI_ORDER_ID_MISSING'.
Identify and return the list of products (SKUs) from this PO document strictly following these steps:
Step 1: Locate the "LIEF.-ARTNR" field in the PO document.
Step 2: Identify numeric codes within the “LIEF.-ARTNR” field. Make sure to ignore the "ARTNR" field, it contains similar values but they are not SKU ids.
Step 2.1: Resulting product codes must be numeric, longer than three characters, and free of letters or special characters.
Step 2.2: If identified codes contain leading zeroes, disregard the leading zeroes and consider only the numeric part of the code for identification and further processing. For example, if the code is "0045416" treat it as "45416".
Step 2.4: If the "LIEF.-ARTNR" field is empty for a product or does not contain a numeric value, exclude that product line from processing.
Step 3: Locate the "GEBINDE" field in the PO document. This field contains the requested product quantities.
Step 3.1: Identify numeric values within "GEBINDE" field, which represent the product quantities. Make sure to ignore the "PALETTEN" field, it contains similar values but they are not requested product quantities.
Step 3.2. If the "GEBINDE" field is empty for a product, exclude that product line from processing.
Step 4: Assign the packageType as “VAT” for all identified SKUs
Step 5: Return list of all found SKUs in skuIds array, make sure every item has an id, quantity, and packageType. Make sure SKU ID is a string, not number.
`;
[3]:
/** CHANGE ME IF NEEDED (XLSX/CSV ONLY) */
const attachment = '';
/** CHANGE ME IF NEEDED (PDF ONLY) */
const content = 'GLASL\nGetränkefachgroßhandel\n0 88 56. 80 200-0 0 88 56. 80 200-20\n00020428 @getraenke-glasl.de bestellung@getraenke-glasl.de\nwww.getraenke-glasl.de\nGetränke Glasl GmbH . Steinbacher Weg 14 . 82387 Antdorf\nUnsere Getränke für Bayern Spaten-Löwenbräu Daimlerstr. 4 85221 Dachau\nBESTELLUNG 2042 Blatt 1\nLieferant\nDatum Lieferdatum\n70001\n30.06.25\n1.07.25\nVersand:\nABHOLUNG\nLkw:\nAnh :\nFah:\nohne Fahrer\nKundennr. :\n10560049\nTel .- Nr. :\n08952002237\nARTNR BEZEICHNUNG\nGEBINDE PALETTEN\nLIEF . - ARTNR\n1014 Löwenbräu Hell 50 1 KEG Faß\n18\n3\n21430\n1043 Franz WB 30 1 KEG Faß\n6\n1\n21412\n2831 Bluna Zitrone POSTMIX POM\n1\n7600114\nSUMMEN :\n25\n4\n(o. Pal. - Artikel)\nGEFAKO MEIN GETRÄNKE-PROFI\nGetränke Glasl GmbH Steinbacher Weg 14 82387 Antdorf\nGeschäftsführer: Christian Glasl\nSparkasse Oberland\nIBAN:DE 94 70 35 1030 0032 5191 59\nBIC: BYLADEM1WHM\nSparkasse Bad Tölz IBAN:DE 84 7005 4306 0000 1199 33\nBIC: BYLADEM 1WOR\nBIO-Zertifizierung: DE-ÖKO-006\nUst-Nr. 119/127/30095 Ust ID DE128360264 HRB München 90095';
/** CHANGE ME IF NEEDED (PDF ONLY) */
const tables = [
{
"rowCount": 2,
"columnCount": 3,
"cells": [
{
"kind": "columnHeader",
"rowIndex": 0,
"columnIndex": 0,
"content": "Lieferant"
},
{
"kind": "columnHeader",
"rowIndex": 0,
"columnIndex": 1,
"content": "Datum"
},
{
"kind": "columnHeader",
"rowIndex": 0,
"columnIndex": 2,
"content": "Lieferdatum"
},
{
"rowIndex": 1,
"columnIndex": 0,
"content": "70001"
},
{
"rowIndex": 1,
"columnIndex": 1,
[26]:
!npm install zod@3.25.76
!npm install zod-to-json-schema

import { z } from 'zod';
import { zodToJsonSchema } from 'zod-to-json-schema';

const schema = z.object({
content: z.string().describe('Raw OCR result'),
type: z.string().nullish().describe('Type of the document, e.g. pdf/csv/xlsx'),
tables: z
.array(
z
.object({
rowCount: z.number().describe('Number of rows in the table'),
columnCount: z.number().describe('Number of columns in the table'),
cells: z
.array(
z
.object({
kind: z.string().describe('Kind of the cell, e.g. columnHeader').optional(),
rowIndex: z.number().describe('Row index of the cell'),
columnIndex: z.number().describe('Column index of the cell'),
content: z.string().describe('Content of the cell'),
})
.describe('Table cell'),
)
.describe('Cells in the table'),
})
.describe('Table parsed by OCR'),
)
.optional()
.describe('Tables parsed by OCR'),
});

const jsonSchema = zodToJsonSchema(schema);

$ npm install zod@3.25.76

up to date in 531ms

29 packages are looking for funding
  run `npm fund` for details
$ npm install zod-to-json-schema

up to date in 916ms

29 packages are looking for funding
  run `npm fund` for details
--- COPY-PASTE FROM HERE ---

Answer in JSON format.
  Current time is 2025-07-22T10:54:06.732Z.
  You will be provided with a text, which contains OCR processing result and potentially 
  this can be a purchase order.

That document was processed by OCR and has the following JSON format:
        {"type":"object","properties":{"content":{"type":"string","description":"Raw OCR result"},"type":{"type":["string","null"],"description":"Type of the document, e.g. pdf/csv/xlsx"},"tables":{"type":"array","items":{"type":"object","properties":{"rowCount":{"type":"number","description":"Number of rows in the table"},"columnCount":{"type":"number","description":"Number of columns in the table"},"cells":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","description":"Kind of the cell, e.g. columnHeader"},"rowIndex":{"type":"number","description":"Row index of the cell"},"columnIndex":{"type":"number","description":"Column index of the cell"},"content":{"type":"string","description":"Content of the cell"}},"required":["rowIndex","columnIndex","content"],"additionalProperties":false,"description":"Table cell"},"description":"Cells in the table"}},"required":["rowCount","columnCount","cells"],"additionalProperties":false,"description":"Table parsed by OCR"},"description":"Tables parsed by OCR"}},"required":["content"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}
        Analyze tables carefully and always match cells with correct columns by indexes.


The provided OCR text (document) is most likely the customer Purchase Order (PO). 
First verify if it is a PO. Criterias for verification of a PO - must contain list of SKUs, "Artikel / Lev.Ref." and "Aantal" fields. If not a PO - return 'ERR_AI_PO_INVALID' error.

Return the Requested Delivery Date from this PO document using the following algorithm:  
Step 1. Locate the "Leverdatum" field in the PO document. This field contains the Requested Delivery Date in the DD-MM-YYYY format. If the PO document does not contain the "Leverdatum" field, Use the D+2 date (2 days after the order date) as the requested delivery date.
Step 2. Return the Requested Delivery Date in the ISO 8601 format: YYYY-MM-DDTHH:MM:SSZ.   

Return the Order ID using the following algorithm: 
Step 1. Locate the "Bestelbon" field in the PO document. This field contains the customer's PO number. (example - Bestelbon: 2025/01/00196) 
Step 2. Return the PO number indicated in the "Bestelbon" field (example - 2025/01/00196). 
If you cannot find the order id, return error 'ERR_AI_ORDER_ID_MISSING'.  

Identify and return the list of products (SKUs) from this PO document strictly following these steps:  
Step 1: Locate the "Artikel / Lev.Ref." field in the PO document. This field contains SKU IDs. 
Step 2: Identify the numeric codes within the “Artikel / Lev.Ref.” field. The correct product code is always the second numeric value in the sequence. Make sure to ignore the first numeric value and any text that goes after the second numeric value. Example: If the field contains “70000072 7516468”, the required product code is “7516468”. If the field contains “00150007 7516468 (oude ref755)”, the required product code is “7516468”. 
Step 2.1: Resulting product codes must be numeric, longer than three characters, and free of letters or special characters.  
Step 2.2: If identified codes contain leading zeroes, disregard the leading zeroes and consider only the numeric part of the code for identification and further processing. For example, if the code is "0045416" treat it as "45416". 
Step 2.3. If the “Artikel / Lev.Ref.” field is empty for a product, exclude that product line from processing.
Step 3: Locate the "Aantal" field in the PO document. This field contains the requested product quantities. 
Step 3.1: Identify numeric values within "Aantal" field, which represent the product quantities. The product quantity is always the first numeric value in the field and appears before “PALLET,” “BAK,” or any other unit code. For example, if the "Aantal" field contains “25 BAK”, the product quantity is “25”.
Step 4: Assign the packageType as “VAT” for all identified SKUs
Step 5: Return list of all found SKUs in skuIds array, make sure every item has an id, quantity, and packageType. Make sure SKU ID is a string, not number.


Raw OCR result: GLASL
Getränkefachgroßhandel
0 88 56. 80 200-0 0 88 56. 80 200-20
00020428 @getraenke-glasl.de bestellung@getraenke-glasl.de
www.getraenke-glasl.de
Getränke Glasl GmbH . Steinbacher Weg 14 . 82387 Antdorf
Unsere Getränke für Bayern Spaten-Löwenbräu Daimlerstr. 4 85221 Dachau
BESTELLUNG 2042 Blatt 1
Lieferant
Datum Lieferdatum
70001
30.06.25
1.07.25
Versand:
ABHOLUNG
Lkw:
Anh :
Fah:
ohne Fahrer
Kundennr. :
10560049
Tel .- Nr. :
08952002237
ARTNR BEZEICHNUNG
GEBINDE PALETTEN
LIEF . - ARTNR
1014 Löwenbräu Hell 50 1 KEG Faß
18
3
21430
1043 Franz WB 30 1 KEG Faß
6
1
21412
2831 Bluna Zitrone POSTMIX POM
1
7600114
SUMMEN :
25
4
(o. Pal. - Artikel)
GEFAKO MEIN GETRÄNKE-PROFI
Getränke Glasl GmbH Steinbacher Weg 14 82387 Antdorf
Geschäftsführer: Christian Glasl
Sparkasse Oberland
IBAN:DE 94 70 35 1030 0032 5191 59
BIC: BYLADEM1WHM
Sparkasse Bad Tölz IBAN:DE 84 7005 4306 0000 1199 33
BIC: BYLADEM 1WOR
BIO-Zertifizierung: DE-ÖKO-006
Ust-Nr. 119/127/30095 Ust ID DE128360264 HRB München 90095

Tables recognized by OCR: [{"rowCount":2,"columnCount":3,"cells":[{"kind":"columnHeader","rowIndex":0,"columnIndex":0,"content":"Lieferant"},{"kind":"columnHeader","rowIndex":0,"columnIndex":1,"content":"Datum"},{"kind":"columnHeader","rowIndex":0,"columnIndex":2,"content":"Lieferdatum"},{"rowIndex":1,"columnIndex":0,"content":"70001"},{"rowIndex":1,"columnIndex":1,"content":"30.06.25"},{"rowIndex":1,"columnIndex":2,"content":"1.07.25"}]},{"rowCount":6,"columnCount":3,"cells":[{"rowIndex":0,"columnIndex":0,"content":"Versand:"},{"rowIndex":0,"columnIndex":1,"content":"ABHOLUNG"},{"rowIndex":0,"columnIndex":2,"content":""},{"rowIndex":1,"columnIndex":0,"content":"Lkw:"},{"rowIndex":1,"columnIndex":1,"content":""},{"rowIndex":1,"columnIndex":2,"content":""},{"rowIndex":2,"columnIndex":0,"content":"Anh :"},{"rowIndex":2,"columnIndex":1,"content":""},{"rowIndex":2,"columnIndex":2,"content":""},{"rowIndex":3,"columnIndex":0,"content":"Fah:"},{"rowIndex":3,"columnIndex":1,"content":"ohne Fahrer"},{"rowIndex":4,"columnIndex":0,"content":"Kundennr. :"},{"rowIndex":4,"columnIndex":1,"content":"10560049"},{"rowIndex":5,"columnIndex":0,"content":"Tel .- Nr. :"},{"rowIndex":5,"columnIndex":1,"content":"08952002237"}]},{"rowCount":5,"columnCount":5,"cells":[{"kind":"columnHeader","rowIndex":0,"columnIndex":0,"content":"ARTNR"},{"kind":"columnHeader","rowIndex":0,"columnIndex":1,"content":"BEZEICHNUNG"},{"kind":"columnHeader","rowIndex":0,"columnIndex":2,"content":"GEBINDE"},{"kind":"columnHeader","rowIndex":0,"columnIndex":3,"content":"PALETTEN"},{"kind":"columnHeader","rowIndex":0,"columnIndex":4,"content":"LIEF . - ARTNR"},{"rowIndex":1,"columnIndex":0,"content":"1014 Löwenbräu Hell 50 1 KEG Faß"},{"rowIndex":1,"columnIndex":2,"content":"18"},{"rowIndex":1,"columnIndex":3,"content":"3"},{"rowIndex":1,"columnIndex":4,"content":"21430"},{"rowIndex":2,"columnIndex":0,"content":"1043"},{"rowIndex":2,"columnIndex":1,"content":"Franz WB 30 1 KEG Faß"},{"rowIndex":2,"columnIndex":2,"content":"6"},{"rowIndex":2,"columnIndex":3,"content":"1"},{"rowIndex":2,"columnIndex":4,"content":"21412"},{"rowIndex":3,"columnIndex":0,"content":"2831"},{"rowIndex":3,"columnIndex":1,"content":"Bluna Zitrone POSTMIX POM"},{"rowIndex":3,"columnIndex":2,"content":"1"},{"rowIndex":3,"columnIndex":3,"content":""},{"rowIndex":3,"columnIndex":4,"content":"7600114"},{"rowIndex":4,"columnIndex":0,"content":"SUMMEN"},{"rowIndex":4,"columnIndex":1,"content":":"},{"rowIndex":4,"columnIndex":2,"content":"25"},{"rowIndex":4,"columnIndex":3,"content":"4"},{"rowIndex":4,"columnIndex":4,"content":"(o. Pal. - Artikel)"}]}]
Sign in to save your work and access it from anywhere