| import gradio as gr |
| import anthropic |
| import pdfplumber |
| import os |
|
|
| |
| client = anthropic.Anthropic( |
| api_key=os.environ.get("ANTHROPIC_API_KEY"), |
| default_headers={ |
| "anthropic-beta": "zero-data-retention-1" |
| } |
| ) |
|
|
| PRIVACY_NOTICE = """ |
| ### π Privacy & Data Security |
| |
| **Your documents are protected:** |
| - Documents are processed in memory only β never stored on our servers |
| - All processing uses Anthropic's API with **zero-data-retention** enabled β your content is not stored or used for AI training |
| - Uploaded files are discarded immediately after extraction |
| - No database, no logs, no third-party sharing |
| |
| **You retain full control:** This tool extracts and displays data on your screen only. Nothing is saved anywhere. |
| |
| β οΈ *Always verify AI-extracted fields before submitting to customs authorities. This tool is AI-assisted β final responsibility for all customs declarations remains with the licensed broker or importer.* |
| """ |
|
|
| def extract_from_invoice(pdf_file): |
| if pdf_file is None: |
| return "Please upload a PDF invoice." |
|
|
| |
| text = "" |
| with pdfplumber.open(pdf_file.name) as pdf: |
| for page in pdf.pages: |
| text += page.extract_text() or "" |
|
|
| if not text.strip(): |
| return "Could not extract text from this PDF. It may be a scanned image β please try a text-based PDF." |
|
|
| response = client.messages.create( |
| model="claude-sonnet-4-6", |
| max_tokens=1024, |
| system=( |
| "You are an expert at extracting structured data from trade documents " |
| "for customs declarations. Be precise and thorough." |
| ), |
| messages=[{ |
| "role": "user", |
| "content": f"""Extract these customs fields from the invoice below. |
| If a field is not found, write NOT FOUND. |
| |
| Fields to extract: |
| - Shipper name and address |
| - Consignee name and address |
| - Invoice number |
| - Invoice date |
| - HS Code(s) |
| - Description of goods |
| - Declared value and currency |
| - Country of origin |
| - Net weight |
| - Gross weight |
| |
| Invoice text: |
| {text[:4000]} |
| |
| β οΈ AI-assisted extraction β verify all fields before submitting to customs authorities.""" |
| }] |
| ) |
| return response.content[0].text |
|
|
|
|
| with gr.Blocks(theme=gr.themes.Soft(), title="Trade Document Intelligence") as demo: |
| gr.Markdown("# Trade Document Intelligence") |
| gr.Markdown( |
| "AI-powered extraction of customs fields from commercial invoices. " |
| "Built for customs brokers and freight forwarders worldwide." |
| ) |
|
|
| with gr.Accordion("π Privacy & Data Security β click to read before uploading", open=False): |
| gr.Markdown(PRIVACY_NOTICE) |
|
|
| with gr.Row(): |
| with gr.Column(): |
| pdf_input = gr.File( |
| label="Upload Commercial Invoice (PDF)", |
| file_types=[".pdf"] |
| ) |
| submit_btn = gr.Button("Extract Customs Fields", variant="primary") |
| clear_btn = gr.Button("Clear", variant="secondary") |
|
|
| with gr.Column(): |
| output = gr.Textbox( |
| label="Extracted Customs Fields", |
| lines=25, |
| placeholder="Extracted fields will appear here after upload..." |
| ) |
|
|
| submit_btn.click(fn=extract_from_invoice, inputs=pdf_input, outputs=output) |
| clear_btn.click(fn=lambda: (None, ""), outputs=[pdf_input, output]) |
|
|
| gr.Markdown( |
| "---\n" |
| "*Trade Document Intelligence β AI-assisted customs data extraction. " |
| "Built for customs brokers and freight forwarders worldwide.*\n\n" |
| "[Terms of Service](https://github.com/tradedocs-ai/trade-document-intelligence/blob/main/docs/TERMS.md)" |
| ) |
|
|
| demo.launch() |