Salman Adnan

zarailink

ZaraiLink Team

Suppose you trade farm goods and need suppliers of dextrose from Brazil under $800 a tonne. You type that question in plain words, typos and all, and this site searches Pakistani customs records for a ranked list of companies, with contact details locked behind a paid subscription. Three students built it as their final-year project, led by Salman; the demo runs on 14 made-up companies, not live customs data.

Team project, led by Salman

A three-person team project. Salman Adnan led it (64 of 97 commits), with Umar Kashif and Fahad Nadeem. Salman owned the database design, accounts and auth, the subscription and token economy, the admin dashboard, Trade Ledger and Trade Lens, GNN graph building, and frontend integration. Its source is private since it's shared team work and publishing it isn't Salman's call to make alone; available on request. The linked demo replays the same search-to-ledger flow with fabricated companies, not the real customs data.

Field of Trade: wind moves across a wheat field while trade routes pulse in the sky above it, the two halves of what the site joins up: farm commodities on the ground, customs records overhead. Live and interactive: drag it to orbit, scroll or pinch to zoom. Open full screen
The real ZaraiLink Trade Directory, showing a live supplier search against the seeded database.
Live local run: Find Suppliers, 14 real seeded companies.
63backend tests passing
49frontend tests passing
64 / 97commits led by Salman

Overview

An agricultural trade-intelligence platform built as a final-year project at Habib University. It sits on Pakistani customs trade data and answers plain-language supplier queries through an NLU pipeline, a hybrid retrieval layer, and a learning-to-rank model.

The platform answers queries like find dextrose suppliers from Brazil under $800 per MT: the query passes through intent classification, entity extraction, and country and price parsing, a hybrid retrieval layer, and a learning-to-rank model, and comes back as ranked companies with trade history, partners, and gated contact details.

Key features

  • Natural-language search for buyers and suppliers, handling typos, mixed intent, price constraints, and country mentions.
  • A Trade Ledger aggregating company activity from customs transactions (volumes, average prices, partners, growth).
  • A company directory with sector filtering and similar-company suggestions (fuzzy matching plus node2vec embeddings over trade graphs).
  • Subscriptions and a token economy with per-contact access gating, enforced server-side.
  • HS-code and category search alongside free-text queries.

How the search works

  • Intent (BUY/SELL): a SetFit few-shot classifier on a MiniLM base, trained on about 350 labelled queries.
  • Entities: GLiNER zero-shot NER plus pycountry country resolution and regex price and quantity parsing.
  • Retrieval: PostgreSQL trigram similarity (pg_trgm) plus sentence-transformer embeddings.
  • Ranking: a LightGBM LambdaMART learning-to-rank model.

Results

  • 63 backend tests and 49 frontend tests passing.
  • Led by Salman Adnan (64 of 97 commits); the team also ran an end-of-project QA audit that is honest about the remaining security issues.

Tech stack

  • Django 4.2 + DRF
  • PostgreSQL (pg_trgm)
  • PyTorch
  • sentence-transformers
  • SetFit
  • GLiNER
  • LightGBM
  • node2vec
  • React 19
  • Tailwind

Challenges

  • Serving transformer models on CPU without crashing at import time: torch's meta-tensor init path raced with sentence-transformers' .to('cpu'), so the fix patches is_accelerate_available at the cached call sites and swaps init_empty_weights for a no-op.
  • A requirements file that did not install: gliner required a newer transformers than the rest of the stack pinned, and pycountry was missing entirely; both are fixed here.
  • Tests that outlived the code they tested: four tests targeted deleted models and pytest.ini's testpaths pointed at uninstalled apps, so the suite was rebuilt to a trustworthy 63 passing.

What I learned

  • Pin dependencies from a clean-room install, not from whatever the dev machine happens to have.
  • testpaths in pytest.ini is a silent filter: tests outside it neither run nor fail.
  • When monkeypatching library internals, patch where the symbol is used, not where it is defined.
  • Anything with monetary meaning must be enforced in the API layer and verified by tests that hit the endpoints.

Book a call

Let's talk about what you're building.

Pick a slot below. No forms, no back-and-forth emails.