livekit-plugins-anthropic 0.2.7__py3-none-any.whl → 0.2.8__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.
- livekit/plugins/anthropic/llm.py +43 -98
- livekit/plugins/anthropic/version.py +1 -1
- {livekit_plugins_anthropic-0.2.7.dist-info → livekit_plugins_anthropic-0.2.8.dist-info}/METADATA +2 -2
- livekit_plugins_anthropic-0.2.8.dist-info/RECORD +10 -0
- livekit_plugins_anthropic-0.2.7.dist-info/RECORD +0 -10
- {livekit_plugins_anthropic-0.2.7.dist-info → livekit_plugins_anthropic-0.2.8.dist-info}/WHEEL +0 -0
- {livekit_plugins_anthropic-0.2.7.dist-info → livekit_plugins_anthropic-0.2.8.dist-info}/top_level.txt +0 -0
livekit/plugins/anthropic/llm.py
CHANGED
@@ -24,8 +24,8 @@ from typing import (
|
|
24
24
|
Awaitable,
|
25
25
|
List,
|
26
26
|
Literal,
|
27
|
-
Tuple,
|
28
27
|
Union,
|
28
|
+
cast,
|
29
29
|
get_args,
|
30
30
|
get_origin,
|
31
31
|
)
|
@@ -40,6 +40,10 @@ from livekit.agents import (
|
|
40
40
|
utils,
|
41
41
|
)
|
42
42
|
from livekit.agents.llm import ToolChoice
|
43
|
+
from livekit.agents.llm.function_context import (
|
44
|
+
_create_ai_function_info,
|
45
|
+
_is_optional_type,
|
46
|
+
)
|
43
47
|
from livekit.agents.types import DEFAULT_API_CONNECT_OPTIONS, APIConnectOptions
|
44
48
|
|
45
49
|
import anthropic
|
@@ -427,12 +431,36 @@ def _build_anthropic_message(
|
|
427
431
|
def _build_anthropic_image_content(
|
428
432
|
image: llm.ChatImage, cache_key: Any
|
429
433
|
) -> anthropic.types.ImageBlockParam:
|
430
|
-
if isinstance(image.image, str): # image
|
431
|
-
|
432
|
-
"
|
433
|
-
|
434
|
-
|
435
|
-
|
434
|
+
if isinstance(image.image, str): # image is a URL
|
435
|
+
if not image.image.startswith("data:"):
|
436
|
+
raise ValueError("LiveKit Anthropic Plugin: Image URLs must be data URLs")
|
437
|
+
|
438
|
+
try:
|
439
|
+
header, b64_data = image.image.split(",", 1)
|
440
|
+
media_type = header.split(";")[0].split(":")[1]
|
441
|
+
|
442
|
+
supported_types = {"image/jpeg", "image/png", "image/webp", "image/gif"}
|
443
|
+
if media_type not in supported_types:
|
444
|
+
raise ValueError(
|
445
|
+
f"LiveKit Anthropic Plugin: Unsupported media type {media_type}. Must be jpeg, png, webp, or gif"
|
446
|
+
)
|
447
|
+
|
448
|
+
return {
|
449
|
+
"type": "image",
|
450
|
+
"source": {
|
451
|
+
"type": "base64",
|
452
|
+
"data": b64_data,
|
453
|
+
"media_type": cast(
|
454
|
+
Literal["image/jpeg", "image/png", "image/gif", "image/webp"],
|
455
|
+
media_type,
|
456
|
+
),
|
457
|
+
},
|
458
|
+
}
|
459
|
+
except (ValueError, IndexError) as e:
|
460
|
+
raise ValueError(
|
461
|
+
f"LiveKit Anthropic Plugin: Invalid image data URL {str(e)}"
|
462
|
+
)
|
463
|
+
elif isinstance(image.image, rtc.VideoFrame): # image is a VideoFrame
|
436
464
|
if cache_key not in image._cache:
|
437
465
|
# inside our internal implementation, we allow to put extra metadata to
|
438
466
|
# each ChatImage (avoid to reencode each time we do a chatcompletion request)
|
@@ -441,7 +469,7 @@ def _build_anthropic_image_content(
|
|
441
469
|
opts.resize_options = utils.images.ResizeOptions(
|
442
470
|
width=image.inference_width,
|
443
471
|
height=image.inference_height,
|
444
|
-
strategy="
|
472
|
+
strategy="scale_aspect_fit",
|
445
473
|
)
|
446
474
|
|
447
475
|
encoded_data = utils.images.encode(image.image, opts)
|
@@ -456,65 +484,8 @@ def _build_anthropic_image_content(
|
|
456
484
|
},
|
457
485
|
}
|
458
486
|
|
459
|
-
raise ValueError(
|
460
|
-
|
461
|
-
|
462
|
-
def _create_ai_function_info(
|
463
|
-
fnc_ctx: llm.function_context.FunctionContext,
|
464
|
-
tool_call_id: str,
|
465
|
-
fnc_name: str,
|
466
|
-
raw_arguments: str, # JSON string
|
467
|
-
) -> llm.function_context.FunctionCallInfo:
|
468
|
-
if fnc_name not in fnc_ctx.ai_functions:
|
469
|
-
raise ValueError(f"AI function {fnc_name} not found")
|
470
|
-
|
471
|
-
parsed_arguments: dict[str, Any] = {}
|
472
|
-
try:
|
473
|
-
if raw_arguments: # ignore empty string
|
474
|
-
parsed_arguments = json.loads(raw_arguments)
|
475
|
-
except json.JSONDecodeError:
|
476
|
-
raise ValueError(
|
477
|
-
f"AI function {fnc_name} received invalid JSON arguments - {raw_arguments}"
|
478
|
-
)
|
479
|
-
|
480
|
-
fnc_info = fnc_ctx.ai_functions[fnc_name]
|
481
|
-
|
482
|
-
# Ensure all necessary arguments are present and of the correct type.
|
483
|
-
sanitized_arguments: dict[str, Any] = {}
|
484
|
-
for arg_info in fnc_info.arguments.values():
|
485
|
-
if arg_info.name not in parsed_arguments:
|
486
|
-
if arg_info.default is inspect.Parameter.empty:
|
487
|
-
raise ValueError(
|
488
|
-
f"AI function {fnc_name} missing required argument {arg_info.name}"
|
489
|
-
)
|
490
|
-
continue
|
491
|
-
|
492
|
-
arg_value = parsed_arguments[arg_info.name]
|
493
|
-
if get_origin(arg_info.type) is not None:
|
494
|
-
if not isinstance(arg_value, list):
|
495
|
-
raise ValueError(
|
496
|
-
f"AI function {fnc_name} argument {arg_info.name} should be a list"
|
497
|
-
)
|
498
|
-
|
499
|
-
inner_type = get_args(arg_info.type)[0]
|
500
|
-
sanitized_value = [
|
501
|
-
_sanitize_primitive(
|
502
|
-
value=v, expected_type=inner_type, choices=arg_info.choices
|
503
|
-
)
|
504
|
-
for v in arg_value
|
505
|
-
]
|
506
|
-
else:
|
507
|
-
sanitized_value = _sanitize_primitive(
|
508
|
-
value=arg_value, expected_type=arg_info.type, choices=arg_info.choices
|
509
|
-
)
|
510
|
-
|
511
|
-
sanitized_arguments[arg_info.name] = sanitized_value
|
512
|
-
|
513
|
-
return llm.function_context.FunctionCallInfo(
|
514
|
-
tool_call_id=tool_call_id,
|
515
|
-
raw_arguments=raw_arguments,
|
516
|
-
function_info=fnc_info,
|
517
|
-
arguments=sanitized_arguments,
|
487
|
+
raise ValueError(
|
488
|
+
"LiveKit Anthropic Plugin: ChatImage must be an rtc.VideoFrame or a data URL"
|
518
489
|
)
|
519
490
|
|
520
491
|
|
@@ -541,8 +512,10 @@ def _build_function_description(
|
|
541
512
|
if arg_info.description:
|
542
513
|
p["description"] = arg_info.description
|
543
514
|
|
544
|
-
|
545
|
-
|
515
|
+
is_optional, inner_th = _is_optional_type(arg_info.type)
|
516
|
+
|
517
|
+
if get_origin(inner_th) is list:
|
518
|
+
inner_type = get_args(inner_th)[0]
|
546
519
|
p["type"] = "array"
|
547
520
|
p["items"] = {}
|
548
521
|
p["items"]["type"] = type2str(inner_type)
|
@@ -550,7 +523,7 @@ def _build_function_description(
|
|
550
523
|
if arg_info.choices:
|
551
524
|
p["items"]["enum"] = arg_info.choices
|
552
525
|
else:
|
553
|
-
p["type"] = type2str(
|
526
|
+
p["type"] = type2str(inner_th)
|
554
527
|
if arg_info.choices:
|
555
528
|
p["enum"] = arg_info.choices
|
556
529
|
|
@@ -566,31 +539,3 @@ def _build_function_description(
|
|
566
539
|
"description": fnc_info.description,
|
567
540
|
"input_schema": input_schema,
|
568
541
|
}
|
569
|
-
|
570
|
-
|
571
|
-
def _sanitize_primitive(
|
572
|
-
*, value: Any, expected_type: type, choices: Tuple[Any] | None
|
573
|
-
) -> Any:
|
574
|
-
if expected_type is str:
|
575
|
-
if not isinstance(value, str):
|
576
|
-
raise ValueError(f"expected str, got {type(value)}")
|
577
|
-
elif expected_type in (int, float):
|
578
|
-
if not isinstance(value, (int, float)):
|
579
|
-
raise ValueError(f"expected number, got {type(value)}")
|
580
|
-
|
581
|
-
if expected_type is int:
|
582
|
-
if value % 1 != 0:
|
583
|
-
raise ValueError("expected int, got float")
|
584
|
-
|
585
|
-
value = int(value)
|
586
|
-
elif expected_type is float:
|
587
|
-
value = float(value)
|
588
|
-
|
589
|
-
elif expected_type is bool:
|
590
|
-
if not isinstance(value, bool):
|
591
|
-
raise ValueError(f"expected bool, got {type(value)}")
|
592
|
-
|
593
|
-
if choices and value not in choices:
|
594
|
-
raise ValueError(f"invalid value {value}, not in {choices}")
|
595
|
-
|
596
|
-
return value
|
{livekit_plugins_anthropic-0.2.7.dist-info → livekit_plugins_anthropic-0.2.8.dist-info}/METADATA
RENAMED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: livekit-plugins-anthropic
|
3
|
-
Version: 0.2.
|
3
|
+
Version: 0.2.8
|
4
4
|
Summary: Agent Framework plugin for services from Anthropic
|
5
5
|
Home-page: https://github.com/livekit/agents
|
6
6
|
License: Apache-2.0
|
@@ -19,7 +19,7 @@ Classifier: Programming Language :: Python :: 3.10
|
|
19
19
|
Classifier: Programming Language :: Python :: 3 :: Only
|
20
20
|
Requires-Python: >=3.9.0
|
21
21
|
Description-Content-Type: text/markdown
|
22
|
-
Requires-Dist: livekit-agents>=0.
|
22
|
+
Requires-Dist: livekit-agents>=0.12.3
|
23
23
|
Requires-Dist: anthropic>=0.34
|
24
24
|
|
25
25
|
# LiveKit Plugins Anthropic
|
@@ -0,0 +1,10 @@
|
|
1
|
+
livekit/plugins/anthropic/__init__.py,sha256=1WCyNEaR6qBsX54qJQM0SeY-QHIucww16PLXcSnMqRo,1175
|
2
|
+
livekit/plugins/anthropic/llm.py,sha256=e65Z_YchNHCXN2F1kKb8lczfSY1_Ak8Y_94nT12pZGI,18975
|
3
|
+
livekit/plugins/anthropic/log.py,sha256=fG1pYSY88AnT738gZrmzF9FO4l4BdGENj3VKHMQB3Yo,72
|
4
|
+
livekit/plugins/anthropic/models.py,sha256=wyTr2nl6SL4ylN6s4mHJcqtmgV2mjJysZo89FknWdhI,213
|
5
|
+
livekit/plugins/anthropic/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
6
|
+
livekit/plugins/anthropic/version.py,sha256=711Prlpzg5p2xCBjcE2dctFtzW_seKcOBI5-dvNUVK4,600
|
7
|
+
livekit_plugins_anthropic-0.2.8.dist-info/METADATA,sha256=xG06Y2Xf9RjmmBqJ314_6ZmFlEM0ZCo00K82wJHEHHo,1265
|
8
|
+
livekit_plugins_anthropic-0.2.8.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
|
9
|
+
livekit_plugins_anthropic-0.2.8.dist-info/top_level.txt,sha256=OoDok3xUmXbZRvOrfvvXB-Juu4DX79dlq188E19YHoo,8
|
10
|
+
livekit_plugins_anthropic-0.2.8.dist-info/RECORD,,
|
@@ -1,10 +0,0 @@
|
|
1
|
-
livekit/plugins/anthropic/__init__.py,sha256=1WCyNEaR6qBsX54qJQM0SeY-QHIucww16PLXcSnMqRo,1175
|
2
|
-
livekit/plugins/anthropic/llm.py,sha256=6v_f7G8_zxFnf8D-mIDN-2jYaju8mMPCVnZ485SIuzM,20798
|
3
|
-
livekit/plugins/anthropic/log.py,sha256=fG1pYSY88AnT738gZrmzF9FO4l4BdGENj3VKHMQB3Yo,72
|
4
|
-
livekit/plugins/anthropic/models.py,sha256=wyTr2nl6SL4ylN6s4mHJcqtmgV2mjJysZo89FknWdhI,213
|
5
|
-
livekit/plugins/anthropic/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
6
|
-
livekit/plugins/anthropic/version.py,sha256=ctbdsqNKaYDxuDqpKvxGUGiUJhMWF_Cgw8jw_g8sC_0,600
|
7
|
-
livekit_plugins_anthropic-0.2.7.dist-info/METADATA,sha256=bl5blok7UehQompcSjpT1P00MssZH-H8OOC-au_Je1M,1263
|
8
|
-
livekit_plugins_anthropic-0.2.7.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
|
9
|
-
livekit_plugins_anthropic-0.2.7.dist-info/top_level.txt,sha256=OoDok3xUmXbZRvOrfvvXB-Juu4DX79dlq188E19YHoo,8
|
10
|
-
livekit_plugins_anthropic-0.2.7.dist-info/RECORD,,
|
{livekit_plugins_anthropic-0.2.7.dist-info → livekit_plugins_anthropic-0.2.8.dist-info}/WHEEL
RENAMED
File without changes
|
File without changes
|