Add optional dedicated LLM for context summarization
Adds an field to LLMContextSummarizationConfig that allows routing summarization to a separate LLM service (e.g., Gemini Flash) instead of the pipeline's primary model. This avoids paying for expensive inference when compressing context in long-running sessions.
This commit is contained in:
@@ -16,7 +16,7 @@ import json
|
|||||||
import warnings
|
import warnings
|
||||||
from abc import abstractmethod
|
from abc import abstractmethod
|
||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass, field
|
||||||
from typing import Any, Dict, List, Literal, Optional, Set, Type
|
from typing import TYPE_CHECKING, Any, Dict, List, Literal, Optional, Set, Type
|
||||||
|
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
|
|
||||||
@@ -39,6 +39,7 @@ from pipecat.frames.frames import (
|
|||||||
LLMContextAssistantTimestampFrame,
|
LLMContextAssistantTimestampFrame,
|
||||||
LLMContextFrame,
|
LLMContextFrame,
|
||||||
LLMContextSummaryRequestFrame,
|
LLMContextSummaryRequestFrame,
|
||||||
|
LLMContextSummaryResultFrame,
|
||||||
LLMFullResponseEndFrame,
|
LLMFullResponseEndFrame,
|
||||||
LLMFullResponseStartFrame,
|
LLMFullResponseStartFrame,
|
||||||
LLMMessagesAppendFrame,
|
LLMMessagesAppendFrame,
|
||||||
@@ -83,6 +84,9 @@ from pipecat.utils.context.llm_context_summarization import LLMContextSummarizat
|
|||||||
from pipecat.utils.string import TextPartForConcatenation, concatenate_aggregated_text
|
from pipecat.utils.string import TextPartForConcatenation, concatenate_aggregated_text
|
||||||
from pipecat.utils.time import time_now_iso8601
|
from pipecat.utils.time import time_now_iso8601
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from pipecat.services.llm_service import LLMService
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class LLMUserAggregatorParams:
|
class LLMUserAggregatorParams:
|
||||||
@@ -1248,13 +1252,56 @@ class LLMAssistantAggregator(LLMContextAggregator):
|
|||||||
):
|
):
|
||||||
"""Handle summarization request from the summarizer.
|
"""Handle summarization request from the summarizer.
|
||||||
|
|
||||||
Push the request frame UPSTREAM to the LLM service for processing.
|
If a dedicated summarization LLM is configured, generates the summary
|
||||||
|
directly and feeds the result to the summarizer. Otherwise, pushes the
|
||||||
|
request frame upstream to the pipeline's primary LLM service.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
summarizer: The summarizer that generated the request.
|
summarizer: The summarizer that generated the request.
|
||||||
frame: The summarization request frame to broadcast.
|
frame: The summarization request frame to broadcast.
|
||||||
"""
|
"""
|
||||||
await self.push_frame(frame, FrameDirection.UPSTREAM)
|
summarization_llm = (
|
||||||
|
self._params.context_summarization_config.llm
|
||||||
|
if self._params.context_summarization_config
|
||||||
|
else None
|
||||||
|
)
|
||||||
|
|
||||||
|
if summarization_llm:
|
||||||
|
self.create_task(self._generate_summary_with_dedicated_llm(summarization_llm, frame))
|
||||||
|
else:
|
||||||
|
await self.push_frame(frame, FrameDirection.UPSTREAM)
|
||||||
|
|
||||||
|
async def _generate_summary_with_dedicated_llm(
|
||||||
|
self, llm: "LLMService", frame: LLMContextSummaryRequestFrame
|
||||||
|
):
|
||||||
|
"""Generate summary using a dedicated LLM service.
|
||||||
|
|
||||||
|
Calls the dedicated LLM's _generate_summary directly and feeds the
|
||||||
|
result back to the summarizer, bypassing the pipeline.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
llm: The dedicated LLM service to use for summarization.
|
||||||
|
frame: The summarization request frame.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
summary, last_index = await llm._generate_summary(frame)
|
||||||
|
result_frame = LLMContextSummaryResultFrame(
|
||||||
|
request_id=frame.request_id,
|
||||||
|
summary=summary,
|
||||||
|
last_summarized_index=last_index,
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
error = f"Error generating context summary: {e}"
|
||||||
|
await self.push_error(error, exception=e)
|
||||||
|
result_frame = LLMContextSummaryResultFrame(
|
||||||
|
request_id=frame.request_id,
|
||||||
|
summary="",
|
||||||
|
last_summarized_index=-1,
|
||||||
|
error=f"Error generating context summary: {e}",
|
||||||
|
)
|
||||||
|
|
||||||
|
if self._summarizer:
|
||||||
|
await self._summarizer.process_frame(result_frame)
|
||||||
|
|
||||||
|
|
||||||
class LLMContextAggregatorPair:
|
class LLMContextAggregatorPair:
|
||||||
|
|||||||
@@ -11,7 +11,10 @@ context when token limits are reached, enabling efficient long-running conversat
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import List, Optional
|
from typing import TYPE_CHECKING, List, Optional
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from pipecat.services.llm_service import LLMService
|
||||||
|
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
|
|
||||||
@@ -78,6 +81,11 @@ class LLMContextSummarizationConfig:
|
|||||||
for the generated summary text. Allows applications to wrap the
|
for the generated summary text. Allows applications to wrap the
|
||||||
summary in custom delimiters (e.g., XML tags) so that system
|
summary in custom delimiters (e.g., XML tags) so that system
|
||||||
prompts can distinguish summaries from live conversation.
|
prompts can distinguish summaries from live conversation.
|
||||||
|
llm: Optional separate LLM service for generating summaries. When set,
|
||||||
|
summarization requests are sent to this service instead of the
|
||||||
|
pipeline's primary LLM. Useful for routing summarization to a
|
||||||
|
cheaper/faster model (e.g., Gemini Flash) while keeping an
|
||||||
|
expensive model for conversation. If None, uses the pipeline LLM.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
max_context_tokens: int = 8000
|
max_context_tokens: int = 8000
|
||||||
@@ -86,6 +94,7 @@ class LLMContextSummarizationConfig:
|
|||||||
min_messages_after_summary: int = 4
|
min_messages_after_summary: int = 4
|
||||||
summarization_prompt: Optional[str] = None
|
summarization_prompt: Optional[str] = None
|
||||||
summary_message_template: str = "Conversation summary: {summary}"
|
summary_message_template: str = "Conversation summary: {summary}"
|
||||||
|
llm: Optional["LLMService"] = None
|
||||||
|
|
||||||
def __post_init__(self):
|
def __post_init__(self):
|
||||||
"""Validate configuration parameters."""
|
"""Validate configuration parameters."""
|
||||||
|
|||||||
Reference in New Issue
Block a user