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.
|
||||
|
||||
The model is a REASONING model: max_tokens stays UNSET so long thinking
|
||||
chains cannot truncate the final answer (65k context window).
|
||||
max_tokens stays UNSET so nothing can truncate the final answer (65k
|
||||
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
|
||||
|
||||
@@ -86,7 +91,12 @@ Kategorie Misc.
|
||||
"plus"). Misc = Rahmenbedingungen und alles, was weder Muss noch \
|
||||
Wunsch-Qualifikation ist. Explizite Abschnittsüberschriften haben Vorrang \
|
||||
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 = \
|
||||
Projektstart/Verfügbarkeit (startDate als ISO-Datum YYYY-MM-DD, wenn ein \
|
||||
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 \
|
||||
Server") belegt KEINE Cloud-Plattform-Erfahrung.
|
||||
- "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 \
|
||||
(Beispiel: Ollama/llama.cpp/Transformers decken "LLM-Inference-Stacks wie \
|
||||
z. B. vLLM, TGI, Triton" ab).
|
||||
@@ -126,6 +138,7 @@ z. B. vLLM, TGI, Triton" ab).
|
||||
|
||||
def _post(base, model, messages, schema):
|
||||
body = {"model": model, "messages": messages, "temperature": 0.1,
|
||||
"chat_template_kwargs": {"enable_thinking": False},
|
||||
"response_format": {"type": "json_schema", "json_schema": {
|
||||
"name": "out", "schema": schema}}}
|
||||
return requests.post(f"{base.rstrip('/')}/chat/completions", json=body,
|
||||
|
||||
Reference in New Issue
Block a user