PocketAccountant / scripts /demo_finetune.py
eldinosaur's picture
PocketAccountant: custom ledger UI + deterministic agent (engine, ledger, retrieval, classifier)
c55ab5e verified
Raw
History Blame Contribute Delete
2.28 kB
"""Show the SAT classifier and auto-categorization (uses the deterministic fallback;
the fine-tuned model plugs into the same interface).
Run from the project root: python -m scripts.demo_finetune
"""
import sys
try:
sys.stdout.reconfigure(encoding="utf-8")
except (AttributeError, ValueError):
pass
from src.agent import ToolContext, build_tools
from src.finetune import RuleClassifier
from src.ledger import Ledger
def rule(t):
print("\n" + "═" * 64 + f"\n{t}\n" + "═" * 64)
def main():
rule("CLASSIFY free-text transactions → SAT account")
c = RuleClassifier()
samples = [
"Suscripción anual a Adobe Creative Cloud",
"Carga de gasolina en Pemex rumbo a junta con cliente",
"Compra de una MacBook Pro para la oficina",
"Comida de negocios en Sanborns con un cliente",
"Multa de tránsito por exceso de velocidad",
"Recibo de CFE de la oficina",
"Pago de despensa del supermercado",
]
for s in samples:
r = c.classify(s)
flag = "deducible" if r.deducible else "NO deducible"
ratio = f" ({r.deducible_ratio*100:.1f}%)" if r.deducible_ratio < 1 else ""
print(f" {s[:46]:48}{r.sat_code} {r.cuenta[:28]:30} [{flag}{ratio}, {r.kind}]")
rule("AUTO-CATEGORIZE + BOOK in one step (agent tool)")
lg = Ledger(":memory:")
tools = build_tools(ToolContext(lg))
for date, desc, amt in [
("2024-05-04", "Renovación de Figma", 300),
("2024-05-09", "Compra de laptop Dell para trabajo", 22000),
("2024-05-21", "Comida con cliente en VIPS", 800),
]:
res = tools["record_expense_auto"].handler(date=date, description=desc, amount=amt)
cl = res["classification"]
print(f" {desc[:38]:40}{cl['sat_code']} {cl['cuenta'][:24]:26} | {res['note']}")
m = lg.month_totals(2024, 5)
print(f"\n May deductible expenses (laptop excluded as asset): {m.deductible_expenses}")
print(f" May IVA acreditable (incl. laptop's IVA): {m.iva_acreditable}")
lg.close()
print("\nThe fine-tuned MiniCPM replaces RuleClassifier behind the same interface "
"and generalizes to brands/phrasings never seen in the keyword list.")
if __name__ == "__main__":
main()