Skip to content

Commit b547150

Browse files
authored
chore(deps): bump Python deps to resolve security advisories (#1440)
Resolves 33 of 35 known CVEs reported by pip-audit by bumping direct and transitive dependencies. Two residual issues remain: pytest 8.x (local UNIX tmpdir CVE; bumping cascades to pytest-asyncio 1.x major API break) and diskcache 5.6.3 (no upstream fix; pulled by outlines under the transformers/huggingface extras only, local write-access exploit only). Direct bumps in pyproject.toml: - cryptography >=46.0.5 -> >=46.0.7 - langchain-core >=1.2.15 -> >=1.2.28 - langsmith >=0.7.6 -> >=0.7.31 - litellm ^1.80.11 -> ^1.83.14 (drags in fixed aiohttp + python-dotenv) - requests ^2.32 -> >=2.33.0 - pillow >=12.1.1 -> >=12.2.0 - pypdf >=6.9.1 -> >=6.10.2 - transformers >=4.49 -> >=5.0.0 (also drops the darwin x86_64 <=4.51.3 cap) - peft ^0.17.1 -> ^0.19.1 (required for transformers 5.x compat) Transitive bumps via poetry update: aiohttp 3.13.4, authlib 1.6.11, langchain-text-splitters 1.1.2, lxml 6.1.0, pygments 2.20.0, python-dotenv 1.2.2, python-multipart 0.0.26. Code adjustments forced by the upgrade: - a2a/serve/server.py: starlette 1.0 removed Starlette.add_event_handler; switched the health endpoint readiness tracking to a lifespan context manager assigned via app.router.lifespan_context. - transformers/backend/chat.py: transformers 5.x retyped AutoTokenizer.from_pretrained as TokenizersBackend | None and broadened apply_chat_template/decode return types; added casts so type checks pass. Signed-off-by: Tomáš Dvořák <toomas2d@gmail.com>
1 parent 8435ae4 commit b547150

4 files changed

Lines changed: 3824 additions & 3834 deletions

File tree

python/beeai_framework/adapters/a2a/serve/server.py

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import asyncio
55
import contextlib
66
import signal
7-
from collections.abc import Sequence
7+
from collections.abc import AsyncIterator, Sequence
88
from typing import Any, Literal, Self
99

1010
import uvicorn
@@ -149,19 +149,21 @@ def serve(self) -> None:
149149
def _add_health_endpoint(self, app: Starlette) -> None:
150150
"""Add health endpoint to the Starlette app."""
151151

152-
async def on_startup() -> None:
153-
self._ready = True
154-
155-
async def on_shutdown() -> None:
156-
self._ready = False
157-
158152
async def health_endpoint(request: Request) -> Response:
159153
content = "ok" if self._ready else "not ready"
160154
status = 200 if self._ready else 503
161155
return PlainTextResponse(content, status_code=status)
162156

163-
app.add_event_handler("startup", on_startup)
164-
app.add_event_handler("shutdown", on_shutdown)
157+
# Starlette 1.0 removed add_event_handler — swap in a lifespan context manager instead.
158+
@contextlib.asynccontextmanager
159+
async def lifespan(_app: Any) -> AsyncIterator[None]:
160+
self._ready = True
161+
try:
162+
yield
163+
finally:
164+
self._ready = False
165+
166+
app.router.lifespan_context = lifespan
165167
app.routes.append(Route("/health", endpoint=health_endpoint))
166168

167169
@override

python/beeai_framework/adapters/transformers/backend/chat.py

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,22 @@
44
import asyncio
55
import os
66
from collections.abc import AsyncGenerator
7-
from typing import Any, Unpack
7+
from typing import Any, Unpack, cast
88

99
import outlines
1010
import torch
1111
from outlines.inputs import Chat
1212
from outlines.types import JsonSchema
1313
from peft import PeftModel
1414
from pydantic import BaseModel
15-
from transformers import AutoModelForCausalLM, AutoTokenizer, StoppingCriteria, TextIteratorStreamer, set_seed
15+
from transformers import (
16+
AutoModelForCausalLM,
17+
AutoTokenizer,
18+
PreTrainedTokenizerBase,
19+
StoppingCriteria,
20+
TextIteratorStreamer,
21+
set_seed,
22+
)
1623

1724
from beeai_framework.adapters.litellm.utils import to_strict_json_schema
1825
from beeai_framework.adapters.transformers.backend._utils import (
@@ -71,7 +78,12 @@ def __init__(
7178
self._model_id = (
7279
model_id if model_id else os.getenv("TRANSFORMERS_CHAT_MODEL", "ibm-granite/granite-3.3-8b-instruct")
7380
)
74-
self.tokenizer = AutoTokenizer.from_pretrained(model_id, token=hf_token, **(tokenizer_kwargs or {})) # type: ignore
81+
# AutoTokenizer.from_pretrained is typed as TokenizersBackend | None in transformers 5.x,
82+
# but at runtime returns a PreTrainedTokenizerBase subclass.
83+
self.tokenizer = cast(
84+
PreTrainedTokenizerBase,
85+
AutoTokenizer.from_pretrained(model_id, token=hf_token, **(tokenizer_kwargs or {})),
86+
)
7587
model_base = AutoModelForCausalLM.from_pretrained(
7688
self._model_id,
7789
device_map="auto",
@@ -252,7 +264,9 @@ async def _get_model_output(
252264
self, input: ChatModelInput, streamer: TextIteratorStreamer | None
253265
) -> tuple[str, Any | None]:
254266
llm_input = self._transform_input(input)
255-
inputs = self.tokenizer.apply_chat_template(
267+
# apply_chat_template with return_dict=True returns a BatchEncoding (dict-like) at runtime,
268+
# but the static type covers many shapes (list, str, dict). Cast for indexing.
269+
inputs: Any = self.tokenizer.apply_chat_template(
256270
llm_input["messages"],
257271
tools=llm_input["tools"],
258272
tokenize=True,
@@ -305,7 +319,8 @@ async def _get_model_output(
305319
**kwargs,
306320
)
307321
generated_tokens = model_output[0, prompt_tokens:]
308-
generated_text = self.tokenizer.decode(generated_tokens, skip_special_tokens=True)
322+
# tokenizer.decode is typed as list[str] | str but returns str when given a 1-D tensor.
323+
generated_text = cast(str, self.tokenizer.decode(generated_tokens, skip_special_tokens=True))
309324
return generated_text, None
310325

311326
def _format_tool_model(self, model: type[BaseModel]) -> dict[str, Any]:

0 commit comments

Comments
 (0)