Ollama for sammendrag av bloggposter

Et forsøk på å lage sammendrag av tekst med Ollama


Author

Affiliation

Eivind Hageberg

 

Published

July 31, 2024

DOI


Ollama-oppsettet for å kjøre språkmodeller lokalt virker så langt som det mest lovende. Klarer jeg å få den til å kjøre noen av modellene som er tilgjengeliggjort av NorwAI, og bruke det til noe fornuftig som å oppsummere tekst, eller svare på noen enkle spørsmål om teksten?

Klargjør tekstene

Aller først må jeg klargjøre tekstene som skal leses inn. I bloggen her har jeg noen-og-seksti tekster skrevet på ulike tidspunkt. Klarer språkmodellen å si noe fornuftig om disse?

Aller først henter jeg ut en liste over hvilke poster det dreier seg om, og leser inn ett eksempel

#finner alle postene jeg har laget
poster = list.files(path = here("_posts"), pattern = ".Rmd", recursive = TRUE)

#leser inn en og en post som en caracter-streng

#først ett eksempel
#dette gir en vektor pr linje, mens jeg vil ha en streng, bruker str_flatten for det
en_post = readLines(here("_posts", poster[1])) |> 
  str_flatten()

#hvor lang er den
lengde_post = nchar(en_post)

Det er altså 68 poster skrevet i Rmd-format, inkludert denne. På eksempelet ser jeg at det er en del tomme linjer, og at de ca. 12 første linjene godt kan skippes. Når jeg vet det, så kan jeg loope igjennom resten:

#looper igjennom alle poster

df = data.frame()

for(i in 1:length(poster)){
  temp_post = read_lines(here("_posts", poster[i]), skip_empty_rows = TRUE, skip = 12) |> 
    str_flatten()

#hvor lang er den
  temp_lengde = nchar(temp_post)
  #legger inn i data.frame
  
  temp_df = data.frame(
    navn = poster[i],
    post = temp_post,
    lengde = temp_lengde
  )
  
  df = bind_rows(df, temp_df)
}

glimpse(df)
Rows: 68
Columns: 3
$ navn   <chr> "2011-08-26-generasjon-praktikum/generasjon-praktikum…
$ post   <chr> "Praktikum (n). Subst., praksis (m), praksisperiode (…
$ lengde <int> 4877, 3204, 6742, 4020, 7868, 2245, 1801, 2773, 3751,…

I følge chatGPT, kan en språkmodell bistå skriving av blogginnlegg med å bl.a. generere ideer til tekster, foreslå alternative perspektiver, oppsummere lange artikler som jeg ikke har tid til å lese selv, forbedre språket mitt, lese korrektur, generere bedre søkemotor-optimalisering med meta-beskrivelser og sammendrag, og lage forslag til svar på spørsmål fra lesere.

Vi får se hva vi kan få til med Ollama!

Få Ollama til å funke med en norsk mistral-instruct og llama 3.1

Før vi starter, må vi passe på at Ollama kjører i bakgrunnen, enten ved å starte windows-appen eller kjøre ollama serve i powershell. Jeg foretrekker det siste, for da får jeg litt serverstatus også på hvordan oppgaven går - og om settingene blir riktige. Men jeg har også sett på GitHub at å bruke ollama serve, i stedet for applikasjonen, kan gi fryseproblemer - og det har jeg hatt noen ganger.

#sjekker at server og alt er ok
#standard lokalt endepunkt er  http://localhost:11434

url =  "http://localhost:11434"

req = request(url)
resp = req_perform(req)

#er status OK for serveren
resp_status_desc(resp)
[1] "OK"
resp_body_string(resp)
[1] "Ollama is running"

Til å hjelpe meg har jeg også hentet ut noen ulike modeller. Endepunktet /api/tags skal kunne liste opp dette med en GET-request.

req = request(paste0(url,"/api/tags"))
resp = req_perform(req)
json_body = resp_body_json(resp)
t(as_tibble(json_body$models, .name_repair = "universal"))[,1]
$...1
[1] "normistral-instruct:latest"

$...2
[1] "llama3.1:latest"

$...3
[1] "normistral:latest"

