Question bank
Interview Questions — GenAI Coding Round
24 itemsWhat the provenance labels mean
In this bank
Round: Coding (required) · Difficulty tags relative to mid-level AI/GenAI engineer Provenance: every task below is Generated practice, modelled on a Common industry pattern (GenAI roles often mix standard data-structure questions with small LLM-flavoured implementations). None is verified company-specific.
Rules for practice: narrate the approach first (clarify → brute force → better → complexity → edge cases), write code, dry-run, then state test cases. Prefer pure Python/NumPy; no frameworks.
| # | Task | Difficulty | What it tests | Edge cases to raise | Provenance | Related lesson |
|---|---|---|---|---|---|---|
| C1 | Cosine similarity between two vectors, then top-k nearest from a matrix (vectorised) | below | NumPy, normalisation | zero vector, k > n, ties | Generated practice | Embeddings and similarity search |
| C2 | Token-aware chunker: split text into ≤N-token chunks with overlap, never mid-sentence | at | string handling, budget logic | sentence longer than N, overlap ≥ N, empty input | Generated practice | RAG architecture and chunking |
| C3 | Token budgeter: given system prompt, history, and retrieved chunks, fit within a context limit by dropping/truncating by priority | at | greedy selection, trade-offs | single chunk exceeds budget, reserve output tokens | Generated practice | Context engineering and memory |
| C4 | Minimal RAG pipeline: ingest(docs), retrieve(q,k), build_prompt using TF-IDF or fake embeddings | at | decomposition, interfaces | duplicate docs, no results, k=0 | Generated practice | The core RAG pipeline |
| C5 | Reciprocal Rank Fusion of two ranked lists | at | ranking math | disjoint lists, ties, weights | Generated practice | Better retrieval, Coding drills |
| C6 | Compute recall@k, precision@k, MRR, nDCG@k for retrieval eval | at | metric correctness | no relevant docs, k > len | Generated practice | RAG evaluation in depth |
| C7 | Retry with exponential backoff + jitter wrapper for flaky LLM/API calls (sync, then async) | at | resilience, idempotency | non-retryable errors, max elapsed | Generated practice | RAG security, reliability and release |
| C8 | LRU cache with TTL (building block for response/semantic cache) | at | data structures O(1) | expiry on read, capacity 1 | Generated practice | Cost and latency optimization |
| C9 | Parse and validate structured LLM output (JSON) with repair/retry loop | at | robustness | trailing text, wrong types, truncation | Generated practice | Reasoning models and structured outputs |
| C10 | Streaming token aggregator with stop-sequence detection across chunk boundaries | stretch | stateful parsing | stop string split across chunks | Generated practice | Not covered as a lesson in this course |
| C11 | Simple tool-calling loop with step cap and loop detection | stretch | agent control flow | repeated calls, tool errors | Generated practice | Agentic patterns: ReAct, planning and memory |
| C12 | Rate limiter (token bucket) for per-user LLM calls | at | concurrency basics | burst, clock skew | Generated practice | Not covered as a lesson in this course |
Reference approach for C1 (to check yours after attempting):
import numpy as np
def top_k(query: np.ndarray, M: np.ndarray, k: int):
q = query / (np.linalg.norm(query) + 1e-12)
Mn = M / (np.linalg.norm(M, axis=1, keepdims=True) + 1e-12)
sims = Mn @ q
k = min(k, len(sims))
idx = np.argpartition(-sims, k - 1)[:k] # O(n) selection
idx = idx[np.argsort(-sims[idx])] # sort only the k
return idx, sims[idx]Talking points: normalise once (not per query) in production; argpartition vs full sort; approximate search once brute force is too slow for your corpus (measure, do not guess a threshold).
Also keep standard DSA practice (arrays/hash maps, sliding window, heaps, graphs, DP) — GenAI interview loops often still include a general coding round (a Common industry pattern, not a guarantee).
What a strong solution covers
| # | Strong solution |
|---|---|
| C1 | Normalises once, uses a matrix product, handles zero vectors with an epsilon, clamps k, and explains partial selection versus a full sort. |
| C2 | Splits on sentence boundaries, counts tokens with the target tokenizer (not words), applies overlap by whole sentences, and says what happens to an oversized sentence. |
| C3 | Reserves output tokens first, keeps the system prompt, ranks the rest by priority, and states whether it truncates or drops a chunk that does not fit. |
| C4 | Separates ingest, retrieve and build_prompt, keeps chunk IDs for citations, and returns a clear “no results” path instead of a made-up prompt. |
| C5 | States the formula 1 / (k + rank) summed over lists with k = 60 as the usual default (see Better retrieval), uses ranks not raw scores, and handles documents missing from one list. |
| C6 | Defines each metric before coding it, handles queries with no relevant documents, and shows a tiny worked example by hand. |
| C7 | Retries only retryable errors, uses exponential backoff with jitter and a maximum elapsed time, and notes that retried calls need idempotency. |
| C8 | O(1) get and put (hash map plus ordering structure), expires on read, and says how the clock is injected for tests. |
| C9 | Parses defensively, validates against a schema, retries a bounded number of times with the error fed back, and has a fallback when output is truncated. |
| C10 | Keeps a rolling buffer so a stop string split across chunks is still found, emits only text that cannot be part of a stop string, and tests the split cases. |
| C11 | Caps steps, detects repeated (tool, arguments) pairs, returns tool errors to the model in a readable form, and stops with a useful message. |
| C12 | Refills tokens by elapsed time, allows a bounded burst, keeps one bucket per user, and discusses what a rejected call returns. |