mirror of
https://github.com/crewAIInc/crewAI.git
synced 2025-12-16 04:18:35 +00:00
This fixes issue #3934 where 'crewai chat' fails when the crew has module-level LLM instantiation that requires OPENAI_API_KEY. The issue occurred because 'crewai chat' imports the crew module directly using __import__(), and any module-level code executes immediately during import. At this point, the .env file hadn't been loaded yet, so OPENAI_API_KEY was not available in the environment. Changes: - Load .env file in load_crew_and_name() before importing the crew module - Use os.environ.setdefault() to avoid overriding existing env vars - Add comprehensive tests covering: - Loading crew with .env containing OPENAI_API_KEY - Environment variable precedence (existing vars not overridden) - Loading crew without .env file Fixes #3934 Co-Authored-By: João <joao@crewai.com>
213 lines
5.5 KiB
Python
213 lines
5.5 KiB
Python
"""Tests for crew_chat.py environment variable loading."""
|
|
|
|
import os
|
|
from unittest.mock import Mock, patch
|
|
|
|
import pytest
|
|
|
|
from crewai.cli.crew_chat import load_crew_and_name
|
|
|
|
|
|
@pytest.fixture
|
|
def temp_crew_project(tmp_path):
|
|
"""Create a temporary crew project with .env file."""
|
|
project_dir = tmp_path / "test_crew"
|
|
project_dir.mkdir()
|
|
|
|
src_dir = project_dir / "src" / "test_crew"
|
|
src_dir.mkdir(parents=True)
|
|
|
|
env_file = project_dir / ".env"
|
|
env_file.write_text("OPENAI_API_KEY=test-api-key-from-env\nMODEL=gpt-4\n")
|
|
|
|
pyproject = project_dir / "pyproject.toml"
|
|
pyproject.write_text("""[project]
|
|
name = "test_crew"
|
|
version = "0.1.0"
|
|
description = "Test crew"
|
|
requires-python = ">=3.10"
|
|
dependencies = ["crewai"]
|
|
|
|
[tool.crewai]
|
|
type = "crew"
|
|
""")
|
|
|
|
(src_dir / "__init__.py").write_text("")
|
|
|
|
crew_py = src_dir / "crew.py"
|
|
crew_py.write_text("""from crewai import Agent, Crew, Process, Task, LLM
|
|
from crewai.project import CrewBase, agent, crew, task
|
|
|
|
default_llm = LLM(model="openai/gpt-4")
|
|
|
|
@CrewBase
|
|
class TestCrew:
|
|
'''Test crew'''
|
|
|
|
@agent
|
|
def researcher(self) -> Agent:
|
|
return Agent(
|
|
role="Researcher",
|
|
goal="Research topics",
|
|
backstory="You are a researcher",
|
|
llm=default_llm,
|
|
)
|
|
|
|
@task
|
|
def research_task(self) -> Task:
|
|
return Task(
|
|
description="Research {topic}",
|
|
expected_output="A report",
|
|
agent=self.researcher(),
|
|
)
|
|
|
|
@crew
|
|
def crew(self) -> Crew:
|
|
return Crew(
|
|
agents=[self.researcher()],
|
|
tasks=[self.research_task()],
|
|
process=Process.sequential,
|
|
verbose=True,
|
|
)
|
|
""")
|
|
|
|
config_dir = src_dir / "config"
|
|
config_dir.mkdir()
|
|
|
|
agents_yaml = config_dir / "agents.yaml"
|
|
agents_yaml.write_text("""researcher:
|
|
role: Researcher
|
|
goal: Research topics
|
|
backstory: You are a researcher
|
|
""")
|
|
|
|
tasks_yaml = config_dir / "tasks.yaml"
|
|
tasks_yaml.write_text("""research_task:
|
|
description: Research {topic}
|
|
expected_output: A report
|
|
agent: researcher
|
|
""")
|
|
|
|
return project_dir
|
|
|
|
|
|
def test_load_crew_with_env_file(temp_crew_project, monkeypatch):
|
|
"""Test that load_crew_and_name loads .env before importing crew module."""
|
|
monkeypatch.chdir(temp_crew_project)
|
|
|
|
monkeypatch.delenv("OPENAI_API_KEY", raising=False)
|
|
|
|
with patch("crewai.llm.LLM") as mock_llm:
|
|
mock_llm.return_value = Mock()
|
|
|
|
crew_instance, crew_name = load_crew_and_name()
|
|
|
|
assert crew_instance is not None
|
|
assert crew_name == "TestCrew"
|
|
|
|
assert os.environ.get("OPENAI_API_KEY") == "test-api-key-from-env"
|
|
assert os.environ.get("MODEL") == "gpt-4"
|
|
|
|
|
|
def test_env_var_precedence(temp_crew_project, monkeypatch):
|
|
"""Test that existing environment variables are not overridden by .env."""
|
|
monkeypatch.chdir(temp_crew_project)
|
|
|
|
existing_key = "existing-api-key-from-shell"
|
|
monkeypatch.setenv("OPENAI_API_KEY", existing_key)
|
|
|
|
with patch("crewai.llm.LLM") as mock_llm:
|
|
mock_llm.return_value = Mock()
|
|
|
|
crew_instance, crew_name = load_crew_and_name()
|
|
|
|
assert crew_instance is not None
|
|
assert crew_name == "TestCrew"
|
|
|
|
assert os.environ.get("OPENAI_API_KEY") == existing_key
|
|
|
|
assert os.environ.get("MODEL") == "gpt-4"
|
|
|
|
|
|
def test_load_crew_without_env_file(tmp_path, monkeypatch):
|
|
"""Test that load_crew_and_name works even without .env file."""
|
|
project_dir = tmp_path / "test_crew_no_env"
|
|
project_dir.mkdir()
|
|
|
|
src_dir = project_dir / "src" / "test_crew_no_env"
|
|
src_dir.mkdir(parents=True)
|
|
|
|
pyproject = project_dir / "pyproject.toml"
|
|
pyproject.write_text("""[project]
|
|
name = "test_crew_no_env"
|
|
version = "0.1.0"
|
|
description = "Test crew without env"
|
|
requires-python = ">=3.10"
|
|
dependencies = ["crewai"]
|
|
|
|
[tool.crewai]
|
|
type = "crew"
|
|
""")
|
|
|
|
(src_dir / "__init__.py").write_text("")
|
|
|
|
crew_py = src_dir / "crew.py"
|
|
crew_py.write_text("""from crewai import Agent, Crew, Process, Task
|
|
from crewai.project import CrewBase, agent, crew, task
|
|
|
|
@CrewBase
|
|
class TestCrewNoEnv:
|
|
'''Test crew without env'''
|
|
|
|
@agent
|
|
def researcher(self) -> Agent:
|
|
return Agent(
|
|
role="Researcher",
|
|
goal="Research topics",
|
|
backstory="You are a researcher",
|
|
)
|
|
|
|
@task
|
|
def research_task(self) -> Task:
|
|
return Task(
|
|
description="Research {topic}",
|
|
expected_output="A report",
|
|
agent=self.researcher(),
|
|
)
|
|
|
|
@crew
|
|
def crew(self) -> Crew:
|
|
return Crew(
|
|
agents=[self.researcher()],
|
|
tasks=[self.research_task()],
|
|
process=Process.sequential,
|
|
verbose=True,
|
|
)
|
|
""")
|
|
|
|
config_dir = src_dir / "config"
|
|
config_dir.mkdir()
|
|
|
|
agents_yaml = config_dir / "agents.yaml"
|
|
agents_yaml.write_text("""researcher:
|
|
role: Researcher
|
|
goal: Research topics
|
|
backstory: You are a researcher
|
|
""")
|
|
|
|
tasks_yaml = config_dir / "tasks.yaml"
|
|
tasks_yaml.write_text("""research_task:
|
|
description: Research {topic}
|
|
expected_output: A report
|
|
agent: researcher
|
|
""")
|
|
|
|
monkeypatch.chdir(project_dir)
|
|
|
|
monkeypatch.setenv("OPENAI_API_KEY", "test-key")
|
|
|
|
crew_instance, crew_name = load_crew_and_name()
|
|
|
|
assert crew_instance is not None
|
|
assert crew_name == "TestCrewNoEnv"
|