smart-importer


Namesmart-importer JSON
Version 0.5 PyPI version JSON
download
home_pagehttps://github.com/beancount/smart_importer
SummaryAugment Beancount importers with machine learning functionality.
upload_time2024-01-21 09:37:40
maintainer
docs_urlNone
authorJohannes Harms
requires_python
licenseMIT
keywords fava beancount accounting machinelearning
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            smart_importer
==============

https://github.com/beancount/smart_importer

.. image:: https://github.com/beancount/smart_importer/actions/workflows/ci.yml/badge.svg?branch=main
   :target: https://github.com/beancount/smart_importer/actions?query=branch%3Amain

Augments
`Beancount <http://furius.ca/beancount/>`__ importers
with machine learning functionality.


Status
------

Working protoype, development status: beta


Installation
------------

The ``smart_importer`` can be installed from PyPI:

.. code:: bash

    pip install smart_importer


Quick Start
-----------

This package provides import hooks that can modify the imported entries. When
running the importer, the existing entries will be used as training data for a
machine learning model, which will then predict entry attributes.

The following example shows how to apply the ``PredictPostings`` hook to
an existing CSV importer:

.. code:: python

    from beancount.ingest.importers import csv
    from beancount.ingest.importers.csv import Col

    from smart_importer import apply_hooks, PredictPostings


    class MyBankImporter(csv.Importer):
        '''Conventional importer for MyBank'''

        def __init__(self, *, account):
            super().__init__(
                {Col.DATE: 'Date',
                 Col.PAYEE: 'Transaction Details',
                 Col.AMOUNT_DEBIT: 'Funds Out',
                 Col.AMOUNT_CREDIT: 'Funds In'},
                account,
                'EUR',
                (
                    'Date, Transaction Details, Funds Out, Funds In'
                )
            )


    CONFIG = [
        apply_hooks(MyBankImporter(account='Assets:MyBank:MyAccount'), [PredictPostings()])
    ]


Documentation
-------------

This section explains in detail the relevant concepts and artifacts
needed for enhancing Beancount importers with machine learning.


Beancount Importers
~~~~~~~~~~~~~~~~~~~~

Let's assume you have created an importer for "MyBank" called
``MyBankImporter``:

.. code:: python

    class MyBankImporter(importer.ImporterProtocol):
        """My existing importer"""
        # the actual importer logic would be here...

Note:
This documentation assumes you already know how to create Beancount importers.
Relevant documentation can be found in the `beancount import documentation
<https://beancount.github.io/docs/importing_external_data.html>`__.
With the functionality of beancount.ingest, users can
write their own importers and use them to convert downloaded bank statements
into lists of Beancount entries.
An example is provided as part of beancount v2's source code under
`examples/ingest/office
<https://github.com/beancount/beancount/tree/v2/examples/ingest/office>`__.

smart_importer only works by appending onto incomplete single-legged postings
(i.e. It will not work by modifying postings with accounts like "Expenses:TODO").
The `extract` method in the importer should follow the
`latest interface <https://github.com/beancount/beancount/blob/v2/beancount/ingest/importer.py#L61>`__
and include an `existing_entries` argument.

Applying `smart_importer` hooks
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Any Beancount importer can be converted into a smart importer by applying one
of the following hooks:

* ``PredictPostings`` - predict the list of postings.
* ``PredictPayees``- predict the payee of the transaction.
* ``DuplicateDetector`` - detect duplicates

For example, to convert an existing ``MyBankImporter`` into a smart importer:

.. code:: python

    from your_custom_importer import MyBankImporter
    from smart_importer import apply_hooks, PredictPayees, PredictPostings

    my_bank_importer =  MyBankImporter('whatever', 'config', 'is', 'needed')
    apply_hooks(my_bank_importer, [PredictPostings(), PredictPayees()])

    CONFIG = [
        my_bank_importer,
    ]

Note that the importer hooks need to be applied to an importer instance, as
shown above.


Specifying Training Data
~~~~~~~~~~~~~~~~~~~~~~~~

The ``smart_importer`` hooks need training data, i.e. an existing list of
transactions in order to be effective. Training data can be specified by
calling bean-extract with an argument that references existing Beancount
transactions, e.g., ``bean-extract -f existing_transactions.beancount``. When
using the importer in Fava, the existing entries are used as training data
automatically.


Usage with Fava
~~~~~~~~~~~~~~~

Smart importers play nice with `Fava <https://github.com/beancount/fava>`__.
This means you can use smart importers together with Fava in the exact same way
as you would do with a conventional importer. See `Fava's help on importers
<https://github.com/beancount/fava/blob/main/src/fava/help/import.md>`__ for more
information.


Development
-----------

Pull requests welcome!


Executing the Unit Tests
~~~~~~~~~~~~~~~~~~~~~~~~

Simply run (requires tox):

