From d8a3e1f0fc50a409105ee3f52dca9e5da9d52b87 Mon Sep 17 00:00:00 2001 From: ViditOstwal Date: Mon, 19 Oct 2026 15:19:52 +0530 Subject: [PATCH] refactor(llm): share summary prompt builder --- lib/crewai/src/crewai/llms/context_window.py | 19 +++---------------- .../src/crewai/utilities/message_utils.py | 15 +++++++++++++++ lib/crewai/tests/llms/test_context_window.py | 6 +++--- 3 files changed, 21 insertions(+), 19 deletions(-) diff --git a/lib/crewai/src/crewai/llms/context_window.py b/lib/crewai/src/crewai/llms/context_window.py index 5403a7809..12750b9c0 100644 --- a/lib/crewai/src/crewai/llms/context_window.py +++ b/lib/crewai/src/crewai/llms/context_window.py @@ -26,10 +26,10 @@ from crewai.utilities.exceptions.context_window_exceeding_exception import ( ) from crewai.utilities.i18n import I18N_DEFAULT from crewai.utilities.message_utils import ( + build_summary_prompt, collect_user_message_files, format_message_for_llm, message_content_text, - messages_content_text, ) @@ -316,7 +316,7 @@ def _summarize_chunks( try: async with semaphore: response = str( - await llm.acall(_build_summary_prompt(chunk), callbacks=callbacks) + await llm.acall(build_summary_prompt(chunk), callbacks=callbacks) ) except Exception as error: if not LLMContextLengthExceededError( @@ -403,19 +403,6 @@ def _compact_summaries( ) -def _build_summary_prompt(chunk: list[LLMMessage]) -> list[LLMMessage]: - return [ - format_message_for_llm( - I18N_DEFAULT.slice("summarizer_system_message"), "system" - ), - format_message_for_llm( - I18N_DEFAULT.slice("summarize_instruction").format( - conversation=messages_content_text(chunk) - ) - ), - ] - - def _chunk_messages( llm: Any, messages: list[LLMMessage], max_tokens: int ) -> list[list[LLMMessage]]: @@ -501,4 +488,4 @@ def _split_message_to_fit( def _summary_request_tokens(llm: Any, messages: list[LLMMessage]) -> int: """Count the exact request used for a summary call through the active LLM.""" - return int(llm.get_input_tokens_count(_build_summary_prompt(messages))) + return int(llm.get_input_tokens_count(build_summary_prompt(messages))) diff --git a/lib/crewai/src/crewai/utilities/message_utils.py b/lib/crewai/src/crewai/utilities/message_utils.py index bb18fb068..70f9c2a7e 100644 --- a/lib/crewai/src/crewai/utilities/message_utils.py +++ b/lib/crewai/src/crewai/utilities/message_utils.py @@ -4,6 +4,7 @@ from __future__ import annotations from typing import Any, Literal +from crewai.utilities.i18n import I18N_DEFAULT from crewai.utilities.types import LLMMessage @@ -57,6 +58,20 @@ def messages_content_text(messages: list[LLMMessage]) -> str: return "\n\n".join(lines) +def build_summary_prompt(chunk: list[LLMMessage]) -> list[LLMMessage]: + """Build the LLM request used to summarize a conversation chunk.""" + return [ + format_message_for_llm( + I18N_DEFAULT.slice("summarizer_system_message"), "system" + ), + format_message_for_llm( + I18N_DEFAULT.slice("summarize_instruction").format( + conversation=messages_content_text(chunk) + ) + ), + ] + + def collect_user_message_files(messages: list[LLMMessage]) -> dict[str, Any]: """Merge files attached to user messages.""" files: dict[str, Any] = {} diff --git a/lib/crewai/tests/llms/test_context_window.py b/lib/crewai/tests/llms/test_context_window.py index 527e366a5..6ec23b03d 100644 --- a/lib/crewai/tests/llms/test_context_window.py +++ b/lib/crewai/tests/llms/test_context_window.py @@ -13,11 +13,11 @@ from crewai.llms.context_window import ( LLM_CONTEXT_WINDOW_SIZES, bare_context_windows, context_windows_from_catalog, - _build_summary_prompt, _chunk_messages, summarize_messages, resolve_context_window_size, ) +from crewai.utilities.message_utils import build_summary_prompt from crewai.utilities.exceptions.context_window_exceeding_exception import ( LLMContextLengthExceededError, ) @@ -283,7 +283,7 @@ def test_summary_chunking_uses_the_rendered_request_token_estimator() -> None: assert chunks == [[messages[0]], [messages[1]]] assert all( - llm.get_input_tokens_count(_build_summary_prompt(chunk)) <= 125 + llm.get_input_tokens_count(build_summary_prompt(chunk)) <= 125 for chunk in chunks ) assert all(len(request) == 2 for request in llm.requests) @@ -411,7 +411,7 @@ def test_summary_chunking_splits_a_single_oversized_text_message() -> None: assert len(chunks) == 3 assert "".join(chunk[0]["content"] for chunk in chunks) == message["content"] assert all( - CountingLLM().get_input_tokens_count(_build_summary_prompt(chunk)) <= 20 + CountingLLM().get_input_tokens_count(build_summary_prompt(chunk)) <= 20 for chunk in chunks )