Update utils.py
Browse files
utils.py
CHANGED
@@ -24,30 +24,60 @@ class CSVAnalyzer:
|
|
24 |
self.tokenizer, self.model = CSVAnalyzer.load_model()
|
25 |
|
26 |
def prepare_context(self, df: pd.DataFrame) -> str:
|
|
|
|
|
|
|
27 |
try:
|
28 |
if df.empty:
|
29 |
return "Keine Daten verfügbar"
|
30 |
|
31 |
-
#
|
32 |
-
|
33 |
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
|
|
|
|
41 |
|
42 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
43 |
|
44 |
-
#
|
45 |
-
|
46 |
-
|
47 |
-
context +=
|
48 |
-
for
|
49 |
-
context += f"- {
|
50 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
51 |
|
52 |
return context
|
53 |
|
@@ -55,17 +85,23 @@ class CSVAnalyzer:
|
|
55 |
raise Exception(f"Fehler bei der Kontextvorbereitung: {str(e)}")
|
56 |
|
57 |
def generate_response(self, context: str, query: str) -> str:
|
58 |
-
prompt = f"""<|system|>
|
|
|
59 |
Berücksichtige dabei:
|
60 |
-
1.
|
61 |
-
2.
|
62 |
-
3.
|
|
|
|
|
|
|
|
|
63 |
|
64 |
<|user|>
|
|
|
65 |
{context}
|
66 |
|
|
|
67 |
{query}
|
68 |
-
Nenne direkt das problematischste Gebäude und begründe kurz warum.
|
69 |
|
70 |
<|assistant|>"""
|
71 |
|
@@ -74,7 +110,7 @@ Nenne direkt das problematischste Gebäude und begründe kurz warum.
|
|
74 |
prompt,
|
75 |
return_tensors="pt",
|
76 |
truncation=True,
|
77 |
-
max_length=
|
78 |
padding=True,
|
79 |
return_attention_mask=True
|
80 |
)
|
@@ -83,8 +119,8 @@ Nenne direkt das problematischste Gebäude und begründe kurz warum.
|
|
83 |
outputs = self.model.generate(
|
84 |
input_ids=inputs["input_ids"],
|
85 |
attention_mask=inputs["attention_mask"],
|
86 |
-
max_new_tokens=
|
87 |
-
temperature=0.
|
88 |
top_p=0.95,
|
89 |
repetition_penalty=1.15,
|
90 |
do_sample=True
|
|
|
24 |
self.tokenizer, self.model = CSVAnalyzer.load_model()
|
25 |
|
26 |
def prepare_context(self, df: pd.DataFrame) -> str:
|
27 |
+
"""
|
28 |
+
Bereitet einen allgemeinen Kontext aus dem DataFrame vor.
|
29 |
+
"""
|
30 |
try:
|
31 |
if df.empty:
|
32 |
return "Keine Daten verfügbar"
|
33 |
|
34 |
+
# Grundlegende Informationen
|
35 |
+
context = "DATASET ÜBERSICHT:\n\n"
|
36 |
|
37 |
+
# Dimensionen
|
38 |
+
context += f"Datensatzgröße: {len(df)} Zeilen, {len(df.columns)} Spalten\n\n"
|
39 |
+
|
40 |
+
# Spaltenliste mit Datentypen
|
41 |
+
context += "SPALTENINFORMATIONEN:\n"
|
42 |
+
for col in df.columns:
|
43 |
+
dtype = df[col].dtype
|
44 |
+
non_null = df[col].count()
|
45 |
+
null_percentage = (len(df) - non_null) / len(df) * 100
|
46 |
|
47 |
+
# Erkennung spezieller Datentypen
|
48 |
+
if pd.api.types.is_datetime64_any_dtype(df[col]):
|
49 |
+
date_range = f"von {df[col].min()} bis {df[col].max()}"
|
50 |
+
context += f"- {col} (Datum): {date_range}, {null_percentage:.1f}% NULL\n"
|
51 |
+
elif pd.api.types.is_numeric_dtype(df[col]):
|
52 |
+
context += f"- {col} (Numerisch): Min={df[col].min():.2f}, Max={df[col].max():.2f}, {null_percentage:.1f}% NULL\n"
|
53 |
+
else:
|
54 |
+
unique_values = df[col].nunique()
|
55 |
+
context += f"- {col} (Text): {unique_values} eindeutige Werte, {null_percentage:.1f}% NULL\n"
|
56 |
+
|
57 |
+
# Grundlegende Statistiken für numerische Spalten
|
58 |
+
numeric_cols = df.select_dtypes(include=['int64', 'float64']).columns
|
59 |
+
if not numeric_cols.empty:
|
60 |
+
context += "\nNUMERISCHE STATISTIKEN:\n"
|
61 |
+
stats = df[numeric_cols].describe()
|
62 |
+
for col in numeric_cols:
|
63 |
+
context += f"- {col}:\n"
|
64 |
+
context += f" Durchschnitt: {stats[col]['mean']:.2f}\n"
|
65 |
+
context += f" Median: {stats[col]['50%']:.2f}\n"
|
66 |
+
context += f" Standardabweichung: {stats[col]['std']:.2f}\n"
|
67 |
|
68 |
+
# Zeitliche Informationen, falls vorhanden
|
69 |
+
date_cols = df.select_dtypes(include=['datetime64']).columns
|
70 |
+
if not date_cols.empty:
|
71 |
+
context += "\nZEITLICHE INFORMATIONEN:\n"
|
72 |
+
for col in date_cols:
|
73 |
+
context += f"- {col}:\n"
|
74 |
+
context += f" Zeitspanne: von {df[col].min()} bis {df[col].max()}\n"
|
75 |
+
context += f" Anzahl eindeutiger Daten: {df[col].nunique()}\n"
|
76 |
+
|
77 |
+
# Stichprobe der Daten
|
78 |
+
context += "\nDATENBEISPIELE:\n"
|
79 |
+
sample = df.head(3).to_string()
|
80 |
+
context += f"{sample}\n"
|
81 |
|
82 |
return context
|
83 |
|
|
|
85 |
raise Exception(f"Fehler bei der Kontextvorbereitung: {str(e)}")
|
86 |
|
87 |
def generate_response(self, context: str, query: str) -> str:
|
88 |
+
prompt = f"""<|system|>
|
89 |
+
Du bist ein Datenanalyst, der CSV-Dateien analysiert. Deine Aufgabe ist es, Fragen über die Daten zu beantworten.
|
90 |
Berücksichtige dabei:
|
91 |
+
1. Die Struktur und die Arten der verfügbaren Daten
|
92 |
+
2. Statistische Informationen, falls relevant
|
93 |
+
3. Mögliche Zusammenhänge zwischen verschiedenen Spalten
|
94 |
+
4. Zeitliche Muster, falls Datumsinformationen vorhanden sind
|
95 |
+
|
96 |
+
Antworte präzise und faktenbasiert. Wenn die Frage nicht mit den verfügbaren Daten beantwortet werden kann,
|
97 |
+
erkläre warum.
|
98 |
|
99 |
<|user|>
|
100 |
+
KONTEXT:
|
101 |
{context}
|
102 |
|
103 |
+
FRAGE:
|
104 |
{query}
|
|
|
105 |
|
106 |
<|assistant|>"""
|
107 |
|
|
|
110 |
prompt,
|
111 |
return_tensors="pt",
|
112 |
truncation=True,
|
113 |
+
max_length=2048, # Erhöht für komplexere Analysen
|
114 |
padding=True,
|
115 |
return_attention_mask=True
|
116 |
)
|
|
|
119 |
outputs = self.model.generate(
|
120 |
input_ids=inputs["input_ids"],
|
121 |
attention_mask=inputs["attention_mask"],
|
122 |
+
max_new_tokens=256, # Erhöht für ausführlichere Antworten
|
123 |
+
temperature=0.7, # Erhöht für kreativere Analysen
|
124 |
top_p=0.95,
|
125 |
repetition_penalty=1.15,
|
126 |
do_sample=True
|