mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-01-08 15:48:29 +00:00
adding initial support for external prompt file
This commit is contained in:
@@ -44,6 +44,7 @@ class Crew(BaseModel):
|
||||
verbose: Indicates the verbosity level for logging during execution.
|
||||
config: Configuration settings for the crew.
|
||||
max_rpm: Maximum number of requests per minute for the crew execution to be respected.
|
||||
prompt_file: Path to the prompt json file to be used for the crew.
|
||||
id: A unique identifier for the crew instance.
|
||||
full_output: Whether the crew should return the full output with all tasks outputs or just the final output.
|
||||
task_callback: Callback to be executed after each task for every agents execution.
|
||||
@@ -111,13 +112,9 @@ class Crew(BaseModel):
|
||||
default=None,
|
||||
description="Maximum number of requests per minute for the crew execution to be respected.",
|
||||
)
|
||||
language: str = Field(
|
||||
default="en",
|
||||
description="Language used for the crew, defaults to English.",
|
||||
)
|
||||
language_file: str = Field(
|
||||
prompt_file: str = Field(
|
||||
default=None,
|
||||
description="Path to the language file to be used for the crew.",
|
||||
description="Path to the prompt json file to be used for the crew.",
|
||||
)
|
||||
output_log_file: Optional[Union[bool, str]] = Field(
|
||||
default=False,
|
||||
@@ -238,7 +235,7 @@ class Crew(BaseModel):
|
||||
self._interpolate_inputs(inputs)
|
||||
self._set_tasks_callbacks()
|
||||
|
||||
i18n = I18N(language=self.language, language_file=self.language_file)
|
||||
i18n = I18N(prompt_file=self.prompt_file)
|
||||
|
||||
for agent in self.agents:
|
||||
agent.i18n = i18n
|
||||
|
||||
@@ -88,7 +88,7 @@ class Telemetry:
|
||||
self._add_attribute(span, "python_version", platform.python_version())
|
||||
self._add_attribute(span, "crew_id", str(crew.id))
|
||||
self._add_attribute(span, "crew_process", crew.process)
|
||||
self._add_attribute(span, "crew_language", crew.language)
|
||||
self._add_attribute(span, "crew_language", crew.prompt_file)
|
||||
self._add_attribute(span, "crew_memory", crew.memory)
|
||||
self._add_attribute(span, "crew_number_of_tasks", len(crew.tasks))
|
||||
self._add_attribute(span, "crew_number_of_agents", len(crew.agents))
|
||||
@@ -103,7 +103,7 @@ class Telemetry:
|
||||
"verbose?": agent.verbose,
|
||||
"max_iter": agent.max_iter,
|
||||
"max_rpm": agent.max_rpm,
|
||||
"i18n": agent.i18n.language,
|
||||
"i18n": agent.i18n.prompt_file,
|
||||
"llm": json.dumps(self._safe_llm_attributes(agent.llm)),
|
||||
"delegation_enabled?": agent.allow_delegation,
|
||||
"tools_names": [
|
||||
@@ -232,7 +232,7 @@ class Telemetry:
|
||||
"verbose?": agent.verbose,
|
||||
"max_iter": agent.max_iter,
|
||||
"max_rpm": agent.max_rpm,
|
||||
"i18n": agent.i18n.language,
|
||||
"i18n": agent.i18n.prompt_file,
|
||||
"llm": json.dumps(self._safe_llm_attributes(agent.llm)),
|
||||
"delegation_enabled?": agent.allow_delegation,
|
||||
"tools_names": [
|
||||
|
||||
@@ -6,40 +6,32 @@ from pydantic import BaseModel, Field, PrivateAttr, ValidationError, model_valid
|
||||
|
||||
|
||||
class I18N(BaseModel):
|
||||
_translations: Dict[str, Dict[str, str]] = PrivateAttr()
|
||||
language_file: Optional[str] = Field(
|
||||
_prompts: Dict[str, Dict[str, str]] = PrivateAttr()
|
||||
prompt_file: Optional[str] = Field(
|
||||
default=None,
|
||||
description="Path to the translation file to load",
|
||||
)
|
||||
language: Optional[str] = Field(
|
||||
default="en",
|
||||
description="Language used to load translations",
|
||||
description="Path to the prompt_file file to load",
|
||||
)
|
||||
|
||||
@model_validator(mode="after")
|
||||
def load_translation(self) -> "I18N":
|
||||
"""Load translations from a JSON file based on the specified language."""
|
||||
def load_prompts(self) -> "I18N":
|
||||
"""Load prompts from a JSON file."""
|
||||
try:
|
||||
if self.language_file:
|
||||
with open(self.language_file, "r") as f:
|
||||
self._translations = json.load(f)
|
||||
if self.prompt_file:
|
||||
with open(self.prompt_file, "r") as f:
|
||||
self._prompts = json.load(f)
|
||||
else:
|
||||
dir_path = os.path.dirname(os.path.realpath(__file__))
|
||||
prompts_path = os.path.join(
|
||||
dir_path, f"../translations/{self.language}.json"
|
||||
)
|
||||
prompts_path = os.path.join(dir_path, f"../translations/en.json")
|
||||
|
||||
with open(prompts_path, "r") as f:
|
||||
self._translations = json.load(f)
|
||||
self._prompts = json.load(f)
|
||||
except FileNotFoundError:
|
||||
raise ValidationError(
|
||||
f"Translation file for language '{self.language}' not found."
|
||||
)
|
||||
raise ValidationError(f"Prompt file '{self.prompt_file}' not found.")
|
||||
except json.JSONDecodeError:
|
||||
raise ValidationError(f"Error decoding JSON from the prompts file.")
|
||||
|
||||
if not self._translations:
|
||||
self._translations = {}
|
||||
if not self._prompts:
|
||||
self._prompts = {}
|
||||
|
||||
return self
|
||||
|
||||
@@ -54,6 +46,6 @@ class I18N(BaseModel):
|
||||
|
||||
def retrieve(self, kind, key) -> str:
|
||||
try:
|
||||
return self._translations[kind][key]
|
||||
return self._prompts[kind][key]
|
||||
except:
|
||||
raise ValidationError(f"Translation for '{kind}':'{key}' not found.")
|
||||
raise ValidationError(f"Prompt for '{kind}':'{key}' not found.")
|
||||
|
||||
@@ -7,7 +7,7 @@ from crewai.utilities import I18N
|
||||
|
||||
|
||||
class Prompts(BaseModel):
|
||||
"""Manages and generates prompts for a generic agent with support for different languages."""
|
||||
"""Manages and generates prompts for a generic agent."""
|
||||
|
||||
i18n: I18N = Field(default=I18N())
|
||||
tools: list[Any] = Field(default=[])
|
||||
|
||||
40
tests/utilities/prompts.json
Normal file
40
tests/utilities/prompts.json
Normal file
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"hierarchical_manager_agent": {
|
||||
"role": "Lorem ipsum dolor sit amet",
|
||||
"goal": "Lorem ipsum dolor sit amet",
|
||||
"backstory": "Lorem ipsum dolor sit amet."
|
||||
},
|
||||
"planning_manager_agent": {
|
||||
"role": "Lorem ipsum dolor sit amet",
|
||||
"goal": "Lorem ipsum dolor sit amet",
|
||||
"backstory": "Lorem ipsum dolor sit amet."
|
||||
},
|
||||
"slices": {
|
||||
"observation": "Lorem ipsum dolor sit amet",
|
||||
"task": "Lorem ipsum dolor sit amet",
|
||||
"memory": "Lorem ipsum dolor sit amet",
|
||||
"role_playing": "Lorem ipsum dolor sit amet",
|
||||
"tools": "Lorem ipsum dolor sit amet",
|
||||
"no_tools": "Lorem ipsum dolor sit amet",
|
||||
"format": "Lorem ipsum dolor sit amet",
|
||||
"final_answer_format": "Lorem ipsum dolor sit amet",
|
||||
"format_without_tools": "Lorem ipsum dolor sit amet",
|
||||
"task_with_context": "Lorem ipsum dolor sit amet",
|
||||
"expected_output": "Lorem ipsum dolor sit amet",
|
||||
"human_feedback": "Lorem ipsum dolor sit amet",
|
||||
"getting_input": "Lorem ipsum dolor sit amet "
|
||||
},
|
||||
"errors": {
|
||||
"force_final_answer": "Lorem ipsum dolor sit amet",
|
||||
"agent_tool_unexsiting_coworker": "Lorem ipsum dolor sit amet",
|
||||
"task_repeated_usage": "Lorem ipsum dolor sit amet",
|
||||
"tool_usage_error": "Lorem ipsum dolor sit amet",
|
||||
"tool_arguments_error": "Lorem ipsum dolor sit amet",
|
||||
"wrong_tool_name": "Lorem ipsum dolor sit amet",
|
||||
"tool_usage_exception": "Lorem ipsum dolor sit amet"
|
||||
},
|
||||
"tools": {
|
||||
"delegate_work": "Lorem ipsum dolor sit amet",
|
||||
"ask_question": "Lorem ipsum dolor sit amet"
|
||||
}
|
||||
}
|
||||
@@ -3,32 +3,39 @@ import pytest
|
||||
from crewai.utilities.i18n import I18N
|
||||
|
||||
|
||||
def test_load_translation():
|
||||
i18n = I18N(language="en")
|
||||
i18n.load_translation()
|
||||
def test_load_prompts():
|
||||
i18n = I18N()
|
||||
i18n.load_prompts()
|
||||
assert i18n._translations is not None
|
||||
|
||||
|
||||
def test_slice():
|
||||
i18n = I18N(language="en")
|
||||
i18n.load_translation()
|
||||
i18n = I18N()
|
||||
i18n.load_prompts()
|
||||
assert isinstance(i18n.slice("role_playing"), str)
|
||||
|
||||
|
||||
def test_tools():
|
||||
i18n = I18N(language="en")
|
||||
i18n.load_translation()
|
||||
i18n = I18N()
|
||||
i18n.load_prompts()
|
||||
assert isinstance(i18n.tools("ask_question"), str)
|
||||
|
||||
|
||||
def test_retrieve():
|
||||
i18n = I18N(language="en")
|
||||
i18n.load_translation()
|
||||
i18n = I18N()
|
||||
i18n.load_prompts()
|
||||
assert isinstance(i18n.retrieve("slices", "role_playing"), str)
|
||||
|
||||
|
||||
def test_retrieve_not_found():
|
||||
i18n = I18N(language="en")
|
||||
i18n.load_translation()
|
||||
i18n = I18N()
|
||||
i18n.load_prompts()
|
||||
with pytest.raises(Exception):
|
||||
i18n.retrieve("nonexistent_kind", "nonexistent_key")
|
||||
|
||||
|
||||
def test_prompt_file():
|
||||
i18n = I18N(prompt_file="tests/utilities/en.json")
|
||||
i18n.load_prompts()
|
||||
assert isinstance(i18n.retrieve("slices", "role_playing"), str)
|
||||
assert i18n.retrieve("slices", "role_playing") == "Lorem ipsum dolor sit amet"
|
||||
|
||||
Reference in New Issue
Block a user