mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-01-25 08:08:14 +00:00
Compare commits
3 Commits
devin/1768
...
devin/1741
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
36e064b240 | ||
|
|
942d65b1de | ||
|
|
447a994ef8 |
@@ -1,5 +1,5 @@
|
|||||||
from enum import Enum
|
from enum import Enum
|
||||||
from typing import Any, Dict, List, Optional, Union
|
from typing import Any, Dict, List, Literal, Optional, Union
|
||||||
|
|
||||||
from crewai.utilities.events.base_events import CrewEvent
|
from crewai.utilities.events.base_events import CrewEvent
|
||||||
|
|
||||||
@@ -11,11 +11,47 @@ class LLMCallType(Enum):
|
|||||||
LLM_CALL = "llm_call"
|
LLM_CALL = "llm_call"
|
||||||
|
|
||||||
|
|
||||||
|
class ContentType(str, Enum):
|
||||||
|
"""Types of content in multimodal messages"""
|
||||||
|
|
||||||
|
TEXT = "text"
|
||||||
|
IMAGE_URL = "image_url"
|
||||||
|
|
||||||
|
|
||||||
class LLMCallStartedEvent(CrewEvent):
|
class LLMCallStartedEvent(CrewEvent):
|
||||||
"""Event emitted when a LLM call starts"""
|
"""Event emitted when a LLM call starts"""
|
||||||
|
|
||||||
type: str = "llm_call_started"
|
type: str = "llm_call_started"
|
||||||
messages: Union[str, List[Dict[str, str]]]
|
messages: Union[
|
||||||
|
str,
|
||||||
|
List[Union[
|
||||||
|
str,
|
||||||
|
Dict[str, Union[
|
||||||
|
str,
|
||||||
|
List[Dict[str, Union[
|
||||||
|
str,
|
||||||
|
Dict[Literal["url"], str]
|
||||||
|
]]]
|
||||||
|
]]
|
||||||
|
]]
|
||||||
|
]
|
||||||
|
"""
|
||||||
|
Supports both string messages and structured messages including multimodal content.
|
||||||
|
Formats supported:
|
||||||
|
1. Simple string: "This is a message"
|
||||||
|
2. List of message objects: [{"role": "user", "content": "Hello"}]
|
||||||
|
3. Mixed list with strings and objects: ["Simple message", {"role": "user", "content": "Hello"}]
|
||||||
|
4. Multimodal format:
|
||||||
|
{
|
||||||
|
'role': str,
|
||||||
|
'content': List[
|
||||||
|
Union[
|
||||||
|
Dict[Literal["type", "text"], str],
|
||||||
|
Dict[Literal["type", "image_url"], Dict[str, str]]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
"""
|
||||||
tools: Optional[List[dict]] = None
|
tools: Optional[List[dict]] = None
|
||||||
callbacks: Optional[List[Any]] = None
|
callbacks: Optional[List[Any]] = None
|
||||||
available_functions: Optional[Dict[str, Any]] = None
|
available_functions: Optional[Dict[str, Any]] = None
|
||||||
|
|||||||
88
tests/test_multimodal_validation.py
Normal file
88
tests/test_multimodal_validation.py
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
from typing import Any, Dict, List, Union
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
from pydantic import ValidationError
|
||||||
|
|
||||||
|
from crewai.utilities.events.llm_events import LLMCallStartedEvent
|
||||||
|
|
||||||
|
|
||||||
|
def test_llm_call_started_event_with_multimodal_content():
|
||||||
|
"""Test that LLMCallStartedEvent properly handles multimodal content."""
|
||||||
|
# Create a multimodal message structure
|
||||||
|
multimodal_message = {
|
||||||
|
'role': 'user',
|
||||||
|
'content': [
|
||||||
|
{'type': 'text', 'text': 'Please analyze this image'},
|
||||||
|
{
|
||||||
|
'type': 'image_url',
|
||||||
|
'image_url': {
|
||||||
|
'url': 'https://example.com/test-image.jpg',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
# This should not raise a ValidationError
|
||||||
|
event = LLMCallStartedEvent(messages=[multimodal_message])
|
||||||
|
|
||||||
|
# Verify the event was created correctly
|
||||||
|
assert event.messages[0]['role'] == 'user'
|
||||||
|
assert isinstance(event.messages[0]['content'], list)
|
||||||
|
assert len(event.messages[0]['content']) == 2
|
||||||
|
assert event.messages[0]['content'][0]['type'] == 'text'
|
||||||
|
assert event.messages[0]['content'][1]['type'] == 'image_url'
|
||||||
|
|
||||||
|
|
||||||
|
def test_llm_call_started_event_with_string_message():
|
||||||
|
"""Test that LLMCallStartedEvent still works with string messages."""
|
||||||
|
# Create a simple string message
|
||||||
|
message = "This is a test message"
|
||||||
|
|
||||||
|
# This should not raise a ValidationError
|
||||||
|
event = LLMCallStartedEvent(messages=message)
|
||||||
|
|
||||||
|
# Verify the event was created correctly
|
||||||
|
assert event.messages == message
|
||||||
|
|
||||||
|
|
||||||
|
def test_llm_call_started_event_with_standard_messages():
|
||||||
|
"""Test that LLMCallStartedEvent still works with standard message format."""
|
||||||
|
# Create standard messages
|
||||||
|
messages = [
|
||||||
|
{"role": "system", "content": "You are a helpful assistant"},
|
||||||
|
{"role": "user", "content": "Hello, how are you?"}
|
||||||
|
]
|
||||||
|
|
||||||
|
# This should not raise a ValidationError
|
||||||
|
event = LLMCallStartedEvent(messages=messages)
|
||||||
|
|
||||||
|
# Verify the event was created correctly
|
||||||
|
assert len(event.messages) == 2
|
||||||
|
assert event.messages[0]['role'] == 'system'
|
||||||
|
assert event.messages[0]['content'] == 'You are a helpful assistant'
|
||||||
|
assert event.messages[1]['role'] == 'user'
|
||||||
|
assert event.messages[1]['content'] == 'Hello, how are you?'
|
||||||
|
|
||||||
|
|
||||||
|
def test_llm_call_started_event_with_mixed_content():
|
||||||
|
"""Test that LLMCallStartedEvent handles mixed content types."""
|
||||||
|
mixed_messages = [
|
||||||
|
"Simple string message",
|
||||||
|
{
|
||||||
|
'role': 'user',
|
||||||
|
'content': [
|
||||||
|
{'type': 'text', 'text': 'With image'},
|
||||||
|
{'type': 'image_url', 'image_url': {'url': 'https://example.com/image.jpg'}},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
# This should not raise a ValidationError
|
||||||
|
event = LLMCallStartedEvent(messages=mixed_messages)
|
||||||
|
|
||||||
|
# Verify the event was created correctly
|
||||||
|
assert isinstance(event.messages, list)
|
||||||
|
assert isinstance(event.messages[0], str)
|
||||||
|
assert isinstance(event.messages[1], dict)
|
||||||
|
assert event.messages[1]['role'] == 'user'
|
||||||
|
assert isinstance(event.messages[1]['content'], list)
|
||||||
Reference in New Issue
Block a user