Open to remote AI engineering roles and relocation · UK, EU, US, UAE

I build LLM systems and measure them.

AI engineer in Delhi. I design agents, retrieval, voice pipelines and tool servers end to end, test them against the real system, and publish the numbers, including the ones that went against expectation. I run a production AI platform alone, so I know what happens after the demo.

40 / 40conversations an eager LangGraph agent kept within policy with a guard node; 28 / 40 without it
20 / 20callers who paused mid-sentence and were cut off by a 300 ms silence threshold in a voice pipeline
κ −0.40agreement of a transcript-only grader with ground truth on scripted test agents, measured in agentcheck
125end-to-end checks on the accounts platform I run, 112 of them against production

Selected work

Each project answers a question, with numbers.

All of it is public, tested and reproducible from a clean checkout with no API key; CI proves it on every push.

handoff-graphOct 2026

Agent orchestration · Python · LangGraph · FastAPI · Claude

Question: when an agent has to follow rules, where should they live: in the prompt, in the shape of the graph, or in a guard that checks every tool call?

A card-support agent in LangGraph: intent routing, context carried across turns by the checkpointer, an identity-verification gate, a guard that checks each proposed tool call against the policy, and a human handoff that pauses with interrupt() and files the ticket only after a person accepts. It's graded on what happened to the accounts, plus an independent audit of the action log that doesn't trust the guard.

Findings, on scripted planners with known behaviour: with a careful planner every design scores 40/40, so a demo can't tell them apart. With an eager one, the full graph still scored 40/40 because the guard stopped eight actions, while taking out the gate and the guard let it break policy in 12 of 40 conversations.

LangGraphinterrupt / resumepolicy guardFastAPIDocker15 tests

Eager planner · conversations passed of 40

full graph40
no guard32
flat28
  • 8actions the guard stopped: four over-limit disputes became handoffs, four out-of-window disputes became explanations
  • 39 / 40routing accuracy; "How long does a dispute take?" goes to the wrong intent, left in as the first case for an LLM router

voice-latencyOct 2026

Voice agents · Python · Vosk streaming STT · TTS · voice activity detection

Question: in a voice agent, where does the time go between the caller going quiet and the agent starting to answer?

48 recorded requests (12 card-support questions in US, UK, Australian and Indian English) run through an energy endpointer, streaming Vosk recognition, a reply step with a swept time to first token (or Claude, streamed), and local text-to-speech, all offline on a 2020 laptop CPU.

Findings: the silence threshold, not the model, sets the floor. 300 and 500 ms cut off every caller who paused mid-sentence; only 1200 ms caught them all, and it adds over a second to every turn. Recognition left about 30 ms of work once the turn ended, but its error rate was 2.1% on the US voice and about 11% on the other three. Then the speech engine spent about 1.75 s starting up on every reply, so keeping it loaded would save three times what the faster model in the sweep did.

endpointingstreaming STTWERTTS7 tests

Callers with a mid-sentence pause who got cut off

silence thresholdcut offadded to every turn
300 ms20 / 20290 ms
500 ms20 / 20490 ms
800 ms15 / 20790 ms
1200 ms0 / 201190 ms

Word error rate by voice

US2.1%
UK10.0%
Indian11.0%
Australian11.1%

lora-intentsOct 2026

Fine-tuning · Python · PyTorch · Transformers · PEFT

Question: how many labelled examples does a LoRA adapter need before it beats the cheap options?

Learning curves on Banking77 (77 banking intents) from 5 examples per intent to all 10,003: TF-IDF, a frozen MiniLM sentence encoder with logistic regression, a rank-8 LoRA adapter, and a full fine-tune, in plain PyTorch on a laptop CPU. All the MiniLM methods read the same mean-pooled embedding, so only the way the backbone is updated differs.

Findings: the frozen encoder matched or beat LoRA at every data size and trained in minutes rather than half an hour. A full fine-tune only edged ahead with all the data (93.2% vs 93.0%, one seed). For an intent router, start frozen and fine-tune only when the embedding is the problem.

