De la cod la conversație: distracție AI localizată cu LM Studio și pachetul ellmer

URMĂREȘTE-NE
16,065FaniÎmi place
1,142CititoriConectați-vă

Rezumat: în acest post vă demonstrez cum puteți interacționa cu modelele LLM găzduite local în R folosind pachetul ellmer și LM Studio.

Dacă nu ați ghicit deja, titlul acestei postări a fost sugerat de un model de limbă mare (LLM). Mai exact, bartowski/Llama-3.2-3B-Instruct-GGUF LLM. Din nefericire pentru tine, restul acestui blog va fi scris de mine.

Introducere

Dacă v-ați conectat cu mine pe Bluesky sau Linkedin, veți ști că beneficiile și impactul inteligenței artificiale (AI) sunt adesea exagerate. Cu companiile care încearcă din ce în ce mai mult să introducă funcții „AI” în produsele lor pentru a-i satisface pe directori care nu au idee cum funcționează. Dar, veți ști, de asemenea, că nu sunt orb la utilitatea lor, fiind un utilizator frecvent al lui Claude și ChatGPT pentru rafinarea codului, metodologiile steel-manning și îmbunătățirea scrisului meu. De fapt, am scris un ghid despre cum folosesc ChatGPT la începutul nebuniei AI.

De aceea, ori de câte ori le arăt altora cum să folosească instrumentele AI, am petrecut o cantitate exagerată de timp clarând ce pot și nu pot face (reținând că încă ne dăm seama). Să spunem doar că sunt „îndrăgostit sceptic” de tehnologie.

Interacțiunea cu modelele LLM în R

Un LLM este un tip de model de învățare automată care poate fi util pentru procesarea limbajului natural și sarcinile de generare. Deși pot fi utile pentru o varietate de sarcini, le folosesc frecvent atunci când trebuie să generez un set de text standard, să curăț datele nestructurate sau să extrag informații dintr-un document. Prin urmare, am încercat să integrez inteligent LLM-urile mai direct în fluxul meu de lucru R.

Din păcateacest lucru necesită accesarea interfeței de programare a aplicațiilor (API) a unui LLM. Din fericireaccesarea API-urilor este posibilă în R. Din păcateacest lucru necesită deseori interpretarea documentelor de dezvoltator scrise prost și discutarea datelor JSON.

Datele sunt, de asemenea, în format JSON”

Dar, din fericire nu va trebui să suferi ca mine datorită lui Hadley Wickham și echipei din spatele pachetului ellmer. Pentru a afla mai multe despre capabilitățile pachetului, consultați pagina github sau tidyverse, dar, în esență, simplifică foarte mult interacțiunea cu cele mai populare modele LLM.

Problema

Am interacționat foarte mult cu LLM-urile în R recent, deoarece construiesc o conductă de analiză care necesită extragerea metadatelor din documente text nestructurate. Am folosit în principal modelul Claude de la Anthropic, deoarece mi se pare că este mai fiabil decât concurenții săi. Cu toate acestea, limitele solicitărilor API pot face construirea unei noi conducte de analiză greoaie.

Solutia(?)

Deși aș putea doar să încerc să fac mai puține solicitări ale API-ului Anthropic, problema mi s-a părut o scuză la fel de bună ca oricare pentru a-mi da seama cum să implementez un model LLM local care ar putea servi ca înlocuitor temporar până când conducta funcționează. Odată ce totul funcționează, aș reveni la folosirea lui Claude.

LM Studio

LM Studio este o aplicație pentru descărcarea și rularea locală a modelelor LLM. Deși este „gratuit” pentru uz personal, există limite dacă îl utilizați în scopuri comerciale (consultați: termenii și condițiile). Puteți descărca cea mai recentă versiune a LM Studio aici.

Când deschideți pentru prima dată LM Studio, ar trebui să vedeți un ecran similar cu cel de mai jos (fără adnotări). Zonele aplicației care ne interesează includ:

Găsirea și descărcarea unui model

După ce ați instalat LM Studio, probabil că veți dori să descărcați un model LLM. În scopurile noastre, vom alege o versiune mică a modelului Llama al lui Meta, pe care o puteți găsi căutând „llama-3.2-3b-instruct” prin meniul „descoperire” din LM Studio:

