참고소스 수정본
This commit is contained in:
29
참고/instructor-main/tests/llm/test_bedrock/conftest.py
Normal file
29
참고/instructor-main/tests/llm/test_bedrock/conftest.py
Normal file
@@ -0,0 +1,29 @@
|
||||
from __future__ import annotations
|
||||
import base64
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def tiny_png_bytes() -> bytes:
|
||||
return base64.b64decode(
|
||||
b"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR4nGNgYAAAAAMA"
|
||||
b"ASsJTYQAAAAASUVORK5CYII="
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def tiny_png_data_url(tiny_png_bytes: bytes) -> str:
|
||||
return "data:image/png;base64," + base64.b64encode(tiny_png_bytes).decode("utf-8")
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def image_url() -> str:
|
||||
# Public test asset used across the suite
|
||||
return "https://raw.githubusercontent.com/instructor-ai/instructor/main/tests/assets/image.jpg"
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def tiny_pdf_bytes() -> bytes:
|
||||
return base64.b64decode(
|
||||
b"JVBERi0xLjQKJSVPRgoAAAAQAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
|
||||
)
|
||||
@@ -0,0 +1,20 @@
|
||||
from __future__ import annotations
|
||||
from instructor.providers.bedrock.utils import _to_bedrock_content_items
|
||||
|
||||
|
||||
def test_bedrock_native_text_passthrough():
|
||||
content = [{"text": "Bedrock-native text"}]
|
||||
items = _to_bedrock_content_items(content)
|
||||
assert items == [{"text": "Bedrock-native text"}]
|
||||
|
||||
|
||||
def test_bedrock_native_image_passthrough(tiny_png_bytes: bytes):
|
||||
native = {"image": {"format": "png", "source": {"bytes": tiny_png_bytes}}}
|
||||
items = _to_bedrock_content_items([native])
|
||||
assert items[0] == native
|
||||
|
||||
|
||||
def test_bedrock_native_document_passthrough(tiny_pdf_bytes: bytes):
|
||||
native = {"document": {"format": "pdf", "source": {"bytes": tiny_pdf_bytes}}}
|
||||
items = _to_bedrock_content_items([native])
|
||||
assert items[0] == native
|
||||
26
참고/instructor-main/tests/llm/test_bedrock/test_normalize.py
Normal file
26
참고/instructor-main/tests/llm/test_bedrock/test_normalize.py
Normal file
@@ -0,0 +1,26 @@
|
||||
from __future__ import annotations
|
||||
import pytest
|
||||
from instructor.providers.bedrock.utils import _normalize_bedrock_image_format
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"inp,expected",
|
||||
[
|
||||
("image/jpeg", "jpeg"),
|
||||
("image/jpg", "jpeg"),
|
||||
("jpg", "jpeg"),
|
||||
("jpeg", "jpeg"),
|
||||
("image/pjpeg", "jpeg"),
|
||||
("image/png", "png"),
|
||||
("png", "png"),
|
||||
("image/gif", "gif"),
|
||||
("gif", "gif"),
|
||||
("image/webp", "webp"),
|
||||
("webp", "webp"),
|
||||
("", "jpeg"),
|
||||
(None, "jpeg"),
|
||||
("image/whatever", "jpeg"),
|
||||
],
|
||||
)
|
||||
def test_normalize_bedrock_image_format(inp, expected):
|
||||
assert _normalize_bedrock_image_format(inp) == expected
|
||||
@@ -0,0 +1,52 @@
|
||||
from __future__ import annotations
|
||||
import base64
|
||||
import pytest
|
||||
from instructor.providers.bedrock.utils import (
|
||||
_openai_image_part_to_bedrock,
|
||||
_to_bedrock_content_items,
|
||||
)
|
||||
|
||||
|
||||
def test_openai_image_part_to_bedrock_data_url(tiny_png_data_url: str):
|
||||
part = {"type": "image_url", "image_url": {"url": tiny_png_data_url}}
|
||||
out = _openai_image_part_to_bedrock(part)
|
||||
assert "image" in out
|
||||
assert out["image"]["format"] in {"png", "jpeg", "gif", "webp"} # png expected
|
||||
assert out["image"]["source"]["bytes"] == base64.b64decode(
|
||||
tiny_png_data_url.split(",", 1)[1]
|
||||
)
|
||||
|
||||
|
||||
def test_openai_image_part_to_bedrock_https(image_url: str):
|
||||
part = {"type": "image_url", "image_url": {"url": image_url}}
|
||||
out = _openai_image_part_to_bedrock(part)
|
||||
assert "image" in out
|
||||
# GitHub raw returns jpeg for the sample. Normalize is handled in utils.
|
||||
assert out["image"]["format"] in {"jpeg", "png", "gif", "webp"}
|
||||
assert isinstance(out["image"]["source"]["bytes"], (bytes, bytearray))
|
||||
assert len(out["image"]["source"]["bytes"]) > 0
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"text_part",
|
||||
[
|
||||
{"type": "text", "text": "What is in this image?"},
|
||||
{"type": "input_text", "text": "Describe the image."},
|
||||
],
|
||||
)
|
||||
@pytest.mark.parametrize("image_kind", ["data", "https"])
|
||||
def test_to_bedrock_content_items_openai_combo(
|
||||
text_part, image_kind, tiny_png_data_url: str, image_url: str
|
||||
):
|
||||
if image_kind == "data":
|
||||
image_part = {"type": "image_url", "image_url": {"url": tiny_png_data_url}}
|
||||
else:
|
||||
image_part = {"type": "image_url", "image_url": {"url": image_url}}
|
||||
|
||||
content = [text_part, image_part]
|
||||
items = _to_bedrock_content_items(content)
|
||||
|
||||
assert items[0] == {"text": text_part["text"]}
|
||||
assert "image" in items[1]
|
||||
assert isinstance(items[1]["image"]["source"]["bytes"], (bytes, bytearray))
|
||||
assert len(items[1]["image"]["source"]["bytes"]) > 0
|
||||
@@ -0,0 +1,59 @@
|
||||
from __future__ import annotations
|
||||
import pytest
|
||||
from instructor.providers.bedrock.utils import _prepare_bedrock_converse_kwargs_internal
|
||||
|
||||
|
||||
def test_prepare_bedrock_kwargs_openai_text_plus_image(tiny_png_data_url: str):
|
||||
call_kwargs = {
|
||||
"model": "anthropic.claude-3-5-sonnet",
|
||||
"temperature": 0.3,
|
||||
"max_tokens": 256,
|
||||
"top_p": 0.9,
|
||||
"stop": ["<END>"],
|
||||
"system": [{"text": "You are helpful."}],
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": [
|
||||
{"type": "text", "text": "hi"},
|
||||
{"type": "image_url", "image_url": {"url": tiny_png_data_url}},
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
out = _prepare_bedrock_converse_kwargs_internal(call_kwargs)
|
||||
|
||||
assert out["modelId"] == "anthropic.claude-3-5-sonnet"
|
||||
inf = out["inferenceConfig"]
|
||||
assert inf["temperature"] == 0.3
|
||||
assert inf["maxTokens"] == 256
|
||||
assert inf["topP"] == 0.9
|
||||
assert inf["stopSequences"] == ["<END>"]
|
||||
assert out["system"][0]["text"] == "You are helpful."
|
||||
|
||||
parts = out["messages"][0]["content"]
|
||||
assert parts[0] == {"text": "hi"}
|
||||
assert parts[1]["image"]["format"] in {"jpeg", "png", "gif", "webp"}
|
||||
assert isinstance(parts[1]["image"]["source"]["bytes"], (bytes, bytearray))
|
||||
assert len(parts[1]["image"]["source"]["bytes"]) > 0
|
||||
|
||||
|
||||
def test_prepare_bedrock_kwargs_openai_image_url_rejects_http():
|
||||
"""Remote HTTP(S) URLs are not fetched (SSRF prevention) — must use data: URLs."""
|
||||
call_kwargs = {
|
||||
"model": "anthropic.claude-3-5-sonnet",
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": [
|
||||
{
|
||||
"type": "image_url",
|
||||
"image_url": {"url": "https://example.com/image.jpg"},
|
||||
}
|
||||
],
|
||||
}
|
||||
],
|
||||
}
|
||||
with pytest.raises(ValueError, match="Unsupported image_url scheme for Bedrock"):
|
||||
_prepare_bedrock_converse_kwargs_internal(call_kwargs)
|
||||
Reference in New Issue
Block a user