Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 30 additions & 6 deletions libs/core/langchain_core/messages/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -1076,6 +1076,35 @@
return merged


def _is_per_message_counter(fn: Callable) -> bool:
"""Determine if a callable is a per-message token counter.

Returns True if the callable appears to accept a single BaseMessage
rather than a list of BaseMessages. Handles lambdas (no annotation),
postponed annotations (``from __future__ import annotations``),
and subclass annotations (e.g. ``HumanMessage``).
"""
try:
sig = inspect.signature(fn)
except (ValueError, TypeError):
return False
params = list(sig.parameters.values())
if not params:
return False
ann = params[0].annotation
# No annotation (lambda, bare ``def``) — assume per-message counter
if ann is inspect.Parameter.empty:
return True
# Postponed / stringified annotation
if isinstance(ann, str):
return "message" in ann.lower()
# Direct type annotation — check if it's BaseMessage or a subclass
if isinstance(ann, type) and issubclass(ann, BaseMessage):
return True
return False

Check failure on line 1104 in libs/core/langchain_core/messages/utils.py

View workflow job for this annotation

GitHub Actions / lint (libs/core, 3.10) / Python 3.10

ruff (SIM103)

langchain_core/messages/utils.py:1102:5: SIM103 Return the condition directly help: Inline condition

Check failure on line 1104 in libs/core/langchain_core/messages/utils.py

View workflow job for this annotation

GitHub Actions / lint (libs/core, 3.11) / Python 3.11

ruff (SIM103)

langchain_core/messages/utils.py:1102:5: SIM103 Return the condition directly help: Inline condition

Check failure on line 1104 in libs/core/langchain_core/messages/utils.py

View workflow job for this annotation

GitHub Actions / lint (libs/core, 3.14) / Python 3.14

ruff (SIM103)

langchain_core/messages/utils.py:1102:5: SIM103 Return the condition directly help: Inline condition

Check failure on line 1104 in libs/core/langchain_core/messages/utils.py

View workflow job for this annotation

GitHub Actions / lint (libs/core, 3.12) / Python 3.12

ruff (SIM103)

langchain_core/messages/utils.py:1102:5: SIM103 Return the condition directly help: Inline condition

Check failure on line 1104 in libs/core/langchain_core/messages/utils.py

View workflow job for this annotation

GitHub Actions / lint (libs/core, 3.13) / Python 3.13

ruff (SIM103)

langchain_core/messages/utils.py:1102:5: SIM103 Return the condition directly help: Inline condition



# TODO: Update so validation errors (for token_counter, for example) are raised on
# init not at runtime.
@_runnable_support
Expand Down Expand Up @@ -1417,12 +1446,7 @@
if hasattr(actual_token_counter, "get_num_tokens_from_messages"):
list_token_counter = actual_token_counter.get_num_tokens_from_messages
elif callable(actual_token_counter):
if (
next(
iter(inspect.signature(actual_token_counter).parameters.values())
).annotation
is BaseMessage
):
if _is_per_message_counter(actual_token_counter):

def list_token_counter(messages: Sequence[BaseMessage]) -> int:
return sum(actual_token_counter(msg) for msg in messages) # type: ignore[arg-type, misc]
Expand Down
Loading