customs-compass / README.md
Soulay's picture
Shorten README short_description to satisfy HF Space metadata limit
a26b93c
|
Raw
History Blame Contribute Delete
7.9 kB
---
title: Customs Compass
emoji: 🧭
colorFrom: indigo
colorTo: pink
sdk: docker
app_port: 7860
pinned: false
license: mit
short_description: AI compliance copilot for Chinese US exporters
---
# 🧭 Customs Compass
AI compliance assistant for Chinese SMEs (hardware, batteries, robotics, electronics) exporting to the United States. Built with Streamlit + Ollama.
## What it does
Given a product description and/or a compliance question, Customs Compass produces a structured bilingual answer covering:
- **US sales tax obligations** β€” state-by-state economic nexus thresholds, transaction rules, and base sales tax rates
- **Customs duties** β€” HTS codes and duty rates by product category
- **Federal certifications** β€” FCC, UL, FDA flags per product
- **Risk assessment** β€” Low / Medium / High flags based on your sales vs. each state's threshold
- **Source citations** β€” every claim cites the underlying CSV/JSON
- **Live CBP news** β€” relevant headlines from `cbp.gov/newsroom` injected into the context (cached 1 hour)
## Architecture (hybrid)
| Layer | Source | Update model |
|------|--------|--------------|
| Reference data | `nexus_thresholds.csv`, `hts_duty_codes.csv`, `tax_rates_by_state.json` | Manual / version-controlled |
| CBP enforcement alerts | `cbp_alerts.csv` (curated from cbp.gov) | Manual / version-controlled |
| CBP RAG corpus | `cbp_chunks.jsonl` (595 chunks) + `cbp_pages.jsonl` (200 pages) | Scraped from cbp.gov |
| Retrieval | BM25-light (pure Python, title-boosted) | Index built at startup (~0.5s) |
| Live news | `cbp.gov/newsroom` (scraped, cached 1h) | Auto on app load |
| Reasoning | Ollama `llama3.2:3b` (local) | β€” |
| Fallback | Deterministic rule-based templates | β€” |
The app **always works offline**: if Ollama isn't running or the network is down, it gracefully falls back to a rule-based engine that still produces structured bilingual answers from the CSV data.
## Quick start
### 1. Install dependencies
```bash
pip install -r requirements.txt
```
### 2. (Recommended) Install & start Ollama
Download Ollama from <https://ollama.com>, then:
```bash
ollama pull llama3.2:3b
ollama serve
```
### 3. Run the app
```bash
streamlit run app.py
```
Open <http://localhost:8501> in your browser.
## Running without Ollama (fallback mode)
The app detects whether Ollama is reachable at `http://localhost:11434`. If not, the sidebar will show **🟑 Ollama offline β€” fallback mode** and use a deterministic template engine that:
1. Extracts state names, product categories, and sales amounts from your question
2. Looks them up directly in the CSV files
3. Computes risk levels and produces a bilingual checklist
You can also force fallback mode via the sidebar checkbox β€” useful for predictable, fast, offline-only responses.
## Data files
### `nexus_thresholds.csv`
Economic-nexus thresholds for all 50 US states + DC.
Columns: `state, threshold_usd, transaction_rule, notes`
Note: most states use $100,000; large markets (Texas, California, New York) use $500,000; Oregon, Delaware, Montana, New Hampshire, and Alaska have no statewide sales tax (threshold set to 0).
### `hts_duty_codes.csv`
Customs duties + federal certifications per product category.
Columns: `product_category, hts_code, duty_rate, fcc_needed, ul_needed, fda_needed, notes`
Categories: `battery_with_charger`, `battery_only`, `robotics_with_radio`, `consumer_electronics`, `medical_device`, `industrial_machinery`, `power_tools`, `led_lighting`, `drones`, `solar_panels`, `smart_home_devices`, `ev_charger`, `wearables`, `audio_equipment`.
### `tax_rates_by_state.json`
Base state sales tax rates (percentages). No-tax states are set to 0.
### `cbp_alerts.csv`
Curated CBP enforcement & tariff alerts pulled from `cbp.gov`. Critical for Chinese SME exporters.
Columns: `category, title, summary, relevant_products, country_focus, severity, action_required, source_url`
Covers:
- **Section 301 tariffs** on Chinese electronics (+25%)
- **Section 232** steel/aluminum derivatives
- **De Minimis suspension** (EO 14324, effective Aug 29 2025) β€” all sub-$800 shipments now dutiable
- **UFLPA** (Uyghur Forced Labor Prevention Act) β€” rebuttable presumption against XUAR-sourced goods
- **AD/CVD** (Antidumping/Countervailing Duties) β€” solar, batteries, steel
- **IPR seizures** β€” counterfeit electronics/batteries (China = 66% of FY2025 seizures)
- **Lithium battery safety** β€” UN38.3, UL 2054 requirements
- **IEEPA tariffs** β€” emergency authority for rapid tariff changes
## Example queries
- "We sell power banks to Texas, $200k annual sales. Do we need to collect sales tax?"
- "Our startup ships lithium batteries to California and New York. What certifications do we need?"
- "Medical thermometer exports to Florida with $150k revenue β€” what are our obligations?"
- "We're sending drones to Oregon. Any federal compliance needs?"
## Risk model
The app classifies nexus risk in three bands relative to the state's economic threshold:
| Risk | Sales vs threshold | Meaning |
|------|--------------------|---------|
| 🟒 Low | < 70% | No obligation; continue monitoring |
| 🟑 Medium | 70% – 100% | Approaching nexus; register pre-emptively |
| πŸ”΄ High | β‰₯ 100% | Obligation triggered; register & collect immediately |
## Configuration
Edit constants at the top of `app.py` to tune behavior:
- `OLLAMA_MODEL` β€” switch to `llama3.2:1b` for faster responses, `qwen2:7b` for better Chinese
- `NEWS_CACHE_TTL` β€” CBP news cache duration in seconds
- `NEWS_FETCH_TIMEOUT` β€” HTTP timeout for CBP fetches
## Project structure
```
DD/
β”œβ”€β”€ app.py # Single-file Streamlit application
β”œβ”€β”€ requirements.txt # streamlit, pandas, requests
β”œβ”€β”€ nexus_thresholds.csv # Economic nexus data (50 states + DC)
β”œβ”€β”€ hts_duty_codes.csv # Customs duties + certifications
β”œβ”€β”€ tax_rates_by_state.json # State sales tax rates
β”œβ”€β”€ cbp_alerts.csv # CBP enforcement & tariff alerts (Section 301, UFLPA, etc.)
β”œβ”€β”€ cbp_pages.jsonl # CBP page corpus (200 full pages, metadata)
β”œβ”€β”€ cbp_chunks.jsonl # CBP chunked corpus (595 chunks, ~4000 chars each)
└── README.md # This file
```
## How the RAG works
When you ask a question, the app:
1. **Extracts** states, product categories, and sales amounts via regex/keyword matching
2. **Looks up** structured data: nexus thresholds, HTS codes, tax rates, curated CBP alerts
3. **Retrieves** the top-3 most relevant CBP page excerpts from `cbp_chunks.jsonl` using a **BM25-light scoring** (pure Python, no extra deps):
- Tokenizes question + product names + state names
- Scores each chunk via Okapi BM25 (k1=1.5, b=0.75)
- Boosts terms appearing in the page **title** (2.5Γ—)
- Deduplicates so you get at most one chunk per source page
4. **Injects** all retrieved context into the LLM prompt (Ollama) or the fallback template engine
5. **Renders** a bilingual answer with risk flags and source citations
## Limitations
- The included CSV data is for **demonstration only** and reflects general public information. Real engagements should verify against the latest state tax authority and CBP publications.
- The CBP news fetcher relies on the public HTML structure of `cbp.gov/newsroom`. If CBP restructures the site, the fetcher will return an empty list (the app continues to function).
- `llama3.2:3b` is a small model. Chinese output quality may vary; the fallback engine uses pre-translated templates for consistent Chinese.
## Disclaimer
This tool provides **educational guidance only**. It does **not** constitute legal, tax, or customs advice. Always consult a licensed CPA, customs broker, or trade attorney before making compliance decisions.
## License
Provided as-is for educational use.