(De asemenea, puteți consulta clasamentul Hugging Face pentru un clasament al modelelor LLM deschise).

Descărcarea llama-3.2-3b-instruct model

Lîncărcarea și interacțiunea cu un model

După ce ați descărcat modelul, există mai multe moduri de a interacționa cu acesta. Cel mai simplu mod este să-l încărcați prin meniul drop-down și să discutați direct cu el folosind panoul „Chat”:

llama-3.2-3b-instruct: probabil nu este optimizat pentru glume.

Configurarea unui server local LM Studio

La fel de util pe cât este de a avea o cantitate nesfârșită de glume proaste, va trebui să acoperim acest lucru într-o postare ulterioară. Obiectivul nostru astăzi este configurarea unui server local pe care să îl putem accesa în R.

Acest lucru este jenant de simplu și necesită navigarea la fila dezvoltator, încărcarea modelului folosind meniul drop-down și pornirea serverului prin comutarea comutatorului din stânga sus. Acordați o atenție deosebită informațiilor din panoul „Utilizare API”, deoarece ne vom referi la aceasta atunci când interacționăm cu serverul în R.

Nota: Am setat sămânța la „123” când încărc modelul. Am specificat, de asemenea, o temperatură de „0” în setările modelului (vezi: „Modelele mele” > llama-3.2-3b-instruct > „Editați configurația implicită a modelului” > Inferență > Temperatură).

Configurarea unui server LLM local

Interacțiunea cu modelele LLM în R

Dacă ați ajuns până aici, ar trebui să aveți un model LLM care rulează în fundal. Pentru a interacționa cu acesta, vom folosi pachetul ellmer care poate fi instalat folosind install.packages(‘ellmer’). Am folosit în principal ellmer pentru a interacționa cu modelul Claude de la Anthropic, dar pachetul acceptă o varietate de funcții pentru furnizori specifici, cum ar fi OpenAI, Groq și Google Gemini (vezi aici).

Vom folosi funcția chat_vllm() care ne permite să ne conectăm la serverul nostru LLM, dar configurația de bază este similară: configurați un obiect de chat care specifică promptul implicit al sistemului, modelul de utilizat și cheia dvs. API. Pentru funcția chat_vllm() va trebui, de asemenea, să setăm baza_url, astfel încât să cunoască adresa serverului.

În codul de mai jos, după încărcarea pachetelor necesare, am specificat intrările cheie cerute de funcția chat_vllm(). Observați că valorile adresei URL de bază și ale modelului provin direct din LM Studio în secțiunea „Utilizare API” a panoului pentru dezvoltatori. Cheia API este pur și simplu „lm-studio”, conform documentației.

De dragul de a oferi o demonstrație reproductibilă a interacțiunii cu un LLM local în R, îl vom avea să finalizeze o sarcină foarte simplă pentru care nu avem nevoie de un LLM: luăm un șir de numere separate prin „,” și returnează-le ca un șir separat de „;”.

Aceste instrucțiuni sunt specificate în promptul de sistem în ref_prompt (vom genera numerele de mai jos). Observați că promptul îi specifică LLM că nu ar trebui să comenteze rezultatul. Aceasta este o demonstrație excelentă a modului în care LLM-urile pot fi ciudate să lucrezi, așa cum trebuie să fii într-adevăr explicit despre ceea ce vrei. În acest caz, am inclus această linie pentru a evita ca modelul să-și împărtășească povestea de viață atunci când returnează șirul de numere pe care l-am cerut.

Cod: Pregătiți-vă pentru o „distracție” AI localizată:

#load packages
library(ellmer)
library(tidyverse)

#set assumptions
ref_llm_url<-"http://127.0.0.1:1234/v1/"

ref_model<-"llama-3.2-3b-instruct"

