Winter 2021

Building an AI Dictionary for NHSX

During my time with NHSX, I was approached to help design and build an AI dictionary.

With AI rapidly becoming a recurring driver in health care, it's important to consider that some stakeholders may not be from a tech background or familiar with common AI terms.

While attending a meeting or reading an article, it would be handy to reach for a tool to learn what a term might mean within the context of health and care.

Design

I love a side project... so it didn't take much to convince me to help out. I began working on some designs and things started to fall into place. There were a few key objectives I wanted to hit:

  • Make it keyboard navigational
  • Focus on the terms
  • Make it as minimal as possible

Homepage DesignHomepage Design

I was a bit naughty and did not follow NHS's design system. I actually think this system is great and extremely functional, which should be at the heart of any good design. However, as this was not a central service or intended to be used by the general public - I was happy I could get away with being a little more playful.

Leaning on the NHS's iconic blue, I wanted it to be bold and have nothing stand in the way of the user and the terms. A keyboard shortcut of / would trigger the search so the user didn't have to touch their mouse or trackpad to get started.

Term DesignTerm Design

Once you click to view a term, it would load into view without navigating away. We also reference it in the URL so refreshing or linking directly to a term would work too.

You can use your keyboard arrows or on-screen buttons to quickly cycle between different terms. We also added a handy "related" section.

Architecture

The system itself is dead simple. It's a Next.js project with dictionary data stored in a local JSON file.

Recoil was used for state management, although even this was a completely overkill. We could have simply imported the JSON file directly into the component and tracked the current slug with useState.

When the terms are loaded in, we do a basic title sort to get an alphabetically ordered list:

const titleSort = (a, b) => {
	if (a.name < b.name) return -1
	if (b.name < a.name) return 1
	return 0
}

For searching, we filter results first by their acronym and then by their title, description, alternative name and term code. The reason we do these separately is so the first results are what you'd call "direct matches", followed by less certain results.

const textSearch = (search, terms) => {
	// Search by acronym first
	const acronymSearch = terms
		.filter(
			(term) => term.acronym?.toLowerCase().indexOf(search.toLowerCase()) > -1
		)
		.sort(titleSort)
 
	// Search by other fields
	const otherSearch = terms
		.filter(
			(term) =>
				term.name.toLowerCase().indexOf(search.toLowerCase()) > -1 ||
				term.description.toLowerCase().indexOf(search.toLowerCase()) > -1 ||
				term.termCode.toLowerCase().indexOf(search.toLowerCase()) > -1 ||
				term.alternateName?.toLowerCase().indexOf(search.toLowerCase()) > -1
		)
		.sort(titleSort)
 
	// Merge and remove duplicates
	return [...new Set([...acronymSearch, ...otherSearch])]
}

Data

As mentioned, the "database" was a local JSON file. The project was to be open-sourced and data crowd sourced. Storing data in a local file meant users could simply open a PR and edit the JSON file to modify or suggest new terms. Sometimes the simplest solution is the best.

A corresponding JSON schema was also added with automated tests to ensure any changes matched the correct structure.


I love working on tiny projects like this. It's the perfect way to get a much needed distraction if you're working on something else long term. It can also be a source of inspiration. Perhaps there's a new package you've been wanting to try out or you want to play with some design ideas without worrying how it fits into a bigger picture.

Feel free to have a look at the source code or visit the app.