fix formatting

This commit is contained in:
Aleix Conchillo Flaqué
2025-05-06 11:37:23 -07:00
parent 664111a3c9
commit a4b9db9e07
5 changed files with 85 additions and 99 deletions

View File

@@ -13,13 +13,13 @@ from pipecat.audio.vad.silero import SileroVADAnalyzer
from pipecat.pipeline.pipeline import Pipeline
from pipecat.pipeline.runner import PipelineRunner
from pipecat.pipeline.task import PipelineParams, PipelineTask
from pipecat.services.aws.llm import BedrockLLMContext, BedrockLLMService
from pipecat.services.aws.stt import TranscribeSTTService
from pipecat.services.aws.tts import PollyTTSService
from pipecat.transcriptions.language import Language
from pipecat.transports.base_transport import TransportParams
from pipecat.transports.network.small_webrtc import SmallWebRTCTransport
from pipecat.transports.network.webrtc_connection import SmallWebRTCConnection
from pipecat.services.aws.llm import BedrockLLMService, BedrockLLMContext
from pipecat.services.aws.stt import TranscribeSTTService
from pipecat.services.aws.tts import PollyTTSService
load_dotenv(override=True)
@@ -42,28 +42,26 @@ async def run_bot(webrtc_connection: SmallWebRTCConnection, _: argparse.Namespac
region="us-west-2", # only specific regions support generative TTS
voice_id="Joanna",
params=PollyTTSService.InputParams(
engine="generative",
language=Language.EN_US,
rate="1.1"
engine="generative", language=Language.EN_US, rate="1.1"
),
)
llm = BedrockLLMService(
aws_region="us-west-2",
model="us.anthropic.claude-3-5-haiku-20241022-v1:0",
params=BedrockLLMService.InputParams(
temperature=0.8,
latency="optimized"
)
params=BedrockLLMService.InputParams(temperature=0.8, latency="optimized"),
)
messages = [
{
"role": "system",
"content": [{"text": "You are a helpful LLM in a WebRTC call. Your goal is to demonstrate your capabilities in a succinct way. Your output will be converted to audio so don't include special characters in your answers. Respond to what the user said in a creative and helpful way."}],
"content": [
{
"text": "You are a helpful LLM in a WebRTC call. Your goal is to demonstrate your capabilities in a succinct way. Your output will be converted to audio so don't include special characters in your answers. Respond to what the user said in a creative and helpful way."
}
],
},
]
)
context = BedrockLLMContext(messages)
context_aggregator = llm.create_context_aggregator(context)
@@ -94,7 +92,9 @@ async def run_bot(webrtc_connection: SmallWebRTCConnection, _: argparse.Namespac
async def on_client_connected(transport, client):
logger.info(f"Client connected")
# Kick off the conversation.
messages.append({"role": "user", "content": [{"text": "Please introduce yourself to the user."}]})
messages.append(
{"role": "user", "content": [{"text": "Please introduce yourself to the user."}]}
)
await task.queue_frames([context_aggregator.user().get_context_frame()])
@transport.event_handler("on_client_disconnected")

View File

@@ -24,7 +24,7 @@ class BedrockLLMAdapter(BaseLLMAdapter):
"properties": function.properties,
"required": function.required,
},
}
},
}
}

View File

