Mijn programmeerervaringen met Claude AI

,

Streets

Al een tijd was ik bezig met een programmeerproject: ik wilde een Patience spelletje (Streets) maken en dat voorzien van een heuristische solver die het spel waar mogelijk stap voor stap automatisch tot een oplossing zou brengen. Het leek me een leuke uitdaging om dit met behulp van AI te programmeren in de taal Python.

Er zijn verschillende  varianten van Streets, maar ik beschrijf hier alleen deze ene  variant.  Deze versie is beschikbaar gemaakt als freeware door David Mayne (figuur 1) en heb ik opgeduikeld met behulp van de Way Back Machine (https://web.archive.org/web/20170725005933/http://davidmayne.com/https://web.archive.org/web/20170725005933/http://davidmayne.com/).

Afbeelding1streets

Figuur 1: afbeelding van de  Streets variant van David Mayne

Zoals de meeste Patience spelletjes is Streets een sorteerspel met handicaps. Bij Streets begin je met twee spellen met 52 kaarten van Aas tot Heer. Het uiteindelijke doel van het spel is om de kaarten vanaf de Aas tot en met de Heer te sorteren  in 2 x 4 = 8 basis stapels naar de kaartsoorten Klaver, Ruiten, Harten en Schoppen. In dit geval zijn de handicaps 1. Veertig ongesorteerde kaarten die zichtbaar zijn in 10 tableaus van ieder 4 kaarten en 2. Vierenzestig ongesorteerde kaarten die onzichtbaar zijn (voorraad stapel) en een voor een omgedraaid kunnen worden naar een aflegstapel waarvan alleen de bovenste kaart zichtbaar is. Tijdens het spel kunnen de ongesorteerde kaarten van de aflegstapel en de 10 tableaus gesorteerd worden in de 10 tableaus, maar deze sortering is op afwisselende kleur en aflopende  rangorde van de kaarten (bijvoorbeeld: 7H, 6S, 5R, 4K).

Ik heb gewerkt met Claude 4.6 van Antropics. Claude staat bekend als de beste AI-omgeving voor programmeren. Ik had een standaardcontract, waarbij je voor een klein bedrag (€ 21,50 per maand) gebruik kunt maken van het taalmodel Claude.

Spelregels Streets

Streets wordt gespeeld met 2 x 52 kaarten van Aas tot Koning. Deel 40 geschudde kaarten om ​​tableaus te vormen van 10 x 4 zichtbare kaarten.

De 64 resterende geschudde kaarten zijn onzichtbaar in een voorraad stapel, waarvan er telkens 1  zichtbaar gemaakt wordt en op een aflegstapel worden gelegd.

Basiskaart: Aas. Het doel van het spel is om alle kaarten te sorteren in 8 basisstapels van Aas tot Koning op symbool, dus 2 * Klaver, Ruiten, Schoppen, Harten.

Bouw verder op de tableaus in aflopende volgorde en wissel van kleur. Alleen de bovenste zichtbare kaarten mogen worden verplaatst naar een andere tableau stapel als daarvan de bovenste kaart een andere kleur heeft en een rangorde die 1 hoger is. Elke kaart kan een lege plek vullen in de tableau stapels.

Als er een Aas zichtbaar wordt kan deze verplaatst worden naar de juiste basisstapel. Daarbovenop kan vervolgens een 2 geplaatst worden, enzovoorts tot de Koning. Het spel eindigt als op alle basisstapels de Koning ligt.

Eerste ervaringen
De eerste stap was om het spel zelf te maken. Dat ging razendsnel: binnen een beperkt aantal uren had ik een visuele omgeving waarmee ik het spel kon spelen (figuur 2).

Ik moet zeggen: ik was wild enthousiast. Het ging gemakkelijk en als ik zelf de code had moeten schrijven was ik vele dagen langer zoet geweest met coderen en debuggen. Het ging min of meer van een leien dakje. Ik gaf Claude de spelregels en wat extra uitleg hoe het eruit moest zien en de code was er binnen de kortste keren. Het was niet direct perfect en er moesten wel wat fouten gecorrigeerd worden, maar toch: razendsnel resultaat. Wel een paar opmerkingen. Een: van dit soort kaartspelletjes zijn er talrijke voorbeelden in het public domain op het internet te vinden en aangezien dit soort AI programma’s gevoed zijn vanaf het internet mag verwacht worden dat ook Claude hier  mee bekend is. Twee: ik liep wel aan tegen fabulatie. Claude had geheel zelfstandig een eigen sorteer regel ontwikkeld: hij dacht dat kaarten op het tableau gesorteerd moeten worden op kaartsoort en rangorde. Die instructie had ik niet gegeven en de juiste regel moest uitdrukkelijk opnieuw gegeven worden: sorteer op afwisselende kleur en rangorde. Maar al met al: razend snel een goed werkend programma. Aardig was ook dat bij dit spel de mogelijkheid werd toegevoegd om een spel opnieuw te spelen en met behulp van een getal een bepaald spel opnieuw opgeroepen kon worden.

Afbeelding2streets

Figuur 2: Streets programma in Python

Tweede fase: de solver
Ik kwam er al snel achter dat de tweede fase een ander verhaal werd. Het grote verschil met de eerste stap is dat zo’n solver geen platgetreden pad is. Het vereist de constructie van verschillende, relatief complexe beslissingsbomen. Er zijn mij geen voorbeelden van bekend op het internet, niet commercieel en zeker niet als freeware. De constructie van de code vereist dus wel wat. Wat ik niet verwacht had maar wat wel gebeurde, is dat ik hiermee wel op de grens liep van wat AI op dit moment kan.

Ik begon met een beschrijvend ontwerp van de solver in gewone taal en met de vraag aan Claude of dit duidelijk genoeg was. Na enig heen en weer praten kwamen Claude en ik tot een ontwerp waarmee Claude aan de slag kon. De eerste codering werkte best aardig maar had tekortkomingen waardoor het niet tot een oplossing voor het spel kon komen, ook niet van spellen die ik zelf betrekkelijk eenvoudig kon oplossen met de benodigde heuristische stappen. Onverwacht was voor mij dat Claude een beginnersfout maakte: een one-off programmeerfout. Python werkt met rangordes vanaf 0 en niet vanaf 1. Een routine produceerde daardoor een rangordesom van 0 zowel voor een lege stapel kaarten en voor een stapel van een Aas die dus ook rangorde som 0 had. Simpel op te lossen, maar ik verwachtte dit probleem niet van AI.

Noch het debuggen, noch het toevoegen van nieuwe heuristische stappen ging van een leien dakje. Na enige weken werken met Claude heb ik nog steeds geen goed werkende solver. Omdat ik knettergek werd van Claude heb ik besloten om de fouten er verder maar zelf uit te halen. Waarom ik knettergek werd van Claude zal ik hieronder uitleggen. Het was regelmatig een uiterst frustrerende ervaring.

  1. Fabulatie. Dit was ik al eerder tegen gekomen bij de constructie van het basisprogramma. Toch was deze nieuwe ervaring onverwacht. Het bleek bij het debuggen dat Claude soms volkomen onjuiste uitgangspunten bedacht en daar dan razendsnel verder op redeneerde. Die onjuiste uitgangspunten kwamen onder meer door het niet zorgvuldig lezen van screenshots, waardoor de fout niet goed geanalyseerd werd. Een andere basis was de onjuiste interpretatie van regels. In dit spel zijn er twee sorteringsregels, een voor de basisstapels (per kaartsoort oplopende rangorde) en een ander voor de tableaus (afwisselende kleur en aflopende rangorde). Claude kan nogal hardnekkig een verkeerde regel hanteren. Wat ook een rol speelde, en hier moet ik eerlijk zijn: gebrekkige of zelfs onjuiste informatie mijnerzijds. Dit laatste probleem speelde zeker ook een rol, maar de eerste twee kwamen veel vaker en hardnekkiger voor.
  2. Vergeetachtigheid. Dit was het meest onverwacht. Claude kan een tijd helemaal zoals bedoeld opereren en dan opeens iets vergeten zijn. Zo had ik Claude op een gegeven ogenblik geïnstrueerd dat hij alleen Python-code mocht wijzigen na instemming mijnerzijds. Dat gaat dan een tijdje goed, maar op een gegeven ogenblik ging hij toch weer zonder instemming code produceren. En dat wil je absoluut niet als de uitgangspunten verkeerd zijn. Een andere vorm van vergeetachtigheid is dat Claude vergeten is wat hij enkele uren daarvoor nog volledig correct heeft uitgevoerd en nu spontaan iets doet wat niet correct is. Het resultaat is dat ik nu met een 40-tal verschillende versies zit, waarbij bij de ene versie iets goed gaat maar iets anders fout, en bij een andere versie na een debug die fout er uit gehaald is, maar nu iets fout gaat wat in de vorige versie nog correct werd afgehandeld. Een derde vorm van vergeetachtigheid is dat de context vergeten wordt. De context is de conceptualisatie van het programma, maar ook mijn eigen wensen als programmeur en mijn wensen voor de interactie tussen mijzelf en Claude. Zo kwam ik er op een gegeven ogenblik achter dat de regels van het spel niet langer toegepast werden, zodat het programma fundamenteel onjuist was gaan werken. Het lijkt er op dat die context telkens opnieuw gegeven moet worden. Het frustrerende hier is dat het urenlang goed gaat en dan opeens niet meer. Er is geen aankondiging van die vergeetachtigheid.
  3. Geen terugkeer naar een uitgangspunt. Na vaststelling van fabulatie of vergeetachtigheid wil je graag terug naar een uitgangspunt waarbij de boel nog correct werkte. Het terugzetten van stappen blijkt een probleem te zijn. Eén keer had ik versie 30, na een debug met verkeerde uitgangspunten had Claude v31 van de code gegenereerd. Na instructie dat een en ander onjuist was en weer teruggedraaid moest worden, ging Claude versie 32 aanmaken op basis van versie 31, waarin dus de nodige fouten geslopen waren. Terug naar versie 30 bleek een probleem te zijn. Claude had daar geen administratie van, maar bouwt vrolijk verder op de laatste versie, juist of niet.
  4. Output spugen. Zoals gezegd produceert Claude razendsnel output en dat is een groot plezier als de uitgangspunten juist zijn. Als er echter een denkfout gemaakt wordt wil je dat stopzetten. Het detecteren van zo’n denkfout is echter geen sinecure, aangezien Claude aanmerkelijk sneller tekst genereert dan ik als mens kan lezen. Claude produceert veel output, heel erg veel output.  Instructies om dat te beperken tot hoofdlijnen, veronderstellingen, conclusies werken niet, niet geweldig of slechts tijdelijk. De tekst productie is niet bij te benen. Ook de code productie is groot. Duizend nieuwe regels zijn binnen enkele minuten geproduceerd. Prachtig als alles goed werkt, maar als je het zorgvuldig door moet lezen op mogelijke fouten dan kost dat zeeën van tijd. Zelfgeproduceerde code is betrekkelijk snel te lezen, maar als je code van een ander door moet nemen (ook bij een menselijke collega), dan kost dat aanzienlijk meer tijd.
  5. Hardnekkigheid en overgeneralisatie. Bij de solver moeten uiteenlopende beslissingsbomen opgezet worden. Die verschillen soms subtiel, maar soms moeten ook tegengestelde regels toegepast worden. Het onderscheid tussen verschillende stappen blijkt lastig voor Claude te zijn. Hoewel ik geprobeerd heb die stappen duidelijk te onderscheiden, bleek Claude graag een beslissingsregel die in eerste stap werkte opnieuw in een volgende stap toe te passen. Het plaatsen van een kaart op een lege plek kan uiteraard, maar als een serie kaarten verplaatst moet worden, bleek Claude nog steeds te rekenen met éen kaart per lege plek, ook na uitleg dat het correcte aantal 2 tot de macht van het aantal lege plekken was. Nog moeilijker bleek de omkering van een beslissingsregel te zijn. Zo bleek het toevoegen van een kaart aan de bodem van een (nieuwe) stapel een probleem te zijn, omdat dezelfde regel werd toegepast die geldig was voor het toevoegen van een kaart aan de top van een stapel. Eerst had ik dat probleem niet in de gaten, maar toen ik eenmaal doorhad dat dat het probleem was, kostte het vrij veel moeite om duidelijk te maken dat hier een tegengestelde beslissingsregel toegepast moest worden.
  6. Gebrek aan zelfkennis. Claude heeft geen inzicht in de eigen sterke en zwakke kanten en kan stevig  doordraven  in een verkeerde richting. Toegegeven: zelfkennis is ook geen alomtegenwoordige eigenschap bij mensen. Maar Claude kan soms een zekere hardnekkigheid tonen en dat is lastig. Vooral ook omdat Claude soms uitstekend werk kan afleveren en dan opeens broddelwerk op basis van verkeerde uitgangspunten. Ook als gebruiker is het niet eenvoudig om te zien wanneer Claude goed werk aflevert en wanneer werk met problematische fouten.
  7. Het is geen mens. Om te leren werken met AI moet je goed in de gaten hebben dat je niet met een mens te maken hebt. Soms zijn dingen gemakkelijk voor een mens te zien, maar lastig voor een computer. Ik heb al genoemd dat het foutloos lezen van een screenshot voor een computer niet gemakkelijk is, terwijl een mens dat in een oogopslag zou kunnen. Ook het essentiële verschil tussen een bodemkaart en een topkaart hoef je aan een mens nauwelijks uit te leggen, maar voor een AI machine is dat lastiger en moet dat verschil herhaaldelijk geëxpliciteerd worden.

Al met al heb ik nog steeds niet de solver die ik hebben wil. Het zit er dicht tegenaan, maar het is nog niet waar ik het hebben wil. Ik ga eerst de code die ik nu heb doorpluizen en debuggen zonder AI. Met Claude draai ik nu al te lang in cirkeltjes rond. Fouten er uit halen zonder nieuwe fouten te introduceren blijkt lastig te zijn.

Ik heb er wel veel van geleerd en heb voor mezelf enig inzicht verkregen wat ik wel en wat ik niet kan verwachten van AI. Een programma als Claude heeft veel duidelijkheid nodig en de benodigde duidelijkheid moet vooral niet onderschat worden. Een andere conclusie is dat je die duidelijkheid ook herhaaldelijk moet verschaffen. In tegenstelling tot wat je zou verwachten bij gecomputeriseerde intelligentie, heeft AI een gebrekkig geheugen.

Wat kun je van AI verwachten? Duidelijk is dat als er veel bestaande, goedwerkende code is, AI dat voortreffelijk toepast. Daar zit belangrijke winst. Bijvoorbeeld het maken van een grafische gebruiksomgeving is iets wat met AI snel en goed mogelijk is.

Een aantal van bovengenoemde problemen zullen wel opgelost worden, maar niet alle. Als je nieuwe betrekkelijk unieke code nodig hebt, reken dan niet op AI. Daarbij kun je er niet van uitgaan dat AI iets begrijpt of doorheeft. Zelfs als AI correcte code heeft gecreëerd op een plek, kan het nog heel goed zo zijn dat het op een andere plek niet goed gaat. De AI taalmodellen zijn niet creatief en leren niet van het toepassen principes of van een (nieuwe) formule, maar een taalmodel leert van het toepassen van veel correcte voorbeelden.  Bij het creëren van nieuwe, betrekkelijk unieke code is vooral het telkens herhalen van instructies nodig en dat is iets waar het moeilijk is om aan te wennen. Wij mensen zijn er aan gewend dat een ander mens iets leert en doorheeft en het dan een volgende keer correct toepast. Reken daar niet op bij AI.

'Meld je aan voor de nieuwsbrief'

'Abonneer je nu op een of meerdere van onze nieuwsbrieven en blijf op de hoogte van onze activiteiten!'

Aanmelden