library(reticulate)
#virtualenv_create("chatgpt")
use_virtualenv("chatgpt")
chatgpt-sentiment-loop-all
Aufgabe
Fragen Sie ChatGPT via API zum Sentiment der Texte aus dem Germeval-2018-Datensatz (Test).
Hinweise:
- Beachten Sie die Standardhinweise des Datenwerks.
- Nutzen Sie Python, nicht R.
- Das Verwenden der OpenAI-API kostet Geld. đž Informieren Sie sich vorab ĂŒber die Preise von OpenAI. Um auf die API zugreifen zu können, mĂŒssen Sie sich ein Konto angelegt haben und ĂŒber ein Guthaben verfĂŒgen. Sie können unter https://platform.openai.com/usage Ihre Kosten prĂŒfen.
Lösung
Achtung
OpenAI hat eine neue API (Stand: 2023-11-23), V1.3.5. Der Code der alten API bricht. đ \(\square\)
Setup
Die richtige venv nutzen:
Check zu Python:
::py_config() reticulate
python: /Users/sebastiansaueruser/.virtualenvs/chatgpt/bin/python
libpython: /Users/sebastiansaueruser/.pyenv/versions/3.11.1/lib/libpython3.11.dylib
pythonhome: /Users/sebastiansaueruser/.virtualenvs/chatgpt:/Users/sebastiansaueruser/.virtualenvs/chatgpt
version: 3.11.1 (main, Oct 4 2023, 18:12:06) [Clang 15.0.0 (clang-1500.0.40.1)]
numpy: /Users/sebastiansaueruser/.virtualenvs/chatgpt/lib/python3.11/site-packages/numpy
numpy_version: 1.26.2
NOTE: Python version was forced by use_python() function
Ggf. noch Module installieren:
#reticulate::py_install("pandas")
#py_install("tiktoken")
#py_install("datar")
#py_install("scikit-learn")
R-Pakete und Python-Module
library(tidyverse)
library(tidymodels)
library(plotly)
Attaching package: 'plotly'
The following object is masked from 'package:ggplot2':
last_plot
The following object is masked from 'package:stats':
filter
The following object is masked from 'package:graphics':
layout
Module importieren:
from openai import OpenAI
import pandas as pd
import numpy as np
import time
from datetime import datetime
#from sklearn.metrics import classification_report
from sklearn.metrics import accuracy_score
Versionen der importierten Module:
pd.__version__
'2.1.3'
```{zsh openai-version-zsh}
pip list | grep openai
```
[notice] A new release of pip is available: 23.3.1 -> 23.3.2
[notice] To update, run: pip install --upgrade pip
openai 1.3.5
Wir brauchen >= 1.35
.
Der Operator |
ist die âPfeifeâ der Kommandozeile, also sozusagen der âUND-DANN-Befehlâ.
Daten
Daten importieren:
= 'https://github.com/sebastiansauer/pradadata/raw/master/data-raw/germeval_test.csv'
csv_file_path_test
= pd.read_csv(csv_file_path_test) germeval_test
Die ersten paar Texte herausziehen:
= 0
start_pos = 3531
end_pos = germeval_test["text"].iloc[start_pos:(end_pos+1)].tolist() tweets
Prompt
Prompt definieren:
= "Als KI mit Exertise in natĂŒrlicher Sprache und Emotionserkennung ist es Ihre Aufgabe, das Sentiment des folgenden Textes einzuschĂ€tzen. Bitte antworten Sie nur mit einem einzigen Wort, entweder 'positiv', 'neutral' oder 'negativ'. Ihre Antwort soll Ihre Insgesamt-EinschĂ€tzung zum Sentiments des Textes zusammenfassen. Nach dem Doppelpunkt folgt der Text, dessen Sentiment Sie einschĂ€tzen sollen: " prompt_stem
Gute Prompts können helfen, gute Antworten vom Modell zu erhalten.
Mit âList Comprehensionâ können wir die Tweets jeweils mit dem Prompt verknĂŒpfen:
= [prompt_stem + tweet for tweet in tweets]
prompts 0] prompts[
"Als KI mit Exertise in natĂŒrlicher Sprache und Emotionserkennung ist es Ihre Aufgabe, das Sentiment des folgenden Textes einzuschĂ€tzen. Bitte antworten Sie nur mit einem einzigen Wort, entweder 'positiv', 'neutral' oder 'negativ'. Ihre Antwort soll Ihre Insgesamt-EinschĂ€tzung zum Sentiments des Textes zusammenfassen. Nach dem Doppelpunkt folgt der Text, dessen Sentiment Sie einschĂ€tzen sollen: Meine Mutter hat mir erzĂ€hlt, dass mein Vater einen Wahlkreiskandidaten nicht gewĂ€hlt hat, weil der gegen die Homo-Ehe ist âș"
Check: Wie viele Elemente hat die Liste prompts
?
len(prompts)
3532
Laut OpenAI kostet 1k Token fĂŒr das Modell gpt-3.5-turbo-1106
$0.001.
Authentifizieren
Anmelden bei OpenAI:
= OpenAI() client
Dieses Anmeldeverfahren setzt voraus, dass in .Renviron
die Variable OPENAI_API_KEY
hinterlegt ist. \(\square\)
Anfrage an die API, in eine Funktion gepackt:
def get_completion(prompt, client_instance, model="gpt-3.5-turbo"):
= [{"role": "user", "content": prompt}]
messages = client_instance.chat.completions.create(
response =model,
model=messages,
messages=50,
max_tokens=0,
temperature
)return response.choices[0].message.content
API anfragen
Und jetzt als Schleife. Ergebnisliste anlegen, am Anfang noch leer:
= [] predicted_values
= time.time()
start_time
for prompt in prompts:
= get_completion(prompt, client)
result
predicted_values.append(result)
= time.time()
end_time - start_time end_time
VoilĂ :
print(predicted_values[:5])
[]
Als CSV speichern
= [i for i in range(start_pos, end_pos + 1)]
id_seq = pd.DataFrame(id_seq, columns = ["id"])
predicted_values_df "pred"] = predicted_values
predicted_values_df[
= datetime.now().strftime("%Y-%m-%d %H:%M:%S")
now = "germeval_test_preds_at_" + now
csv_output_name predicted_values_df.to_csv(csv_output_name)
Oder Vorhersagen aus CSV importieren
= 'https://raw.githubusercontent.com/sebastiansauer/Datenwerk2/main/posts/chatgpt-sentiment-loop-all/germeval_test_preds_at_2023-12-20%2014%3A06%3A00'
preds_path
= pd.read_csv(preds_path)
preds
preds.head()
Unnamed: 0 id pred
0 0 0 neutral
1 1 1 negativ
2 2 2 negativ
3 3 3 neutral
4 4 4 negativ
Man kann eine Python-Variable an R ĂŒbergeben:
<- py$preds preds_r
Vorhersagen (Predictions) betrachten
ZĂ€hlen wir mal kurz aus:
|>
preds_r count(pred) |>
slice(3:5) # zwei komische, kaputte Zeilen, weg damit
pred n
1 negativ 1792
2 neutral 1354
3 positiv 384
Oder in Python:
"pred"].value_counts() preds[
pred
negativ 1792
neutral 1354
positiv 384
muss. #AfD #Grenzschutz #Deutschland: negativ 1
kommen, in den eigenen vier WĂ€nden haben. Das ist doch wohl klar. #ltwlsa #ltw21 1
Name: count, dtype: int64
Puh, das ist ein bisschen was kaput gegangen.
Predictions reparieren
= ["positiv", "neutral", "negativ"]
allowed_preds ~preds["pred"].isin(allowed_preds), "pred"] = np.nan preds.loc[
Check:
"pred"].value_counts() preds[
pred
negativ 1792
neutral 1354
positiv 384
Name: count, dtype: int64
Passt!
Scoring vorbereiten
Was waren noch mal die Variablen unser Tabelle?
germeval_test.columns
Index(['id', 'text', 'c1', 'c2'], dtype='object')
Die ersten paar Werte:
germeval_test.head()
id text c1 c2
0 1 Meine Mutter hat mir erzÀhlt, dass mein Vater ... OTHER OTHER
1 2 @Tom174_ @davidbest95 Meine Reaktion; |LBR| Ni... OTHER OTHER
2 3 #Merkel rollt dem Emir von #Katar, der islamis... OTHER OTHER
3 4 âMerle ist kein junges unschuldiges MĂ€dchenâ K... OTHER OTHER
4 5 @umweltundaktiv Asylantenflut bringt eben nur ... OFFENSE ABUSE
Rescore im Test-Set:
= germeval_test
df "c1"] = df["c1"].replace({"OFFENSE": "negativ"})
df[
"c1"].value_counts() df[
c1
OTHER 2330
negativ 1202
Name: count, dtype: int64
Rescore in den Vorhersagen
"pred"] = preds["pred"].replace({"neutral": "OTHER", "positiv": "OTHER"})
preds[
"pred"].value_counts() preds[
pred
negativ 1792
OTHER 1738
Name: count, dtype: int64
= preds["pred"].tolist() preds_list
Hier ist die Liste der wahren Werte:
= df["c1"].values.tolist() y
Scoring
= accuracy_score(y, preds_list)
accuracy print("Accuracy:", accuracy)
Accuracy: 0.7355605889014722
Oder mit tidymodels
; zuerst aufbereiten:
= as.factor(py$y)
y_truth = py$preds_list
y_pred
# replace NAN with NA and convert to factor:
= as.character(y_pred)
y_pred is.nan(y_pred)] <- NA
y_pred[!y_pred %in% c("negativ", "OTHER")] <- NA
y_pred[<- as.factor(y_pred)
y_pred
table(y_pred)
y_pred
negativ OTHER
1792 1738
accuracy_vec(truth = y_truth,
estimate = y_pred)
[1] 0.7359773
Fun
<- plot_ly(
fig domain = list(x = c(0, 1), y = c(0, 1)),
value = 74,
title = list(text = "Accuracy"),
type = "indicator",
mode = "gauge+number")
<- fig %>%
fig layout(margin = list(l=20,r=30))
fig