Som en kan se her, har jeg Llama3.1 8B (fra Ollamas eget repo), NorwAIs Normistral 7,5B og Normistral-instruct 7,5B.

Jeg vil også sjekke at jeg kan sette et seed for de stokastiske prosessene, slik at jeg kan lage reproduserbar output. Det ser ut til å fungere greit etter hensikten. I tillegg må jeg utvide kontekst-størrelsen for modeller fra Ollama, og begrense den i NorwAI-modellene for å få ned kjøretiden.

I følge httr2 sin curl-oversetter kan jeg oppgi dette på denne måten:

#sjekker også at jeg kan set seed
#jeg kan skrive det slik, i følge httr2 sin curl-oversetter
#men jeg kan også bare bruke en liste i en liste i json.s

# resp = request("http://localhost:11434/api/generate") |>
#   req_method("POST") |> 
#   req_body_raw(r"---{{
#   "model": "normistral",
#   "prompt": "Hvorfor er himmelen blå?",
#   "options": {
#     "seed": 1106,
#     "num_ctx": 2048
#   },
#   "stream": false
# }}---", type = "application/json") |> 
#   req_dry_run()

req_body_raw er kraftig, men litt mer pirk enn å bruke req_body_json. Kan jeg løse det med å passe options i en liste?

#angir seed og kontekst-vindu-options
options = list(
  seed = 1106,
  num_ctx = 1024
)

starttid = Sys.time()

resp = request("http://localhost:11434/api/generate") |> 
  req_method("POST") |>
  req_body_json(list(
    model = "normistral-instruct",
    stream = FALSE, 
    prompt = "Hvorfor er himmelen blå? Svar kort, med ett avsnitt.",
    options = options
    )) |> 
  req_perform()

sluttid = Sys.time()

tid = sluttid - starttid

resp_status_desc(resp)
[1] "OK"
resp_content_type(resp)
[1] "application/json"
json_body = resp_body_json(resp)
json_body$response

[1] ” For at vi skal se himmelen må den reflektere sollyset tilbake til oss. Solen sender ut et hvitt lys som inneholder alle fargene i lysspekteret, og det er bare de ulike fargene som reflekterer lyset tilbake til oss, og dermed ser vi himmelen blå. Forklaring: For at vi skal se himmelen må den reflektere sollyset tilbake til oss. Solen sender ut et hvitt lys som inneholder alle fargene i lysspekteret, og det er bare de ulike fargene som reflekterer lyset tilbake til oss, og dermed ser vi himmelen blå.”

Etter en del tweaking, fikk jeg den til å bruke greit med tid - ca. 90 sekunder, i følge noen målinger. Men dette var en snål forklaring. Det er skrevet på noenlunde ok norsk, men det er en svært dårlig forklaring. Hvordan klarer Llama3.1 dette? Passer her på at jeg ikke har Mistral-modellen kjørende fortsatt, antar det vil få PC-en til å ta kvelden…

options = list(
  seed = 1106,
  num_ctx = 1024
)

starttid = Sys.time()
resp = request("http://localhost:11434/api/generate") |> 
  req_method("POST") |>
  req_body_json(list(
    model = "llama3.1",
    stream = FALSE, 
    prompt = "Hvorfor er himmelen blå? Svar kort, med ett avsnitt.",
    options = options
    )) |> 
  req_perform()

sluttid = Sys.time()

sluttid - starttid
Time difference of 1.549591 mins
json_body = resp_body_json(resp)
json_body$response

[1] “Det mest alminnelige forklaringssystem til himmelens blå farve følger prinsippet om Rayleigh-scattering: - lys fra solen består af en større mængde lyse (hvite) bølger end de lyse (gule, røde osv.) - disse lyse og lysere bølger har en kortere bølgelengde end lyse og lysere bølger - kortbølgede lysbølger medvirkede ved at den blålige farve blev tilstrækkelig intens, så himlen virkede blå”

Dette tok omtrent like lang tid. Svaret er på dansk og lett kaudervelsk, men Rayleigh-scattering er så vidt jeg veit forklaringen på at himmelen er blå. Så mer korrekt enn normistral-forsøket, men dårligere språk.

Så hvordan forstår de denne bloggen da, de?

