fix formatting
This commit is contained in:
@@ -13,13 +13,13 @@ from pipecat.audio.vad.silero import SileroVADAnalyzer
|
|||||||
from pipecat.pipeline.pipeline import Pipeline
|
from pipecat.pipeline.pipeline import Pipeline
|
||||||
from pipecat.pipeline.runner import PipelineRunner
|
from pipecat.pipeline.runner import PipelineRunner
|
||||||
from pipecat.pipeline.task import PipelineParams, PipelineTask
|
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.transcriptions.language import Language
|
||||||
from pipecat.transports.base_transport import TransportParams
|
from pipecat.transports.base_transport import TransportParams
|
||||||
from pipecat.transports.network.small_webrtc import SmallWebRTCTransport
|
from pipecat.transports.network.small_webrtc import SmallWebRTCTransport
|
||||||
from pipecat.transports.network.webrtc_connection import SmallWebRTCConnection
|
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)
|
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
|
region="us-west-2", # only specific regions support generative TTS
|
||||||
voice_id="Joanna",
|
voice_id="Joanna",
|
||||||
params=PollyTTSService.InputParams(
|
params=PollyTTSService.InputParams(
|
||||||
engine="generative",
|
engine="generative", language=Language.EN_US, rate="1.1"
|
||||||
language=Language.EN_US,
|
|
||||||
rate="1.1"
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
llm = BedrockLLMService(
|
llm = BedrockLLMService(
|
||||||
aws_region="us-west-2",
|
aws_region="us-west-2",
|
||||||
model="us.anthropic.claude-3-5-haiku-20241022-v1:0",
|
model="us.anthropic.claude-3-5-haiku-20241022-v1:0",
|
||||||
params=BedrockLLMService.InputParams(
|
params=BedrockLLMService.InputParams(temperature=0.8, latency="optimized"),
|
||||||
temperature=0.8,
|
|
||||||
latency="optimized"
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
messages = [
|
messages = [
|
||||||
{
|
{
|
||||||
"role": "system",
|
"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 = BedrockLLMContext(messages)
|
||||||
context_aggregator = llm.create_context_aggregator(context)
|
context_aggregator = llm.create_context_aggregator(context)
|
||||||
@@ -77,8 +75,8 @@ async def run_bot(webrtc_connection: SmallWebRTCConnection, _: argparse.Namespac
|
|||||||
tts, # TTS
|
tts, # TTS
|
||||||
transport.output(), # Transport bot output
|
transport.output(), # Transport bot output
|
||||||
context_aggregator.assistant(), # Assistant spoken responses
|
context_aggregator.assistant(), # Assistant spoken responses
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
task = PipelineTask(
|
task = PipelineTask(
|
||||||
pipeline,
|
pipeline,
|
||||||
@@ -94,7 +92,9 @@ async def run_bot(webrtc_connection: SmallWebRTCConnection, _: argparse.Namespac
|
|||||||
async def on_client_connected(transport, client):
|
async def on_client_connected(transport, client):
|
||||||
logger.info(f"Client connected")
|
logger.info(f"Client connected")
|
||||||
# Kick off the conversation.
|
# 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()])
|
await task.queue_frames([context_aggregator.user().get_context_frame()])
|
||||||
|
|
||||||
@transport.event_handler("on_client_disconnected")
|
@transport.event_handler("on_client_disconnected")
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ class BedrockLLMAdapter(BaseLLMAdapter):
|
|||||||
"properties": function.properties,
|
"properties": function.properties,
|
||||||
"required": function.required,
|
"required": function.required,
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -226,7 +226,9 @@ class BedrockLLMContext(OpenAILLMContext):
|
|||||||
if message["role"] == "tool":
|
if message["role"] == "tool":
|
||||||
# Try to parse the content as JSON if it looks like JSON
|
# Try to parse the content as JSON if it looks like JSON
|
||||||
try:
|
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"])
|
content_json = json.loads(message["content"])
|
||||||
tool_result_content = [{"json": content_json}]
|
tool_result_content = [{"json": content_json}]
|
||||||
else:
|
else:
|
||||||
@@ -240,7 +242,7 @@ class BedrockLLMContext(OpenAILLMContext):
|
|||||||
{
|
{
|
||||||
"toolResult": {
|
"toolResult": {
|
||||||
"toolUseId": message["tool_call_id"],
|
"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")
|
encoded_image = base64.b64encode(buffer.getvalue()).decode("utf-8")
|
||||||
|
|
||||||
# Image should be the first content block in the message
|
# Image should be the first content block in the message
|
||||||
content = [
|
content = [{"type": "image", "format": "jpeg", "source": {"bytes": encoded_image}}]
|
||||||
{
|
|
||||||
"type": "image",
|
|
||||||
"format": "jpeg",
|
|
||||||
"source": {
|
|
||||||
"bytes": encoded_image
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
if text:
|
if text:
|
||||||
content.append({"text": text})
|
content.append({"text": text})
|
||||||
self.add_message({"role": "user", "content": content})
|
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
|
# if the last message has just a content string, convert it to a list
|
||||||
# in the proper format
|
# in the proper format
|
||||||
if isinstance(self.messages[-1]["content"], str):
|
if isinstance(self.messages[-1]["content"], str):
|
||||||
self.messages[-1]["content"] = [
|
self.messages[-1]["content"] = [{"text": self.messages[-1]["content"]}]
|
||||||
{"text": self.messages[-1]["content"]}
|
|
||||||
]
|
|
||||||
# if this message has just a content string, convert it to a list
|
# if this message has just a content string, convert it to a list
|
||||||
# in the proper format
|
# in the proper format
|
||||||
if isinstance(message["content"], str):
|
if isinstance(message["content"], str):
|
||||||
@@ -452,7 +444,7 @@ class BedrockAssistantContextAggregator(LLMAssistantContextAggregator):
|
|||||||
"toolUse": {
|
"toolUse": {
|
||||||
"toolUseId": frame.tool_call_id,
|
"toolUseId": frame.tool_call_id,
|
||||||
"name": frame.function_name,
|
"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": {
|
"toolResult": {
|
||||||
"toolUseId": frame.tool_call_id,
|
"toolUseId": frame.tool_call_id,
|
||||||
"content": [
|
"content": [{"text": "IN_PROGRESS"}],
|
||||||
{
|
|
||||||
"text": "IN_PROGRESS"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@@ -520,6 +508,7 @@ class BedrockLLMService(LLMService):
|
|||||||
|
|
||||||
Requires AWS credentials to be configured in the environment or through boto3 configuration.
|
Requires AWS credentials to be configured in the environment or through boto3 configuration.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
class InputParams(BaseModel):
|
class InputParams(BaseModel):
|
||||||
max_tokens: Optional[int] = Field(default_factory=lambda: 4096, ge=1)
|
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)
|
temperature: Optional[float] = Field(default_factory=lambda: 0.7, ge=0.0, le=1.0)
|
||||||
@@ -546,19 +535,16 @@ class BedrockLLMService(LLMService):
|
|||||||
if not client_config:
|
if not client_config:
|
||||||
client_config = Config(
|
client_config = Config(
|
||||||
connect_timeout=300, # 5 minutes
|
connect_timeout=300, # 5 minutes
|
||||||
read_timeout=300, # 5 minutes
|
read_timeout=300, # 5 minutes
|
||||||
retries={'max_attempts': 3}
|
retries={"max_attempts": 3},
|
||||||
)
|
)
|
||||||
session = boto3.Session(
|
session = boto3.Session(
|
||||||
aws_access_key_id=aws_access_key,
|
aws_access_key_id=aws_access_key,
|
||||||
aws_secret_access_key=aws_secret_key,
|
aws_secret_access_key=aws_secret_key,
|
||||||
aws_session_token=aws_session_token,
|
aws_session_token=aws_session_token,
|
||||||
region_name=aws_region
|
region_name=aws_region,
|
||||||
)
|
|
||||||
self._client = session.client(
|
|
||||||
service_name='bedrock-runtime',
|
|
||||||
config=client_config
|
|
||||||
)
|
)
|
||||||
|
self._client = session.client(service_name="bedrock-runtime", config=client_config)
|
||||||
|
|
||||||
self.set_model_name(model)
|
self.set_model_name(model)
|
||||||
self._settings = {
|
self._settings = {
|
||||||
@@ -566,7 +552,9 @@ class BedrockLLMService(LLMService):
|
|||||||
"temperature": params.temperature,
|
"temperature": params.temperature,
|
||||||
"top_p": params.top_p,
|
"top_p": params.top_p,
|
||||||
"latency": params.latency,
|
"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}")
|
logger.info(f"Using AWS Bedrock model: {model}")
|
||||||
@@ -639,7 +627,7 @@ class BedrockLLMService(LLMService):
|
|||||||
"modelId": self.model_name,
|
"modelId": self.model_name,
|
||||||
"messages": context.messages,
|
"messages": context.messages,
|
||||||
"inferenceConfig": inference_config,
|
"inferenceConfig": inference_config,
|
||||||
"additionalModelRequestFields": self._settings["additional_model_request_fields"]
|
"additionalModelRequestFields": self._settings["additional_model_request_fields"],
|
||||||
}
|
}
|
||||||
|
|
||||||
# Add system message
|
# Add system message
|
||||||
@@ -647,9 +635,7 @@ class BedrockLLMService(LLMService):
|
|||||||
|
|
||||||
# Add tools if present
|
# Add tools if present
|
||||||
if context.tools:
|
if context.tools:
|
||||||
tool_config = {
|
tool_config = {"tools": context.tools}
|
||||||
"tools": context.tools
|
|
||||||
}
|
|
||||||
|
|
||||||
# Add tool_choice if specified
|
# Add tool_choice if specified
|
||||||
if context.tool_choice:
|
if context.tool_choice:
|
||||||
@@ -658,20 +644,18 @@ class BedrockLLMService(LLMService):
|
|||||||
elif context.tool_choice == "none":
|
elif context.tool_choice == "none":
|
||||||
# Skip adding toolChoice for "none"
|
# Skip adding toolChoice for "none"
|
||||||
pass
|
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_config["toolChoice"] = {
|
||||||
"tool": {
|
"tool": {"name": context.tool_choice["function"]["name"]}
|
||||||
"name": context.tool_choice["function"]["name"]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
request_params["toolConfig"] = tool_config
|
request_params["toolConfig"] = tool_config
|
||||||
|
|
||||||
# Add performance config if latency is specified
|
# Add performance config if latency is specified
|
||||||
if self._settings["latency"] in ["standard", "optimized"]:
|
if self._settings["latency"] in ["standard", "optimized"]:
|
||||||
request_params["performanceConfig"] = {
|
request_params["performanceConfig"] = {"latency": self._settings["latency"]}
|
||||||
"latency": self._settings["latency"]
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.debug(f"Calling Bedrock model with: {request_params}")
|
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"]:
|
elif "toolUse" in delta and "input" in delta["toolUse"]:
|
||||||
# Handle partial JSON for tool use
|
# Handle partial JSON for tool use
|
||||||
json_accumulator += delta["toolUse"]["input"]
|
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
|
# Handle tool use start
|
||||||
elif "contentBlockStart" in event:
|
elif "contentBlockStart" in event:
|
||||||
content_block_start = event["contentBlockStart"]['start']
|
content_block_start = event["contentBlockStart"]["start"]
|
||||||
if "toolUse" in content_block_start:
|
if "toolUse" in content_block_start:
|
||||||
tool_use_block = {
|
tool_use_block = {
|
||||||
"id": content_block_start["toolUse"].get("toolUseId", ""),
|
"id": content_block_start["toolUse"].get("toolUseId", ""),
|
||||||
"name": content_block_start["toolUse"].get("name", "")
|
"name": content_block_start["toolUse"].get("name", ""),
|
||||||
}
|
}
|
||||||
json_accumulator = ""
|
json_accumulator = ""
|
||||||
|
|
||||||
@@ -750,7 +736,7 @@ class BedrockLLMService(LLMService):
|
|||||||
prompt_tokens=prompt_tokens,
|
prompt_tokens=prompt_tokens,
|
||||||
completion_tokens=comp_tokens,
|
completion_tokens=comp_tokens,
|
||||||
cache_read_input_tokens=cache_read_input_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):
|
async def process_frame(self, frame: Frame, direction: FrameDirection):
|
||||||
@@ -783,7 +769,7 @@ class BedrockLLMService(LLMService):
|
|||||||
prompt_tokens: int,
|
prompt_tokens: int,
|
||||||
completion_tokens: int,
|
completion_tokens: int,
|
||||||
cache_read_input_tokens: int,
|
cache_read_input_tokens: int,
|
||||||
cache_creation_input_tokens: int
|
cache_creation_input_tokens: int,
|
||||||
):
|
):
|
||||||
if prompt_tokens or completion_tokens:
|
if prompt_tokens or completion_tokens:
|
||||||
tokens = LLMTokenUsage(
|
tokens = LLMTokenUsage(
|
||||||
@@ -791,6 +777,6 @@ class BedrockLLMService(LLMService):
|
|||||||
completion_tokens=completion_tokens,
|
completion_tokens=completion_tokens,
|
||||||
total_tokens=prompt_tokens + completion_tokens,
|
total_tokens=prompt_tokens + completion_tokens,
|
||||||
cache_read_input_tokens=cache_read_input_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)
|
await self.start_llm_usage_metrics(tokens)
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ from pipecat.frames.frames import (
|
|||||||
Frame,
|
Frame,
|
||||||
TranscriptionFrame,
|
TranscriptionFrame,
|
||||||
InterimTranscriptionFrame,
|
InterimTranscriptionFrame,
|
||||||
StartFrame
|
StartFrame,
|
||||||
)
|
)
|
||||||
from pipecat.services.ai_services import STTService
|
from pipecat.services.ai_services import STTService
|
||||||
from pipecat.transcriptions.language import Language
|
from pipecat.transcriptions.language import Language
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ from pipecat.frames.frames import (
|
|||||||
Frame,
|
Frame,
|
||||||
TTSAudioRawFrame,
|
TTSAudioRawFrame,
|
||||||
TTSStartedFrame,
|
TTSStartedFrame,
|
||||||
TTSStoppedFrame
|
TTSStoppedFrame,
|
||||||
)
|
)
|
||||||
from pipecat.services.ai_services import TTSService
|
from pipecat.services.ai_services import TTSService
|
||||||
from pipecat.transcriptions.language import Language
|
from pipecat.transcriptions.language import Language
|
||||||
@@ -195,7 +195,7 @@ class PollyTTSService(TTSService):
|
|||||||
# logger.warning("Prosody tags are not supported for generative engine. Ignoring.")
|
# logger.warning("Prosody tags are not supported for generative engine. Ignoring.")
|
||||||
|
|
||||||
if prosody_attrs:
|
if prosody_attrs:
|
||||||
ssml += f"<prosody {' '.join(prosody_attrs)}>"
|
ssml += f"<prosody {' '.join(prosody_attrs)}>"
|
||||||
|
|
||||||
ssml += text
|
ssml += text
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user