.. code:: bash

    make test


Configuring Logging
~~~~~~~~~~~~~~~~~~~

Python's `logging` module is used by the smart_importer module.
The according log level can be changed as follows:


.. code:: python

    import logging
    logging.getLogger('smart_importer').setLevel(logging.DEBUG)


Using Tokenizer
~~~~~~~~~~~~~~~~~~

Custom tokenizers can let smart_importer support more languages, eg. Chinese.

If you looking for Chinese tokenizer, you can follow this example:

First make sure that `jieba` is installed in your python environment:

.. code:: bash

    pip install jieba


In your importer code, you can then pass `jieba` to be used as tokenizer:

.. code:: python

    from smart_importer import PredictPostings
    import jieba

    jieba.initialize()
    tokenizer = lambda s: list(jieba.cut(s))

    predictor = PredictPostings(string_tokenizer=tokenizer)

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/beancount/smart_importer",
    "name": "smart-importer",
    "maintainer": "",
    "docs_url": null,
    "requires_python": "",
    "maintainer_email": "",
    "keywords": "fava beancount accounting machinelearning",
    "author": "Johannes Harms",
    "author_email": "",
    "download_url": "https://files.pythonhosted.org/packages/b9/be/c7096f5a569e10456338a1db9ef126da8e06aa1c79a9ae61319fb202b210/smart_importer-0.5.tar.gz",
    "platform": null,
    "description": "smart_importer\n==============\n\nhttps://github.com/beancount/smart_importer\n\n.. image:: https://github.com/beancount/smart_importer/actions/workflows/ci.yml/badge.svg?branch=main\n   :target: https://github.com/beancount/smart_importer/actions?query=branch%3Amain\n\nAugments\n`Beancount <http://furius.ca/beancount/>`__ importers\nwith machine learning functionality.\n\n\nStatus\n------\n\nWorking protoype, development status: beta\n\n\nInstallation\n------------\n\nThe ``smart_importer`` can be installed from PyPI:\n\n.. code:: bash\n\n    pip install smart_importer\n\n\nQuick Start\n-----------\n\nThis package provides import hooks that can modify the imported entries. When\nrunning the importer, the existing entries will be used as training data for a\nmachine learning model, which will then predict entry attributes.\n\nThe following example shows how to apply the ``PredictPostings`` hook to\nan existing CSV importer:\n\n.. code:: python\n\n    from beancount.ingest.importers import csv\n    from beancount.ingest.importers.csv import Col\n\n    from smart_importer import apply_hooks, PredictPostings\n\n\n    class MyBankImporter(csv.Importer):\n        '''Conventional importer for MyBank'''\n\n        def __init__(self, *, account):\n            super().__init__(\n                {Col.DATE: 'Date',\n                 Col.PAYEE: 'Transaction Details',\n                 Col.AMOUNT_DEBIT: 'Funds Out',\n                 Col.AMOUNT_CREDIT: 'Funds In'},\n                account,\n                'EUR',\n                (\n                    'Date, Transaction Details, Funds Out, Funds In'\n                )\n            )\n\n\n    CONFIG = [\n        apply_hooks(MyBankImporter(account='Assets:MyBank:MyAccount'), [PredictPostings()])\n    ]\n\n\nDocumentation\n-------------\n\nThis section explains in detail the relevant concepts and artifacts\nneeded for enhancing Beancount importers with machine learning.\n\n\nBeancount Importers\n~~~~~~~~~~~~~~~~~~~~\n\nLet's assume you have created an importer for \"MyBank\" called\n``MyBankImporter``:\n\n.. code:: python\n\n    class MyBankImporter(importer.ImporterProtocol):\n        \"\"\"My existing importer\"\"\"\n        # the actual importer logic would be here...\n\nNote:\nThis documentation assumes you already know how to create Beancount importers.\nRelevant documentation can be found in the `beancount import documentation\n<https://beancount.github.io/docs/importing_external_data.html>`__.\nWith the functionality of beancount.ingest, users can\nwrite their own importers and use them to convert downloaded bank statements\ninto lists of Beancount entries.\nAn example is provided as part of beancount v2's source code under\n`examples/ingest/office\n<https://github.com/beancount/beancount/tree/v2/examples/ingest/office>`__.\n\nsmart_importer only works by appending onto incomplete single-legged postings\n(i.e. It will not work by modifying postings with accounts like \"Expenses:TODO\").\nThe `extract` method in the importer should follow the\n`latest interface <https://github.com/beancount/beancount/blob/v2/beancount/ingest/importer.py#L61>`__\nand include an `existing_entries` argument.\n\nApplying `smart_importer` hooks\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nAny Beancount importer can be converted into a smart importer by applying one\nof the following hooks:\n\n* ``PredictPostings`` - predict the list of postings.\n* ``PredictPayees``- predict the payee of the transaction.\n* ``DuplicateDetector`` - detect duplicates\n\nFor example, to convert an existing ``MyBankImporter`` into a smart importer:\n\n.. code:: python\n\n    from your_custom_importer import MyBankImporter\n    from smart_importer import apply_hooks, PredictPayees, PredictPostings\n\n    my_bank_importer =  MyBankImporter('whatever', 'config', 'is', 'needed')\n    apply_hooks(my_bank_importer, [PredictPostings(), PredictPayees()])\n\n    CONFIG = [\n        my_bank_importer,\n    ]\n\nNote that the importer hooks need to be applied to an importer instance, as\nshown above.\n\n\nSpecifying Training Data\n~~~~~~~~~~~~~~~~~~~~~~~~\n\nThe ``smart_importer`` hooks need training data, i.e. an existing list of\ntransactions in order to be effective. Training data can be specified by\ncalling bean-extract with an argument that references existing Beancount\ntransactions, e.g., ``bean-extract -f existing_transactions.beancount``. When\nusing the importer in Fava, the existing entries are used as training data\nautomatically.\n\n\nUsage with Fava\n~~~~~~~~~~~~~~~\n\nSmart importers play nice with `Fava <https://github.com/beancount/fava>`__.\nThis means you can use smart importers together with Fava in the exact same way\nas you would do with a conventional importer. See `Fava's help on importers\n<https://github.com/beancount/fava/blob/main/src/fava/help/import.md>`__ for more\ninformation.\n\n\nDevelopment\n-----------\n\nPull requests welcome!\n\n\nExecuting the Unit Tests\n~~~~~~~~~~~~~~~~~~~~~~~~\n\nSimply run (requires tox):\n\n.. code:: bash\n\n    make test\n\n\nConfiguring Logging\n~~~~~~~~~~~~~~~~~~~\n\nPython's `logging` module is used by the smart_importer module.\nThe according log level can be changed as follows:\n\n\n.. code:: python\n\n    import logging\n    logging.getLogger('smart_importer').setLevel(logging.DEBUG)\n\n\nUsing Tokenizer\n~~~~~~~~~~~~~~~~~~\n\nCustom tokenizers can let smart_importer support more languages, eg. Chinese.\n\nIf you looking for Chinese tokenizer, you can follow this example:\n\nFirst make sure that `jieba` is installed in your python environment:\n\n.. code:: bash\n\n    pip install jieba\n\n\nIn your importer code, you can then pass `jieba` to be used as tokenizer:\n\n.. code:: python\n\n    from smart_importer import PredictPostings\n    import jieba\n\n    jieba.initialize()\n    tokenizer = lambda s: list(jieba.cut(s))\n\n    predictor = PredictPostings(string_tokenizer=tokenizer)\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Augment Beancount importers with machine learning functionality.",
    "version": "0.5",
    "project_urls": {
        "Homepage": "https://github.com/beancount/smart_importer"
    },
    "split_keywords": [
        "fava",
        "beancount",
        "accounting",
        "machinelearning"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "e604aafd1307007c2133c859f18699c28be2a68c067d77879b1e5451673d4765",
                "md5": "66f1e69f91340774f30003eb5c9195cc",
                "sha256": "8f99a4f444a485477aec6a3b70ed566c6de415ea1cb1552ac4d5524023c2883b"
            },
            "downloads": -1,
            "filename": "smart_importer-0.5-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "66f1e69f91340774f30003eb5c9195cc",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": null,
            "size": 10575,
            "upload_time": "2024-01-21T09:37:38",
            "upload_time_iso_8601": "2024-01-21T09:37:38.438969Z",
            "url": "https://files.pythonhosted.org/packages/e6/04/aafd1307007c2133c859f18699c28be2a68c067d77879b1e5451673d4765/smart_importer-0.5-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "b9bec7096f5a569e10456338a1db9ef126da8e06aa1c79a9ae61319fb202b210",
                "md5": "8f9fbb9090765de180ef5661772d29c5",
                "sha256": "9f49816b2837372ff9787072a270e7aa90de12bbf7b43869e7bedc0a833a9752"
            },
            "downloads": -1,
            "filename": "smart_importer-0.5.tar.gz",
            "has_sig": false,
            "md5_digest": "8f9fbb9090765de180ef5661772d29c5",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": null,
            "size": 16836,
            "upload_time": "2024-01-21T09:37:40",
            "upload_time_iso_8601": "2024-01-21T09:37:40.837326Z",
            "url": "https://files.pythonhosted.org/packages/b9/be/c7096f5a569e10456338a1db9ef126da8e06aa1c79a9ae61319fb202b210/smart_importer-0.5.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-01-21 09:37:40",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "beancount",
    "github_project": "smart_importer",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "tox": true,
    "lcname": "smart-importer"
}
        
Elapsed time: 0.17793s