Real-world projects

Real-world projects

A brief, open data, and named things to deliver — the way work actually arrives. Each project runs on a model on your own machine and a vector database. No API key, no account, nothing sent anywhere.

Optional and never counted. Each task has a check, and the checks are there so you know when you are done, not to score you.

Project What you build
01 — What are customers really saying? Embeddings of 958 real clothing reviews, a 2-D map of them, topics, and a "find reviews like this one" search with ChromaDB
02 — What are these companies worried about? A RAG pipeline on the risk sections of eight real annual reports, in the order a real project goes: the model alone, the raw HTML, cleaning, chunking, embedding, ChromaDB, answers with the paragraph they came from, and keyword search measured against embeddings on 20 labelled questions
03 — Did the extra agents earn their calls? Four narrow roles over project 02's filings index: a coordinator that picks the company with no model call, a researcher with read-only tools, a writer that may cite only what came back, and a critic with exactly one revision. The same team runs as a LangGraph state graph and as plain Python, routing is measured on its own against the 20 labelled questions, and the team's model calls are counted against a single loop's
04 — What went wrong on that one? The team from project 03, wrapped rather than edited, so one run records what it did in what order. Then the 20 labelled questions graded against a pass condition written down before the run, and every failure read against its own trace and put in one of five buckets, because the bucket is the thing you fix

Ask your assistant. Each project has a file your coding assistant reads first, with the project's purpose, goals and how to run it: project 01, project 02, project 03, project 04.

Before you start

uv sync --extra projects          # ChromaDB, scikit-learn, pandas, matplotlib
ollama pull nomic-embed-text      # a 274 MB embedding model
ollama pull qwen2.5:7b-instruct   # project 02 only: the model that writes the answers (4.7 GB)
uv sync --extra projects --extra agents   # project 03 also needs LangGraph

Project 02 also runs without the 7B model. Its first cell prints [live] when Ollama answers and [recorded] when it replays one real run instead, so every step still runs.

Only 8 GB of RAM? Run the model on Google Colab instead — see demos/04_ollama_on_colab.ipynb, then ollama pull nomic-embed-text there.

The ideas you need, in one page

An embedding is meaning, turned into position

An embedding model reads a piece of text and returns a long list of numbers — 768 of them for nomic-embed-text. The numbers are placed so that texts which mean similar things end up close together, even when they share no words. "Runs small" and "order a size up" land near each other.

Close means similar: cosine distance

To compare two embeddings, measure the angle between them. Cosine distance is 0 when two vectors point the same way and grows as they diverge. In Python, scipy.spatial.distance.cosine(a, b). Everything else in the project is built on this one comparison.

Nobody can look at 768 dimensions: t-SNE

t-SNE squeezes high-dimensional points down to two, trying to keep neighbours as neighbours, so you can plot them. Read the plot for neighbourhoods. The gap between two far-apart clusters means very little — t-SNE does not preserve large distances, so do not read one cluster as "twice as different" as another.

A vector database stores vectors and answers "what is nearest?"

Comparing a query against 958 reviews one at a time is fine. Against a million it is not. A vector database such as ChromaDB stores the embeddings once and finds the nearest ones quickly. You give it an embedding function, add documents with ids, and query with text.

The nearest thing to a review is that review

Search a vector database with a review that is already in it, and the first result is the review itself. Ask for one more than you need, and leave it out.

Read the whole result, and measure before you claim an improvement

A search that looks wrong from the first line of each result can be right: a review that opens with the colour of a skirt may be a complaint about its quality two sentences later. And a setting the documentation recommends is still a hypothesis about your data until you have counted what it changed.

Data and licences

Project 01 uses a sample of Women's E-Commerce Clothing Reviews, released into the public domain (CC0) on Kaggle.

Project 02 uses Item 1A, Risk Factors, from the latest annual report (Form 10-K) of eight companies, as the SEC publishes it on EDGAR. These are public filings, open for anyone to read and reuse; the companies wrote them, so they are not government works. data/sources.json gives the URL, accession number and dates of every file.

See each project's data/LICENSE.md.