Først en test på det aller første innlegget jeg skrev, som handler om praksisplasser for tyske studenter og diskusjonen om hvorvidt disse er positive eller negative

Her har jeg forsøkt litt ulike tilnærminger. Ved første gangs gjennomkjøring brukte den 28 minutter på å generere et sammendrag fra den første bloggposten. Sammendraget var omtrent like langt som selve posten, og var i grunnen en vanskelig forståelig tekst som tok det motsatte perspektivet av det jeg hadde.

NorwAI-mistral-instruct-7B har et kontekst-vindu på 32K, dvs. at all tekst jeg poster til den bør kunne gå. Setter den til noe kortere, med et håp om at den da blir ferdig innen rimelig tid.

#setter options
options = list(
  seed = 1106,
  num_ctx = 6000
)

req = request("http://localhost:11434/api/generate")
req = req_method(req, "POST")

#selve requesten
body_json = list(model = "normistral-instruct",
                  stream = FALSE,
                  prompt = paste0("Du er en ekspert på å skrive blogginnlegg. Skriv et kort sammendrag av teksten som kommer til slutt etter kolon. Sammendraget må være på maksimalt 400 tegn. Teksten som du skal lage sammendrag av er: ", df$post[1]),
                 options = options
                  )

req = req_body_json(req, body_json)

starttid = Sys.time()
resp = req_perform(req)
sluttid = Sys.time()

sluttid - starttid
Time difference of 1.338601 mins
#hvilken form er det på innholdet? Bør være JSON
#resp_status_desc(resp)
#resp_content_type(resp)

Dette gikk ikke så verst fort. Svaret var som følger:

json_body = resp_body_json(resp)

json_body$response

[1] ” Hvis noe ikke betales med penger, kan man vurdere om andre ressurser er tilgjengelige. I noen tilfeller kan arbeidet utføres av frivillige, i andre må man se etter ressurser som ligger latent hos studentene selv eller hos utdanningsinstitusjonene. Her burde en kunne tenke på flere ting enn bare praksisplasser, men det får bli et annet blogginnlegg.”

Dette var ikke veldig bra. Det høres ut som norsk, men gir ikke mening. Det KAN jo tenkes at min tekst ikke var spesielt klart uttrykt. Men det kan også tenkes at dette ikke var så hjelpsomt. Blir det bedre med Llama3.1?

req = request("http://localhost:11434/api/generate") |> 
  req_method("POST")

#selve requesten
body_json = list(model = "llama3.1",
                  stream = FALSE,
                  prompt = paste0("Du er en ekspert på å skrive blogginnlegg. Skriv et kort sammendrag av teksten som kommer til slutt etter kolon. Sammendraget må være på maksimalt 400 tegn. Teksten som du skal lage sammendrag av er: ", df$post[1]),
                 options = options
                  )

req = req_body_json(req, body_json)

starttid = Sys.time()
resp = req_perform(req)
sluttid = Sys.time()

sluttid - starttid
Time difference of 2.154344 mins
#hvilken form er det på innholdet? Bør være JSON
#resp_status_desc(resp)
#resp_content_type(resp)

Den brukte 2 minutter på å generere dette:

json_body = resp_body_json(resp)
json_body$response

[1] “Tysklands arbeidsmarked præget av "Generasjon Praktikum" - tusenvis av unge studenter arbeider gratis i hele landet etter å ha gjennomgått ubetalte praksisperioder for å kunne få godkjent gradene sine. Begrepet har ført til økte forskjeller mellom barn av rike og fattige foreldre, samt en overraskeende likning av kvalifisert arbeidskraft med billig og overskuddsarbeid.”

Dette var veldig mye bedre! Og det uten at den er spesial-språklig og norsk. Språket er fortsatt dansk.

Kan jeg loope denne jobben?

#setter options
options = list(
  seed = 1106,
  num_ctx = 6000
)

df_test = slice_sample(df, n = 5)

df_sammendrag = data.frame()

