Pass all three outputs (structured invoice data, call transcript, and logo verification result) to a reasoning-capable LLM. Ask it to compare the invoice against the transcript for verbal commitments, flag any discrepancies, assess the logo result, and draft either an approval confirmation or a rejection message for the procurement team to review and send.
Python · reasoning LLM with all three modality outputs
import anthropic
import json
def analyze_and_draft_response(
invoice_data: dict,
transcript: str,
logo_result: dict,
) -> dict:
"""
Combine document AI extraction, call transcript, and VLM logo
verification into a final analysis and draft approval or rejection.
Returns: {recommendation: str, discrepancies: list, draft_message: str}
"""
client = anthropic.Anthropic()
prompt = f"""You are a procurement verification assistant. Review the following
three inputs from a supplier invoice processing pipeline and produce a
structured analysis.
--- EXTRACTED INVOICE DATA ---
{json.dumps(invoice_data, indent=2)}
--- SUPPLIER CALL TRANSCRIPT ---
{transcript}
--- LOGO VERIFICATION RESULT ---
{json.dumps(logo_result, indent=2)}
Tasks:
1. Compare the invoice line items and totals against any pricing or
quantity commitments mentioned in the call transcript.
2. Flag any discrepancies between the written invoice and verbal commitments.
3. Note whether the logo verification passed or failed and at what confidence.
4. Draft either an approval confirmation or a rejection message to the supplier.
The message should be professional, specific about any issues, and suitable
for a procurement manager to review and send without rewriting.
Return a JSON object with these keys:
- recommendation: "approve" or "reject"
- discrepancies: array of strings describing each discrepancy found (empty if none)
- logo_status: "verified" or "mismatch" or "low_confidence"
- draft_message: full text of the message to send to the supplier
Return only the JSON object."""
response = client.messages.create(
model="claude-opus-4-5",
max_tokens=2048,
messages=[{"role": "user", "content": prompt}],
)
text = response.content[0].text.strip()
if text.startswith("```"):
text = text.split("```")[1]
if text.startswith("json"):
text = text[4:]
return json.loads(text.strip())
# Wire all four steps together
def run_invoice_intelligence_pipeline(
pdf_path: str,
audio_path: str,
header_image_path: str,
expected_supplier: str,
) -> dict:
print("[1/4] Extracting invoice line items...")
invoice_data = extract_invoice_line_items(pdf_path)
print("[2/4] Transcribing supplier call...")
transcript = transcribe_supplier_call(audio_path)
print("[3/4] Verifying supplier logo...")
logo_result = verify_invoice_logo(header_image_path, expected_supplier)
print("[4/4] Running discrepancy analysis...")
result = analyze_and_draft_response(invoice_data, transcript, logo_result)
return {
"invoice_data": invoice_data,
"transcript_word_count": len(transcript.split()),
"logo_result": logo_result,
"analysis": result,
}
# Run the full pipeline
output = run_invoice_intelligence_pipeline(
pdf_path="supplier_invoice.pdf",
audio_path="supplier_call.mp3",
header_image_path="invoice_header.png",
expected_supplier="Acme Components Ltd",
)
print(json.dumps(output["analysis"], indent=2))