Palasin hiljan oman AI-omavaraisuuteni kehittämiseen. Kirjoitin edellisessä kirjoituksessani AI-omavaraisuuden ensimmäisistä askelista: miksi se kannattaa, mitä kotiin tai toimistoon pitää hankkia ja mistä avoimia kielimalleja saa. Postauksen jälkeen olen tutkinut asiaa aktiivisesti työympäristössä: ohjelmistokehityksestä AI-avusteisesti lokaalien kielimallien avustuksella.
Työ on ollut mielenkiintoista ja ajatuksia herättävää, kuten aina. Ajattelin kuitenkin käyttää näitä ponnistelujani kehyskertomuksena esitelläkseni tiettyä tekoälyaihetta, joka on tällä hetkellä koko kenttää läpäisevä ja huikaisevan tärkeä tekoäly-yleissivistyksen kannalta: kielimallin ja työkalujen välistä suhdetta. Samalta pohjalta on luontevaa selittää myös miten kielimalli ja agentti eroavat toisistaan.
Lokaalin kielimallin käyttö Cursorissa
Cursor on tekoälyavusteinen IDE ("integrated development environment") pääasiassa ohjelmistokehitykseen. Cursor on melko uusi tuote. Se on yksi tekoälyn soveltajien varhaisen aallon edustajista ja monen mielestä se on tällä hetkellä paras tekoälyavusteinen IDE. Käytännössä Cursorin käyttö kulminoituu siihen, että ostat Cursorin lisenssin (tai ilmaisversion) ja AI-krediittejä eli "tokeneita" tai "token-kiintiötä" Cursorilta tai syötät valitsemasi mallitarjoajan API-avaimen Cursoriin ja ryhdyt koodailemaan AI-avusteisesti.
Toinen asia tässä kappaleessa on lokaali kielimalli. Siitä kirjoitin melko laajasti viime kirjoituksessani.
Cursorin kanssa on mahdollista käyttää lokaaleja kielimalleja. Lyhyesti kerrottuna se tapahtuu näin:
- määrittelet vaihtoehtoisen OpenAI API -URLin (Cursorissa),
- ohjaat mainitun URL:in liikenteen omalle kielimallillesi ja
- lisäät mallisi cursorin mallipalettiin.
Kielimalli täytyy tarjoilla OpenAI API-spesifikaation mukaisesti. Tätä tarkoitusta varten on olemassa avoimen lähdekoodin projekteja ja omaan kokeiluuni valitsin mlx-openai-serverin.
Valitsin malliksi kehutun Qwen3-Coder-Nextin kvantisoidun version. Melko pikaisesti malli jo vastasikin Cursorissa: "Hei Henri. Miten voin auttaa sinua projektissasi mlx-openai-server?". Aikailematta ryhdyin töihin ja pyysin mallia lukemaan projektin lisenssitiedoston. Siitä seurasi töksähys: Cursor näytti kovasti yrittävän jotakin mutta mitään ei tapahtunut. Tiedostojen lukeminen Cursorissa edellyttää työkaluja, joten tiesin että minulla on työkalujen käyttöön liittyvä ongelma järjestelmässäni.
Miten kielimalli ja työkalut liittyvät toisiinsa?
Kerrataan nyt mikä kielimalli on. Se on koneoppimismalli, joka mallintaa luonnollista (ja usein myös keinotekoista) kieltä. Malli on koulutettu lukuisilla keskusteluilla ja sen kyvykkyyksin kuuluu mm. lauseiden täydentäminen ja erityisesti se pystyy koulutuksensa perusteella arvaamaan mikä voisi olla tyypillinen vastaus kuhunkin kysymykseen tai pyyntöön. Tämä voi kuulostaa monimutkaiselta mutta seuraava lause yksinkertaistaa asiaa huomattavasti: kielimalli saa syötteekseen pelkkää tekstiä ja tuottaa vastauksenaan pelkkää tekstiä. Kielimalli ei pysty mihinkään muuhun eikä tee mitään muuta.
Tämä näyttää olevan ristiriidassa kokemuksemme kanssa. Tiedämme, että kun tapailemme ChatGPT:tä ja Claudea, niin ne pystyvät monenlaisiin asioihin: ne osaavat suorittaa verkkohakuja, ne osaavat tehdä sinulle tiedoston jonka voit ladata koneellesi, kertoa sinulle ajan ja niin edelleen.
Jokainen edellämainituista toiminnoista edellyttää jotakin muuta kuin pelkkää tekstin lukemista ja tuottamista.
Asian selventämiseksi täytyy huomata, että harva meistä kirjoittaa suoraan kielimallille:
- ChatGPT ja Claude ovat itse asiassa verkkosivuja käyttäjän ja kielimallin välissä,
- Cursor on ohjelmisto, joka pääasiassa välittää käyttäjän pyyntöjä ja muuta dataa kielimallille ja takaisin käyttäjälle.
Näissä ohjelmistotuotteissa on niin kutsuttu tool prompt, joka lisätään jokaiseen keskusteluun, ennen käyttäjän lähettämiä viestejä. Tool prompt kertoo mitä työkaluja kutsuvalla alustalla on käytettävissään. Tästä johtuen kielimalli tietää, että työkaluja voidaan käyttää ja se tietää mitä työkaluja ovat käytettävissä.
Mitä kaikkea tapahtuu kun käyttäjä lähettää viestin kielimallille? Kielimalli saa tiedon työkaluista ja ohjeen harkita pitääkö jotakin työkalua käyttää, ottaen huomioon käyttäjän viestin sisältö. Kielimalli ei edelleenkään voi tehdä mitään muuta kuin tuottaa tekstiä.
Tämän jälkeen kielimalli tekee sen ainoa asian, jonka se osaa, eli se tuottaa tekstiä. Jos se katsoo, että jotakin työkalua pitäisi käyttää, se sanoo sen. Se tuottaa sellaisen vastauksen, jossa ilmaistaan että nyt pitää käyttää tätä tai tuota työkalua.
Useimmissa open-source malleissa kielimallin tuottama tool call -ohje näyttää esimerkiksi tällaiselta:
<tool_call>
<function=Read>
<parameter=path>
/home/henri/mlx-openai-server/app/middleware/auth.py
</parameter>
</function>
</tool_call>
Ohjeessa kerrotaan, että nyt pitäisi käyttää työkalua, mitä työkalua käytetään ja miten työkalua käytetään, esimerkiksi käytetään verkkohakua kissakuvien löytämiseksi.
Niinpä jos pyydät ChatGPT:tä tarkistamaan mikä on maailman onnellisin maa, niin GPT-kielimallin vastaus voi näyttää esimerkiksi tällaiselta:
Okei minä tarkistan sen sinulle.<tool_call>
<function=WebSearch>
<parameter=query>
onnellisin maa
</parameter>
</function>
</tool_call>
Sinä näet ChatGPT:n vastaavan "Okei minä tarkistan sen sinulle." Konepellin alla ChatGPT-verkkosivu tunnistaa tool_call markerin-tunnisteen, suorittaa pienen verkkohakuohjelman ja lähettää ohjelman tuottamat tulokset taas kielimallille, joka lukee vastauksen ja jatkaa taas keskustelua sinun kanssasi: "Tällä hetkellä maailman onnellisimmaksi maaksi arvioidaan Suomi..."
Kielimalli vs agentti
Työkalut ovat välttämättömiä myös agenteille.
Agentit ovat jossakin määrin itsenäisiä ohjelmia: ne voi lähettää suorittamaan jotakin tehtävää. Agentin tuottama työlaatu vaihtelee mutta oleellista siinä on se, että agentti pystyy toimimaan jossakin määrin itsenäisesti ja että sillä on jonkin verran harkintakykyä ja valinnanvapautta. Enemmän kuin pelkällä kielimallilla, joka voi ainoastaan tuottaa tekstiä.
Tyypillisesti agentin harkintakyky riippuu pääasiassa kielimallin kyvykkyydestä mutta valinnanvapaus sille tulee vasta siitä, että sillä on useampia vaihtoehtoja. Se voi esimerkiksi päättää käyttää jotakin työkalua sen sijaan, että se vastaisi suoraan käyttäjälle. Tästä syystä työkalujen saatavilla olemista pidetään valttämättömänä ehtona agentille.
Muutamia loppuhuomioita
Pääpiirteissään kommunikaatio kielimallien ja työkalujen välillä toimii niin kuin edellä kuvasin. Ilmiö on kuitenkin usein melko seikkaperäinen. Esimerkiksi OpenAI API:ssa pätee se, että OpenAI ei lähetä tool call -tunnisteita raakatekstinä vastaanottajalle vaan parsii ne ja lähettää tool callit käyttäjälle rakenteisessa muodossa. Tällaisiin mallitarjoajakohtaisiin seikkoihin pääsee tutustumaan melko nopeasti kun työskentelee kielimallien, agenttisten alustojen ja muiden ohjelmistotuotteiden rajapinnassa. Esimerkiksi minun tapauksessani piti kirjoittaa malliserveriin sama OpenAI API:n parsintaominaisuus ennen kuin työkalut alkoivat toimimaan Cursorissa avointen kielimallien kanssa.
Työ Cursorin ja OpenAI API:n kanssa tuotti myös käytännön hedelmää. Annoin Cursorille ja lokaalille kielimallilleni koetehtäväksi suhteellisen pienen ja selkeärajaisen ohjelmointitehtävän: lisää lmx-openai-server:iin tuki API avaimelle. Viidentoista minuutin kuluttua ja koneen huomattavasti kuumennuttua työ oli valmis ja testeissä ilmeni, että ratkaisu toimii odotetusti. Lisäksi malli kirjoitti testit lisätylle ominaisuudelle.
Seuraavaksi aion perehtyä uusiin asioihin:
- kokeilen pienempien mallien käyttöä - ne ovat nopeampia ja edullisempia ajaa,
- yritän tehdä jonkinlaisen mallireitittimen eli komponen, joka valitsee antamaani tehtävään sopivan kielimallin, ja
- kokeilen OpenSource -IDE:n käyttöä.