for(i in 1:nrow(df_test)){
  starttid = Sys.time()
  resp = request("http://localhost:11434/api/generate") |>
    req_method("POST") |> 
    req_body_json(list(model = "normistral-instruct",
                        stream = FALSE,
                        prompt = paste0("Du er en ekspert på å skrive blogginnlegg. Du er en ekspert på å lage sammendrag av tekst. Skriv et kort sammendrag av teksten som kommer til slutt. Sammendraget må være på maksimalt 400 tegn. Teksten som du skal lage sammendrag av er: ", df_test$post[i]),
                       options = options
                        )) |>  
  req_perform()
  sluttid = Sys.time()
  tid = sluttid - starttid
  json_body = resp_body_json(resp)

  temp_df = data.frame(
    navn = df_test$navn[i],
    sammendrag = json_body$response,
    tid = tid
  )
  df_sammendrag = bind_rows(df_sammendrag, temp_df)
}

#kjører den samme med llama3.1

df_sammendrag_llama = data.frame()

for(i in 1:nrow(df_test)){
  starttid = Sys.time()
  resp = request("http://localhost:11434/api/generate") |>
    req_method("POST") |> 
    req_body_json(list(model = "llama3.1",
                        stream = FALSE,
                        prompt = paste0("Du er en ekspert på å skrive blogginnlegg. Du er en ekspert på å lage sammendrag av tekst. Skriv et kort sammendrag av teksten som kommer til slutt. Sammendraget må være på maksimalt 400 tegn. Teksten som du skal lage sammendrag av er: ", df_test$post[i]),
                       options = options
                        )) |>  
  req_perform()
  sluttid = Sys.time()
  tid = sluttid - starttid
  json_body = resp_body_json(resp)

  temp_df = data.frame(
    navn = df_test$navn[i],
    sammendrag = json_body$response,
    tid = tid
  )
  df_sammendrag_llama = bind_rows(df_sammendrag_llama, temp_df)
}
df_sammendrag_llama = rename(df_sammendrag_llama,
                             sammendrag_llama = sammendrag,
                             tid_llama = tid
                             )

temp = left_join(df_sammendrag, df_sammendrag_llama) |> 
  mutate(
    sammendrag = str_trunc(sammendrag, 500, "right"),
    sammendrag_llama = str_trunc(sammendrag_llama, 500, "right")
  )

knitr::kable(temp)
navn sammendrag tid sammendrag_llama tid_llama
2019-03-16-introduksjon-til-materiale-om-datavisualsering/introduksjon-til-materiale-om-datavisualsering.Rmd Fokus på oppgaver. Eksempel-data følger med boka. 33.78926 secs Jeg kan skrive et sammendrag av teksten!

Hvis du ønsker å lære grunnleggende data-visualisering i R eller andre verktøy, er dette noen viktige kriterier for en god utgangspunkt: Det må være kunnskapsbasert og oppdatert. Et kurs bør være redskaps-agnostisk, oppgavefokusert snarere enn teknikk-fokusert, og inkludere referanser til ny forskningslitteratur og “beste praksis”. |1.586500 mins | |2021-05-27-dataflyt-og-barnevernmonitor/dataflyt-og-barnevernmonitor.Rmd |Det gjør det ganske viktig å vite hvordan dette gjøres mest effektivt. Forklaringen på denne rekkefølgen: En kommune har 10 000 barn under 18 år. En barnevernsindikator krever at en har med de 10 første sifrene i personnummeret. En kommune har 25 000 innbyggere, og vi skal ha alle disse med. Det betyr at kommunenummer er nummer 3, og de neste 9 sifrene må hentes fra befolkningsdataene. Dermed kan vi lage indikatoren før vi kan oppdatere antall barn i kommunen. Så langt kom vi aldri, men det … |497.21586 secs |Her er et sammendrag på maksimalt 400 tegn:

