Merge pull request #1250 from pipecat-ai/aleix/context-aggregation-simulatenous-text-tools

AssistantContextAggregator: append aggregation and tools in the same turn
This commit is contained in:
Aleix Conchillo Flaqué
2025-02-20 17:32:57 -08:00
committed by GitHub
6 changed files with 24 additions and 19 deletions

View File

@@ -32,6 +32,9 @@ stt = DeepgramSTTService(..., live_options=LiveOptions(model="nova-2-general"))
### Fixed ### Fixed
- Fixed a context aggregator issue that would not append the LLM text response
to the context if a function call happened in the same LLM turn.
- Fixed an issue that was causing HTTP TTS services to push `TTSStoppedFrame` - Fixed an issue that was causing HTTP TTS services to push `TTSStoppedFrame`
more than once. more than once.

View File

@@ -145,6 +145,9 @@ class LLMResponseAggregator(BaseLLMResponseAggregator):
frame = LLMMessagesFrame(self._messages) frame = LLMMessagesFrame(self._messages)
await self.push_frame(frame) await self.push_frame(frame)
# Reset our accumulator state.
self.reset()
class LLMContextResponseAggregator(BaseLLMResponseAggregator): class LLMContextResponseAggregator(BaseLLMResponseAggregator):
"""This is a base LLM aggregator that uses an LLM context to store the """This is a base LLM aggregator that uses an LLM context to store the

View File

@@ -743,18 +743,19 @@ class AnthropicAssistantContextAggregator(LLMAssistantContextAggregator):
run_llm = False run_llm = False
properties: Optional[FunctionCallResultProperties] = None properties: Optional[FunctionCallResultProperties] = None
aggregation = self._aggregation aggregation = self._aggregation.strip()
self.reset() self.reset()
try: try:
if aggregation:
self._context.add_message({"role": "assistant", "content": aggregation})
if self._function_call_result: if self._function_call_result:
frame = self._function_call_result frame = self._function_call_result
properties = frame.properties properties = frame.properties
self._function_call_result = None self._function_call_result = None
if frame.result: if frame.result:
assistant_message = {"role": "assistant", "content": []} assistant_message = {"role": "assistant", "content": []}
if aggregation:
assistant_message["content"].append({"type": "text", "text": aggregation})
assistant_message["content"].append( assistant_message["content"].append(
{ {
"type": "tool_use", "type": "tool_use",
@@ -782,8 +783,6 @@ class AnthropicAssistantContextAggregator(LLMAssistantContextAggregator):
else: else:
# Default behavior # Default behavior
run_llm = True run_llm = True
elif aggregation:
self._context.add_message({"role": "assistant", "content": aggregation})
if self._pending_image_frame_message: if self._pending_image_frame_message:
frame = self._pending_image_frame_message frame = self._pending_image_frame_message

View File

@@ -565,10 +565,15 @@ class GoogleAssistantContextAggregator(OpenAIAssistantContextAggregator):
run_llm = False run_llm = False
properties: Optional[FunctionCallResultProperties] = None properties: Optional[FunctionCallResultProperties] = None
aggregation = self._aggregation aggregation = self._aggregation.strip()
self.reset() self.reset()
try: try:
if aggregation:
self._context.add_message(
glm.Content(role="model", parts=[glm.Part(text=aggregation)])
)
if self._function_call_result: if self._function_call_result:
frame = self._function_call_result frame = self._function_call_result
properties = frame.properties properties = frame.properties
@@ -608,11 +613,6 @@ class GoogleAssistantContextAggregator(OpenAIAssistantContextAggregator):
else: else:
# Default behavior is to run the LLM if there are no function calls in progress # Default behavior is to run the LLM if there are no function calls in progress
run_llm = not bool(self._function_calls_in_progress) run_llm = not bool(self._function_calls_in_progress)
else:
if aggregation.strip():
self._context.add_message(
glm.Content(role="model", parts=[glm.Part(text=aggregation)])
)
if self._pending_image_frame_message: if self._pending_image_frame_message:
frame = self._pending_image_frame_message frame = self._pending_image_frame_message

View File

@@ -37,10 +37,13 @@ class GrokAssistantContextAggregator(OpenAIAssistantContextAggregator):
run_llm = False run_llm = False
properties: Optional[FunctionCallResultProperties] = None properties: Optional[FunctionCallResultProperties] = None
aggregation = self._aggregation aggregation = self._aggregation.strip()
self.reset() self.reset()
try: try:
if aggregation:
self._context.add_message({"role": "assistant", "content": aggregation})
if self._function_call_result: if self._function_call_result:
frame = self._function_call_result frame = self._function_call_result
properties = frame.properties properties = frame.properties
@@ -77,9 +80,6 @@ class GrokAssistantContextAggregator(OpenAIAssistantContextAggregator):
# Default behavior is to run the LLM if there are no function calls in progress # Default behavior is to run the LLM if there are no function calls in progress
run_llm = not bool(self._function_calls_in_progress) run_llm = not bool(self._function_calls_in_progress)
else:
self._context.add_message({"role": "assistant", "content": aggregation})
if self._pending_image_frame_message: if self._pending_image_frame_message:
frame = self._pending_image_frame_message frame = self._pending_image_frame_message
self._pending_image_frame_message = None self._pending_image_frame_message = None

View File

@@ -631,10 +631,13 @@ class OpenAIAssistantContextAggregator(LLMAssistantContextAggregator):
run_llm = False run_llm = False
properties: Optional[FunctionCallResultProperties] = None properties: Optional[FunctionCallResultProperties] = None
aggregation = self._aggregation aggregation = self._aggregation.strip()
self.reset() self.reset()
try: try:
if aggregation:
self._context.add_message({"role": "assistant", "content": aggregation})
if self._function_call_result: if self._function_call_result:
frame = self._function_call_result frame = self._function_call_result
properties = frame.properties properties = frame.properties
@@ -669,9 +672,6 @@ class OpenAIAssistantContextAggregator(LLMAssistantContextAggregator):
# Default behavior is to run the LLM if there are no function calls in progress # Default behavior is to run the LLM if there are no function calls in progress
run_llm = not bool(self._function_calls_in_progress) run_llm = not bool(self._function_calls_in_progress)
else:
self._context.add_message({"role": "assistant", "content": aggregation})
if self._pending_image_frame_message: if self._pending_image_frame_message:
frame = self._pending_image_frame_message frame = self._pending_image_frame_message
self._pending_image_frame_message = None self._pending_image_frame_message = None