Pipelinen parannuksia building blockeilla
This commit is contained in:
@@ -230,6 +230,144 @@ mitä luokkia importata.
|
||||
|
||||
---
|
||||
|
||||
## Rakennuspalaset vs. vapaa generointi
|
||||
|
||||
Kielimalli voi generoida koodia kahdella perustavanlaatuisesti eri tavalla.
|
||||
Ymmärtäminen milloin kumpikin toimii on avain luotettavaan koodigenerointi-pipelineen.
|
||||
|
||||
### Tapa 1: Vapaa generointi (naivi)
|
||||
|
||||
LLM generoi jokaisen tiedoston tyhjästä. Prompti kuvaa mitä halutaan,
|
||||
malli tuottaa koko tiedoston — importeista lähtien.
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
P["Prompti"] --> LLM1["LLM: models.py"]
|
||||
LLM1 --> V1{"Validointi"}
|
||||
V1 -->|virhe| LLM1
|
||||
V1 -->|ok| LLM2["LLM: schemas.py"]
|
||||
LLM2 --> V2{"Validointi"}
|
||||
V2 -->|virhe| LLM2
|
||||
V2 -->|ok| LLM3["LLM: main.py"]
|
||||
LLM3 --> V3{"..."}
|
||||
|
||||
style V1 fill:#1a1e2e,stroke:#f85149,color:#c9d1d9
|
||||
style V2 fill:#1a1e2e,stroke:#f85149,color:#c9d1d9
|
||||
style V3 fill:#1a1e2e,stroke:#f85149,color:#c9d1d9
|
||||
```
|
||||
|
||||
**Ongelma:** Pieni malli (0.5B–7B) tekee toistuvia rakenteellisia virheitä:
|
||||
|
||||
| Virhe | Esiintymistiheys | Selitys |
|
||||
|-------|:---:|------|
|
||||
| Puuttuva import | ~60% | `from datetime import date` unohtuu |
|
||||
| SQLite `connect_args` | ~80% | Malli ei muista SQLite-erityisyyttä |
|
||||
| Väärä Enum-käyttö | ~50% | Sekoittaa `sqlalchemy.Enum` ja `enum.Enum` |
|
||||
| Poetry pyproject.toml:ssa | ~40% | Malli suosii Poetryä vaikka ohje sanoo uv |
|
||||
| Testit kopioivat koko appin | ~70% | Malli ei osaa importata, luo uudet reitit |
|
||||
|
||||
Retry-loopilla (virhe → uusi yritys virheviestin kanssa) osa korjautuu,
|
||||
mutta **sama malli toistaa samoja virheitä** koska ne johtuvat harjoitusdatasta.
|
||||
7 tiedoston projekti vaatii 7–14 LLM-kutsua ja 80–120 sekuntia.
|
||||
|
||||
### Tapa 2: Rakennuspalaset (template pipeline)
|
||||
|
||||
LLM:ltä pyydetään **vain JSON-speksi** — entiteetit, kentät ja tyypit.
|
||||
Koodi kootaan mekaanisesti valmiista pohjista joiden rakenne on todistettavasti
|
||||
oikein.
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
P["Projektin kuvaus"] --> LLM["LLM: JSON-speksi"]
|
||||
LLM --> S["{ entities: [...] }"]
|
||||
S --> T1["Template: models.py"]
|
||||
S --> T2["Template: schemas.py"]
|
||||
S --> T3["Template: main.py"]
|
||||
S --> T4["Template: test_main.py"]
|
||||
S --> T5["Template: Dockerfile"]
|
||||
T1 & T2 & T3 & T4 & T5 --> D["Docker build + pytest"]
|
||||
|
||||
style LLM fill:#1a1e2e,stroke:#d29922,color:#c9d1d9
|
||||
style S fill:#1a1e2e,stroke:#3fb950,color:#c9d1d9
|
||||
style D fill:#1a1e2e,stroke:#58a6ff,color:#c9d1d9
|
||||
```
|
||||
|
||||
**Idea:** Malli on hyvä päättämään *mitä* (entiteetit, kentät), mutta huono
|
||||
muistamaan *miten* (importit, engine setup, testikonfiguraatio). Annetaan
|
||||
mallin tehdä se missä se on hyvä, ja hoidetaan loput mekaanisesti.
|
||||
|
||||
### LLM:n ainoa tehtävä
|
||||
|
||||
Malli tuottaa JSON-rakenteen kuten:
|
||||
|
||||
```json
|
||||
{
|
||||
"project_name": "todo-app",
|
||||
"entities": [
|
||||
{
|
||||
"name": "Todo",
|
||||
"table_name": "todos",
|
||||
"fields": [
|
||||
{"name": "title", "sa_type": "String(255)", "py_type": "str", "nullable": false},
|
||||
{"name": "due_date", "sa_type": "Date", "py_type": "date | None", "nullable": true},
|
||||
{"name": "status", "sa_type": "String(20)", "py_type": "str", "default": "pending"}
|
||||
]
|
||||
}
|
||||
],
|
||||
"extra_imports": ["from datetime import date"]
|
||||
}
|
||||
```
|
||||
|
||||
Tämä on yksinkertainen tehtävä jossa pienikin malli onnistuu luotettavasti:
|
||||
entiteettien tunnistus projektin kuvauksesta ja kenttätyyppien valinta.
|
||||
|
||||
### Template täyttää loput
|
||||
|
||||
Jokainen template on kuin madlib — aukot täytetään speksin datalla:
|
||||
|
||||
**models.py template (yksinkertaistettu):**
|
||||
```python
|
||||
from sqlalchemy import create_engine, Column, Integer, {sa_types}
|
||||
# ... aina samat importit, engine setup, SessionLocal ...
|
||||
|
||||
class {entity.name}(Base):
|
||||
__tablename__ = "{entity.table_name}"
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
{field.name} = Column({field.sa_type}, nullable={field.nullable})
|
||||
# ... jokainen kenttä speksistä ...
|
||||
```
|
||||
|
||||
Tulos: importit ovat aina oikein, `connect_args` on aina mukana,
|
||||
testit importoivat aina `main.py`:stä eivätkä kopioi sitä.
|
||||
|
||||
### Vertailu: mittaustulokset
|
||||
|
||||
| | Vapaa generointi | Rakennuspalaset |
|
||||
|---|:---:|:---:|
|
||||
| LLM-kutsuja | 7–14 | **1** |
|
||||
| Aika | 80–120s | **~20s** |
|
||||
| Syntaksi OK | ~70% | **100%** |
|
||||
| Docker build | vaihteleva | **100%** |
|
||||
| Pytest läpi | 0% | **100%** |
|
||||
| API toimii | ~30% | **100%** |
|
||||
|
||||
### Milloin kumpikin toimii
|
||||
|
||||
**Rakennuspalaset** kun:
|
||||
- Projektin rakenne on tunnettu (FastAPI + SQLAlchemy CRUD)
|
||||
- Laatu ja luotettavuus ovat tärkeitä
|
||||
- Malli on pieni (0.5B–7B)
|
||||
|
||||
**Vapaa generointi** kun:
|
||||
- Projektin rakenne on epätavallinen
|
||||
- Tarvitaan custom-logiikkaa jota template ei kata
|
||||
- Malli on riittävän iso (>70B tai pilvi-API)
|
||||
|
||||
Paras lopputulos syntyy yhdistelmällä: **rakennuspalaset perusrakenteelle,
|
||||
vapaa generointi business-logiikalle**.
|
||||
|
||||
---
|
||||
|
||||
## Laadun parantaminen
|
||||
|
||||
### 1. Isompi malli (suurin vaikutus)
|
||||
|
||||
Reference in New Issue
Block a user