Documentation updates (#236)

Remove vague or flowery language, use Simplified Technical English whenever possible
This commit is contained in:
Aaron Po
2026-08-04 09:38:24 -04:00
committed by GitHub
parent 3087d599ae
commit a4da01586d
10 changed files with 272 additions and 250 deletions

View File

@@ -1,28 +1,28 @@
# Ethics, Bias, and Known Issues
# Ethics, bias, and known issues
This document covers the ethical context of the Biergarten Pipeline's output,
the model's biases, and known issues including hallucinated brewing science and
low-resource language failures.
> Note that all testing was used using `google_gemma-4-E4B-it-Q6_K.gguf`.
> All testing described below used `google_gemma-4-E4B-it-Q6_K.gguf`.
## Table of Contents
## Table of contents
- [What This Dataset Is](#what-this-dataset-is)
- [What This Dataset Is Not](#what-this-dataset-is-not)
- [Model Bias and Language Quality](#model-bias-and-language-quality)
- [Western and Eurocentric Lens](#western-and-eurocentric-lens)
- [Wikipedia Enrichment](#wikipedia-enrichment)
- [Names-by-Country Dataset](#names-by-country-dataset)
- [The "Avoid AI Phrases" Prompt Instruction](#the-avoid-ai-phrases-prompt-instruction)
- [Known Issues](#known-issues)
- [Hallucinated Brewing Techniques](#hallucinated-brewing-techniques)
- [Low-Resource Language Hallucination](#low-resource-language-hallucination)
- [Synthetic Postal Codes](#synthetic-postal-codes)
- [What this dataset is](#what-this-dataset-is)
- [What this dataset is not](#what-this-dataset-is-not)
- [Model bias and language quality](#model-bias-and-language-quality)
- [Western and Eurocentric lens](#western-and-eurocentric-lens)
- [Wikipedia enrichment](#wikipedia-enrichment)
- [Names-by-country dataset](#names-by-country-dataset)
- [The "avoid AI phrases" prompt instruction](#the-avoid-ai-phrases-prompt-instruction)
- [Known issues](#known-issues)
- [Hallucinated brewing techniques](#hallucinated-brewing-techniques)
- [Low-resource language hallucination](#low-resource-language-hallucination)
- [Synthetic postal codes](#synthetic-postal-codes)
---
## What This Dataset Is
## What this dataset is
This is AI-generated fixture data for a proof-of-concept version of The
Biergarten App. Anyone who interacts with an application seeded from this
@@ -30,29 +30,29 @@ pipeline must be told upfront that the content is AI-generated.
---
## What This Dataset Is Not
## What this dataset is not
The pipeline is not intended to produce accurate brewing science, faithful
cultural representation, or reliable local-language text. Hallucinations such as
invented fermentation techniques, or incoherent local-language prose, are
expected, observed, and partially documented in [Known Issues](#known-issues)
expected, observed, and partially documented in [Known issues](#known-issues)
below.
Human control sits at the context layer (i.e. prompt design, Wikipedia
Human control sits at the context layer (that is, prompt design, Wikipedia
enrichment). Statistical output shapes in future pipeline stages (check-in
distributions, rating skews, activity profiles) will be handled the same way.
**Treat this data as an exercise in prompt engineering and model behaviour, not
as a source of truth for brewing techniques or cultural representation.**
**Natural language processing, although a powerful tool for data analysis and
generation is to be taken with scrutiny. Human language is not simply just data
points to be analyzed, but it also carries deep cultural and human meaning that
artificial intelligence is incapable of.**
**Natural language processing is a powerful tool for data analysis and
generation, but its output should be treated with scrutiny. Human language is
not simply data points to be analyzed — it carries cultural and human meaning
that artificial intelligence cannot capture.**
---
## Model Bias and Language Quality
## Model bias and language quality
The underlying model's training biases surface within this pipeline. Output
quality tracks with how well a language is represented in the training corpus:
@@ -67,9 +67,9 @@ large language models trained predominantly on English-language
material.[^llm-bias]
Mitigations are documented in
[Known Issues: Low-Resource Language Hallucination](#low-resource-language-hallucination).
[Known issues: Low-resource language hallucination](#low-resource-language-hallucination).
### Western and Eurocentric Lens
### Western and Eurocentric lens
The model's training data skews heavily Western and North American. When
generating brewery descriptions for Kinshasa, Abidjan, or Osaka, for example, it
@@ -81,19 +81,19 @@ some generation in city-specific material, but it does not eliminate the skew.
---
## Wikipedia Enrichment
## Wikipedia enrichment
City and beer context is fetched from the Wikipedia API. Wikipedia text is
co-licensed under the **Creative Commons Attribution-ShareAlike 4.0
International License (CC BY-SA 4.0)** and the **GNU Free Documentation License
(GFDL)**.[^wp-license]
International License (CC BY-SA 4.0)**[^cc-sa] and the **GNU Free Documentation
License (GFDL)**.[^wp-license]
Wikipedia's own accuracy limitations and editorial biases can propagate into
generated descriptions.
---
## Names-by-Country Dataset
## Names-by-country dataset
`tooling/pipeline/forenames-by-country.json` and `surnames-by-country.json`
(used to sample a `Name` per ISO 3166-1 country code for user generation) are
@@ -118,7 +118,7 @@ same way brewery generation skips cities whose enrichment lookup fails.
---
## The "Avoid AI Phrases" Prompt Instruction
## The "avoid AI phrases" prompt instruction
The system prompt instructs the model to avoid common AI-generated phrasing
patterns. This is a prompt engineering experiment:
@@ -130,14 +130,14 @@ consumers are informed of the AI-generated origin before engagement.
---
## Known Issues
## Known issues
### Hallucinated Brewing Techniques
### Hallucinated brewing techniques
When forced by the system prompt to generate a "highly specialized technical
brewing detail," the model frequently hallucinates fermentation science and
brewing chemistry. While the resulting sounds confident, it will be nonsensical
to reader with brewing and/or scientific expertise.
brewing chemistry. While the resulting text sounds confident, it is
nonsensical to a reader with brewing or scientific expertise.
Small-parameter models such as Gemma 4 E4B cannot reliably satisfy prompts
calling for specialist brewing detail. This is consistent with the **CHOKE**
@@ -155,9 +155,9 @@ and factually wrong output.
[2026-04-21 15:04:40.258] [info] brewery_description_local="早朝の、たこ焼きや香ばしいイカ焼きの湿った匂いは、いつも乾燥小屋の外にある使用済み麦芽の金属的な匂いと奇妙に混ざり合って近隣に漂います。私たちはこの場所に店を構えることを決めたのです。なぜなら、大阪は決して止まることのない都市であり、商品と味が絶え間なく交換されることで築かれた場所だからです。地元の多くの方々は、信頼できる大規模な淡麗ラガーの味が習慣になっていますが、私たちは発酵の、より深く、より複雑な表現を探求することに関心があります。私たちのベースモルトは、山田錦のような地元の米の品種を意図的に組み込んで作られています。この米を酒ではなく、麦芽として、仕込みの最中にその複雑でバターのような風味を引き出すために使用しています。この組み合わせを、ゆっくりとした嫌気的な熟成プロセスに続けることで、私たちのビールは、慌ただしい市場のスタイルとは一線を画す、深みのある、満足感のある複雑さを持っています。オリジナルの倉庫の重く深紅のレンガ壁は、関西特有の湿気と季節の雨を何十年も吸収し、この地区の絶え間ない動きの正確な物語を語るような古色を帯びています。私たちはこの構造物を、その魅力のためではなく、その回復力とモルタルに込められた地域の歴史の密度ゆえに選びました。私たちの目標は、ただこの力強い交易都市に値する飲み物を提供することだけです。もしメインの通りから離れた静かな場所をお探しなら、新世界近くの脇道にある私たちを探してください。"
```
A review of the following text for brewing techniques reveals several
inaccuracies, and no comments could be made on the local-language version due to
my own lack of proficiency in Japanese:
A review of the following text for brewing techniques reveals three
inaccuracies. No comments are made on the local-language version, since its
reviewer does not read Japanese:
#### 1. "Buttery flavours" framed as a desirable malt-derived flavour
@@ -191,7 +191,7 @@ fermentable sugars.[^yn-sakeonline]
**Misleading**
Anaerobic conditions during packaging and aging are not differentiating
Anaerobic conditions during packaging and aging are not a differentiating
technique. Anaerobic conditions are the standard baseline for all commercial
beer production. Breweries exclude oxygen as a top priority for packaging and
shelf stability; published research in _Microbiology Spectrum_ confirms that
@@ -200,7 +200,7 @@ Professional packaging lines use CO_2 purges and closed transfers specifically
to maintain this state.[^packaging] Framing anaerobic aging as a distinctive
practice is misleading and suggests hallucinated output.
### Low-Resource Language Hallucination
### Low-resource language hallucination
The generation pipeline passes local language codes to the model to retrieve a
translated `description_local`. Output quality is reliable for high-resource
@@ -262,9 +262,9 @@ idiomatic phrasing.
]
```
This dataset, when fed into the pipeline will often times reason that a local
variant of French is needed, but will often times just default to a standardized
dialect of French, devoid of any cultural or linguistic nuance.
When fed into the pipeline, this dataset often causes the model to reason that
a local variant of French is needed, but it often defaults to a standardized
dialect of French, without cultural or linguistic nuance.
For languages such as Welsh (Wales), Māori (Aotearoa/New Zealand), or Sicilian
(Sicily, Italy), the model can generate text that looks syntactically plausible
@@ -273,7 +273,7 @@ rather than prompt engineering.
Output sample: [./french-cities.example](french-cities.example)
#### Proposed Mitigations
#### Proposed mitigations
- **Prevention via allowlist:** introduce a high-resource language allowlist. If
a location's code is unlisted, skip `description_local` generation and fall
@@ -284,7 +284,7 @@ Output sample: [./french-cities.example](french-cities.example)
SQLite schema so downstream applications can filter or flag potentially
hallucinated text by language tier.
### Synthetic Postal Codes
### Synthetic postal codes
When the pipeline is run without `--mocked`, `XegerPostalCodeService` generates
a fresh postal code per brewery/user address by reverse-matching one of the
@@ -312,7 +312,7 @@ not a source of truth.
Simhi, Itay Itzhak, Fazl Barez, Gabriel Stanovsky, Yonatan Belinkov.
[^llm-bias]:
e.g., Blasi et al. (2022), "Systematic Inequalities in Language Technology
For example, Blasi et al. (2022), "Systematic Inequalities in Language Technology
Performance across the World's Languages," _ACL Anthology_. The pattern is
consistent with models trained predominantly on English-language web
corpora.

View File

@@ -14,8 +14,8 @@ deterministic mock.
## Table of Contents
- [How It Fits The Main App](#how-it-fits-the-main-app)
- [Quick Start](#quick-start)
- [How it fits the main app](#how-it-fits-the-main-app)
- [Quick start](#quick-start)
- [Build](#build)
- [Model](#model)
- [Run](#run)
@@ -24,17 +24,17 @@ deterministic mock.
- [Pipeline Stages](#pipeline-stages)
- [Key Components](#key-components)
- [Runtime Behaviour](#runtime-behaviour)
- [Generated Output](#generated-output)
- [Tech Stack](#tech-stack)
- [Tested Hardware](#tested-hardware)
- [Fixture Strategy](#fixture-strategy)
- [Repo Layout](#repo-layout)
- [Code Tour](#code-tour)
- [Next Steps](#next-steps)
- [Generated output](#generated-output)
- [Tech stack](#tech-stack)
- [Tested hardware](#tested-hardware)
- [Fixture strategy](#fixture-strategy)
- [Repo layout](#repo-layout)
- [Code tour](#code-tour)
- [Next steps](#next-steps)
---
## How It Fits The Main App
## How it fits the main app
The pipeline is a data ingestion layer. It sits outside the web app runtime and
produces seed records the app imports at startup or during a dedicated seed
@@ -50,7 +50,7 @@ step.
---
## Quick Start
## Quick start
### Build
@@ -99,13 +99,13 @@ Each run writes a fresh dated SQLite file such as
--temperature 1.0 --top-p 0.95 --top-k 64 --n-ctx 8192 --seed -1
```
#### CLI Flags
#### CLI flags
| Flag | Purpose |
| ------------------ | ---------------------------------------------------------------------------------------------------- |
| `--mocked` | Deterministic mock generator, no model required. |
| `--model, -m` | Path to a GGUF file. Required unless `--mocked` is set. |
| `--prompt-dir` | Directory containing prompt files (e.g. `BREWERY_GENERATION.md`). Required unless `--mocked` is set. |
| `--prompt-dir` | Directory containing prompt files (for example, `BREWERY_GENERATION.md`). Required unless `--mocked` is set. |
| `--output, -o` | Directory for generated SQLite artifacts. Default: `output`. |
| `--log-path` | Path for application logs. Default: `pipeline.log`. |
| `--location-count` | Number of cities to sample from `locations.json` per run. Default: `10`. |
@@ -176,7 +176,7 @@ output to confirm the fast path was taken.
### Run the container
The container always runs the model-backed path; there is no `--mocked`
container mode (use a native build for that — see [Quick Start](#quick-start)).
container mode (use a native build for that — see [Quick start](#quick-start)).
The entrypoint, `runpod/start.sh`, downloads the GGUF model automatically if it
is not already present at the configured path.
@@ -218,7 +218,7 @@ environment variables listed above to match your run.
## Architecture
### Pipeline Stages
### Pipeline stages
| Stage | Implementation |
| ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
@@ -234,7 +234,7 @@ If name sampling, enrichment, or generation fails for a city, that city is
skipped and the pipeline continues. `GenerateUsers()` runs before
`GenerateBreweries()` in `BiergartenPipelineOrchestrator::Run()`.
### Key Components
### Key components
- `src/main.cc` — argument parsing and Boost.DI composition root.
- `CuratedJsonDataService` — implements `ICuratedDataService`; takes a
@@ -260,7 +260,7 @@ skipped and the pipeline continues. `GenerateUsers()` runs before
LLM-generated username/bio/activity weight, and a programmatically generated
(not LLM-authored) unique email and date of birth.
### Runtime Behaviour
### Runtime behaviour
`WikipediaEnrichmentService` fetches two Wikipedia extracts per city: a generic
"brewing" extract and a "beer in `{country}`" extract. It does not currently
@@ -290,17 +290,17 @@ absent from either name fixture (currently `KE`, `SE`, `SG`, `TH`, `VN`, `ZA`)
are skipped, the same way a failed enrichment or generation call skips a city —
see ETHICS-AND-KNOWN-ISSUES.md's Names-by-Country Dataset section.
### Process Flow - Activity Diagram
### Process flow - activity diagram
![An activity diagram](./diagrams/current/output/activity.svg)
### Architectural Overview - Class Diagram
### Architectural overview - class diagram
![A class diagram](./diagrams/current/output/class.svg)
---
## Generated Output
## Generated output
Each successful run stores a `BreweryRecord` pair with the source location and a
`BreweryResult` payload, and a `UserRecord` pair with the source location and a
@@ -328,7 +328,7 @@ SQLite export file named with the current UTC timestamp.
The log dump also includes city, country, state or province, ISO subdivision
code, latitude, and longitude for each entry.
### Consumer Data Shape
### Consumer data shape
| Field | Why it matters |
| ----------------------------------- | ------------------------------------------------ |
@@ -341,7 +341,7 @@ code, latitude, and longitude for each entry.
---
## Tech Stack
## Tech stack
- C++20
- CMake 3.31+
@@ -363,7 +363,7 @@ Silicon; CUDA or HIP/ROCm is detected on Linux when the toolkit is present.
---
## Tested Hardware
## Tested hardware
### ARM macOS — M1 Pro
@@ -398,7 +398,7 @@ Silicon; CUDA or HIP/ROCm is detected on Linux when the toolkit is present.
---
## Fixture Strategy
## Fixture strategy
- `--mocked` for stable fixtures, repeatable screenshots, and Storybook runs.
`MockCuratedDataService` swaps in for `CuratedJsonDataService`, so no fixture
@@ -414,7 +414,7 @@ Silicon; CUDA or HIP/ROCm is detected on Linux when the toolkit is present.
---
## Repo Layout
## Repo layout
| Path | Purpose |
| -------------------------------------------- | ----------------------------------------------------------- |
@@ -431,7 +431,7 @@ Silicon; CUDA or HIP/ROCm is detected on Linux when the toolkit is present.
---
## Code Tour
## Code tour
Paths below are relative to `tooling/pipeline/`.
@@ -450,7 +450,7 @@ Paths below are relative to `tooling/pipeline/`.
---
## Next Steps
## Next steps
The pipeline currently produces city-aware brewery and user records and dated
SQLite exports. The next passes add additional fixture types so the app can
@@ -458,7 +458,7 @@ exercise the full brewery and social domains without live data. For the detailed
engineering breakdown of what's needed to reach the architecture in
[`diagrams/planned/`](./diagrams/planned/), see [ROADMAP.md](./ROADMAP.md).
### Testing — Very High Priority
### Testing — very high priority
- Unit test JSON validation and retry logic against malformed, truncated, and
empty model outputs.
@@ -472,19 +472,19 @@ engineering breakdown of what's needed to reach the architecture in
- Confirm the retry path is reachable when the reasoning block consumes
available token budget.
### Beer Generation
### Beer generation
Generate catalog entries with style, ABV, IBU, color, aroma notes, and food
pairing hints. Link beers back to breweries and cities. Keep style coverage wide
enough to exercise search, sort, and category filters.
### Check-In System
### Check-in system
Produce timestamped check-in events between users and breweries. Use a J-curve
activity profile — a small set of users accounts for most check-ins, the rest
appear occasionally. Add bursty behaviour around weekends and travel periods.
### Beer Ratings
### Beer ratings
Generate rating events with a strong positive skew and a long tail of lower
scores. Avoid uniform distributions. Attach timestamps and user IDs so the app