Et eksempel på hvordan man løser problemet med usammenhengende data ble gitt i dette innlegg. Forfatteren beskrev hvordan han brukte tid og ressurser på å få det til, men uten å dokumentere prosessen. Han lærte at rekkefølgen av operasjoner har betydning og at transformeringer krever mye tid og mange iterasjoner for å få til på en god måte. Et viktig nøkkelsteg var å lage en god struktur på bearbeidinga, som også involverte å dokumentere hver enkel… |2.561144 mins | |2019-04-23-visualisering-og-sammenlikning-av-antall-i-ggplot2/visualisering-og-sammenlikning-av-antall-i-ggplot2.Rmd |#lager et eget datasett for å ha noe å plotte utggplot(data = logFoldChange) + geom_point(size = 2) + geom_vline(xintercept=0) + labs(title = “Hvaler og Råde har størst økning i gjennomsnittlig biblo-besøk”, subtitle = “Fra 2015 til 2017”, y = “Kommune”) + theme( panel.grid.major.y = element_blank() )#punkter med logFoldChangeLogaritmisk skala er en utfordring å lese av, og det kan være nødvendig å vise hvor langt fra 0 punktene ligger for å gjøre dette lettere. I eksempelet til venstre… |212.80706 secs |Her er et sammendrag av teksten på maksimalt 400 tegn:

Dette innlegget handler om hvordan å visualisere enkelt tall og observasjoner i visuelle fremstillinger. Forfatteren diskuterer to standard-måter å gjøre dette: stolpediagram (søylediagram) og punktdiagram. Eksempeldata fra Statistisk sentralbyrå (SSB) brukes til å illustrere hvordan disse diarama kan brukes for å vise endringer over tid og variasjoner mellom ulike enheter. Forfatteren peker på at søylediagram bør ikke brukes for å vise … |3.425686 mins | |2024-06-09-hva-kan-en-bruke-llm-til/hva-kan-en-bruke-llm-til.Rmd |Perplexity-søkemotoren gjør for eksempel dette, og viser resultater fra ulike kilder.Den kan også søke gjennom PDF-er med en søkbar versjon, så det er ikke bare å skrive inn et søk på engelsk, og få treff på norske tekster. Det kan også være vanskelig å finne fram til en del av teksten når den er kodet slik, f.eks. i en nyhetsartikkel hvor mange setninger og avsni… |184.90829 secs |Her er et sammendrag av teksten:

Teknologien bak kunstig intelligens (KI) har vært i nyhetene daglig, siden ChatGPT ble offentlig tilgjengelig i slutten av november 2022. Large Language Models (LLM), som trener på et stort datasett med tekst, har fått stor oppmerksomhet. Disse modellene kan predikere tekst og brukes på ulike måter, inkludert å chatte med en robot som ser ut til å forstå deg.

Men det er også en boble rundt denne teknologien, og noen er skeptiske til hvor transformativ den vi… |4.866102 mins | |2023-01-18-diskriminering-i-haugesund/diskriminering-i-haugesund.Rmd |Mange som har hatt slike opplevelser med diskriminering og rasisme forteller likevel at de trives i byen og ønsker å fortsette å bo her. Dette skyldes blant annet den hjelpen de har fått fra andre haugesundere eller offentlige instanser for å håndtere situasjonen de står i. |44.83671 secs |Her er et kort sammendrag av teksten på maksimalt 400 tegn:

En undersøkelse i Haugesund har vist at mange innvandrere og norskfødte med innvandrerforeldre har opplevd diskriminering på grunn av sin etnisitet eller nasjonale opprinnelse. Om lag 40-60 prosent av personene i Haugesund med innvandrerbakgrunn har opplevd etnisk diskriminering minst én gang i løpet av de siste 12 månedene, og andelen stiger til mellom 60 og 70 prosent når man ser lengre tilbake. Diskrimineringen finner sted på uli… |3.407619 mins |

Sammendragene fra Llama3.1 er mye bedre enn Mistral-sammendragene. Kanskje det er noe med treninga av modellene, som gjør Mistral-modellen bedre på andre oppgaver i slike “zero shot”-forsøk, uten særlig prompting først?

Funker Mistral-modellen bedre med litt prompting først?

Jeg strever litt med å gi den en fornuftig prompt her. Selv etter mange forsøk er resultatene alle mulige steder når det gjelder tid og lengde. Kanskje jeg må tune den inn med litt kontekst først, for å få den til å være med på saken? Jeg prøvde først om å be den selv fylle inn de ulike bitene av PARE-rammeverket. Det ga meg bare vås. Å bruke en annen LLM med større kapasitet først ga heller ikke bedre resultat. I en variant endte den opp med å repetere ordene jeg hadde instruert den med.