LoRAPEFTlearning curves3 seeds7 tests

Accuracy by labelled examples per intent

method520all
TF-IDF54.5%77.0%89.4%
frozen MiniLM80.3%88.3%93.0%
LoRA, rank 878.0%87.7%92.5%
full fine-tune––93.2%
  • 3 minto embed all the data and train the frozen-encoder classifier, against 36 min for LoRA on the same CPU

agentcheck

Agent evaluation · Python · Anthropic SDK

Question: when you grade a tool-using agent from its conversation, what do you miss?

A deterministic back-office world with seven tools and 36 tasks. Every run is graded on the end state of the world, a zero-tolerance policy check over the action log, and the facts in the answer. The environment enforces physics but not policy, so violations happen and get caught rather than being prevented and hidden.

Findings, on scripted reference agents with known behaviour: a grader that reads only the transcript agreed with ground truth worse than chance on the agent that skips checks, passing 16 runs that broke policy and failing every correct refusal. And an agent that looks 96% reliable per attempt gets all eight attempts right on only 75% of tasks. Real-model runs plug in through a Claude adapter on the Anthropic SDK.

pass^kCohen's κMcNemartool use22 tests

pass^k vs pass@k · 8 trials per task

k1248
pass^k (all succeed)96%93%86%75%
pass@k (any succeeds)96%100%100%100%

Transcript-only grader vs truth

judge80.6%
truth47.2%

Solquara: a production AI platform, built and run alone

Founder & lead engineer · PHP, JavaScript, WebGL, Python · Jul 2026 – present

An AI video-ad and automation studio at solquara.com. I'm the only engineer: a 40-route site, an accounts, plans and entitlements system with signed billing webhooks, a generative-media pipeline, and an MCP server that lets Claude drive Gemini, Veo and TTS.

The work I'm proudest of is the testing: 125 end-to-end checks covering IDOR, sessions, throttling and every subscription state, run locally on real PHP 8.3 and 112 of them against production through a self-expiring harness. Production found two traps no local run could: a host cache serving each user a stale plan, and a security plugin locking out IPs. Both are handled and documented.

auth & billingwebhooksWebGLperf profiling

Measured

  • 23 → 2homepage stylesheets; 26 scripts → 1; HTML 123 kB → 36 kB
  • 6 → 55 fpsafter profiling found backdrop-filter eating ~80% of the frame budget
  • ~4×cheaper video on a 25-second Short: keyframe-then-animate vs Higgsfield's built-in narrated-video workflow, priced per model before committing
  • ~920UK companies verified by a Python crawler + Companies House pipeline

pg-hybrid-search

Retrieval · TypeScript · PostgreSQL · pgvector · Docker

Question: can Postgres alone do hybrid search well, and what does it take?

Full-text, BM25 and pgvector retrieval fused with reciprocal rank fusion in a single SQL statement, benchmarked on BEIR SciFact (300 expert-judged claims, 5,183 abstracts). The same tests run on PGlite (Postgres 18 in WASM) and on a real pgvector server in CI, which caught two portability bugs the in-process run could not show.

Findings: hybrid search only helped with real BM25. Built on Postgres's own ts_rank_cd, which has no IDF, fusion made the top 10 worse than vectors alone. And pgvector's default ef_search silently returned 40 rows when asked for 100.

pgvectorHNSWBM25RRF in SQLDocker14 tests · 2 engines

nDCG@10 · BEIR SciFact

BM25+vec0.712
BM250.689
vector0.643
ts+vec0.597
ts_rank0.362
  • 40 / 100rows pgvector returned at its default ef_search; recall fell 0.925 → 0.875 with no error

rag-document-qaCloud Run · Oct 2026

RAG service · Python · FastAPI · Terraform · Google Cloud Run

Question: can a RAG service say "I don't know" honestly, and what does it take to put it on the internet?

