ZeeAI1 commited on
Commit
2f69907
Β·
verified Β·
1 Parent(s): 67e5774

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +179 -0
app.py ADDED
@@ -0,0 +1,179 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ from transformers import BertTokenizer, BertModel
3
+ import spacy
4
+ from typing import Dict, List, Tuple
5
+ import sqlite3
6
+ from datetime import datetime
7
+ import uuid
8
+
9
+ class AccountingNLP:
10
+ def __init__(self):
11
+ # Initialize BERT tokenizer and model
12
+ self.tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
13
+ self.model = BertModel.from_pretrained('bert-base-uncased')
14
+ # Initialize spaCy for entity extraction
15
+ self.nlp = spacy.load("en_core_web_sm")
16
+ # Initialize accounting knowledge base
17
+ self.accounting_rules = self.load_accounting_rules()
18
+ self.connection = sqlite3.connect('accounting_db.sqlite')
19
+ self.create_tables()
20
+
21
+ def load_accounting_rules(self) -> Dict:
22
+ """Load GAAP/IFRS rules and chart of accounts"""
23
+ return {
24
+ 'accounts': {
25
+ 'cash': {'type': 'Asset', 'normal_balance': 'Debit'},
26
+ 'office_supplies': {'type': 'Asset', 'normal_balance': 'Debit'},
27
+ 'accounts_payable': {'type': 'Liability', 'normal_balance': 'Credit'}
28
+ },
29
+ 'rules': {
30
+ 'purchase': {
31
+ 'debit': ['office_supplies'],
32
+ 'credit': ['cash', 'accounts_payable']
33
+ }
34
+ }
35
+ }
36
+
37
+ def create_tables(self):
38
+ """Create database tables for general ledger and journal entries"""
39
+ cursor = self.connection.cursor()
40
+ cursor.execute('''
41
+ CREATE TABLE IF NOT EXISTS journal_entries (
42
+ entry_id TEXT PRIMARY KEY,
43
+ date TEXT,
44
+ account TEXT,
45
+ debit REAL,
46
+ credit REAL,
47
+ description TEXT
48
+ )
49
+ ''')
50
+ cursor.execute('''
51
+ CREATE TABLE IF NOT EXISTS general_ledger (
52
+ account TEXT,
53
+ balance REAL,
54
+ last_updated TEXT
55
+ )
56
+ ''')
57
+ self.connection.commit()
58
+
59
+ def process_input(self, text: str) -> Dict:
60
+ """Process natural language input and extract intent and entities"""
61
+ doc = self.nlp(text)
62
+ entities = {
63
+ 'amount': None,
64
+ 'account': None,
65
+ 'date': None,
66
+ 'payment_method': None
67
+ }
68
+
69
+ # Extract entities
70
+ for ent in doc.ents:
71
+ if ent.label_ == "MONEY":
72
+ entities['amount'] = float(ent.text.replace('$', ''))
73
+ elif ent.label_ == "DATE":
74
+ entities['date'] = ent.text
75
+ elif ent.text.lower() in self.accounting_rules['accounts']:
76
+ entities['account'] = ent.text.lower()
77
+
78
+ # Simple intent classification
79
+ intent = 'record_transaction' if 'record' in text.lower() else 'query'
80
+
81
+ return {'intent': intent, 'entities': entities, 'raw_text': text}
82
+
83
+ def generate_journal_entry(self, processed_input: Dict) -> List[Dict]:
84
+ """Generate double-entry journal entries"""
85
+ if processed_input['intent'] != 'record_transaction':
86
+ return []
87
+
88
+ entities = processed_input['entities']
89
+ entry_id = str(uuid.uuid4())
90
+ date = entities['date'] or datetime.now().strftime('%Y-%m-%d')
91
+ entries = []
92
+
93
+ if entities['account'] in self.accounting_rules['rules']['purchase']['debit']:
94
+ # Debit entry
95
+ entries.append({
96
+ 'entry_id': entry_id,
97
+ 'date': date,
98
+ 'account': entities['account'],
99
+ 'debit': entities['amount'],
100
+ 'credit': 0.0,
101
+ 'description': processed_input['raw_text']
102
+ })
103
+ # Credit entry (assuming cash payment for simplicity)
104
+ entries.append({
105
+ 'entry_id': entry_id,
106
+ 'date': date,
107
+ 'account': 'cash',
108
+ 'debit': 0.0,
109
+ 'credit': entities['amount'],
110
+ 'description': processed_input['raw_text']
111
+ })
112
+
113
+ return entries
114
+
115
+ def validate_transaction(self, entries: List[Dict]) -> Tuple[bool, str]:
116
+ """Validate journal entries for double-entry compliance"""
117
+ total_debit = sum(entry['debit'] for entry in entries)
118
+ total_credit = sum(entry['credit'] for entry in entries)
119
+
120
+ if total_debit != total_credit:
121
+ return False, "Debits and credits must balance"
122
+ if not entries:
123
+ return False, "No valid entries generated"
124
+ return True, "Valid transaction"
125
+
126
+ def update_ledger(self, entries: List[Dict]):
127
+ """Update general ledger with validated entries"""
128
+ cursor = self.connection.cursor()
129
+ for entry in entries:
130
+ cursor.execute('''
131
+ INSERT INTO journal_entries (entry_id, date, account, debit, credit, description)
132
+ VALUES (?, ?, ?, ?, ?, ?)
133
+ ''', (
134
+ entry['entry_id'],
135
+ entry['date'],
136
+ entry['account'],
137
+ entry['debit'],
138
+ entry['credit'],
139
+ entry['description']
140
+ ))
141
+
142
+ # Update general ledger balance
143
+ cursor.execute('''
144
+ INSERT OR REPLACE INTO general_ledger (account, balance, last_updated)
145
+ VALUES (?,
146
+ (SELECT COALESCE((SELECT balance FROM general_ledger WHERE account = ?), 0)
147
+ + ? - ?),
148
+ ?)
149
+ ''', (
150
+ entry['account'],
151
+ entry['account'],
152
+ entry['debit'],
153
+ entry['credit'],
154
+ entry['date']
155
+ ))
156
+
157
+ self.connection.commit()
158
+
159
+ def generate_response(self, processed_input: Dict, entries: List[Dict]) -> str:
160
+ """Generate natural language response"""
161
+ if processed_input['intent'] == 'record_transaction':
162
+ is_valid, message = self.validate_transaction(entries)
163
+ if is_valid:
164
+ self.update_ledger(entries)
165
+ return f"Successfully recorded transaction: {processed_input['raw_text']}"
166
+ return f"Error: {message}"
167
+ return "Query processing not implemented"
168
+
169
+ def process(self, text: str) -> str:
170
+ """Main processing pipeline"""
171
+ processed_input = self.process_input(text)
172
+ entries = self.generate_journal_entry(processed_input)
173
+ return self.generate_response(processed_input, entries)
174
+
175
+ # Example usage
176
+ if __name__ == "__main__":
177
+ accounting_ai = AccountingNLP()
178
+ result = accounting_ai.process("Record a $500 office supplies purchase paid by check")
179
+ print(result)