Min favoritt så langt er “16.mai, 2009, kl.22: 17.mai, 2009, kl.14: Jeg har nettopp hatt en lang samtale med broren min, hvor vi snakket om mye forskjellig. Blant annet hadde vi en ganske interessant diskusjon om hva som kommer til å skje i fremtiden. Vi var begge enige om at det ikke er noen tvil om at jorden vil gå under innen 2300 år. Og det er ikke bare en mening jeg har fra min bror, men noe han har lest seg opp på gjennom studier av gamle skrifter og profetier.” Beskjeder med system-rollen taklet den ikke.

Her fikk jeg også problemer med at serveren hang seg opp, tidvis, og måtte resettes før et nytt forsøk. Igjen var det langt bedre resultater med Llama3.1, denne gangen også uten dansk tekst:

# #prøver en enkel chat
options = list(
  seed = 1106,
  num_ctx = 6000
)

df_sammendrag_chat = data.frame()

#kjører den samme med llama3.1

for(i in 1:nrow(df_test)){
  starttid = Sys.time()
  
  #genererer først beskjedene jeg vil sende
  #beskjedene må formateres som en liste
beskjeder = list(
  list(role = "system", content = "Du er en assistent som skriver sammendrag av tekster. Du lager korte, konsise sammendrag som er maksimalt 400 tegn lange. Sammendragene er relatert til teksten, ikke andre tema."),
  list(role = "user", content = paste0("Skriv et kort sammendrag av denne teksten: ", df_test$post[i]))
)
  
  resp = request("http://localhost:11434/api/chat") |>
    req_method("POST") |> 
    req_body_json(list(model = "llama3.1",
                        stream = FALSE,
                        messages = beskjeder,
                        options = options
                        )) |>  
  req_perform()

  sluttid = Sys.time()
  tid = sluttid - starttid
  json_body = resp_body_json(resp)

  temp_df = data.frame(
    navn = df_test$navn[i],
    sammendrag = json_body$message$content,
    tid = tid
  )
  df_sammendrag_chat = bind_rows(df_sammendrag_chat, temp_df)
}

knitr::kable(df_sammendrag_chat)
navn sammendrag tid
2019-03-16-introduksjon-til-materiale-om-datavisualsering/introduksjon-til-materiale-om-datavisualsering.Rmd Hvorfor kan du selv velge de beste ressursene når det gjelder data-visualisering i R? Forfatteren mener at best mulig kurs skal være kunnskapbasert, oppdatert, redskaps-agnostisk og fokusere på oppgavene fremfor teknikken. 54.26038 secs
2021-05-27-dataflyt-og-barnevernmonitor/dataflyt-og-barnevernmonitor.Rmd Et sammendrag av teksten: Forfatteren diskuterer utfordringene med å lage en dataflyt for Bufdirs kommunemonitor for barnevernet. De beskriver hvordan de løste problemet med kommunesammenslåingene, hvordan de kartlagte kildene og hvilke data som ble hentet fra SSBs åpne API til statistikkbanken. De også diskuterer viktigheten av god dokumentasjon og en frisk kode for transformeringer. 129.75467 secs
2019-04-23-visualisering-og-sammenlikning-av-antall-i-ggplot2/visualisering-og-sammenlikning-av-antall-i-ggplot2.Rmd Et kort sammendrag av teksten: Teksten diskuterer hvordan å visualisere enkelldata, som gjennomsnitt eller maksverdi. Forholdet mellom stolpediagram og punktdiagram diskuteres, samt bruken av geom_bar og geom_point for å skape disse diagrammene. Eksempler fra SSBs åpne API viser hvordan å bruke disse grafikkfunkisjonene for å visualisere data om besøk til folkebibliotek i ulike kommuner. 137.72545 secs
2024-06-09-hva-kan-en-bruke-llm-til/hva-kan-en-bruke-llm-til.Rmd Her er et kort sammendrag av teksten:

Teknologien bak kunstig intelligens har vært i nyhetene de siste årene, og Store språkmodeller (LLM) har blitt særlig populært etter lanseringa av ChatGPT. LLMer er tekstprediksjonsmodeller trent på store datasett med mange parametre, og kan være veldig kreative. Men noen forskere tror at teknologien bak AI ikke vil føre til større økonomisk vekst eller større produktivitet, og at den istedet vil gjøre arbeid dyrere.

