Pattern Recognition
Template Extraction
Computational Linguistics
String Analysis
Machine Learning

Inferring templates from a collection of strings

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

Introduction

Inferring a template from many strings means finding which parts are stable and which parts vary. This shows up in log parsing, record extraction, data cleaning, and any system that needs to turn messy text into a structured pattern.

The hard part is that there is rarely one perfect template for the entire dataset. Real collections usually contain several related formats, so the job is often “cluster similar strings, then infer one template per cluster.”

Start by Tokenizing the Strings

Template inference becomes easier once the strings are broken into meaningful pieces. Depending on the domain, tokens might be:

  • words
  • punctuation separators
  • numbers
  • timestamps
  • path fragments
  • fixed keywords

For example, these strings:

  • 'user=alice status=200 latency=34'
  • 'user=bob status=404 latency=12'

clearly share a structure even though some values differ.

A simple tokenizer can split on whitespace and = signs.

python
1import re
2
3
4def tokenize(text: str):
5    return re.findall(r"[A-Za-z_]+|\d+|=", text)
6
7
8sample = "user=alice status=200 latency=34"
9print(tokenize(sample))

This produces tokens that are easier to align than raw characters.

Infer Constants Versus Variables

Once tokenized, compare strings position by position. If the same token appears in the same place across many examples, it is probably part of the template. If the token changes but still follows the same type pattern, it is a placeholder.

A simple toy inference routine looks like this:

python
1import re
2
3
4def classify(token: str) -> str:
5    if re.fullmatch(r"\d+", token):
6        return "<INT>"
7    if re.fullmatch(r"[A-Za-z_]+", token):
8        return "<WORD>"
9    return token
10
11
12def infer_template(lines):
13    tokenized = [line.split() for line in lines]
14    width = len(tokenized[0])
15    result = []
16
17    for i in range(width):
18        column = [tokens[i] for tokens in tokenized]
19        if all(value == column[0] for value in column):
20            result.append(column[0])
21        else:
22            classes = {classify(value) for value in column}
23            result.append(classes.pop() if len(classes) == 1 else "<VAR>")
24
25    return " ".join(result)
26
27
28examples = [
29    "user=alice status=200 latency=34",
30    "user=bob status=404 latency=12",
31    "user=carol status=500 latency=91",
32]
33
34print(infer_template(examples))

This kind of code is not production-grade, but it demonstrates the core idea: stable tokens stay literal, varying tokens become placeholders.

Why Clustering Usually Comes First

Consider these strings:

  • 'ERROR user=alice code=500'
  • 'INFO cache refreshed'
  • 'WARN disk=90 host=db-1'

Trying to infer one template for all three would produce something too vague to be useful. In practice, you first group similar strings by shape, keywords, or token count, then infer one template per group.

That is why log-template systems often do a first-pass clustering step based on token positions, delimiters, or approximate similarity.

Character-Level Versus Token-Level Methods

There are two broad approaches.

Token-level methods work well when delimiters are meaningful, such as logs, CSV-like text, and structured messages.

Character-level methods are useful when the format is tighter, such as IDs, dates, or serial numbers. For example:

  • 'AB-1234-X'
  • 'CD-7821-Z'

A character-level template might become AA-9999-A or a more semantic version such as <LET><LET>-<INT><INT><INT><INT>-<LET>.

The right level depends on how the strings are generated.

Choosing Placeholder Types

A good template is not just “something varies here.” It should say what kind of thing varies there.

Useful placeholder categories include:

  • integer
  • float
  • date
  • identifier
  • IP address
  • free text tail

The better your placeholder typing, the more useful the inferred template becomes for downstream validation and parsing.

Common Pitfalls

A common mistake is trying to infer one template from strings that actually belong to several formats. Cluster first, infer second.

Another mistake is tokenizing too aggressively or too weakly. If delimiters carry meaning, dropping them may destroy structure.

People also infer placeholders that are too generic, such as replacing everything with <VAR>. That loses information that could help validation later.

Finally, do not assume exact position matching is always enough. Optional fields, reordered keys, and noisy free text often require more sophisticated alignment than a simple column-by-column scan.

Summary

  • Template inference is the process of separating stable structure from varying values.
  • Tokenization is usually the first step because raw strings are too noisy to compare directly.
  • Infer constants where tokens stay fixed and placeholders where values vary systematically.
  • Cluster similar strings before inferring templates, especially for mixed-format datasets.
  • Useful templates preserve type information such as numbers, identifiers, and dates instead of replacing everything with a generic variable marker.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

All Rights Reserved.