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
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)
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__
```{zsh openai-version-zsh}
pip list | grep openai
```
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[
Check: Wie viele Elemente hat die Liste prompts
?
len(prompts)
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()
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
Oder in Python:
"pred"].value_counts() preds[
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[
Passt!
Scoring vorbereiten
Was waren noch mal die Variablen unser Tabelle?
germeval_test.columns
Die ersten paar Werte:
germeval_test.head()
Rescore im Test-Set:
= germeval_test
df "c1"] = df["c1"].replace({"OFFENSE": "negativ"})
df[
"c1"].value_counts() df[
Rescore in den Vorhersagen
"pred"] = preds["pred"].replace({"neutral": "OTHER", "positiv": "OTHER"})
preds[
"pred"].value_counts() preds[
= 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)
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)
accuracy_vec(truth = y_truth,
estimate = y_pred)
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