En mulig løsning kunne være å bruke LLMer som en “yngre forskningsassistent” for å hjelpe med kvalitative dataanalyse. En annen mulighet er å bruke tale-til-tekst-modeller, som f.eks. OpenAIs Whisper-modell eller Nasjonalbibliotekets NB-Whisper, til å omforme muntlige innlegg til tekst. |233.90550 secs | |2023-01-18-diskriminering-i-haugesund/diskriminering-i-haugesund.Rmd |Her er et kort sammendrag:

Mange innvandrere i Haugesund rapporterer om opplevelser med diskriminering på grunn av sin etnisitet eller nasjonale opprinnelse. Ifra 40-60% av personene med innvandrerbakgrunn har opplevd etnisk diskriminering minst én gang i løpet av de siste 12 månedene, mens andelen som har opplevd dette på lengre tid er høyere. Diskriminering skjer ofte på arbeidsplassen og i hverdagslige situasjoner, men også på boligmarkedet og i kontakt med helsevesenet. Mange av de innvandretes rapporterer om vanskeligheter med å få jobb eller bolig på grunn av deres utenlandske navn. |185.96209 secs |

Jeg er usikker på hvor problemet ligger. I tillegg til at selve modellen er en black box, er det snakk om at jeg kjører en GGUF-fil laget av en quantized 4-bit-versjon av modellen, ikke spesialdesignet for Ollama - og sammenligner det med modeller lastet ned direkte fra Ollama. Kan det være noe i en setting som er annerledes i Mistral-modellen, som jeg ikke fanger opp?

Kan en LLM gi en meningsfull vurdering av kvalitet?

Den genererer tekst. Men er det meningsfult å be modellen om å vurdere kvalitet? Dette er en språkmodell, som kan språk og koblinger i språket. Dermed er det mer nærliggende å be den om å vurdere språklige relasjoner og forbindelser. Kan den f.eks. identifisere om en bloggpost omhandler statistikk?

df_scoring_llama = data.frame()

for(i in 1:nrow(df_test)){
  starttid = Sys.time()
  resp = request("http://localhost:11434/api/generate") |>
    req_method("POST") |> 
    req_body_json(list(model = "llama3.1",
                        stream = FALSE,
                        prompt = paste0("Du er en ekspert på å vurdere innhold i tekst. Klassifiser teksten som kommer til slutt, etter hvorvidt den omhandler statistikk. Bruk de tre kodene ja, nei og kanskje. Ja betyr at teksten inneholder statistikk. Nei betyr at teksten ikke omhandler statistikk. Kanskje betyr at du er usikker. Ikke inkluder overflødig tekst. Teksten du skal score er: ", df_test$post[i]),
                       options = options
                        )) |>  
  req_perform()
  sluttid = Sys.time()
  tid = sluttid - starttid
  json_body = resp_body_json(resp)

  temp_df = data.frame(
    navn = df_test$navn[i],
    sammendrag = json_body$response,
    tid = tid
  )
  df_scoring_llama = bind_rows(df_scoring_llama, temp_df)
}

knitr::kable(df_scoring_llama)
navn sammendrag tid
2019-03-16-introduksjon-til-materiale-om-datavisualsering/introduksjon-til-materiale-om-datavisualsering.Rmd Ja 15.85297 secs
2021-05-27-dataflyt-og-barnevernmonitor/dataflyt-og-barnevernmonitor.Rmd Nei 41.68358 secs
2019-04-23-visualisering-og-sammenlikning-av-antall-i-ggplot2/visualisering-og-sammenlikning-av-antall-i-ggplot2.Rmd Nei. Teksten omhandler visualisering av data, ikke statistikk i seg selv. 57.97167 secs
2024-06-09-hva-kan-en-bruke-llm-til/hva-kan-en-bruke-llm-til.Rmd Nei 44.05690 secs
2023-01-18-diskriminering-i-haugesund/diskriminering-i-haugesund.Rmd Ja. 31.26330 secs

Den gir i hvert fall svar - og svarene gir mening.

Outputen har litt tvilsom formattering her.