@@ -226,7 +226,9 @@ class BedrockLLMContext(OpenAILLMContext):
if message["role"] == "tool":
# Try to parse the content as JSON if it looks like JSON
try:
if message["content"].strip().startswith('{') and message["content"].strip().endswith('}'):
if message["content"].strip().startswith("{") and message[
"content"
].strip().endswith("}"):
content_json = json.loads(message["content"])
tool_result_content = [{"json": content_json}]
else:
@@ -240,7 +242,7 @@ class BedrockLLMContext(OpenAILLMContext):
{
"toolResult": {
"toolUseId": message["tool_call_id"],
"content": tool_result_content
"content": tool_result_content,
},
},
],
@@ -287,15 +289,7 @@ class BedrockLLMContext(OpenAILLMContext):
encoded_image = base64.b64encode(buffer.getvalue()).decode("utf-8")
# Image should be the first content block in the message
content = [
{
"type": "image",
"format": "jpeg",
"source": {
"bytes": encoded_image
}
}
]
content = [{"type": "image", "format": "jpeg", "source": {"bytes": encoded_image}}]
if text:
content.append({"text": text})
self.add_message({"role": "user", "content": content})
@@ -309,9 +303,7 @@ class BedrockLLMContext(OpenAILLMContext):
# if the last message has just a content string, convert it to a list
# in the proper format
if isinstance(self.messages[-1]["content"], str):
self.messages[-1]["content"] = [
{"text": self.messages[-1]["content"]}
]
self.messages[-1]["content"] = [{"text": self.messages[-1]["content"]}]
# if this message has just a content string, convert it to a list
# in the proper format
if isinstance(message["content"], str):
@@ -452,7 +444,7 @@ class BedrockAssistantContextAggregator(LLMAssistantContextAggregator):
"toolUse": {
"toolUseId": frame.tool_call_id,
"name": frame.function_name,
"input": frame.arguments if frame.arguments else {}
"input": frame.arguments if frame.arguments else {},
}
}
],
@@ -465,11 +457,7 @@ class BedrockAssistantContextAggregator(LLMAssistantContextAggregator):
{
"toolResult": {
"toolUseId": frame.tool_call_id,
"content": [
{
"text": "IN_PROGRESS"
}
],
"content": [{"text": "IN_PROGRESS"}],
}
}
],
@@ -520,6 +508,7 @@ class BedrockLLMService(LLMService):
Requires AWS credentials to be configured in the environment or through boto3 configuration.
"""
class InputParams(BaseModel):
max_tokens: Optional[int] = Field(default_factory=lambda: 4096, ge=1)
temperature: Optional[float] = Field(default_factory=lambda: 0.7, ge=0.0, le=1.0)
@@ -547,18 +536,15 @@ class BedrockLLMService(LLMService):
client_config = Config(
connect_timeout=300, # 5 minutes
read_timeout=300, # 5 minutes
retries={'max_attempts': 3}
retries={"max_attempts": 3},
)
session = boto3.Session(
aws_access_key_id=aws_access_key,
aws_secret_access_key=aws_secret_key,
aws_session_token=aws_session_token,
region_name=aws_region
)
self._client = session.client(
service_name='bedrock-runtime',
config=client_config
region_name=aws_region,
)
self._client = session.client(service_name="bedrock-runtime", config=client_config)
self.set_model_name(model)
self._settings = {
@@ -566,7 +552,9 @@ class BedrockLLMService(LLMService):
"temperature": params.temperature,
"top_p": params.top_p,
"latency": params.latency,
"additional_model_request_fields": params.additional_model_request_fields if isinstance(params.additional_model_request_fields, dict) else {},
"additional_model_request_fields": params.additional_model_request_fields
if isinstance(params.additional_model_request_fields, dict)
else {},
}
logger.info(f"Using AWS Bedrock model: {model}")
@@ -639,7 +627,7 @@ class BedrockLLMService(LLMService):
"modelId": self.model_name,
"messages": context.messages,
"inferenceConfig": inference_config,
"additionalModelRequestFields": self._settings["additional_model_request_fields"]
"additionalModelRequestFields": self._settings["additional_model_request_fields"],
}
# Add system message
@@ -647,9 +635,7 @@ class BedrockLLMService(LLMService):
# Add tools if present
if context.tools:
tool_config = {
"tools": context.tools
}
tool_config = {"tools": context.tools}
# Add tool_choice if specified
if context.tool_choice:
@@ -658,20 +644,18 @@ class BedrockLLMService(LLMService):
elif context.tool_choice == "none":
# Skip adding toolChoice for "none"
pass
elif isinstance(context.tool_choice, dict) and "function" in context.tool_choice:
elif (
isinstance(context.tool_choice, dict) and "function" in context.tool_choice
):
tool_config["toolChoice"] = {
"tool": {
"name": context.tool_choice["function"]["name"]
}
"tool": {"name": context.tool_choice["function"]["name"]}
}
request_params["toolConfig"] = tool_config
# Add performance config if latency is specified
if self._settings["latency"] in ["standard", "optimized"]:
request_params["performanceConfig"] = {
"latency": self._settings["latency"]
}
request_params["performanceConfig"] = {"latency": self._settings["latency"]}
logger.debug(f"Calling Bedrock model with: {request_params}")
@@ -694,15 +678,17 @@ class BedrockLLMService(LLMService):
elif "toolUse" in delta and "input" in delta["toolUse"]:
# Handle partial JSON for tool use
json_accumulator += delta["toolUse"]["input"]
completion_tokens_estimate += self._estimate_tokens(delta["toolUse"]["input"])
completion_tokens_estimate += self._estimate_tokens(
delta["toolUse"]["input"]
)
# Handle tool use start
elif "contentBlockStart" in event:
content_block_start = event["contentBlockStart"]['start']
content_block_start = event["contentBlockStart"]["start"]
if "toolUse" in content_block_start:
tool_use_block = {
"id": content_block_start["toolUse"].get("toolUseId", ""),
"name": content_block_start["toolUse"].get("name", "")
"name": content_block_start["toolUse"].get("name", ""),
}
json_accumulator = ""
@@ -750,7 +736,7 @@ class BedrockLLMService(LLMService):
prompt_tokens=prompt_tokens,
completion_tokens=comp_tokens,
cache_read_input_tokens=cache_read_input_tokens,
cache_creation_input_tokens=cache_creation_input_tokens
cache_creation_input_tokens=cache_creation_input_tokens,
)
async def process_frame(self, frame: Frame, direction: FrameDirection):
@@ -783,7 +769,7 @@ class BedrockLLMService(LLMService):
prompt_tokens: int,
completion_tokens: int,
cache_read_input_tokens: int,
cache_creation_input_tokens: int
cache_creation_input_tokens: int,
):
if prompt_tokens or completion_tokens:
tokens = LLMTokenUsage(
@@ -791,6 +777,6 @@ class BedrockLLMService(LLMService):
completion_tokens=completion_tokens,
total_tokens=prompt_tokens + completion_tokens,
cache_read_input_tokens=cache_read_input_tokens,
cache_creation_input_tokens=cache_creation_input_tokens
cache_creation_input_tokens=cache_creation_input_tokens,
)
await self.start_llm_usage_metrics(tokens)

View File

@@ -19,7 +19,7 @@ from pipecat.frames.frames import (
Frame,
TranscriptionFrame,
InterimTranscriptionFrame,
StartFrame
StartFrame,
)
from pipecat.services.ai_services import STTService
from pipecat.transcriptions.language import Language

View File

@@ -17,7 +17,7 @@ from pipecat.frames.frames import (
Frame,
TTSAudioRawFrame,
TTSStartedFrame,
TTSStoppedFrame
TTSStoppedFrame,
)
from pipecat.services.ai_services import TTSService
from pipecat.transcriptions.language import Language