dv-pipecat-ai 0.0.74.dev770__py3-none-any.whl → 0.0.82.dev776__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of dv-pipecat-ai might be problematic. Click here for more details.
- {dv_pipecat_ai-0.0.74.dev770.dist-info → dv_pipecat_ai-0.0.82.dev776.dist-info}/METADATA +137 -93
- dv_pipecat_ai-0.0.82.dev776.dist-info/RECORD +340 -0
- pipecat/__init__.py +17 -0
- pipecat/adapters/base_llm_adapter.py +36 -1
- pipecat/adapters/schemas/direct_function.py +296 -0
- pipecat/adapters/schemas/function_schema.py +15 -6
- pipecat/adapters/schemas/tools_schema.py +55 -7
- pipecat/adapters/services/anthropic_adapter.py +22 -3
- pipecat/adapters/services/aws_nova_sonic_adapter.py +23 -3
- pipecat/adapters/services/bedrock_adapter.py +22 -3
- pipecat/adapters/services/gemini_adapter.py +16 -3
- pipecat/adapters/services/open_ai_adapter.py +17 -2
- pipecat/adapters/services/open_ai_realtime_adapter.py +23 -3
- pipecat/audio/filters/base_audio_filter.py +30 -6
- pipecat/audio/filters/koala_filter.py +37 -2
- pipecat/audio/filters/krisp_filter.py +59 -6
- pipecat/audio/filters/noisereduce_filter.py +37 -0
- pipecat/audio/interruptions/base_interruption_strategy.py +25 -5
- pipecat/audio/interruptions/min_words_interruption_strategy.py +21 -4
- pipecat/audio/mixers/base_audio_mixer.py +30 -7
- pipecat/audio/mixers/soundfile_mixer.py +53 -6
- pipecat/audio/resamplers/base_audio_resampler.py +17 -9
- pipecat/audio/resamplers/resampy_resampler.py +26 -1
- pipecat/audio/resamplers/soxr_resampler.py +32 -1
- pipecat/audio/resamplers/soxr_stream_resampler.py +101 -0
- pipecat/audio/utils.py +194 -1
- pipecat/audio/vad/silero.py +60 -3
- pipecat/audio/vad/vad_analyzer.py +114 -30
- pipecat/clocks/base_clock.py +19 -0
- pipecat/clocks/system_clock.py +25 -0
- pipecat/extensions/voicemail/__init__.py +0 -0
- pipecat/extensions/voicemail/voicemail_detector.py +707 -0
- pipecat/frames/frames.py +590 -156
- pipecat/metrics/metrics.py +64 -1
- pipecat/observers/base_observer.py +58 -19
- pipecat/observers/loggers/debug_log_observer.py +56 -64
- pipecat/observers/loggers/llm_log_observer.py +8 -1
- pipecat/observers/loggers/transcription_log_observer.py +19 -7
- pipecat/observers/loggers/user_bot_latency_log_observer.py +32 -5
- pipecat/observers/turn_tracking_observer.py +26 -1
- pipecat/pipeline/base_pipeline.py +5 -7
- pipecat/pipeline/base_task.py +52 -9
- pipecat/pipeline/parallel_pipeline.py +121 -177
- pipecat/pipeline/pipeline.py +129 -20
- pipecat/pipeline/runner.py +50 -1
- pipecat/pipeline/sync_parallel_pipeline.py +132 -32
- pipecat/pipeline/task.py +263 -280
- pipecat/pipeline/task_observer.py +85 -34
- pipecat/pipeline/to_be_updated/merge_pipeline.py +32 -2
- pipecat/processors/aggregators/dtmf_aggregator.py +29 -22
- pipecat/processors/aggregators/gated.py +25 -24
- pipecat/processors/aggregators/gated_openai_llm_context.py +22 -2
- pipecat/processors/aggregators/llm_response.py +398 -89
- pipecat/processors/aggregators/openai_llm_context.py +161 -13
- pipecat/processors/aggregators/sentence.py +25 -14
- pipecat/processors/aggregators/user_response.py +28 -3
- pipecat/processors/aggregators/vision_image_frame.py +24 -14
- pipecat/processors/async_generator.py +28 -0
- pipecat/processors/audio/audio_buffer_processor.py +78 -37
- pipecat/processors/consumer_processor.py +25 -6
- pipecat/processors/filters/frame_filter.py +23 -0
- pipecat/processors/filters/function_filter.py +30 -0
- pipecat/processors/filters/identity_filter.py +17 -2
- pipecat/processors/filters/null_filter.py +24 -1
- pipecat/processors/filters/stt_mute_filter.py +56 -21
- pipecat/processors/filters/wake_check_filter.py +46 -3
- pipecat/processors/filters/wake_notifier_filter.py +21 -3
- pipecat/processors/frame_processor.py +488 -131
- pipecat/processors/frameworks/langchain.py +38 -3
- pipecat/processors/frameworks/rtvi.py +719 -34
- pipecat/processors/gstreamer/pipeline_source.py +41 -0
- pipecat/processors/idle_frame_processor.py +26 -3
- pipecat/processors/logger.py +23 -0
- pipecat/processors/metrics/frame_processor_metrics.py +77 -4
- pipecat/processors/metrics/sentry.py +42 -4
- pipecat/processors/producer_processor.py +34 -14
- pipecat/processors/text_transformer.py +22 -10
- pipecat/processors/transcript_processor.py +48 -29
- pipecat/processors/user_idle_processor.py +31 -21
- pipecat/runner/__init__.py +1 -0
- pipecat/runner/daily.py +132 -0
- pipecat/runner/livekit.py +148 -0
- pipecat/runner/run.py +543 -0
- pipecat/runner/types.py +67 -0
- pipecat/runner/utils.py +515 -0
- pipecat/serializers/base_serializer.py +42 -0
- pipecat/serializers/exotel.py +17 -6
- pipecat/serializers/genesys.py +95 -0
- pipecat/serializers/livekit.py +33 -0
- pipecat/serializers/plivo.py +16 -15
- pipecat/serializers/protobuf.py +37 -1
- pipecat/serializers/telnyx.py +18 -17
- pipecat/serializers/twilio.py +32 -16
- pipecat/services/ai_service.py +5 -3
- pipecat/services/anthropic/llm.py +113 -43
- pipecat/services/assemblyai/models.py +63 -5
- pipecat/services/assemblyai/stt.py +64 -11
- pipecat/services/asyncai/__init__.py +0 -0
- pipecat/services/asyncai/tts.py +501 -0
- pipecat/services/aws/llm.py +185 -111
- pipecat/services/aws/stt.py +217 -23
- pipecat/services/aws/tts.py +118 -52
- pipecat/services/aws/utils.py +101 -5
- pipecat/services/aws_nova_sonic/aws.py +82 -64
- pipecat/services/aws_nova_sonic/context.py +15 -6
- pipecat/services/azure/common.py +10 -2
- pipecat/services/azure/image.py +32 -0
- pipecat/services/azure/llm.py +9 -7
- pipecat/services/azure/stt.py +65 -2
- pipecat/services/azure/tts.py +154 -23
- pipecat/services/cartesia/stt.py +125 -8
- pipecat/services/cartesia/tts.py +102 -38
- pipecat/services/cerebras/llm.py +15 -23
- pipecat/services/deepgram/stt.py +19 -11
- pipecat/services/deepgram/tts.py +36 -0
- pipecat/services/deepseek/llm.py +14 -23
- pipecat/services/elevenlabs/tts.py +330 -64
- pipecat/services/fal/image.py +43 -0
- pipecat/services/fal/stt.py +48 -10
- pipecat/services/fireworks/llm.py +14 -21
- pipecat/services/fish/tts.py +109 -9
- pipecat/services/gemini_multimodal_live/__init__.py +1 -0
- pipecat/services/gemini_multimodal_live/events.py +83 -2
- pipecat/services/gemini_multimodal_live/file_api.py +189 -0
- pipecat/services/gemini_multimodal_live/gemini.py +218 -21
- pipecat/services/gladia/config.py +17 -10
- pipecat/services/gladia/stt.py +82 -36
- pipecat/services/google/frames.py +40 -0
- pipecat/services/google/google.py +2 -0
- pipecat/services/google/image.py +39 -2
- pipecat/services/google/llm.py +176 -58
- pipecat/services/google/llm_openai.py +26 -4
- pipecat/services/google/llm_vertex.py +37 -15
- pipecat/services/google/rtvi.py +41 -0
- pipecat/services/google/stt.py +65 -17
- pipecat/services/google/test-google-chirp.py +45 -0
- pipecat/services/google/tts.py +390 -19
- pipecat/services/grok/llm.py +8 -6
- pipecat/services/groq/llm.py +8 -6
- pipecat/services/groq/stt.py +13 -9
- pipecat/services/groq/tts.py +40 -0
- pipecat/services/hamsa/__init__.py +9 -0
- pipecat/services/hamsa/stt.py +241 -0
- pipecat/services/heygen/__init__.py +5 -0
- pipecat/services/heygen/api.py +281 -0
- pipecat/services/heygen/client.py +620 -0
- pipecat/services/heygen/video.py +338 -0
- pipecat/services/image_service.py +5 -3
- pipecat/services/inworld/__init__.py +1 -0
- pipecat/services/inworld/tts.py +592 -0
- pipecat/services/llm_service.py +127 -45
- pipecat/services/lmnt/tts.py +80 -7
- pipecat/services/mcp_service.py +85 -44
- pipecat/services/mem0/memory.py +42 -13
- pipecat/services/minimax/tts.py +74 -15
- pipecat/services/mistral/__init__.py +0 -0
- pipecat/services/mistral/llm.py +185 -0
- pipecat/services/moondream/vision.py +55 -10
- pipecat/services/neuphonic/tts.py +275 -48
- pipecat/services/nim/llm.py +8 -6
- pipecat/services/ollama/llm.py +27 -7
- pipecat/services/openai/base_llm.py +54 -16
- pipecat/services/openai/image.py +30 -0
- pipecat/services/openai/llm.py +7 -5
- pipecat/services/openai/stt.py +13 -9
- pipecat/services/openai/tts.py +42 -10
- pipecat/services/openai_realtime_beta/azure.py +11 -9
- pipecat/services/openai_realtime_beta/context.py +7 -5
- pipecat/services/openai_realtime_beta/events.py +10 -7
- pipecat/services/openai_realtime_beta/openai.py +37 -18
- pipecat/services/openpipe/llm.py +30 -24
- pipecat/services/openrouter/llm.py +9 -7
- pipecat/services/perplexity/llm.py +15 -19
- pipecat/services/piper/tts.py +26 -12
- pipecat/services/playht/tts.py +227 -65
- pipecat/services/qwen/llm.py +8 -6
- pipecat/services/rime/tts.py +128 -17
- pipecat/services/riva/stt.py +160 -22
- pipecat/services/riva/tts.py +67 -2
- pipecat/services/sambanova/llm.py +19 -17
- pipecat/services/sambanova/stt.py +14 -8
- pipecat/services/sarvam/tts.py +60 -13
- pipecat/services/simli/video.py +82 -21
- pipecat/services/soniox/__init__.py +0 -0
- pipecat/services/soniox/stt.py +398 -0
- pipecat/services/speechmatics/stt.py +29 -17
- pipecat/services/stt_service.py +47 -11
- pipecat/services/tavus/video.py +94 -25
- pipecat/services/together/llm.py +8 -6
- pipecat/services/tts_service.py +77 -53
- pipecat/services/ultravox/stt.py +46 -43
- pipecat/services/vision_service.py +5 -3
- pipecat/services/websocket_service.py +12 -11
- pipecat/services/whisper/base_stt.py +58 -12
- pipecat/services/whisper/stt.py +69 -58
- pipecat/services/xtts/tts.py +59 -2
- pipecat/sync/base_notifier.py +19 -0
- pipecat/sync/event_notifier.py +24 -0
- pipecat/tests/utils.py +73 -5
- pipecat/transcriptions/language.py +24 -0
- pipecat/transports/base_input.py +112 -8
- pipecat/transports/base_output.py +235 -13
- pipecat/transports/base_transport.py +119 -0
- pipecat/transports/local/audio.py +76 -0
- pipecat/transports/local/tk.py +84 -0
- pipecat/transports/network/fastapi_websocket.py +174 -15
- pipecat/transports/network/small_webrtc.py +383 -39
- pipecat/transports/network/webrtc_connection.py +214 -8
- pipecat/transports/network/websocket_client.py +171 -1
- pipecat/transports/network/websocket_server.py +147 -9
- pipecat/transports/services/daily.py +792 -70
- pipecat/transports/services/helpers/daily_rest.py +122 -129
- pipecat/transports/services/livekit.py +339 -4
- pipecat/transports/services/tavus.py +273 -38
- pipecat/utils/asyncio/task_manager.py +92 -186
- pipecat/utils/base_object.py +83 -1
- pipecat/utils/network.py +2 -0
- pipecat/utils/string.py +114 -58
- pipecat/utils/text/base_text_aggregator.py +44 -13
- pipecat/utils/text/base_text_filter.py +46 -0
- pipecat/utils/text/markdown_text_filter.py +70 -14
- pipecat/utils/text/pattern_pair_aggregator.py +18 -14
- pipecat/utils/text/simple_text_aggregator.py +43 -2
- pipecat/utils/text/skip_tags_aggregator.py +21 -13
- pipecat/utils/time.py +36 -0
- pipecat/utils/tracing/class_decorators.py +32 -7
- pipecat/utils/tracing/conversation_context_provider.py +12 -2
- pipecat/utils/tracing/service_attributes.py +80 -64
- pipecat/utils/tracing/service_decorators.py +48 -21
- pipecat/utils/tracing/setup.py +13 -7
- pipecat/utils/tracing/turn_context_provider.py +12 -2
- pipecat/utils/tracing/turn_trace_observer.py +27 -0
- pipecat/utils/utils.py +14 -14
- dv_pipecat_ai-0.0.74.dev770.dist-info/RECORD +0 -319
- pipecat/examples/daily_runner.py +0 -64
- pipecat/examples/run.py +0 -265
- pipecat/utils/asyncio/watchdog_async_iterator.py +0 -72
- pipecat/utils/asyncio/watchdog_event.py +0 -42
- pipecat/utils/asyncio/watchdog_priority_queue.py +0 -48
- pipecat/utils/asyncio/watchdog_queue.py +0 -48
- {dv_pipecat_ai-0.0.74.dev770.dist-info → dv_pipecat_ai-0.0.82.dev776.dist-info}/WHEEL +0 -0
- {dv_pipecat_ai-0.0.74.dev770.dist-info → dv_pipecat_ai-0.0.82.dev776.dist-info}/licenses/LICENSE +0 -0
- {dv_pipecat_ai-0.0.74.dev770.dist-info → dv_pipecat_ai-0.0.82.dev776.dist-info}/top_level.txt +0 -0
- /pipecat/{examples → extensions}/__init__.py +0 -0
pipecat/services/aws/llm.py
CHANGED
|
@@ -55,9 +55,10 @@ from pipecat.services.llm_service import LLMService
|
|
|
55
55
|
from pipecat.utils.tracing.service_decorators import traced_llm
|
|
56
56
|
|
|
57
57
|
try:
|
|
58
|
-
import
|
|
58
|
+
import aioboto3
|
|
59
59
|
import httpx
|
|
60
60
|
from botocore.config import Config
|
|
61
|
+
from botocore.exceptions import ReadTimeoutError
|
|
61
62
|
except ModuleNotFoundError as e:
|
|
62
63
|
logger.error(f"Exception: {e}")
|
|
63
64
|
logger.error(
|
|
@@ -104,12 +105,6 @@ class AWSBedrockLLMContext(OpenAILLMContext):
|
|
|
104
105
|
Extends OpenAI LLM context to handle AWS Bedrock's specific message format
|
|
105
106
|
and system message handling. Manages conversion between OpenAI and Bedrock
|
|
106
107
|
message formats.
|
|
107
|
-
|
|
108
|
-
Args:
|
|
109
|
-
messages: List of conversation messages in OpenAI format.
|
|
110
|
-
tools: List of available function calling tools.
|
|
111
|
-
tool_choice: Tool selection strategy or specific tool choice.
|
|
112
|
-
system: System message content for AWS Bedrock.
|
|
113
108
|
"""
|
|
114
109
|
|
|
115
110
|
def __init__(
|
|
@@ -120,6 +115,14 @@ class AWSBedrockLLMContext(OpenAILLMContext):
|
|
|
120
115
|
*,
|
|
121
116
|
system: Optional[str] = None,
|
|
122
117
|
):
|
|
118
|
+
"""Initialize AWS Bedrock LLM context.
|
|
119
|
+
|
|
120
|
+
Args:
|
|
121
|
+
messages: List of conversation messages in OpenAI format.
|
|
122
|
+
tools: List of available function calling tools.
|
|
123
|
+
tool_choice: Tool selection strategy or specific tool choice.
|
|
124
|
+
system: System message content for AWS Bedrock.
|
|
125
|
+
"""
|
|
123
126
|
super().__init__(messages=messages, tools=tools, tool_choice=tool_choice)
|
|
124
127
|
self.system = system
|
|
125
128
|
|
|
@@ -205,20 +208,37 @@ class AWSBedrockLLMContext(OpenAILLMContext):
|
|
|
205
208
|
Handles text content and function calls for both user and assistant messages.
|
|
206
209
|
|
|
207
210
|
Args:
|
|
208
|
-
obj: Message in AWS Bedrock format
|
|
209
|
-
{
|
|
210
|
-
"role": "user/assistant",
|
|
211
|
-
"content": [{"text": str} | {"toolUse": {...}} | {"toolResult": {...}}]
|
|
212
|
-
}
|
|
211
|
+
obj: Message in AWS Bedrock format.
|
|
213
212
|
|
|
214
213
|
Returns:
|
|
215
|
-
List of messages in standard format
|
|
216
|
-
|
|
214
|
+
List of messages in standard format.
|
|
215
|
+
|
|
216
|
+
Examples:
|
|
217
|
+
AWS Bedrock format input::
|
|
218
|
+
|
|
217
219
|
{
|
|
218
|
-
"role": "
|
|
219
|
-
"content": [
|
|
220
|
+
"role": "assistant",
|
|
221
|
+
"content": [
|
|
222
|
+
{"text": "Hello"},
|
|
223
|
+
{"toolUse": {"toolUseId": "123", "name": "search", "input": {"q": "test"}}}
|
|
224
|
+
]
|
|
220
225
|
}
|
|
221
|
-
|
|
226
|
+
|
|
227
|
+
Standard format output::
|
|
228
|
+
|
|
229
|
+
[
|
|
230
|
+
{"role": "assistant", "content": [{"type": "text", "text": "Hello"}]},
|
|
231
|
+
{
|
|
232
|
+
"role": "assistant",
|
|
233
|
+
"tool_calls": [
|
|
234
|
+
{
|
|
235
|
+
"type": "function",
|
|
236
|
+
"id": "123",
|
|
237
|
+
"function": {"name": "search", "arguments": '{"q": "test"}'}
|
|
238
|
+
}
|
|
239
|
+
]
|
|
240
|
+
}
|
|
241
|
+
]
|
|
222
242
|
"""
|
|
223
243
|
role = obj.get("role")
|
|
224
244
|
content = obj.get("content")
|
|
@@ -292,23 +312,38 @@ class AWSBedrockLLMContext(OpenAILLMContext):
|
|
|
292
312
|
Empty text content is converted to "(empty)".
|
|
293
313
|
|
|
294
314
|
Args:
|
|
295
|
-
message: Message in standard format
|
|
315
|
+
message: Message in standard format.
|
|
316
|
+
|
|
317
|
+
Returns:
|
|
318
|
+
Message in AWS Bedrock format.
|
|
319
|
+
|
|
320
|
+
Examples:
|
|
321
|
+
Standard format input::
|
|
322
|
+
|
|
296
323
|
{
|
|
297
|
-
"role": "
|
|
298
|
-
"
|
|
299
|
-
|
|
324
|
+
"role": "assistant",
|
|
325
|
+
"tool_calls": [
|
|
326
|
+
{
|
|
327
|
+
"id": "123",
|
|
328
|
+
"function": {"name": "search", "arguments": '{"q": "test"}'}
|
|
329
|
+
}
|
|
330
|
+
]
|
|
300
331
|
}
|
|
301
332
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
333
|
+
AWS Bedrock format output::
|
|
334
|
+
|
|
335
|
+
{
|
|
336
|
+
"role": "assistant",
|
|
337
|
+
"content": [
|
|
338
|
+
{
|
|
339
|
+
"toolUse": {
|
|
340
|
+
"toolUseId": "123",
|
|
341
|
+
"name": "search",
|
|
342
|
+
"input": {"q": "test"}
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
]
|
|
346
|
+
}
|
|
312
347
|
"""
|
|
313
348
|
if message["role"] == "tool":
|
|
314
349
|
# Try to parse the content as JSON if it looks like JSON
|
|
@@ -656,16 +691,6 @@ class AWSBedrockLLMService(LLMService):
|
|
|
656
691
|
Provides inference capabilities for AWS Bedrock models including Amazon Nova
|
|
657
692
|
and Anthropic Claude. Supports streaming responses, function calling, and
|
|
658
693
|
vision capabilities.
|
|
659
|
-
|
|
660
|
-
Args:
|
|
661
|
-
model: The AWS Bedrock model identifier to use.
|
|
662
|
-
aws_access_key: AWS access key ID. If None, uses default credentials.
|
|
663
|
-
aws_secret_key: AWS secret access key. If None, uses default credentials.
|
|
664
|
-
aws_session_token: AWS session token for temporary credentials.
|
|
665
|
-
aws_region: AWS region for the Bedrock service.
|
|
666
|
-
params: Model parameters and configuration.
|
|
667
|
-
client_config: Custom boto3 client configuration.
|
|
668
|
-
**kwargs: Additional arguments passed to parent LLMService.
|
|
669
694
|
"""
|
|
670
695
|
|
|
671
696
|
# Overriding the default adapter to use the Anthropic one.
|
|
@@ -700,8 +725,24 @@ class AWSBedrockLLMService(LLMService):
|
|
|
700
725
|
aws_region: str = "us-east-1",
|
|
701
726
|
params: Optional[InputParams] = None,
|
|
702
727
|
client_config: Optional[Config] = None,
|
|
728
|
+
retry_timeout_secs: Optional[float] = 5.0,
|
|
729
|
+
retry_on_timeout: Optional[bool] = False,
|
|
703
730
|
**kwargs,
|
|
704
731
|
):
|
|
732
|
+
"""Initialize the AWS Bedrock LLM service.
|
|
733
|
+
|
|
734
|
+
Args:
|
|
735
|
+
model: The AWS Bedrock model identifier to use.
|
|
736
|
+
aws_access_key: AWS access key ID. If None, uses default credentials.
|
|
737
|
+
aws_secret_key: AWS secret access key. If None, uses default credentials.
|
|
738
|
+
aws_session_token: AWS session token for temporary credentials.
|
|
739
|
+
aws_region: AWS region for the Bedrock service.
|
|
740
|
+
params: Model parameters and configuration.
|
|
741
|
+
client_config: Custom boto3 client configuration.
|
|
742
|
+
retry_timeout_secs: Request timeout in seconds for retry logic.
|
|
743
|
+
retry_on_timeout: Whether to retry the request once if it times out.
|
|
744
|
+
**kwargs: Additional arguments passed to parent LLMService.
|
|
745
|
+
"""
|
|
705
746
|
super().__init__(**kwargs)
|
|
706
747
|
|
|
707
748
|
params = params or AWSBedrockLLMService.InputParams()
|
|
@@ -713,15 +754,21 @@ class AWSBedrockLLMService(LLMService):
|
|
|
713
754
|
read_timeout=300, # 5 minutes
|
|
714
755
|
retries={"max_attempts": 3},
|
|
715
756
|
)
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
757
|
+
|
|
758
|
+
self._aws_session = aioboto3.Session()
|
|
759
|
+
|
|
760
|
+
# Store AWS session parameters for creating client in async context
|
|
761
|
+
self._aws_params = {
|
|
762
|
+
"aws_access_key_id": aws_access_key,
|
|
763
|
+
"aws_secret_access_key": aws_secret_key,
|
|
764
|
+
"aws_session_token": aws_session_token,
|
|
765
|
+
"region_name": aws_region,
|
|
766
|
+
"config": client_config,
|
|
767
|
+
}
|
|
723
768
|
|
|
724
769
|
self.set_model_name(model)
|
|
770
|
+
self._retry_timeout_secs = retry_timeout_secs
|
|
771
|
+
self._retry_on_timeout = retry_on_timeout
|
|
725
772
|
self._settings = {
|
|
726
773
|
"max_tokens": params.max_tokens,
|
|
727
774
|
"temperature": params.temperature,
|
|
@@ -742,6 +789,31 @@ class AWSBedrockLLMService(LLMService):
|
|
|
742
789
|
"""
|
|
743
790
|
return True
|
|
744
791
|
|
|
792
|
+
async def _create_converse_stream(self, client, request_params):
|
|
793
|
+
"""Create converse stream with optional timeout and retry.
|
|
794
|
+
|
|
795
|
+
Args:
|
|
796
|
+
client: The AWS Bedrock client instance.
|
|
797
|
+
request_params: Parameters for the converse_stream call.
|
|
798
|
+
|
|
799
|
+
Returns:
|
|
800
|
+
Async stream of response events.
|
|
801
|
+
"""
|
|
802
|
+
if self._retry_on_timeout:
|
|
803
|
+
try:
|
|
804
|
+
response = await asyncio.wait_for(
|
|
805
|
+
await client.converse_stream(**request_params), timeout=self._retry_timeout_secs
|
|
806
|
+
)
|
|
807
|
+
return response
|
|
808
|
+
except (ReadTimeoutError, asyncio.TimeoutError) as e:
|
|
809
|
+
# Retry, this time without a timeout so we get a response
|
|
810
|
+
logger.debug(f"{self}: Retrying converse_stream due to timeout")
|
|
811
|
+
response = await client.converse_stream(**request_params)
|
|
812
|
+
return response
|
|
813
|
+
else:
|
|
814
|
+
response = await client.converse_stream(**request_params)
|
|
815
|
+
return response
|
|
816
|
+
|
|
745
817
|
def create_context_aggregator(
|
|
746
818
|
self,
|
|
747
819
|
context: OpenAILLMContext,
|
|
@@ -867,70 +939,72 @@ class AWSBedrockLLMService(LLMService):
|
|
|
867
939
|
|
|
868
940
|
logger.debug(f"Calling AWS Bedrock model with: {request_params}")
|
|
869
941
|
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
if "
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
delta["toolUse"]["input"]
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
942
|
+
async with self._aws_session.client(
|
|
943
|
+
service_name="bedrock-runtime", **self._aws_params
|
|
944
|
+
) as client:
|
|
945
|
+
# Call AWS Bedrock with streaming
|
|
946
|
+
response = await self._create_converse_stream(client, request_params)
|
|
947
|
+
|
|
948
|
+
await self.stop_ttfb_metrics()
|
|
949
|
+
|
|
950
|
+
# Process the streaming response
|
|
951
|
+
tool_use_block = None
|
|
952
|
+
json_accumulator = ""
|
|
953
|
+
|
|
954
|
+
function_calls = []
|
|
955
|
+
|
|
956
|
+
async for event in response["stream"]:
|
|
957
|
+
# Handle text content
|
|
958
|
+
if "contentBlockDelta" in event:
|
|
959
|
+
delta = event["contentBlockDelta"]["delta"]
|
|
960
|
+
if "text" in delta:
|
|
961
|
+
await self.push_frame(LLMTextFrame(delta["text"]))
|
|
962
|
+
completion_tokens_estimate += self._estimate_tokens(delta["text"])
|
|
963
|
+
elif "toolUse" in delta and "input" in delta["toolUse"]:
|
|
964
|
+
# Handle partial JSON for tool use
|
|
965
|
+
json_accumulator += delta["toolUse"]["input"]
|
|
966
|
+
completion_tokens_estimate += self._estimate_tokens(
|
|
967
|
+
delta["toolUse"]["input"]
|
|
968
|
+
)
|
|
969
|
+
|
|
970
|
+
# Handle tool use start
|
|
971
|
+
elif "contentBlockStart" in event:
|
|
972
|
+
content_block_start = event["contentBlockStart"]["start"]
|
|
973
|
+
if "toolUse" in content_block_start:
|
|
974
|
+
tool_use_block = {
|
|
975
|
+
"id": content_block_start["toolUse"].get("toolUseId", ""),
|
|
976
|
+
"name": content_block_start["toolUse"].get("name", ""),
|
|
977
|
+
}
|
|
978
|
+
json_accumulator = ""
|
|
979
|
+
|
|
980
|
+
# Handle message completion with tool use
|
|
981
|
+
elif "messageStop" in event and "stopReason" in event["messageStop"]:
|
|
982
|
+
if event["messageStop"]["stopReason"] == "tool_use" and tool_use_block:
|
|
983
|
+
try:
|
|
984
|
+
arguments = json.loads(json_accumulator) if json_accumulator else {}
|
|
985
|
+
|
|
986
|
+
# Only call function if it's not the no_operation tool
|
|
987
|
+
if not using_noop_tool:
|
|
988
|
+
function_calls.append(
|
|
989
|
+
FunctionCallFromLLM(
|
|
990
|
+
context=context,
|
|
991
|
+
tool_call_id=tool_use_block["id"],
|
|
992
|
+
function_name=tool_use_block["name"],
|
|
993
|
+
arguments=arguments,
|
|
994
|
+
)
|
|
920
995
|
)
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
cache_creation_input_tokens += usage.get("cacheWriteInputTokens", 0)
|
|
996
|
+
else:
|
|
997
|
+
logger.debug("Ignoring no_operation tool call")
|
|
998
|
+
except json.JSONDecodeError:
|
|
999
|
+
logger.error(f"Failed to parse tool arguments: {json_accumulator}")
|
|
1000
|
+
|
|
1001
|
+
# Handle usage metrics if available
|
|
1002
|
+
if "metadata" in event and "usage" in event["metadata"]:
|
|
1003
|
+
usage = event["metadata"]["usage"]
|
|
1004
|
+
prompt_tokens += usage.get("inputTokens", 0)
|
|
1005
|
+
completion_tokens += usage.get("outputTokens", 0)
|
|
1006
|
+
cache_read_input_tokens += usage.get("cacheReadInputTokens", 0)
|
|
1007
|
+
cache_creation_input_tokens += usage.get("cacheWriteInputTokens", 0)
|
|
934
1008
|
|
|
935
1009
|
await self.run_function_calls(function_calls)
|
|
936
1010
|
except asyncio.CancelledError:
|