| 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181 | """Werkzeugfaehige Modelle.
Nur Eintraege, deren GGUF-Vorlage Werkzeuge kennt. Geprueft am 16.10.2026
ueber den GGUF-Kopf (HTTP-Bereichsabruf, keine Miete):
`tools` kommt in tokenizer.chat_template vor.
Herausgefallen: glm-53 (keine Vorlage, 460 GB), r1-distill-32b,
mistral-small-24b-abliterated, cydonia-24b (Vorlage ohne Werkzeuge).
Die Vorlage ist die halbe Wahrheit - Ollama muss sie auch als werkzeugfaehig
erkennen. Das prueft karte.py nach dem Laden ueber /api/show
(`capabilities` enthaelt "tools") und gibt die Karte sonst zurueck.
"kontext" bei den Coding-Modellen stammt aus einer KV-Rechnung (nicht
gemessen). Bei den uebrigen ist er hier gesetzt und ebenfalls **nicht
gemessen**; karte.py prueft nach dem Aufwaermen, ob alles im Grafikspeicher
liegt. 8192 bei den 70B auf 48 GB ist fuer Agentenarbeit knapp.
"""
MODELLE: dict[str, dict] = {
# --- fuers Programmieren gebaut
"qwen3-coder-30b": {
"name": "Qwen3-Coder 30B A3B",
"hf": "hf.co/unsloth/Qwen3-Coder-30B-A3B-Instruct-GGUF:Q4_K_M",
"gb": 18.6, "vram": 24, "kontext": 24576, "denkt": False, "code": True,
"notiz": "Arbeitspferd, schnell (3 Mrd. aktiv), Original von Alibaba",
},
"qwen3-coder-30b-heretic": {
"name": "Qwen3-Coder 30B A3B heretic",
"hf": "hf.co/mradermacher/Qwen3-Coder-30B-A3B-Instruct-Heretic-GGUF:Q4_K_M",
"gb": 18.6, "vram": 24, "kontext": 24576, "denkt": False, "code": True,
"notiz": "wie oben, enthemmt",
},
"qwen3-coder-next": {
"name": "Qwen3-Coder-Next 80B A3B",
"hf": "hf.co/unsloth/Qwen3-Coder-Next-GGUF:Q4_K_M",
"gb": 48.5, "vram": 80, "kontext": 65536, "denkt": False, "code": True,
"notiz": "stärkstes Coding-Modell hier, langer Kontext, 80-GB-Karte",
},
"qwen3-coder-next-heretic": {
"name": "Qwen3-Coder-Next 80B heretic",
"hf": "hf.co/mradermacher/Qwen3-Coder-Next-Uncensored-Heretic-GGUF:Q4_K_M",
"gb": 48.5, "vram": 80, "kontext": 65536, "denkt": False, "code": True,
"notiz": "wie oben, enthemmt",
},
# 17.10.2026: grosse heretic-Modelle, die denken. Vorlage per GGUF-Kopf
# geprueft (tools + Denkteil), beide Einzeldateien. Kontext geschaetzt,
# nicht gemessen: beide haben kleinen KV-Speicher (gpt-oss: halbe
# Schichten Gleitfenster, Qwen3.5: 3/4 lineare Aufmerksamkeit).
"gpt-oss-120b-heretic": {
"name": "gpt-oss 120B heretic v2",
"hf": "hf.co/llmfan46/gpt-oss-120b-heretic-v2-GGUF:MXFP4",
"gb": 65.4, "vram": 80, "kontext": 32768, "denkt": True, "code": True,
"notiz": "denkt, groß, 5 Mrd. aktiv und damit flott, 80-GB-Karte",
},
"qwen35-122b-heretic": {
"name": "Qwen 3.5 122B A10B heretic v2",
"hf": "hf.co/mradermacher/Qwen3.5-122B-A10B-heretic-v2-GGUF:IQ4_XS",
"gb": 66.0, "vram": 80, "kontext": 32768, "denkt": True, "code": True,
"notiz": "denkt, größtes Modell im Katalog, 80-GB-Karte",
},
"devstral-small-2": {
"name": "Devstral Small 2 24B",
"hf": "hf.co/unsloth/Devstral-Small-2-24B-Instruct-2512-GGUF:Q4_K_M",
"gb": 14.3, "vram": 24, "kontext": 32768, "denkt": False, "code": True,
"notiz": "von Mistral für Agenten-Coding trainiert",
},
"devstral-small-2-abliterated": {
"name": "Devstral Small 2 24B abliterated",
"hf": "hf.co/mradermacher/Huihui-Devstral-Small-2-24B-Instruct-2512-abliterated-GGUF:Q4_K_M",
"gb": 14.3, "vram": 24, "kontext": 32768, "denkt": False, "code": True,
"notiz": "wie oben, enthemmt",
},
"glm47-flash": {
"name": "GLM-4.7-Flash 30B A3B",
"hf": "hf.co/unsloth/GLM-4.7-Flash-GGUF:Q4_K_M",
"gb": 18.3, "vram": 24, "kontext": 32768, "denkt": True, "code": True,
"notiz": "denkt vor der Antwort, schnell",
},
"glm47-flash-heretic": {
"name": "GLM-4.7-Flash heretic",
"hf": "hf.co/mradermacher/GLM-4.7-Flash-heretic-1.2.0-GGUF:Q4_K_M",
"gb": 18.1, "vram": 24, "kontext": 32768, "denkt": True, "code": True,
"notiz": "wie oben, enthemmt",
},
"qwen25-coder-32b": {
"name": "Qwen 2.5 Coder 32B abliterated",
"hf": "hf.co/mradermacher/Qwen2.5-Coder-32B-Instruct-abliterated-GGUF:Q4_K_M",
"gb": 19.9, "vram": 24, "kontext": 16384, "denkt": False, "code": True,
"notiz": "ältere Generation, dicht und damit langsamer",
},
# --- allgemeine Modelle mit Werkzeugvorlage
"gemma4-31b-heretic": {
"name": "Gemma 4 31B heretic",
"hf": "hf.co/mradermacher/gemma-4-31B-it-heretic-GGUF:Q4_K_M",
"gb": 18.7, "vram": 24, "kontext": 16384, "denkt": False, "code": False,
"notiz": "klügstes Allround-Modell im Katalog",
},
"qwen36-35b-a3b-heretic": {
"name": "Qwen 3.6 35B A3B heretic",
"hf": "hf.co/mradermacher/Qwen3.6-35B-A3B-uncensored-heretic-GGUF:Q4_K_M",
"gb": 21.2, "vram": 24, "kontext": 16384, "denkt": True, "code": False,
"notiz": "schnelles Denkmodell",
},
"qwen3-30b-a3b-abliterated": {
"name": "Qwen 3 30B A3B abliterated",
"hf": "hf.co/mradermacher/Qwen3-30B-A3B-abliterated-GGUF:Q4_K_M",
"gb": 18.6, "vram": 24, "kontext": 16384, "denkt": True, "code": False,
"notiz": "denkt und ist trotzdem schnell",
},
"qwen3-32b-abliterated": {
"name": "Qwen 3 32B abliterated",
"hf": "hf.co/mradermacher/Qwen3-32B-abliterated-GGUF:Q4_K_M",
"gb": 19.8, "vram": 24, "kontext": 16384, "denkt": True, "code": False,
"notiz": "dicht, langsam beim Denken",
},
"qwq-32b-abliterated": {
"name": "QwQ 32B abliterated",
"hf": "hf.co/mradermacher/QwQ-32B-abliterated-GGUF:Q4_K_M",
"gb": 19.9, "vram": 24, "kontext": 16384, "denkt": True, "code": False,
"notiz": "denkt immer lange",
},
"qwen25-72b-abliterated": {
"name": "Qwen 2.5 72B abliterated",
"hf": "hf.co/mradermacher/Qwen2.5-72B-Instruct-abliterated-GGUF:Q4_K_M",
"gb": 47.4, "vram": 80, "kontext": 32768, "denkt": False, "code": False,
"notiz": "groß und gemächlich, 80-GB-Karte",
},
"llama33-70b-abliterated": {
"name": "Llama 3.3 70B abliterated",
"hf": "hf.co/mradermacher/Llama-3.3-70B-Instruct-abliterated-GGUF:Q4_K_M",
"gb": 42.5, "vram": 48, "kontext": 8192, "denkt": False, "code": False,
"notiz": "gemächlich, Kontext knapp",
},
"llama31-70b-lorablated": {
"name": "Llama 3.1 70B lorablated",
"hf": "hf.co/bartowski/Llama-3.1-70B-Instruct-lorablated-GGUF:Q4_K_M",
"gb": 42.5, "vram": 48, "kontext": 8192, "denkt": False, "code": False,
"notiz": "gemächlich, Kontext knapp",
},
"anubis-70b": {
"name": "Anubis 70B v1.1",
"hf": "hf.co/bartowski/TheDrummer_Anubis-70B-v1.1-GGUF:Q4_K_M",
"gb": 42.5, "vram": 48, "kontext": 8192, "denkt": False, "code": False,
"notiz": "Rollenspielmodell, für Code kaum geeignet",
},
"llama31-8b-lexi": {
"name": "Llama 3.1 8B Lexi",
"hf": "hf.co/bartowski/Llama-3.1-8B-Lexi-Uncensored-V2-GGUF:Q4_K_M",
"gb": 4.9, "vram": 16, "kontext": 16384, "denkt": False, "code": False,
"notiz": "sehr schnell und billig, zum Ausprobieren",
},
}
STANDARD_MODELL = "qwen3-coder-30b-heretic"
def finden(text: str) -> str | None:
"""Kennung, Nummer aus der Liste oder eindeutiger Namensteil."""
text = text.strip().lower()
if text in MODELLE:
return text
if text.isdigit():
liste = list(MODELLE)
n = int(text)
return liste[n - 1] if 1 <= n <= len(liste) else None
treffer = [k for k, m in MODELLE.items()
if text in k or text in m["name"].lower()]
return treffer[0] if len(treffer) == 1 else None
# Zum Testen gegen ein festes Ollama (KODE_BASIS): beliebiges Modell dort.
import os as _os # noqa: E402
if _os.getenv("KODE_BASIS") and _os.getenv("KODE_LOKAL_MODELL"):
MODELLE["lokal"] = {
"name": f"lokal: {_os.environ['KODE_LOKAL_MODELL']}",
"hf": _os.environ["KODE_LOKAL_MODELL"], "gb": 0, "vram": 0,
"kontext": int(_os.getenv("KODE_LOKAL_KONTEXT", "8192")),
"denkt": _os.getenv("KODE_LOKAL_DENKT") == "1", "code": True,
"notiz": "fester Endpunkt, nichts gemietet",
} |