#specify prompt to provide LLM
ref_prompt<-c("Output this data as numeric string using ';' as the deliminator. 
                  Do not comment on the output:")
#set up chat object
fnc_chat<-chat_vllm(base_url=ref_llm_url, 
                    api_key= "lm-studio",
                model=ref_model,
                system_prompt = ref_prompt)

Un lucru pe care l-ați putea observa când rulați acest cod este că funcția chat_vllm() nu a interacționat încă cu serverul. În schimb, l-am salvat ca obiect R6 cu care putem interacționa apelând metoda „chat”. Puteți citi mai multe despre acest lucru pe pagina Github, dar un avantaj al acestei abordări este că conversațiile anterioare sunt salvate. De exemplu, după ce am apelat metoda de chat de mai jos, rezultatele conversației sunt stocate în „last_turn()”.

Codul de mai jos configurează exemplul prin crearea unui cadru de date cu o serie de 100 de numere aleatorii în coloana source_data. Am setat rotunjirea la nouă pentru a reduce șansa de a întâlni erori în virgulă mobilă atunci când comparăm rezultatul produs de modelul nostru LLM cu datele sursă.

Promptul și datele sunt apoi trimise la LLM local prin fnc_chat$chat(). Rezultatele conversației au fost salvate sub dta_llm_reply și convertite într-o variabilă în cadrul de date dta_rnorm. Dar, dacă te uiți la dta_llm_reply, vei vedea ce a fost returnat de model – un șir de numere separate prin „;”. Deoarece am specificat să nu comentăm rezultatul, nici nu ne-a oferit informații narative despre sarcină, ceea ce este la îndemână deoarece suntem doar interesați să obținem șirul de numere.

Linia finală a codului demonstrează pur și simplu că interacțiunea anterioară este salvată în fnc_chat sub $last_turn.

Cod: Începând conversația:

#generate a random string
#(I've rounded to avoid a floating point errors)
set.seed(123)
dta_rnorm<-data.frame(source_data=rnorm(100)) |> 
  round(9)

#send prompt to local LLM model and save results 
dta_llm_reply<-fnc_chat$chat(paste(dta_rnorm$source_data))(1)

#save results from LLM as a column in dta_rnorm  
dta_rnorm<-dta_rnorm |> 
  mutate(llm_transcribed=dta_llm_reply((1)) |> 
  str_split(pattern=';') |> 
  unlist() |> 
  as.numeric())

#show last conversation
fnc_chat$last_turn()

Încă o dată, chiar nu există niciun motiv pentru care ai folosi un LLM pentru o sarcină ca aceasta. La urma urmei, dacă avem nevoie într-adevăr de a finaliza o sarcină atât de simplă, am putea folosi doar str_replace(). Dar, asta face oferiți o ilustrare simplă a modului de interacțiune cu un model LLM local în R.

Cod: Verificarea funcționării acestuia

#calculate the difference
dta_rnorm<-dta_rnorm |> 
  mutate(diff=source_data-llm_transcribed )

#Check whether the numbers match:
table(dta_rnorm$source_data==dta_rnorm$llm_transcribed)

#plot the data series for good measure: 
plot(x=dta_rnorm$source_data, 
     y=dta_rnorm$llm_transcribed, 
     xlab="Source value",
     ylab="Value outputted (LLM)", 
     main="Source values vs values outputted by LLM")

Deși aceasta nu este în niciun caz o modalitate eficientă de a schimba eliminatorul folosit într-un șir, am fost surprins să constat că a durat laptopul meu cu specificații moderate în jur de zece secunde pentru a executa întregul script și că numerele afișate au fost toate corecte:

Încheiere: câteva puncte finale

Dacă vă întrebați de ce sunt surprins că un LLM ar putea îndeplini această sarcină, este pentru că sunt notoriu de rău la aritmetică. De asemenea, se știe că „halucinează”, ceea ce mă așteptam s-ar putea rezultă în afișarea numerelor care păreau corecte, dar nu se potriveau cu ceea ce i-am furnizat. Dar, m-am înșelat în ambele aspecte: modelul părea să scoată exact ceea ce am cerut. Acest lucru ar putea fi atribuit unei varietăți de surse, cum ar fi faptul că modelul ar fi fost instruit pentru probleme de codare asemănătoare sarcinii noastre, dar aceasta este o problemă pentru o altă postare.

Dominic Botezariu
Dominic Botezariuhttps://www.noobz.ro/
Creator de site și redactor-șef.

Cele mai noi știri

Pe același subiect

LĂSAȚI UN MESAJ

Vă rugăm să introduceți comentariul dvs.!
Introduceți aici numele dvs.