Implement code changes to enhance functionality and improve performance
This commit is contained in:
@@ -132,6 +132,9 @@ class LLMTaxAnalyzer:
|
|||||||
logger.info(
|
logger.info(
|
||||||
f"Completed batch tax analysis, enhanced {len(enhanced_matches)} matches"
|
f"Completed batch tax analysis, enhanced {len(enhanced_matches)} matches"
|
||||||
)
|
)
|
||||||
|
# logger.info(
|
||||||
|
# f"\n\n\nFinal batch enhanced matches: {enhanced_matches}"
|
||||||
|
# )
|
||||||
return enhanced_matches
|
return enhanced_matches
|
||||||
|
|
||||||
def _process_matches_individually(self, matches: list, user_location: str) -> list:
|
def _process_matches_individually(self, matches: list, user_location: str) -> list:
|
||||||
@@ -218,7 +221,6 @@ class LLMTaxAnalyzer:
|
|||||||
RECEIPT DETAILS:
|
RECEIPT DETAILS:
|
||||||
- Vendor: {receipt.vendor}
|
- Vendor: {receipt.vendor}
|
||||||
- Amount: ${receipt.amount:.2f}
|
- Amount: ${receipt.amount:.2f}
|
||||||
- Tax: ${receipt.tax:.2f}
|
|
||||||
- Currency: {receipt.currency}
|
- Currency: {receipt.currency}
|
||||||
- Date: {receipt.receipt_date.strftime("%Y-%m-%d")}
|
- Date: {receipt.receipt_date.strftime("%Y-%m-%d")}
|
||||||
- Category: {receipt.category}
|
- Category: {receipt.category}
|
||||||
@@ -322,7 +324,8 @@ CCA DEPRECIATION RATES BY ASSET CLASS:
|
|||||||
"""Get tax rule analysis from LLM"""
|
"""Get tax rule analysis from LLM"""
|
||||||
|
|
||||||
prompt = f"""
|
prompt = f"""
|
||||||
You are a Canadian tax expert analyzing a receipt-transaction match. Apply the following tax rules intelligently:
|
You are a tax expert analyzing a receipt-transaction match. Apply the following tax rules intelligently:
|
||||||
|
And you are to calculate the tax for the receipt based on the context provided.
|
||||||
|
|
||||||
{context}
|
{context}
|
||||||
|
|
||||||
@@ -437,16 +440,23 @@ b) **CCA Depreciation** (for tax purposes - Canada):
|
|||||||
|
|
||||||
Provide a structured JSON response with the following format:
|
Provide a structured JSON response with the following format:
|
||||||
|
|
||||||
|
**CRITICAL INSTRUCTION FOR final_tax_amount:**
|
||||||
|
- This field MUST contain ONLY the calculated sales tax amount in dollars
|
||||||
|
- This is NOT the total amount including tax
|
||||||
|
- This is ONLY the tax portion (HST/GST/PST/QST)
|
||||||
|
- Example: If receipt total is $100 and calculated tax is $13, return 13.00 (not 113.00)
|
||||||
|
- For meals & entertainment: Return the FULL calculated tax amount (not the 50% adjusted amount)
|
||||||
|
|
||||||
{{
|
{{
|
||||||
"final_tax_amount": XX.XX,
|
"final_tax_amount": XX.XX, // ONLY the calculated tax amount (e.g., 13.00 for $100 + $13 HST)
|
||||||
"sales_tax": {{
|
"sales_tax": {{
|
||||||
"applicable_province": "XX",
|
"applicable_province": "XX",
|
||||||
"applicable_rate": 0.XX,
|
"applicable_rate": 0.XX,
|
||||||
"tax_name": "HST/GST/PST/QST",
|
"tax_name": "HST/GST/PST/QST",
|
||||||
"calculated_tax": XX.XX,
|
"calculated_tax": XX.XX, // This should match final_tax_amount above
|
||||||
"stated_tax": XX.XX,
|
"stated_tax": XX.XX,
|
||||||
"discrepancy": XX.XX,
|
"discrepancy": XX.XX,
|
||||||
"reason": "Detailed explanation: which address used (billing/shipping), why this location, which scenario applies",
|
"reason": "Detailed explanation",
|
||||||
"requires_review": true/false
|
"requires_review": true/false
|
||||||
}},
|
}},
|
||||||
"foreign_exchange": {{
|
"foreign_exchange": {{
|
||||||
@@ -638,7 +648,6 @@ MATCH {i} (ID: match_{i}):
|
|||||||
Receipt Details:
|
Receipt Details:
|
||||||
- Vendor: {receipt.vendor}
|
- Vendor: {receipt.vendor}
|
||||||
- Amount: ${receipt.amount:.2f}
|
- Amount: ${receipt.amount:.2f}
|
||||||
- Tax: ${receipt.tax:.2f}
|
|
||||||
- Currency: {receipt.currency}
|
- Currency: {receipt.currency}
|
||||||
- Date: {receipt.receipt_date.strftime("%Y-%m-%d")}
|
- Date: {receipt.receipt_date.strftime("%Y-%m-%d")}
|
||||||
- Category: {receipt.category}
|
- Category: {receipt.category}
|
||||||
@@ -679,13 +688,11 @@ CCA DEPRECIATION RATES BY ASSET CLASS:
|
|||||||
"""
|
"""
|
||||||
return context
|
return context
|
||||||
|
|
||||||
def _get_llm_tax_analysis_batch(
|
def _get_llm_tax_analysis_batch(self, context: str, num_matches: int) -> Dict[str, Any]:
|
||||||
self, context: str, num_matches: int
|
|
||||||
) -> Dict[str, Any]:
|
|
||||||
"""Get tax rule analysis from LLM for ALL matches in a single call"""
|
"""Get tax rule analysis from LLM for ALL matches in a single call"""
|
||||||
|
|
||||||
prompt = f"""
|
prompt = f"""
|
||||||
You are a Canadian tax expert analyzing MULTIPLE receipt-transaction matches. Apply the following tax rules intelligently to EACH match.
|
You are a Canadian tax expert analyzing MULTIPLE receipt-transaction matches.
|
||||||
|
|
||||||
{context}
|
{context}
|
||||||
|
|
||||||
@@ -747,13 +754,22 @@ c) User in Ontario, Receipt has NO address information:
|
|||||||
|
|
||||||
=== YOUR TASK ===
|
=== YOUR TASK ===
|
||||||
|
|
||||||
Analyze EACH match (match_0, match_1, match_2, etc.) and return a JSON object where each key is the match ID (e.g., "match_0") and the value is the complete tax analysis for that match.
|
Analyze EACH match and return a JSON object where each key is the match ID and the value is the complete tax analysis.
|
||||||
|
|
||||||
|
**CRITICAL INSTRUCTION FOR final_tax_amount:**
|
||||||
|
- This field MUST contain ONLY the calculated sales tax amount in dollars
|
||||||
|
- This is NOT the total amount including tax
|
||||||
|
- This is ONLY the tax portion (HST/GST/PST/QST)
|
||||||
|
- Example: If receipt total is $100 and calculated tax is $13, return 13.00 (not 113.00)
|
||||||
|
- For meals & entertainment: Return the FULL calculated tax amount (not the 50% adjusted amount)
|
||||||
|
- VERIFY: final_tax_amount should equal sales_tax.calculated_tax
|
||||||
|
-
|
||||||
|
|
||||||
Return your response as a SINGLE JSON object in this format:
|
Return your response as a SINGLE JSON object in this format:
|
||||||
|
|
||||||
{{
|
{{
|
||||||
"match_0": {{
|
"match_0": {{
|
||||||
"final_tax_amount": XX.XX,
|
"final_tax_amount": XX.XX, // ONLY the calculated tax amount
|
||||||
"sales_tax": {{
|
"sales_tax": {{
|
||||||
"applicable_province": "XX",
|
"applicable_province": "XX",
|
||||||
"applicable_rate": 0.XX,
|
"applicable_rate": 0.XX,
|
||||||
@@ -800,17 +816,7 @@ Return your response as a SINGLE JSON object in this format:
|
|||||||
}},
|
}},
|
||||||
... for all {num_matches} matches ...
|
... for all {num_matches} matches ...
|
||||||
}}
|
}}
|
||||||
|
|
||||||
**Critical Reminders**:
|
|
||||||
- Sales tax uses RECEIPT location (or user location if receipt has none)
|
|
||||||
- Depreciation ALWAYS uses USER location
|
|
||||||
- For different addresses, use SHIPPING address for sales tax
|
|
||||||
- International transactions: no Canadian tax + FX flag
|
|
||||||
- Be precise with all calculations
|
|
||||||
- Always explain your reasoning clearly
|
|
||||||
- Return analysis for ALL {num_matches} matches
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
response = self.client.chat.completions.create(
|
response = self.client.chat.completions.create(
|
||||||
model=self.model,
|
model=self.model,
|
||||||
@@ -902,9 +908,36 @@ Return your response as a SINGLE JSON object in this format:
|
|||||||
|
|
||||||
def _apply_tax_analysis_to_match(self, match, tax_analysis: Dict[str, Any]):
|
def _apply_tax_analysis_to_match(self, match, tax_analysis: Dict[str, Any]):
|
||||||
"""Apply tax analysis results to a match object"""
|
"""Apply tax analysis results to a match object"""
|
||||||
|
|
||||||
# Store the complete tax analysis
|
# **CRITICAL FIX: Ensure final_tax_amount matches calculated_tax**
|
||||||
|
final_tax = tax_analysis.get("final_tax_amount", 0.0)
|
||||||
|
calculated_tax = tax_analysis.get("sales_tax", {}).get("calculated_tax", 0.0)
|
||||||
|
|
||||||
|
# If there's a mismatch, use calculated_tax as the source of truth
|
||||||
|
if abs(final_tax - calculated_tax) > 0.01:
|
||||||
|
logger.warning(
|
||||||
|
f"Correcting final_tax_amount mismatch for {match.receipt.vendor}: "
|
||||||
|
f"LLM returned final_tax_amount={final_tax}, but calculated_tax={calculated_tax}. "
|
||||||
|
f"Using calculated_tax as final value."
|
||||||
|
)
|
||||||
|
tax_analysis["final_tax_amount"] = calculated_tax
|
||||||
|
|
||||||
|
# Special case: If final_tax is 0 but calculated_tax > 0, always use calculated_tax
|
||||||
|
if final_tax == 0.0 and calculated_tax > 0.0:
|
||||||
|
logger.warning(
|
||||||
|
f"Correcting zero final_tax_amount for {match.receipt.vendor}: "
|
||||||
|
f"LLM returned 0 but calculated {calculated_tax} HST. Setting final_tax_amount={calculated_tax}"
|
||||||
|
)
|
||||||
|
tax_analysis["final_tax_amount"] = calculated_tax
|
||||||
|
tax_analysis["sales_tax"]["requires_review"] = True
|
||||||
|
|
||||||
|
# Apply the corrected tax analysis
|
||||||
match.tax_analysis = tax_analysis
|
match.tax_analysis = tax_analysis
|
||||||
|
|
||||||
|
logger.debug(
|
||||||
|
f"Applied tax analysis to match: {match.receipt.vendor} -> "
|
||||||
|
f"final_tax_amount={tax_analysis['final_tax_amount']}"
|
||||||
|
)
|
||||||
|
|
||||||
# Apply confidence adjustments based on tax analysis
|
# Apply confidence adjustments based on tax analysis
|
||||||
confidence_adj = tax_analysis.get("confidence_adjustment", {})
|
confidence_adj = tax_analysis.get("confidence_adjustment", {})
|
||||||
|
|||||||
Reference in New Issue
Block a user