mirror of
https://github.com/crewAIInc/crewAI.git
synced 2025-12-16 04:18:35 +00:00
Some checks failed
Build uv cache / build-cache (3.10) (push) Has been cancelled
Build uv cache / build-cache (3.11) (push) Has been cancelled
Build uv cache / build-cache (3.12) (push) Has been cancelled
Build uv cache / build-cache (3.13) (push) Has been cancelled
CodeQL Advanced / Analyze (actions) (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled
Notify Downstream / notify-downstream (push) Has been cancelled
Mark stale issues and pull requests / stale (push) Has been cancelled
Consolidates pytest config, standardizes env handling, reorganizes cassette layout, removes outdated VCR configs, improves sync with threading.Condition, updates event-waiting logic, ensures cleanup, regenerates Gemini cassettes, and reverts unintended test changes.
291 lines
8.3 KiB
Python
291 lines
8.3 KiB
Python
"""Integration tests for streaming with real LLM interactions using cassettes."""
|
|
|
|
import pytest
|
|
|
|
from crewai import Agent, Crew, Task
|
|
from crewai.flow.flow import Flow, start
|
|
from crewai.types.streaming import CrewStreamingOutput, FlowStreamingOutput
|
|
|
|
|
|
@pytest.fixture
|
|
def researcher() -> Agent:
|
|
"""Create a researcher agent for testing."""
|
|
return Agent(
|
|
role="Research Analyst",
|
|
goal="Gather comprehensive information on topics",
|
|
backstory="You are an experienced researcher with excellent analytical skills.",
|
|
allow_delegation=False,
|
|
)
|
|
|
|
|
|
@pytest.fixture
|
|
def simple_task(researcher: Agent) -> Task:
|
|
"""Create a simple research task."""
|
|
return Task(
|
|
description="Research the latest developments in {topic}",
|
|
expected_output="A brief summary of recent developments",
|
|
agent=researcher,
|
|
)
|
|
|
|
|
|
class TestStreamingCrewIntegration:
|
|
"""Integration tests for crew streaming that match documentation examples."""
|
|
|
|
@pytest.mark.vcr()
|
|
def test_basic_crew_streaming_from_docs(
|
|
self, researcher: Agent, simple_task: Task
|
|
) -> None:
|
|
"""Test basic streaming example from documentation."""
|
|
crew = Crew(
|
|
agents=[researcher],
|
|
tasks=[simple_task],
|
|
stream=True,
|
|
verbose=False,
|
|
)
|
|
|
|
streaming = crew.kickoff(inputs={"topic": "artificial intelligence"})
|
|
|
|
assert isinstance(streaming, CrewStreamingOutput)
|
|
|
|
chunks = []
|
|
for chunk in streaming:
|
|
chunks.append(chunk.content)
|
|
|
|
assert len(chunks) > 0
|
|
|
|
result = streaming.result
|
|
assert result.raw is not None
|
|
assert len(result.raw) > 0
|
|
|
|
@pytest.mark.vcr()
|
|
def test_streaming_with_chunk_context_from_docs(
|
|
self, researcher: Agent, simple_task: Task
|
|
) -> None:
|
|
"""Test streaming with chunk context example from documentation."""
|
|
crew = Crew(
|
|
agents=[researcher],
|
|
tasks=[simple_task],
|
|
stream=True,
|
|
verbose=False,
|
|
)
|
|
|
|
streaming = crew.kickoff(inputs={"topic": "AI"})
|
|
|
|
chunk_contexts = []
|
|
for chunk in streaming:
|
|
chunk_contexts.append(
|
|
{
|
|
"task_name": chunk.task_name,
|
|
"task_index": chunk.task_index,
|
|
"agent_role": chunk.agent_role,
|
|
"content": chunk.content,
|
|
"type": chunk.chunk_type,
|
|
}
|
|
)
|
|
|
|
assert len(chunk_contexts) > 0
|
|
assert all("agent_role" in ctx for ctx in chunk_contexts)
|
|
|
|
result = streaming.result
|
|
assert result is not None
|
|
|
|
@pytest.mark.vcr()
|
|
def test_streaming_properties_from_docs(
|
|
self, researcher: Agent, simple_task: Task
|
|
) -> None:
|
|
"""Test streaming properties example from documentation."""
|
|
crew = Crew(
|
|
agents=[researcher],
|
|
tasks=[simple_task],
|
|
stream=True,
|
|
verbose=False,
|
|
)
|
|
|
|
streaming = crew.kickoff(inputs={"topic": "AI"})
|
|
|
|
for _ in streaming:
|
|
pass
|
|
|
|
assert streaming.is_completed is True
|
|
full_text = streaming.get_full_text()
|
|
assert len(full_text) > 0
|
|
assert len(streaming.chunks) > 0
|
|
|
|
result = streaming.result
|
|
assert result.raw is not None
|
|
|
|
@pytest.mark.vcr()
|
|
@pytest.mark.asyncio
|
|
async def test_async_streaming_from_docs(
|
|
self, researcher: Agent, simple_task: Task
|
|
) -> None:
|
|
"""Test async streaming example from documentation."""
|
|
crew = Crew(
|
|
agents=[researcher],
|
|
tasks=[simple_task],
|
|
stream=True,
|
|
verbose=False,
|
|
)
|
|
|
|
streaming = await crew.kickoff_async(inputs={"topic": "AI"})
|
|
|
|
assert isinstance(streaming, CrewStreamingOutput)
|
|
|
|
chunks = []
|
|
async for chunk in streaming:
|
|
chunks.append(chunk.content)
|
|
|
|
assert len(chunks) > 0
|
|
|
|
result = streaming.result
|
|
assert result.raw is not None
|
|
|
|
@pytest.mark.vcr()
|
|
def test_kickoff_for_each_streaming_from_docs(
|
|
self, researcher: Agent, simple_task: Task
|
|
) -> None:
|
|
"""Test kickoff_for_each streaming example from documentation."""
|
|
crew = Crew(
|
|
agents=[researcher],
|
|
tasks=[simple_task],
|
|
stream=True,
|
|
verbose=False,
|
|
)
|
|
|
|
inputs_list = [{"topic": "AI in healthcare"}, {"topic": "AI in finance"}]
|
|
|
|
streaming_outputs = crew.kickoff_for_each(inputs=inputs_list)
|
|
|
|
assert len(streaming_outputs) == 2
|
|
assert all(isinstance(s, CrewStreamingOutput) for s in streaming_outputs)
|
|
|
|
results = []
|
|
for streaming in streaming_outputs:
|
|
for _ in streaming:
|
|
pass
|
|
|
|
result = streaming.result
|
|
results.append(result)
|
|
|
|
assert len(results) == 2
|
|
assert all(r.raw is not None for r in results)
|
|
|
|
|
|
class TestStreamingFlowIntegration:
|
|
"""Integration tests for flow streaming that match documentation examples."""
|
|
|
|
@pytest.mark.vcr()
|
|
def test_basic_flow_streaming_from_docs(self) -> None:
|
|
"""Test basic flow streaming example from documentation."""
|
|
|
|
class ResearchFlow(Flow):
|
|
stream = True
|
|
|
|
@start()
|
|
def research_topic(self) -> str:
|
|
researcher = Agent(
|
|
role="Research Analyst",
|
|
goal="Research topics thoroughly",
|
|
backstory="Expert researcher with analytical skills",
|
|
allow_delegation=False,
|
|
)
|
|
|
|
task = Task(
|
|
description="Research AI trends and provide insights",
|
|
expected_output="Detailed research findings",
|
|
agent=researcher,
|
|
)
|
|
|
|
crew = Crew(
|
|
agents=[researcher],
|
|
tasks=[task],
|
|
stream=True,
|
|
verbose=False,
|
|
)
|
|
|
|
streaming = crew.kickoff()
|
|
for _ in streaming:
|
|
pass
|
|
return streaming.result.raw
|
|
|
|
flow = ResearchFlow()
|
|
|
|
streaming = flow.kickoff()
|
|
|
|
assert isinstance(streaming, FlowStreamingOutput)
|
|
|
|
chunks = []
|
|
for chunk in streaming:
|
|
chunks.append(chunk.content)
|
|
|
|
assert len(chunks) > 0
|
|
|
|
result = streaming.result
|
|
assert result is not None
|
|
|
|
@pytest.mark.vcr()
|
|
def test_flow_streaming_properties_from_docs(self) -> None:
|
|
"""Test flow streaming properties example from documentation."""
|
|
|
|
class SimpleFlow(Flow):
|
|
stream = True
|
|
|
|
@start()
|
|
def execute(self) -> str:
|
|
return "Flow result"
|
|
|
|
flow = SimpleFlow()
|
|
streaming = flow.kickoff()
|
|
|
|
for _ in streaming:
|
|
pass
|
|
|
|
assert streaming.is_completed is True
|
|
streaming.get_full_text()
|
|
assert len(streaming.chunks) >= 0
|
|
|
|
result = streaming.result
|
|
assert result is not None
|
|
|
|
@pytest.mark.vcr()
|
|
@pytest.mark.asyncio
|
|
async def test_async_flow_streaming_from_docs(self) -> None:
|
|
"""Test async flow streaming example from documentation."""
|
|
|
|
class AsyncResearchFlow(Flow):
|
|
stream = True
|
|
|
|
@start()
|
|
def research(self) -> str:
|
|
researcher = Agent(
|
|
role="Researcher",
|
|
goal="Research topics",
|
|
backstory="Expert researcher",
|
|
allow_delegation=False,
|
|
)
|
|
|
|
task = Task(
|
|
description="Research AI",
|
|
expected_output="Research findings",
|
|
agent=researcher,
|
|
)
|
|
|
|
crew = Crew(agents=[researcher], tasks=[task], stream=True, verbose=False)
|
|
streaming = crew.kickoff()
|
|
for _ in streaming:
|
|
pass
|
|
return streaming.result.raw
|
|
|
|
flow = AsyncResearchFlow()
|
|
|
|
streaming = await flow.kickoff_async()
|
|
|
|
assert isinstance(streaming, FlowStreamingOutput)
|
|
|
|
chunks = []
|
|
async for chunk in streaming:
|
|
chunks.append(chunk.content)
|
|
|
|
result = streaming.result
|
|
assert result is not None
|