Skip to main content

Reading an Invoice

This example extracts information from an invoice — the value of the service and the CNPJ (a Brazilian tax identification number).

File uploads belong in a Page: the uploaded bytes arrive in-memory as file["content"] and you persist them with get_persistent_dir(). The AI extracts more reliably from text than from a raw document, so we extract_text first and prompt on the resulting string.

from pathlib import Path

from abstra.pages import register_function
from abstra.common import get_persistent_dir
from abstra.ai import extract_text, prompt


@register_function
def analyze(file: dict):
# The upload arrives as {"filename", "content_type", "content"}; persist the bytes.
dest = get_persistent_dir() / "uploads" / Path(file["filename"]).name
dest.parent.mkdir(parents=True, exist_ok=True)
dest.write_bytes(file["content"])

# Extract the text first, then prompt on the text
text = extract_text(dest)
answer = prompt(
["Here is an invoice", text],
format={
"value": {"type": "number", "description": "Value of the service in dollars"},
"CNPJ": {"type": "string"},
},
)
return {"value": answer["value"], "cnpj": answer["CNPJ"]}


@register_function
def __render__():
return """
<input type="file" id="invoice" accept=".pdf,.jpg,.jpeg,.png">
<button onclick="go()">Read invoice</button>
<pre id="out"></pre>
<script>
async function go() {
const file = document.getElementById('invoice').files[0];
const result = await analyze(file); // pass the File directly
document.getElementById('out').textContent = JSON.stringify(result, null, 2);
}
</script>
"""