Skip to main content

Pure syntagmatic rule-based parser for English RFQ documents (Vietnamese mode included) — LLM pre-processing layer for product name and spec extraction

Project description

rfq-parser

Pure syntagmatic rule-based parser for English RFQ documents and short product queries, with a Vietnamese mode.

No semantic model, no embeddings, no LLM — purely structural analysis of surface form. Built in Rust with Python bindings via PyO3, it runs in <1ms and is designed as a lightweight pre-processing layer for LLM-based product name and spec extraction: strip quantities, units, colours, sizes, and materials from the raw text so the model only sees what it actually needs to reason about.

Install

pip install rfq-parser

Quick start

import rfq_parser

# Short product query
result = rfq_parser.parse("500 polo shirts red size XL")
item = result.items[0]
print(item.chunks)     # "polo shirts"
print(item.qty)        # 500.0
print(item.uom)        # None (implicit pieces)
print(item.colors)     # ["red"]
print(item.sizes)      # ["XL"]

# RFQ document
rfq = """
Please quote for:
1. Car Battery, 3000 Cartons, Black, 70Ah, Japan. Target: 12 USD/unit.
2. Silk Fabric, 500 Yards, Red, 150cm width, China.
"""
result = rfq_parser.parse(rfq)
for item in result.items:
    print(f"{item.index}. {item.chunks} — qty={item.qty} {item.uom}")
    print(f"   colors={item.colors}, origin={item.origin}")

if result.is_rfq:
    tt = result.trade_terms()  # TradeTerms | None

Syntagmatic analysis in practice

Consider the ambiguous query:

"I want 500 shirts or polos in size XL"

A semantic model has to guess: does in size XL modify only polos, or the entire coordination shirts or polos? It will lean on world knowledge, training distribution, or hallucinate.

rfq-parser resolves this structurally. The surface parse is:

NP[qty=500]
 ├── NP "shirts"
 │    └── COORD "or"
 │         └── NP "polos"
 └── PP[size] "in size XL"   ← attaches to the root NP, shared across coordination

Rule: a post-head PP always scopes over the nearest NP node, which here is the coordinated root — not just polos. No semantic reasoning needed.

result = rfq_parser.parse("I want 500 shirts or polos in size XL")
item = result.items[0]
print(item.chunks)   # "shirts or polos"
print(item.qty)      # 500.0
print(item.sizes)    # ["XL"]

The LLM downstream receives chunks = "shirts or polos" — a clean noun phrase — instead of the raw query. Quantity and size are already extracted; the model only needs to reason about the product names.

What it extracts

Each ParsedItem contains:

Field Description
chunks Product noun phrase(s), connectors preserved ("polo shirt OR t-shirt")
qty, qty_max, uom Quantity and unit of measure
colors, sizes, materials Ontology-matched specs
standards, specs Technical standards and extra specs
origin, price, currency RFQ-specific fields
dims Dimensions (e.g. ["150cm", "70Ah"])

ParseResult.trade_terms() returns a TradeTerms object with incoterm, currency, destination, lead_time, payment for RFQ documents.

Why syntagmatic / rule-based?

  • No semantic bindings — no embeddings, no model weights, no ontology lookups at runtime
  • Deterministic — same input always gives the same output
  • Fast — <1ms, safe to call on every keystroke or in a streaming pipeline
  • No dependencies — no model to download, no API key
  • LLM pre-processing — strips structured fields (qty, uom, colours, sizes, materials) so downstream LLM calls receive a clean noun phrase, reducing token waste and hallucination surface

Supported

  • English, Vietnamese, French product queries
  • Informal RFQ emails and formal procurement documents
  • Multi-item RFQs with trade terms (Incoterms, payment, lead time)

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

rfq_parser-0.1.2.tar.gz (54.5 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

rfq_parser-0.1.2-cp311-abi3-win_amd64.whl (786.2 kB view details)

Uploaded CPython 3.11+Windows x86-64

rfq_parser-0.1.2-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (912.9 kB view details)

Uploaded CPython 3.11+manylinux: glibc 2.17+ x86-64

rfq_parser-0.1.2-cp311-abi3-macosx_11_0_arm64.whl (820.4 kB view details)

Uploaded CPython 3.11+macOS 11.0+ ARM64

File details

Details for the file rfq_parser-0.1.2.tar.gz.

File metadata

  • Download URL: rfq_parser-0.1.2.tar.gz
  • Upload date:
  • Size: 54.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for rfq_parser-0.1.2.tar.gz
Algorithm Hash digest
SHA256 74295d88efa01784b7984d2a400fa40dbc299c7265d63525e38be57bed15b968
MD5 261a665a2b434f0572bb68860bcea3fe
BLAKE2b-256 b27e5dfc708cee59cbfe3f6e73830ab3ac251a40d0cfa0add961701b3500fcd6

See more details on using hashes here.

Provenance

The following attestation bundles were made for rfq_parser-0.1.2.tar.gz:

Publisher: publish.yml on progdinh/rfq-parser

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file rfq_parser-0.1.2-cp311-abi3-win_amd64.whl.

File metadata

  • Download URL: rfq_parser-0.1.2-cp311-abi3-win_amd64.whl
  • Upload date:
  • Size: 786.2 kB
  • Tags: CPython 3.11+, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for rfq_parser-0.1.2-cp311-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 5c9d19973ea339b24f62aabceb3e1346d82aaa2d5c022a4abc6fbd0d4139b93f
MD5 d6e42fdec0cf387b1688c4a52cf69398
BLAKE2b-256 d55ada70eac196e2d9b2fad250246f721f001594371a1fd37a4b8631413c4529

See more details on using hashes here.

Provenance

The following attestation bundles were made for rfq_parser-0.1.2-cp311-abi3-win_amd64.whl:

Publisher: publish.yml on progdinh/rfq-parser

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file rfq_parser-0.1.2-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for rfq_parser-0.1.2-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 c9ef6c4c8e83073935a486bd0953081ef7da394707480883d3c43fc11f64dc66
MD5 71344807a3b98f2cfd4794b01d2051f3
BLAKE2b-256 27c2336d48a19504e7b4f01061dfea3740ac04da759003f2ac02056f5e10ef68

See more details on using hashes here.

Provenance

The following attestation bundles were made for rfq_parser-0.1.2-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: publish.yml on progdinh/rfq-parser

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file rfq_parser-0.1.2-cp311-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for rfq_parser-0.1.2-cp311-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 2aea0ae902636ca3bc943b46bb769351a689a8bc447943fbef5193f273917c9d
MD5 893a0ae269102b0fae8b93c6a671cbb7
BLAKE2b-256 781d640dc8f0248504fc55ddc0acec9c68f42ea8b2f49c40751469177e2a67ae

See more details on using hashes here.

Provenance

The following attestation bundles were made for rfq_parser-0.1.2-cp311-abi3-macosx_11_0_arm64.whl:

Publisher: publish.yml on progdinh/rfq-parser

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page