Citation-grounded Q&A over a folder of documents. A similarity threshold is the usual way to refuse unanswerable questions. Measured here, it can't work: an off-topic question scored higher than a relevant one. A vocabulary-coverage guard separates them cleanly, and a test fails if a future embedder makes the simpler guard viable again.

It ships ready for Cloud Run: Terraform for the service, Artifact Registry and Secret Manager, a non-root container, and a GitHub Actions deploy job that authenticates through Workload Identity Federation, so no cloud key is stored anywhere. Getting it ready for the internet turned up a hole in its own API: the indexing endpoint would read any path on the server. It's now off unless an index root is configured, paths can't leave that root, and CI checks it on every push.

RAGcitationsTerraformCloud Runkeyless CI deploys69 tests

Why a similarity threshold can't refuse

  • 0.907similarity of an off-topic question
  • 0.905similarity of a relevant one

Deploy checks in CI

  • 403what the container now returns when asked to index /etc/passwd
  • 0stored cloud keys: the deploy job uses short-lived OIDC tokens

How I work

Four habits that show up in every repo.

Measure before claiming

Profile before optimising, evaluate before calling something "better". When the numbers disagree with the blog posts, I publish the numbers.

Test the real system

My worst bug passed every HTML-level test while the pricing table was invisible in the browser. Now content is only hidden for a reveal when JavaScript is running, the build fails any price not already in the HTML, and the accounts suite runs against production.

Reproducible from a clean checkout

No key, no network, no "works on my machine": every AI repo has offline fallbacks, and CI asserts it on each push.

Decisions written where the work lives

Each non-obvious choice goes in the README or commit with the measurement that settled it, so anyone can pick up a thread without a meeting.

Experience

  • Jul 2026 – present

    Founder & Lead Engineer, Solquara

    Sole engineer on a live AI video-ad and automation platform: architecture, AI pipeline, testing, deploys, incident repair.

  • 2024 – present

    Independent ML & AI Practitioner

    Self-directed ML and AI projects; the agent, voice, fine-tuning, retrieval and evaluation repos above are public and tested in CI.

  • 2016 – 2024

    Operations & Client Services, family handicraft business

    Ran daily operations with no supervisor: inventory, fulfilment, pricing, after-sales, 20+ client conversations a day. Where the ownership habits come from.

Toolkit

LLM systems
Anthropic Claude, OpenAI and Gemini APIs · LangGraph (checkpointing, human-in-the-loop) · tool calling · structured output · policy guards · MCP
Speech & ML
Streaming speech-to-text (Vosk) · text-to-speech · voice activity detection and endpointing · PyTorch · Hugging Face Transformers · LoRA (PEFT) · scikit-learn
Retrieval & evaluation
BM25, dense and hybrid search · reranking · Recall@k, MRR, nDCG · pass^k · judge calibration · paired significance tests
Backend & cloud
Python · TypeScript · FastAPI · PostgreSQL (full-text, BM25, pgvector) · SQLite / MySQL · Node.js · PHP · Docker · Terraform · Google Cloud Run · Workload Identity Federation · webhooks · crawlers and ETL
Web
TypeScript · JavaScript · WebGL / GLSL · performance profiling · GitHub Actions
Working
Remote and async · UTC+5:30, overlapping UK/EU hours or US-East mornings · contractor or EOR · English (fluent), Hindi (native)

CV

Two pages, updated Oct 2026.

The same facts as this page, laid out for an applicant tracking system: one column, plain headings, no tables.

  • Founder and lead engineer at Solquara since July 2026; eight years of operations and client work before that
  • Projects: handoff-graph, agentcheck, voice-latency, lora-intents, pg-hybrid-search, aistudio-mcp and rag-document-qa
  • Remote from Delhi (UTC+5:30) as a contractor or through an employer of record, or relocation

Your browser can't show the PDF here. Open it directly.

Contact

Hiring for AI engineering? Let's talk.

I'm looking for a remote role on a distributed team (full-time, contract or internship) building LLM products, agents, retrieval or evaluation. I can start within a week.