fix(projekt-matching): disable thinking for structured vLLM calls; retry non-JSON responses
With the vLLM qwen3 reasoning parser active, json_schema guided decoding
plus thinking degenerates: runs burn the whole 65k context
(finish_reason "length", ~63k completion tokens) and return empty or
truncated content. chat_template_kwargs {"enable_thinking": false} fixes
it (extract answers in ~35 s). Also: retry chat_json up to 3x on
non-JSON content, and two prompt calibrations verified against both
gate examples — Nice signal words bind only to their own line (following
unmarked lines stay Must), and compound requirements with clear evidence
for one part rate "unknown" instead of "no".
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,12 @@
|
|||||||
"""vLLM (OpenAI-compatible) calls with response_format json_schema + German prompts.
|
"""vLLM (OpenAI-compatible) calls with response_format json_schema + German prompts.
|
||||||
|
|
||||||
The model is a REASONING model: max_tokens stays UNSET so long thinking
|
max_tokens stays UNSET so nothing can truncate the final answer (65k
|
||||||
chains cannot truncate the final answer (65k context window).
|
context window). Thinking is DISABLED via chat_template_kwargs: with the
|
||||||
|
vLLM qwen3 reasoning parser active, json_schema guided decoding plus
|
||||||
|
thinking degenerates — the run burns the entire context window
|
||||||
|
(finish_reason "length", ~63k completion tokens) and returns empty or
|
||||||
|
truncated content (verified live in Task 13). Without thinking the same
|
||||||
|
extract call answers in ~35 s with valid schema-conformant JSON.
|
||||||
"""
|
"""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
@@ -86,7 +91,12 @@ Kategorie Misc.
|
|||||||
"plus"). Misc = Rahmenbedingungen und alles, was weder Muss noch \
|
"plus"). Misc = Rahmenbedingungen und alles, was weder Muss noch \
|
||||||
Wunsch-Qualifikation ist. Explizite Abschnittsüberschriften haben Vorrang \
|
Wunsch-Qualifikation ist. Explizite Abschnittsüberschriften haben Vorrang \
|
||||||
vor Signalwörtern; "idealerweise" INNERHALB einer Must-Zeile lässt die \
|
vor Signalwörtern; "idealerweise" INNERHALB einer Must-Zeile lässt die \
|
||||||
Zeile Must bleiben.
|
Zeile Must bleiben. Nice-Signalwörter gelten NUR für die Zeile, in der \
|
||||||
|
sie selbst stehen — sie färben NIE auf folgende Zeilen ab: Jede Zeile \
|
||||||
|
eines Anforderungs-Abschnitts OHNE eigenes Nice-Signalwort ist Must, \
|
||||||
|
auch wenn direkt davor Nice-Zeilen stehen. Beispiel: Auf "Idealerweise \
|
||||||
|
zusätzlich Erfahrung mit X" (Nice) folgt "Erfahrung mit Y" ohne \
|
||||||
|
Signalwort → Y ist Must.
|
||||||
- miscType nur für Misc-Zeilen relevant (sonst "other"): start = \
|
- miscType nur für Misc-Zeilen relevant (sonst "other"): start = \
|
||||||
Projektstart/Verfügbarkeit (startDate als ISO-Datum YYYY-MM-DD, wenn ein \
|
Projektstart/Verfügbarkeit (startDate als ISO-Datum YYYY-MM-DD, wenn ein \
|
||||||
konkretes Datum genannt ist, sonst null); workload = Auslastung \
|
konkretes Datum genannt ist, sonst null); workload = Auslastung \
|
||||||
@@ -117,7 +127,9 @@ Proof-of-Concept-Erfahrung deckt "produktiven Betrieb" NICHT ab; \
|
|||||||
"mehrjährig" wörtlich nehmen; ein Produktname (z. B. "Azure DevOps \
|
"mehrjährig" wörtlich nehmen; ein Produktname (z. B. "Azure DevOps \
|
||||||
Server") belegt KEINE Cloud-Plattform-Erfahrung.
|
Server") belegt KEINE Cloud-Plattform-Erfahrung.
|
||||||
- "unknown" NUR bei echter Teilevidenz, wenn die Entscheidung von Wissen \
|
- "unknown" NUR bei echter Teilevidenz, wenn die Entscheidung von Wissen \
|
||||||
abhängt, das nur der Kandidat selbst hat.
|
abhängt, das nur der Kandidat selbst hat. Zusammengesetzte Anforderungen \
|
||||||
|
("X sowie Y", "X und Y"): klare Evidenz für einen Teil und keine \
|
||||||
|
Gegen-Evidenz für den anderen → "unknown", nicht "no".
|
||||||
- "wie z. B."-Aufzählungen: gleichwertige Alternativen zählen als Abdeckung \
|
- "wie z. B."-Aufzählungen: gleichwertige Alternativen zählen als Abdeckung \
|
||||||
(Beispiel: Ollama/llama.cpp/Transformers decken "LLM-Inference-Stacks wie \
|
(Beispiel: Ollama/llama.cpp/Transformers decken "LLM-Inference-Stacks wie \
|
||||||
z. B. vLLM, TGI, Triton" ab).
|
z. B. vLLM, TGI, Triton" ab).
|
||||||
@@ -126,6 +138,7 @@ z. B. vLLM, TGI, Triton" ab).
|
|||||||
|
|
||||||
def _post(base, model, messages, schema):
|
def _post(base, model, messages, schema):
|
||||||
body = {"model": model, "messages": messages, "temperature": 0.1,
|
body = {"model": model, "messages": messages, "temperature": 0.1,
|
||||||
|
"chat_template_kwargs": {"enable_thinking": False},
|
||||||
"response_format": {"type": "json_schema", "json_schema": {
|
"response_format": {"type": "json_schema", "json_schema": {
|
||||||
"name": "out", "schema": schema}}}
|
"name": "out", "schema": schema}}}
|
||||||
return requests.post(f"{base.rstrip('/')}/chat/completions", json=body,
|
return requests.post(f"{base.rstrip('/')}/chat/completions", json=body,
|
||||||
|
|||||||
Reference in New Issue
Block a user