CoolFace
Modelpublic

patdev/k3-a40-bootstrap

sourceHugging Faceotherupdated 19d agoView on Hugging Face
0likes1.3kdownloads
vllm_anthropic_effort_patch.py110 linesDownload Raw Back to root
1"""Patch du serveur Anthropic natif de vLLM 0.27.1 : niveau de raisonnement.2 3Ce que vLLM fait nativement (verifie dans les sources, 22/08) :4  - `output_config.effort` -> `reasoning_effort`, que seul Harmony/GPT-OSS lit ;5    sur Qwen/Ornith ca ne change RIEN (mesure : effort max = effort low).6  - `thinking: {type, budget_tokens}` n'existe pas dans AnthropicMessagesRequest :7    pydantic le jette. Ni `disabled` ni le budget n'agissent.8 9Ce patch, applique a l'installation dans le venv (idempotent, avant `vllm serve`) :10  1. ajoute le champ `thinking` a AnthropicMessagesRequest ;11  2. dans `_handle_output_config` : effort -> `thinking_token_budget`12     (low 1024, medium 4096, high 16384, xhigh 32768, max/illimite = None) ;13     `thinking.budget_tokens` explicite gagne ; `thinking.type == "disabled"`14     -> chat_template_kwargs.enable_thinking = False.15`thinking_token_budget` est applique par vLLM cote echantillonnage (le bloc de16raisonnement est ferme au plafond) : c'est le meme mecanisme que le pont.17 18    /opt/venv/bin/python vllm_anthropic_effort_patch.py        # applique19    /opt/venv/bin/python vllm_anthropic_effort_patch.py --check # verifie seulement20"""21from __future__ import annotations22 23import ast24import importlib.util25import os26import sys27 28MARK = "# [patch effort->thinking_token_budget]"29 30 31def _chemin(mod: str) -> str:32    spec = importlib.util.find_spec(mod)33    if not spec or not spec.origin:34        raise SystemExit(f"module introuvable : {mod}")35    return spec.origin36 37 38def patch_protocol(p: str) -> bool:39    s = open(p, encoding="utf-8").read()40    if MARK in s:41        return False42    anchor = "    output_config: AnthropicOutputConfig | None = None\n"43    if anchor not in s:44        raise SystemExit("protocol.py : ancre output_config introuvable (version differente ?)")45    s = s.replace(anchor, anchor + f"    thinking: dict[str, Any] | None = None  {MARK}\n", 1)46    ast.parse(s)47    open(p, "w", encoding="utf-8").write(s)48    return True49 50 51def patch_serving(p: str) -> bool:52    s = open(p, encoding="utf-8").read()53    if MARK in s:54        return False55    anchor = ("        if output_config and output_config.effort is not None:\n"56              "            req.reasoning_effort = output_config.effort\n")57    if anchor not in s:58        raise SystemExit("serving.py : ancre effort introuvable (version differente ?)")59    new = anchor + f'''        {MARK}60        # Niveau de raisonnement -> plafond de jetons de raisonnement, seul61        # mecanisme que les modeles Qwen/Ornith honorent. Le budget explicite62        # d'Anthropic (thinking.budget_tokens) gagne sur l'effort.63        _BUDGET = {{"low": 1024, "medium": 4096, "high": 16384, "xhigh": 32768, "max": None}}64        _eff = output_config.effort if output_config else None65        if _eff in _BUDGET:66            req.thinking_token_budget = _BUDGET[_eff]67        _th = getattr(anthropic_request, "thinking", None)68        if isinstance(_th, dict):69            if _th.get("type") == "disabled":70                _kw = dict(req.chat_template_kwargs or {{}})71                _kw.setdefault("enable_thinking", False)72                req.chat_template_kwargs = _kw73            elif _th.get("budget_tokens"):74                try:75                    req.thinking_token_budget = max(1, int(_th["budget_tokens"]))76                except (TypeError, ValueError):77                    pass78'''79    s = s.replace(anchor, new, 1)80    ast.parse(s)81    open(p, "w", encoding="utf-8").write(s)82    return True83 84 85def main() -> None:86    check = "--check" in sys.argv87    pp = _chemin("vllm.entrypoints.anthropic.protocol")88    sp = _chemin("vllm.entrypoints.anthropic.serving")89    if check:90        ok = MARK in open(pp, encoding="utf-8").read() and MARK in open(sp, encoding="utf-8").read()91        print("patch effort :", "present" if ok else "ABSENT")92        sys.exit(0 if ok else 1)93    a = patch_protocol(pp)94    b = patch_serving(sp)95    print(f"protocol.py {'patche' if a else 'deja patche'} ; serving.py {'patche' if b else 'deja patche'}")96    # purge des .pyc pour que la version patchee soit bien celle chargee97    for p in (pp, sp):98        d = os.path.join(os.path.dirname(p), "__pycache__")99        if os.path.isdir(d):100            for f in os.listdir(d):101                if f.startswith(os.path.basename(p)[:-3]):102                    try:103                        os.remove(os.path.join(d, f))104                    except OSError:105                        pass106 107 108if __name__ == "__main__":109    main()110