Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
5a33dde
[ADD] ai_document_extraction: scaffold
volkantasci Aug 6, 2026
0d44ac8
[IMP] ai_document_extraction: OCA CI compliance (prettier XML, genera…
volkantasci Aug 6, 2026
b211bc8
[IMP] ai_document_extraction: settings model and view
volkantasci Aug 6, 2026
f9cc60c
[IMP] ai_document_extraction: refine settings (setting id, threshold …
volkantasci Aug 6, 2026
0eeadde
[ADD] ai_document_extraction: image preprocessor service
volkantasci Aug 6, 2026
3f13b2e
[FIX] ai_document_extraction: ruff UP031 format specifier
volkantasci Aug 6, 2026
32723bc
[FIX] ai_document_extraction: use relative import in tests (pylint W8…
volkantasci Aug 6, 2026
9458851
[IMP] ai_document_extraction: harden image preprocessor (imwrite chec…
volkantasci Aug 6, 2026
175ed5a
[ADD] ai_document_extraction: OCR engine service with layout tags
volkantasci Aug 6, 2026
626c7cf
[IMP] ai_document_extraction: cache test + height guard for OCR engine
volkantasci Aug 6, 2026
ea64655
[ADD] ai_document_extraction: LLM extractor service
volkantasci Aug 6, 2026
b6af211
[IMP] ai_document_extraction: robust JSON parsing and LLM client tests
volkantasci Aug 6, 2026
15c5a41
[ADD] ai_document_extraction: account.move integration and views
volkantasci Aug 6, 2026
fb5a037
[IMP] ai_document_extraction: harden account.move integration
volkantasci Aug 6, 2026
06fdf2d
[ADD] ai_document_extraction: extraction wizard for partner fallback
volkantasci Aug 6, 2026
d9ccd2c
[IMP] ai_document_extraction: wizard ACL, empty-partner guard, review…
volkantasci Aug 6, 2026
2a2a935
[IMP] ai_document_extraction: add i18n POT template
volkantasci Aug 6, 2026
5e52bfa
[IMP] ai_document_extraction: final polish for OCA PR
volkantasci Aug 6, 2026
f27125f
[FIX] ai_document_extraction: skip cv2 test in CI without libGL
volkantasci Aug 6, 2026
6b2115a
[FIX] ai_document_extraction: skip pre-processor test when cv2 unimpo…
volkantasci Aug 6, 2026
e4bbdc9
[FIX] ai_document_extraction: default invoice_date to today on new moves
volkantasci Aug 6, 2026
9365dd8
[IMP] ai_document_extraction: UX and extraction quality improvements
volkantasci Aug 6, 2026
fe207d0
[IMP] ai_document_extraction: structured extraction with per-line taxes
volkantasci Aug 6, 2026
384f96f
[FIX] ai_document_extraction: make line-tax test independent of demo …
volkantasci Aug 6, 2026
3fa9394
[IMP] ai_document_extraction: replace misleading upload error for images
volkantasci Aug 6, 2026
7664427
[IMP] ai_document_extraction: extract invoices with a vision LLM inst…
volkantasci Aug 6, 2026
1c957d5
[IMP] ai_document_extraction: use 32k vision model and retry empty re…
volkantasci Aug 6, 2026
5d8f0cd
[FIX] ai_document_extraction: raise LLM timeout and cap image size
volkantasci Aug 6, 2026
907a238
[IMP] ai_document_extraction: support OpenRouter vision models
volkantasci Aug 6, 2026
c7c84d0
[IMP] ai_document_extraction: add payment_reference field to extracti…
volkantasci Aug 6, 2026
324e834
[IMP] ai_document_extraction: keep hash-like receipt numbers and vali…
volkantasci Aug 6, 2026
fbc2ecf
[IMP] ai_document_extraction: prompt for invoice/receipt number and p…
volkantasci Aug 6, 2026
3a35fca
[IMP] ai_document_extraction: store payment reference and fall back t…
volkantasci Aug 6, 2026
e2a61f2
[IMP] ai_document_extraction: add Turkish translations
volkantasci Aug 6, 2026
c635d4d
[IMP] ai_document_extraction: hide AI buttons on non-draft moves
volkantasci Aug 6, 2026
1aff146
[IMP] ai_document_extraction: notify web client when extraction state…
volkantasci Aug 6, 2026
b4bce3b
[IMP] ai_document_extraction: register bus notification frontend asset
volkantasci Aug 6, 2026
24b4c12
[IMP] ai_document_extraction: live update form on AI extraction compl…
volkantasci Aug 6, 2026
252f525
[IMP] eslint.config.cjs: parse Odoo static JS as ES modules
volkantasci Aug 6, 2026
54f2ad9
[IMP] ai_document_extraction: track live resId for bus notification
volkantasci Aug 6, 2026
a8ca0ee
[IMP] ai_document_extraction: skip reload while editing form
volkantasci Aug 6, 2026
5695701
[FIX] ai_document_extraction: use super.setup instead of legacy this.…
volkantasci Aug 6, 2026
fa3906e
[FIX] ai_document_extraction: accept duplicate ' (N)' attachment names
volkantasci Aug 6, 2026
005e3f3
[FIX] ai_document_extraction: handle ' (N)' suffix in AI image prepar…
volkantasci Aug 6, 2026
9b057c8
[FIX] ai_document_extraction: reload form when extraction finishes un…
volkantasci Aug 6, 2026
b2628b1
[DOC] ai_document_extraction: document vision LLM pipeline
volkantasci Aug 11, 2026
09411de
[IMP] ai_document_extraction: add ai_connection openai_compatible kin…
volkantasci Aug 13, 2026
201fd55
[IMP] ai_document_extraction: move HTTP vision call to ai_connection …
volkantasci Aug 13, 2026
d035f16
[IMP] ai_document_extraction: link extraction to an ai_connection record
volkantasci Aug 13, 2026
e242531
[IMP] ai_document_extraction: run extraction job through ai_connection
volkantasci Aug 13, 2026
1407155
[IMP] ai_document_extraction: fix temperature determinism and retry c…
volkantasci Aug 13, 2026
87e319c
[I18N] ai_document_extraction: sync translations for ai_connection re…
volkantasci Aug 13, 2026
4d4534f
[I18N] ai_document_extraction: regenerate readme and description
volkantasci Aug 13, 2026
3fa2f3b
[FIX] ai_document_extraction: run connection layer with sudo and clea…
volkantasci Aug 13, 2026
bbaf3f0
[FIX] ai_document_extraction: return False for unset ai_connection_id…
volkantasci Aug 13, 2026
687b150
[IMP] ai_document_extraction: move settings block up and gate it to d…
volkantasci Aug 13, 2026
01008bc
[IMP] ai_document_extraction: move settings to a Technical-menu form …
volkantasci Aug 13, 2026
985f034
[FIX] ai_document_extraction: move settings transient to wizards/ (py…
volkantasci Aug 13, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
164 changes: 164 additions & 0 deletions ai_document_extraction/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
.. image:: https://odoo-community.org/readme-banner-image
:target: https://odoo-community.org/get-involved?utm_source=readme
:alt: Odoo Community Association

======================
AI Document Extraction
======================

..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:668da0bb9a58a0c06761b3a2ec36dba6550f629e9520ec657a958e094e39af8f
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

.. |badge1| image:: https://img.shields.io/badge/maturity-Alpha-red.png
:target: https://odoo-community.org/page/development-status
:alt: Alpha
.. |badge2| image:: https://img.shields.io/badge/license-AGPL--3-blue.png
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fai-lightgray.png?logo=github
:target: https://github.com/OCA/ai/tree/19.0/ai_document_extraction
:alt: OCA/ai
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/ai-19-0/ai-19-0-ai_document_extraction
:alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png
:target: https://runboat.odoo-community.org/builds?repo=OCA/ai&target_branch=19.0
:alt: Try me on Runboat

|badge1| |badge2| |badge3| |badge4| |badge5|

This module extracts structured invoice data (partner, invoice number,
date and amounts) from uploaded PDF, JPG or PNG documents by sending the
rendered document image to an OpenAI-compatible vision LLM (e.g. Ollama
running ``qwen3-vl`` or a cloud provider such as OpenRouter) that
returns a strict JSON payload.

The result is applied to a draft vendor bill (``account.move``):
partner, date, reference and a single amount line are set automatically.
Processing runs in the background through ``queue_job`` so the user
interface never blocks. If the extracted partner name cannot be matched,
a wizard lets the user pick or create the partner.

The LLM is instructed to ignore logo/slogan texts found in the document
header (e.g. a company name drawn inside a logo), to never compute
missing values, and to output ``null`` for anything it cannot read.

.. IMPORTANT::
This is an alpha version, the data model and design can change at any time without warning.
Only for development or testing purpose, do not use in production.
`More details on development status <https://odoo-community.org/page/development-status>`_

**Table of contents**

.. contents::
:local:

Use Cases / Context
===================

Accounting teams receive invoices in many formats. Reading them manually
is slow and error prone. This module automates the initial data-entry
step while keeping a human in the loop: the extraction is applied to a
draft move that a user reviews and posts. All AI components run
on-premises (Ollama), so document data never leaves the local
infrastructure when a local endpoint is used.

Installation
============

To install and run this module you need the following Python packages
(installed with ``pip``):

- ``Pillow``
- ``pdf2image``
- ``rapidfuzz``
- ``requests``

And the system package:

- ``poppler-utils`` (required by ``pdf2image`` to render PDFs)

A running OpenAI-compatible chat completions endpoint with a vision
model is required, for example Ollama (``http://ollama:11434/v1``)
running a vision model such as ``qwen3-vl``, or a cloud provider such as
OpenRouter (``https://openrouter.ai/api/v1``).

Usage
=====

1. Go to *Accounting > Vendors > Bills* and create a draft vendor bill
(or open an existing draft one).
2. Attach the invoice PDF or image to the chatter.
3. Click **Extract with AI**. The invoice is processed in the
background.
4. When the *AI Extraction State* becomes *Done*, check the extracted
values. The partner is set automatically when a match is found.
5. If the partner could not be matched, click **Review Extraction** and
pick or create the partner in the wizard.

Configure the AI backend as follows:

1. Create an *AI Connection* under *Settings > AI > AI Connection* with
kind **OpenAI-compatible**:

- Set the URL to a cloud provider such as
``https://openrouter.ai/api/v1`` or to a local Ollama server like
``http://localhost:11434/v1``.
- Set the model, e.g. ``qwen/qwen3-vl-32b-instruct`` for OpenRouter
or ``qwen3-vl:8b`` for Ollama.
- Set the API key for cloud providers only (leave it empty for local
Ollama) and set the temperature to 0. For Ollama you can also set
the *Ollama Context Window* and *Ollama Keep Alive*.

2. Link the connection under *Settings > Technical > AI > AI Document
Extraction* in the *AI Connection* field (developer mode is required
to see the Technical menu). The partner match threshold can also be
set there.

The extraction flow is unchanged: upload the invoice, then click
**Extract with AI**.

Bug Tracker
===========

Bugs are tracked on `GitHub Issues <https://github.com/OCA/ai/issues>`_.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us to smash it by providing a detailed and welcomed
`feedback <https://github.com/OCA/ai/issues/new?body=module:%20ai_document_extraction%0Aversion:%2019.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.

Do not contact contributors directly about support or help with technical issues.

Credits
=======

Authors
-------

* VSL

Contributors
------------

- VSL info@voslo.co

Maintainers
-----------

This module is maintained by the OCA.

.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: https://odoo-community.org

OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.

This module is part of the `OCA/ai <https://github.com/OCA/ai/tree/19.0/ai_document_extraction>`_ project on GitHub.

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
1 change: 1 addition & 0 deletions ai_document_extraction/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import models, services, wizards
32 changes: 32 additions & 0 deletions ai_document_extraction/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Copyright 2026 VSL
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

{
"name": "AI Document Extraction",
"summary": "Extract invoice data from PDFs and images using a vision LLM",
"version": "19.0.1.0.0",
"category": "Accounting/Accounting",
"website": "https://github.com/OCA/ai",
"author": "VSL, Odoo Community Association (OCA)",
"license": "AGPL-3",
"development_status": "Alpha",
"application": False,
"installable": True,
"depends": ["base", "account", "bus", "queue_job", "ai_connection"],
"external_dependencies": {
"python": ["Pillow", "pdf2image", "rapidfuzz", "requests"],
},
"data": [
"security/ir.model.access.csv",
"views/account_move_views.xml",
"views/ai_connection_views.xml",
"wizards/ai_document_extraction_settings_views.xml",
"wizards/extraction_wizard_views.xml",
],
"assets": {
"web.assets_backend": [
"ai_document_extraction/static/src/account_move_form_ai_extraction.js",
],
},
"demo": [],
}
Loading
Loading