Validating Message and Image Processing in llama_index
This test suite validates the core message and image handling functionality in LlamaIndex, focusing on ChatMessage types and ImageBlock implementations. It ensures robust handling of different message formats, image processing, and serialization mechanisms.
Test Coverage Overview
Implementation Analysis
Technical Details
Best Practices Demonstrated
run-llama/llama_index
llama-index-core/tests/base/llms/test_types.py
import base64
from io import BytesIO
from pathlib import Path
from unittest import mock
import pytest
from llama_index.core.base.llms.types import (
ChatMessage,
ImageBlock,
MessageRole,
TextBlock,
)
from llama_index.core.bridge.pydantic import BaseModel
from pydantic import AnyUrl
@pytest.fixture()
def png_1px_b64() -> bytes:
return b"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg=="
@pytest.fixture()
def png_1px(png_1px_b64) -> bytes:
return base64.b64decode(png_1px_b64)
def test_chat_message_from_str():
m = ChatMessage.from_str(content="test content")
assert m.content == "test content"
assert len(m.blocks) == 1
assert type(m.blocks[0]) is TextBlock
assert m.blocks[0].text == "test content"
def test_chat_message_content_legacy_get():
m = ChatMessage(content="test content")
assert m.content == "test content"
assert len(m.blocks) == 1
assert type(m.blocks[0]) is TextBlock
assert m.blocks[0].text == "test content"
m = ChatMessage(role="user", content="test content")
assert m.role == "user"
assert m.content == "test content"
assert len(m.blocks) == 1
assert type(m.blocks[0]) is TextBlock
assert m.blocks[0].text == "test content"
m = ChatMessage(
content=[TextBlock(text="test content 1 "), TextBlock(text="test content 2")]
)
assert m.content == "test content 1 test content 2"
assert len(m.blocks) == 2
assert all(type(block) is TextBlock for block in m.blocks)
def test_chat_message_content_legacy_set():
m = ChatMessage()
m.content = "test content"
assert len(m.blocks) == 1
assert type(m.blocks[0]) is TextBlock
assert m.blocks[0].text == "test content"
m = ChatMessage(content="some original content")
m.content = "test content"
assert len(m.blocks) == 1
assert type(m.blocks[0]) is TextBlock
assert m.blocks[0].text == "test content"
m = ChatMessage(content=[TextBlock(text="test content"), ImageBlock()])
with pytest.raises(ValueError):
m.content = "test content"
def test_chat_message_content_returns_empty_string():
m = ChatMessage(content=[TextBlock(text="test content"), ImageBlock()])
assert m.content is None
def test_chat_message__str__():
assert str(ChatMessage(content="test content")) == "user: test content"
def test_chat_message_serializer():
class SimpleModel(BaseModel):
some_field: str = ""
m = ChatMessage(
content="test content",
additional_kwargs={"some_list": ["a", "b", "c"], "some_object": SimpleModel()},
)
assert m.model_dump() == {
"role": MessageRole.USER,
"additional_kwargs": {
"some_list": ["a", "b", "c"],
"some_object": {"some_field": ""},
},
"blocks": [{"block_type": "text", "text": "test content"}],
}
def test_chat_message_legacy_roundtrip():
legacy_message = {
"role": MessageRole.USER,
"content": "foo",
"additional_kwargs": {},
}
m = ChatMessage(**legacy_message)
assert m.model_dump() == {
"additional_kwargs": {},
"blocks": [{"block_type": "text", "text": "foo"}],
"role": MessageRole.USER,
}
def test_image_block_resolve_image(png_1px: bytes, png_1px_b64: bytes):
b = ImageBlock(image=png_1px)
img = b.resolve_image()
assert isinstance(img, BytesIO)
assert img.read() == png_1px
img = b.resolve_image(as_base64=True)
assert isinstance(img, BytesIO)
assert img.read() == png_1px_b64
def test_image_block_resolve_image_path(
tmp_path: Path, png_1px_b64: bytes, png_1px: bytes
):
png_path = tmp_path / "test.png"
png_path.write_bytes(png_1px)
b = ImageBlock(path=png_path)
img = b.resolve_image()
assert isinstance(img, BytesIO)
assert img.read() == png_1px
img = b.resolve_image(as_base64=True)
assert isinstance(img, BytesIO)
assert img.read() == png_1px_b64
def test_image_block_resolve_image_url(png_1px_b64: bytes, png_1px: bytes):
with mock.patch("llama_index.core.base.llms.types.requests") as mocked_req:
url_str = "http://example.com"
mocked_req.get.return_value = mock.MagicMock(content=png_1px)
b = ImageBlock(url=AnyUrl(url=url_str))
img = b.resolve_image()
assert isinstance(img, BytesIO)
assert img.read() == png_1px
img = b.resolve_image(as_base64=True)
assert isinstance(img, BytesIO)
assert img.read() == png_1px_b64
def test_image_block_resolve_error():
with pytest.raises(ValueError, match="No image found in the chat message!"):
b = ImageBlock()
b.resolve_image()
def test_image_block_store_as_anyurl():
url_str = "http://example.com"
b = ImageBlock(url=url_str)
assert b.url == AnyUrl(url=url_str)
def test_image_block_store_as_base64(png_1px_b64: bytes, png_1px: bytes):
# Store regular bytes
assert ImageBlock(image=png_1px).image == png_1px_b64
# Store already encoded data
assert ImageBlock(image=png_1px_b64).image == png_1px_b64