TEMPLATING.md: periaatteet rakennuspalapohjaiselle koodigeneroinnille
This commit is contained in:
157
TEMPLATING.md
Normal file
157
TEMPLATING.md
Normal file
@@ -0,0 +1,157 @@
|
||||
# Templating — rakennuspalaset koodigeneroinnissa
|
||||
|
||||
## Perusperiaate
|
||||
|
||||
Kielimalli päättää **mitä** rakennetaan (entiteetit, kentät, tyypit, yhteydet).
|
||||
Template-funktiot päättävät **miten** se rakennetaan (importit, engine setup, testikonfiguraatio).
|
||||
|
||||
```
|
||||
Projektikuvaus → LLM → JSON-speksi → Templateit → Koodi → Validointi
|
||||
```
|
||||
|
||||
LLM:n kontribuutio on yksi JSON-rakenne. Kaikki muu on determinististä —
|
||||
sama speksi tuottaa aina saman koodin.
|
||||
|
||||
## Miksi tämä toimii
|
||||
|
||||
Pienen kielimallin (0.5B–7B) vahvuudet ja heikkoudet ovat epäsymmetrisiä:
|
||||
|
||||
| Tehtävä | LLM:n kyky | Ratkaisu |
|
||||
|---------|-----------|----------|
|
||||
| Tunnista entiteetit kuvauksesta | Hyvä | LLM tekee |
|
||||
| Valitse kenttätyypit | Hyvä | LLM tekee |
|
||||
| Muista importit oikein | Huono | Template tekee |
|
||||
| SQLite connect_args | Huono | Template tekee |
|
||||
| Testikonfiguraatio | Huono | Template tekee |
|
||||
| Dockerfile-rakenne | Huono | Template tekee |
|
||||
|
||||
Annetaan mallin tehdä se missä se on hyvä. Hoidetaan loput mekaanisesti.
|
||||
|
||||
## JSON-speksi
|
||||
|
||||
Kielimallin ainoa tuotos on JSON joka kuvaa projektin rakenteen:
|
||||
|
||||
```json
|
||||
{
|
||||
"project_name": "library-app",
|
||||
"entities": [
|
||||
{
|
||||
"name": "Author",
|
||||
"table_name": "authors",
|
||||
"fields": [
|
||||
{"name": "name", "sa_type": "String(255)", "py_type": "str", "nullable": false, "default": null}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Book",
|
||||
"table_name": "books",
|
||||
"fields": [
|
||||
{"name": "title", "sa_type": "String(255)", "py_type": "str", "nullable": false, "default": null},
|
||||
{"name": "author_id", "sa_type": "Integer", "py_type": "int", "nullable": false, "default": null}
|
||||
]
|
||||
}
|
||||
],
|
||||
"relationships": [
|
||||
{"from": "Book", "field": "author_id", "to": "Author", "type": "many-to-one"}
|
||||
],
|
||||
"extra_imports": []
|
||||
}
|
||||
```
|
||||
|
||||
Speksin laatu ratkaisee kaiken. Hyvä speksi → hyvä projekti. Huono speksi →
|
||||
teknisesti toimiva mutta sisällöllisesti väärä projekti.
|
||||
|
||||
## Architect-promptin rooli
|
||||
|
||||
Architect-agentti (JSON-speksin generoija) on kriittisin kohta koko pipelinessa.
|
||||
Sitä ohjataan neljällä keinolla:
|
||||
|
||||
1. **Chain-of-thought** — malli miettii ensin entiteetit, sitten kentät,
|
||||
sitten yhteydet, vasta lopuksi JSON
|
||||
2. **Domain-esimerkit** — Todo, verkkokauppa, blogi — malli näkee miltä
|
||||
hyvä speksi näyttää eri domaineissa
|
||||
3. **Anti-patternit** — turhat ID-kentät, Enum-tyypit, suomenkieliset nimet
|
||||
4. **Yhteyssäännöt** — jokainen `_id`-kenttä tarvitsee relationship-merkinnän
|
||||
|
||||
Isompi malli tässä yhdessä kohdassa parantaisi kaikkien projektien laatua.
|
||||
|
||||
## Templateit
|
||||
|
||||
Jokainen template on funktio joka ottaa speksin ja palauttaa koodia:
|
||||
|
||||
```
|
||||
tmplModels(spec) → models.py (SQLAlchemy, ForeignKey, relationship)
|
||||
tmplSchemas(spec) → schemas.py (Pydantic Create/Response/Detail)
|
||||
tmplMain(spec) → main.py (FastAPI CRUD + nested endpoints + FK-validointi)
|
||||
tmplTests(spec) → test_main.py (pytest + TestClient + helper-funktiot)
|
||||
tmplPyproject(spec) → pyproject.toml (PEP 621)
|
||||
tmplDockerfile() → Dockerfile (uv + non-root user)
|
||||
```
|
||||
|
||||
Templateit generoivat automaattisesti:
|
||||
- ForeignKey-constraintit ja relationship()-määrittelyt
|
||||
- Nested endpointit (`GET /authors/{id}/books/`)
|
||||
- FK-validointi (404 jos parent-entiteettiä ei ole)
|
||||
- Detail-schemat (Book + author-data mukana)
|
||||
- Test-helperit jotka luovat parent-entiteetit ensin
|
||||
- Bad FK -testit (varmistaa että orpo-validointi toimii)
|
||||
|
||||
## Validointi
|
||||
|
||||
Generoitu koodi validoidaan mekaanisesti ennen käyttöä:
|
||||
|
||||
- Syntaksitarkistus (AST parse)
|
||||
- Projektin sisäiset importit (löytyykö nimi lähdetiedostosta)
|
||||
- SQLite connect_args
|
||||
- Relatiiviset importit (kielletty)
|
||||
- Testien rakenne (ei saa kopioida appia)
|
||||
- pyproject.toml (ei poetryä)
|
||||
- Dockerfile (ei poetryä, uv cache -oikeudet)
|
||||
|
||||
Docker-testi ajaa koko projektin: build → pytest → API smoke test.
|
||||
|
||||
## Rajoitukset
|
||||
|
||||
Templateit kattavat rakenteellisesti tunnetut projektit:
|
||||
|
||||
| Stack | Kattavuus |
|
||||
|-------|-----------|
|
||||
| FastAPI + SQLAlchemy CRUD | Toimii hyvin |
|
||||
| Streamlit + DuckDB dashboard | Toimii hyvin |
|
||||
| Muu | Ei templatea → ei toimi |
|
||||
|
||||
**Ei kata:**
|
||||
- Custom business-logiikka (algoritmit, laskenta, ML)
|
||||
- Epätyypilliset arkkitehtuurit (WebSocket, graafit, tapahtumapohjaiset)
|
||||
- Frontend-sovellukset (React, Vue)
|
||||
- Mikä tahansa mitä template ei tunne
|
||||
|
||||
Arvio: templateit kattavat ~20% kaikista mahdollisista projekteista, mutta juuri
|
||||
sen 20% mitä opiskelu- ja prototyyppiympäristöissä tarvitaan useimmin.
|
||||
|
||||
## Laajentaminen
|
||||
|
||||
Uuden stackin lisääminen vaatii:
|
||||
|
||||
1. Uudet template-funktiot (käsityö, ~200–400 riviä per stack)
|
||||
2. JSON-speksin laajennos (uudet kentät jos tarvitaan)
|
||||
3. Validointisäännöt uudelle stackille
|
||||
4. Docker-testikonfiguraatio
|
||||
|
||||
Jokainen template on staattinen — se ei opi eikä sopeudu. Kattavuus kasvaa
|
||||
vain kirjoittamalla lisää templateja.
|
||||
|
||||
## Hybridi: seuraava askel
|
||||
|
||||
Paras lopputulos syntyisi yhdistelmällä:
|
||||
|
||||
```
|
||||
Speksi → Template (runko) → LLM (business-logiikka) → Validointi
|
||||
```
|
||||
|
||||
Template tuottaa toimivan CRUD-pohjan. LLM lisää domain-kohtaisen logiikan
|
||||
pienissä palasissa (yksi funktio kerrallaan). Mekaaninen validointi
|
||||
tarkistaa jokaisen lisäyksen.
|
||||
|
||||
Tämä palauttaa LLM:n epäluotettavuuden takaisin peliin, mutta rajattuna:
|
||||
virheet ovat paikallisia (yksi funktio) eivätkä rakenteellisia (koko projekti).
|
||||
Reference in New Issue
Block a user