mirror of
https://github.com/crewAIInc/crewAI.git
synced 2025-12-15 20:08:29 +00:00
feat: Add multi-language support for CrewAI prompts
- Add language parameter to I18N class to support multiple languages - Implement fallback to English for unsupported languages - Add Spanish (es.json) translation file as example - Update Agent and Crew classes to accept language parameter - Add comprehensive tests for multi-language support Fixes #3780 Co-Authored-By: João <joao@crewai.com>
This commit is contained in:
@@ -148,6 +148,10 @@ class BaseAgent(BaseModel, ABC):
|
||||
default=None, description="Language model that will run the agent."
|
||||
)
|
||||
crew: Any = Field(default=None, description="Crew to which the agent belongs.")
|
||||
language: str | None = Field(
|
||||
default=None,
|
||||
description="Language code for the agent's prompts (e.g., 'en', 'es', 'pt'). If not set, defaults to 'en'.",
|
||||
)
|
||||
i18n: I18N = Field(
|
||||
default_factory=I18N, description="Internationalization settings."
|
||||
)
|
||||
@@ -289,6 +293,10 @@ class BaseAgent(BaseModel, ABC):
|
||||
if self.security_config is None:
|
||||
self.security_config = SecurityConfig()
|
||||
|
||||
# Initialize i18n with language if provided
|
||||
if self.language:
|
||||
self.i18n = I18N(language=self.language)
|
||||
|
||||
return self
|
||||
|
||||
@field_validator("id", mode="before")
|
||||
|
||||
@@ -233,6 +233,10 @@ class Crew(FlowTrackable, BaseModel):
|
||||
default=None,
|
||||
description="Path to the prompt json file to be used for the crew.",
|
||||
)
|
||||
language: str | None = Field(
|
||||
default=None,
|
||||
description="Language code for the crew's prompts (e.g., 'en', 'es', 'pt'). If not set, defaults to 'en'.",
|
||||
)
|
||||
output_log_file: bool | str | None = Field(
|
||||
default=None,
|
||||
description="Path to the log file to be saved",
|
||||
@@ -684,7 +688,10 @@ class Crew(FlowTrackable, BaseModel):
|
||||
self._set_tasks_callbacks()
|
||||
self._set_allow_crewai_trigger_context_for_first_task()
|
||||
|
||||
i18n = I18N(prompt_file=self.prompt_file)
|
||||
i18n = I18N(
|
||||
prompt_file=self.prompt_file,
|
||||
language=self.language if self.language else "en",
|
||||
)
|
||||
|
||||
for agent in self.agents:
|
||||
agent.i18n = i18n
|
||||
@@ -826,7 +833,10 @@ class Crew(FlowTrackable, BaseModel):
|
||||
return self._execute_tasks(self.tasks)
|
||||
|
||||
def _create_manager_agent(self):
|
||||
i18n = I18N(prompt_file=self.prompt_file)
|
||||
i18n = I18N(
|
||||
prompt_file=self.prompt_file,
|
||||
language=self.language if self.language else "en",
|
||||
)
|
||||
if self.manager_agent is not None:
|
||||
self.manager_agent.allow_delegation = True
|
||||
manager = self.manager_agent
|
||||
|
||||
61
lib/crewai/src/crewai/translations/es.json
Normal file
61
lib/crewai/src/crewai/translations/es.json
Normal file
@@ -0,0 +1,61 @@
|
||||
{
|
||||
"hierarchical_manager_agent": {
|
||||
"role": "Gerente del Equipo",
|
||||
"goal": "Gestionar el equipo para completar la tarea de la mejor manera posible.",
|
||||
"backstory": "Eres un gerente experimentado con talento para sacar lo mejor de tu equipo.\nTambién eres conocido por tu habilidad para delegar trabajo a las personas adecuadas y hacer las preguntas correctas para obtener lo mejor de tu equipo.\nAunque no realizas tareas por ti mismo, tienes mucha experiencia en el campo, lo que te permite evaluar adecuadamente el trabajo de los miembros de tu equipo."
|
||||
},
|
||||
"slices": {
|
||||
"observation": "\nObservación:",
|
||||
"task": "\nTarea Actual: {input}\n\n¡Comienza! Esto es MUY importante para ti, usa las herramientas disponibles y da tu mejor Respuesta Final, ¡tu trabajo depende de ello!\n\nPensamiento:",
|
||||
"memory": "\n\n# Contexto útil: \n{memory}",
|
||||
"role_playing": "Eres {role}. {backstory}\nTu objetivo personal es: {goal}",
|
||||
"tools": "\nSOLO tienes acceso a las siguientes herramientas, y NUNCA debes inventar herramientas que no estén listadas aquí:\n\n{tools}\n\nIMPORTANTE: Usa el siguiente formato en tu respuesta:\n\n```\nPensamiento: siempre debes pensar en qué hacer\nAcción: la acción a tomar, solo un nombre de [{tool_names}], solo el nombre, exactamente como está escrito.\nEntrada de Acción: la entrada para la acción, solo un objeto JSON simple, encerrado entre llaves, usando \" para envolver claves y valores.\nObservación: el resultado de la acción\n```\n\nUna vez que se recopile toda la información necesaria, devuelve el siguiente formato:\n\n```\nPensamiento: Ahora conozco la respuesta final\nRespuesta Final: la respuesta final a la pregunta de entrada original\n```",
|
||||
"no_tools": "\nPara dar mi mejor respuesta final completa a la tarea, responde usando exactamente el siguiente formato:\n\nPensamiento: Ahora puedo dar una gran respuesta\nRespuesta Final: Tu respuesta final debe ser lo más completa posible, debe describir el resultado.\n\n¡DEBO usar estos formatos, mi trabajo depende de ello!",
|
||||
"format": "DEBO usar una herramienta (usar una a la vez) O dar mi mejor respuesta final, no ambas al mismo tiempo. Al responder, debo usar el siguiente formato:\n\n```\nPensamiento: siempre debes pensar en qué hacer\nAcción: la acción a tomar, debe ser una de [{tool_names}]\nEntrada de Acción: la entrada para la acción, diccionario encerrado entre llaves\nObservación: el resultado de la acción\n```\nEste proceso de Pensamiento/Acción/Entrada de Acción/Resultado puede repetirse N veces. Una vez que conozca la respuesta final, debo devolver el siguiente formato:\n\n```\nPensamiento: Ahora puedo dar una gran respuesta\nRespuesta Final: Tu respuesta final debe ser lo más completa posible, debe describir el resultado\n\n```",
|
||||
"final_answer_format": "Si no necesitas usar más herramientas, debes dar tu mejor respuesta final completa, asegúrate de que satisfaga los criterios esperados, usa el formato EXACTO a continuación:\n\n```\nPensamiento: Ahora puedo dar una gran respuesta\nRespuesta Final: mi mejor respuesta final completa a la tarea.\n\n```",
|
||||
"format_without_tools": "\nLo siento, no usé el formato correcto. DEBO usar una herramienta (entre las disponibles), O dar mi mejor respuesta final.\nAquí está el formato esperado que debo seguir:\n\n```\nPregunta: la pregunta de entrada que debes responder\nPensamiento: siempre debes pensar en qué hacer\nAcción: la acción a tomar, debe ser una de [{tool_names}]\nEntrada de Acción: la entrada para la acción\nObservación: el resultado de la acción\n```\n Este proceso de Pensamiento/Acción/Entrada de Acción/Resultado puede repetirse N veces. Una vez que conozca la respuesta final, debo devolver el siguiente formato:\n\n```\nPensamiento: Ahora puedo dar una gran respuesta\nRespuesta Final: Tu respuesta final debe ser lo más completa posible, debe describir el resultado\n\n```",
|
||||
"task_with_context": "{task}\n\nEste es el contexto con el que estás trabajando:\n{context}",
|
||||
"expected_output": "\nEste es el criterio esperado para tu respuesta final: {expected_output}\nDEBES devolver el contenido completo real como respuesta final, no un resumen.",
|
||||
"human_feedback": "Recibiste retroalimentación humana sobre tu trabajo, reevalúalo y da una nueva Respuesta Final cuando estés listo.\n {human_feedback}",
|
||||
"getting_input": "Esta es la respuesta final del agente: {final_answer}\n\n",
|
||||
"summarizer_system_message": "Eres un asistente útil que resume texto.",
|
||||
"summarize_instruction": "Resume el siguiente texto, asegúrate de incluir toda la información importante: {group}",
|
||||
"summary": "Este es un resumen de nuestra conversación hasta ahora:\n{merged_summary}",
|
||||
"manager_request": "Tu mejor respuesta a tu compañero de trabajo que te pregunta esto, teniendo en cuenta el contexto compartido.",
|
||||
"formatted_task_instructions": "Asegúrate de que tu respuesta final contenga solo el contenido en el siguiente formato: {output_format}\n\nAsegúrate de que la salida final no incluya marcadores de bloque de código como ```json o ```python.",
|
||||
"conversation_history_instruction": "Eres miembro de un equipo que colabora para lograr un objetivo común. Tu tarea es una acción específica que contribuye a este objetivo más amplio. Para contexto adicional, revisa el historial de conversación entre tú y el usuario que llevó a la iniciación de este equipo. Usa cualquier información o retroalimentación relevante de la conversación para informar la ejecución de tu tarea y asegúrate de que tu respuesta se alinee tanto con la tarea inmediata como con los objetivos generales del equipo.",
|
||||
"feedback_instructions": "Retroalimentación del usuario: {feedback}\nInstrucciones: Usa esta retroalimentación para mejorar la próxima iteración de salida.\nNota: No respondas ni agregues comentarios.",
|
||||
"lite_agent_system_prompt_with_tools": "Eres {role}. {backstory}\nTu objetivo personal es: {goal}\n\nSOLO tienes acceso a las siguientes herramientas, y NUNCA debes inventar herramientas que no estén listadas aquí:\n\n{tools}\n\nIMPORTANTE: Usa el siguiente formato en tu respuesta:\n\n```\nPensamiento: siempre debes pensar en qué hacer\nAcción: la acción a tomar, solo un nombre de [{tool_names}], solo el nombre, exactamente como está escrito.\nEntrada de Acción: la entrada para la acción, solo un objeto JSON simple, encerrado entre llaves, usando \" para envolver claves y valores.\nObservación: el resultado de la acción\n```\n\nUna vez que se recopile toda la información necesaria, devuelve el siguiente formato:\n\n```\nPensamiento: Ahora conozco la respuesta final\nRespuesta Final: la respuesta final a la pregunta de entrada original\n```",
|
||||
"lite_agent_system_prompt_without_tools": "Eres {role}. {backstory}\nTu objetivo personal es: {goal}\n\nPara dar mi mejor respuesta final completa a la tarea, responde usando exactamente el siguiente formato:\n\nPensamiento: Ahora puedo dar una gran respuesta\nRespuesta Final: Tu respuesta final debe ser lo más completa posible, debe describir el resultado.\n\n¡DEBO usar estos formatos, mi trabajo depende de ello!",
|
||||
"lite_agent_response_format": "\nIMPORTANTE: Tu respuesta final DEBE contener toda la información solicitada en el siguiente formato: {response_format}\n\nIMPORTANTE: Asegúrate de que la salida final no incluya marcadores de bloque de código como ```json o ```python.",
|
||||
"knowledge_search_query": "La consulta original es: {task_prompt}.",
|
||||
"knowledge_search_query_system_prompt": "Tu objetivo es reescribir la consulta del usuario para que esté optimizada para la recuperación de una base de datos vectorial. Considera cómo se utilizará la consulta para encontrar documentos relevantes y trata de hacerla más específica y consciente del contexto. \n\n No incluyas ningún otro texto que no sea la consulta reescrita, especialmente ningún preámbulo o postámbulo y solo agrega el formato de salida esperado si es relevante para la consulta reescrita. \n\n Concéntrate en las palabras clave de la tarea prevista y en recuperar la información más relevante. \n\n Habrá algún contexto adicional proporcionado que podría necesitar ser eliminado, como formatos de salida esperados, salidas estructuradas y otras instrucciones."
|
||||
},
|
||||
"errors": {
|
||||
"force_final_answer_error": "No puedes continuar, aquí está la mejor respuesta final que generaste:\n\n {formatted_answer}",
|
||||
"force_final_answer": "Ahora es el momento de que DEBES dar tu mejor respuesta final absoluta. Ignorarás todas las instrucciones anteriores, dejarás de usar cualquier herramienta y simplemente devolverás tu MEJOR respuesta final absoluta.",
|
||||
"agent_tool_unexisting_coworker": "\nError al ejecutar la herramienta. El compañero de trabajo mencionado no se encontró, debe ser una de las siguientes opciones:\n{coworkers}\n",
|
||||
"task_repeated_usage": "Intenté reutilizar la misma entrada, debo dejar de usar esta entrada de acción. Intentaré algo más en su lugar.\n\n",
|
||||
"tool_usage_error": "Encontré un error: {error}",
|
||||
"tool_arguments_error": "Error: la Entrada de Acción no es un diccionario válido de clave, valor.",
|
||||
"wrong_tool_name": "Intentaste usar la herramienta {tool}, pero no existe. Debes usar una de las siguientes herramientas, usa una a la vez: {tools}.",
|
||||
"tool_usage_exception": "Encontré un error al intentar usar la herramienta. Este fue el error: {error}.\n La herramienta {tool} acepta estas entradas: {tool_inputs}",
|
||||
"agent_tool_execution_error": "Error al ejecutar la tarea con el agente '{agent_role}'. Error: {error}",
|
||||
"validation_error": "### El intento anterior falló la validación: {guardrail_result_error}\n\n\n### Resultado anterior:\n{task_output}\n\n\nIntenta de nuevo, asegurándote de abordar el error de validación."
|
||||
},
|
||||
"tools": {
|
||||
"delegate_work": "Delega una tarea específica a uno de los siguientes compañeros de trabajo: {coworkers}\nLa entrada para esta herramienta debe ser el compañero de trabajo, la tarea que quieres que hagan y TODO el contexto necesario para ejecutar la tarea, ellos no saben nada sobre la tarea, así que comparte absolutamente todo lo que sabes, no hagas referencia a cosas sino explícalas.",
|
||||
"ask_question": "Haz una pregunta específica a uno de los siguientes compañeros de trabajo: {coworkers}\nLa entrada para esta herramienta debe ser el compañero de trabajo, la pregunta que tienes para ellos y TODO el contexto necesario para hacer la pregunta correctamente, ellos no saben nada sobre la pregunta, así que comparte absolutamente todo lo que sabes, no hagas referencia a cosas sino explícalas.",
|
||||
"add_image": {
|
||||
"name": "Agregar imagen al contenido",
|
||||
"description": "Ver imagen para entender su contenido, opcionalmente puedes hacer una pregunta sobre la imagen",
|
||||
"default_action": "Por favor proporciona una descripción detallada de esta imagen, incluyendo todos los elementos visuales, contexto y cualquier detalle notable que puedas observar."
|
||||
}
|
||||
},
|
||||
"reasoning": {
|
||||
"initial_plan": "Eres {role}, un profesional con el siguiente trasfondo: {backstory}\n\nTu objetivo principal es: {goal}\n\nComo {role}, estás creando un plan estratégico para una tarea que requiere tu experiencia y perspectiva única.",
|
||||
"refine_plan": "Eres {role}, un profesional con el siguiente trasfondo: {backstory}\n\nTu objetivo principal es: {goal}\n\nComo {role}, estás refinando un plan estratégico para una tarea que requiere tu experiencia y perspectiva única.",
|
||||
"create_plan_prompt": "Eres {role} con este trasfondo: {backstory}\n\nTu objetivo principal es: {goal}\n\nSe te ha asignado la siguiente tarea:\n{description}\n\nSalida esperada:\n{expected_output}\n\nHerramientas disponibles: {tools}\n\nAntes de ejecutar esta tarea, crea un plan detallado que aproveche tu experiencia como {role} y describa:\n1. Tu comprensión de la tarea desde tu perspectiva profesional\n2. Los pasos clave que tomarás para completarla, basándote en tu trasfondo y habilidades\n3. Cómo abordarás cualquier desafío que pueda surgir, considerando tu experiencia\n4. Cómo usarás estratégicamente las herramientas disponibles según tu experiencia, exactamente qué herramientas usar y cómo usarlas\n5. El resultado esperado y cómo se alinea con tu objetivo\n\nDespués de crear tu plan, evalúa si te sientes listo para ejecutar la tarea o si podrías hacerlo mejor.\nConcluye con una de estas declaraciones:\n- \"LISTO: Estoy listo para ejecutar la tarea.\"\n- \"NO LISTO: Necesito refinar mi plan porque [razón específica].\"",
|
||||
"refine_plan_prompt": "Eres {role} con este trasfondo: {backstory}\n\nTu objetivo principal es: {goal}\n\nCreaste el siguiente plan para esta tarea:\n{current_plan}\n\nSin embargo, indicaste que aún no estás listo para ejecutar la tarea.\n\nPor favor, refina tu plan aún más, basándote en tu experiencia como {role} para abordar cualquier brecha o incertidumbre. A medida que refines tu plan, sé específico sobre qué herramientas disponibles usarás, cómo las usarás y por qué son las mejores opciones para cada paso. Describe claramente tu estrategia de uso de herramientas como parte de tu plan mejorado.\n\nDespués de refinar tu plan, evalúa si te sientes listo para ejecutar la tarea.\nConcluye con una de estas declaraciones:\n- \"LISTO: Estoy listo para ejecutar la tarea.\"\n- \"NO LISTO: Necesito refinar mi plan aún más porque [razón específica].\""
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,7 @@ class I18N(BaseModel):
|
||||
Attributes:
|
||||
_prompts: Internal dictionary storing loaded prompts.
|
||||
prompt_file: Optional path to a custom JSON file containing prompts.
|
||||
language: Language code for the prompts (e.g., 'en', 'es', 'pt'). Defaults to 'en'.
|
||||
"""
|
||||
|
||||
_prompts: dict[str, dict[str, str]] = PrivateAttr()
|
||||
@@ -21,6 +22,10 @@ class I18N(BaseModel):
|
||||
default=None,
|
||||
description="Path to the prompt_file file to load",
|
||||
)
|
||||
language: str = Field(
|
||||
default="en",
|
||||
description="Language code for the prompts (e.g., 'en', 'es', 'pt')",
|
||||
)
|
||||
|
||||
@model_validator(mode="after")
|
||||
def load_prompts(self) -> Self:
|
||||
@@ -38,12 +43,24 @@ class I18N(BaseModel):
|
||||
self._prompts = json.load(f)
|
||||
else:
|
||||
dir_path = os.path.dirname(os.path.realpath(__file__))
|
||||
prompts_path = os.path.join(dir_path, "../translations/en.json")
|
||||
prompts_path = os.path.join(
|
||||
dir_path, f"../translations/{self.language}.json"
|
||||
)
|
||||
|
||||
with open(prompts_path, encoding="utf-8") as f:
|
||||
self._prompts = json.load(f)
|
||||
try:
|
||||
with open(prompts_path, encoding="utf-8") as f:
|
||||
self._prompts = json.load(f)
|
||||
except FileNotFoundError:
|
||||
if self.language != "en":
|
||||
fallback_path = os.path.join(dir_path, "../translations/en.json")
|
||||
with open(fallback_path, encoding="utf-8") as f:
|
||||
self._prompts = json.load(f)
|
||||
else:
|
||||
raise
|
||||
except FileNotFoundError as e:
|
||||
raise Exception(f"Prompt file '{self.prompt_file}' not found.") from e
|
||||
raise Exception(
|
||||
f"Prompt file '{self.prompt_file or self.language + '.json'}' not found."
|
||||
) from e
|
||||
except json.JSONDecodeError as e:
|
||||
raise Exception("Error decoding JSON from the prompts file.") from e
|
||||
|
||||
|
||||
116
lib/crewai/tests/test_agent_language.py
Normal file
116
lib/crewai/tests/test_agent_language.py
Normal file
@@ -0,0 +1,116 @@
|
||||
import pytest
|
||||
from crewai.agent import Agent
|
||||
from crewai.crew import Crew
|
||||
from crewai.task import Task
|
||||
|
||||
|
||||
def test_agent_default_language():
|
||||
agent = Agent(
|
||||
role="Test Agent",
|
||||
goal="Test goal",
|
||||
backstory="Test backstory"
|
||||
)
|
||||
assert agent.i18n.language == "en"
|
||||
|
||||
|
||||
def test_agent_with_spanish_language():
|
||||
agent = Agent(
|
||||
role="Agente de Prueba",
|
||||
goal="Objetivo de prueba",
|
||||
backstory="Historia de fondo de prueba",
|
||||
language="es"
|
||||
)
|
||||
assert agent.i18n.language == "es"
|
||||
assert "Eres {role}" in agent.i18n.slice("role_playing")
|
||||
|
||||
|
||||
def test_agent_with_english_language_explicit():
|
||||
agent = Agent(
|
||||
role="Test Agent",
|
||||
goal="Test goal",
|
||||
backstory="Test backstory",
|
||||
language="en"
|
||||
)
|
||||
assert agent.i18n.language == "en"
|
||||
assert "You are {role}" in agent.i18n.slice("role_playing")
|
||||
|
||||
|
||||
def test_crew_default_language():
|
||||
agent = Agent(
|
||||
role="Test Agent",
|
||||
goal="Test goal",
|
||||
backstory="Test backstory"
|
||||
)
|
||||
task = Task(
|
||||
description="Test task",
|
||||
expected_output="Test output",
|
||||
agent=agent
|
||||
)
|
||||
crew = Crew(agents=[agent], tasks=[task])
|
||||
assert crew.language is None
|
||||
|
||||
|
||||
def test_crew_with_spanish_language():
|
||||
agent = Agent(
|
||||
role="Agente de Prueba",
|
||||
goal="Objetivo de prueba",
|
||||
backstory="Historia de fondo de prueba"
|
||||
)
|
||||
task = Task(
|
||||
description="Tarea de prueba",
|
||||
expected_output="Salida de prueba",
|
||||
agent=agent
|
||||
)
|
||||
crew = Crew(agents=[agent], tasks=[task], language="es")
|
||||
assert crew.language == "es"
|
||||
|
||||
|
||||
def test_crew_language_propagates_to_agents():
|
||||
agent1 = Agent(
|
||||
role="Agent 1",
|
||||
goal="Goal 1",
|
||||
backstory="Backstory 1"
|
||||
)
|
||||
agent2 = Agent(
|
||||
role="Agent 2",
|
||||
goal="Goal 2",
|
||||
backstory="Backstory 2"
|
||||
)
|
||||
task = Task(
|
||||
description="Test task",
|
||||
expected_output="Test output",
|
||||
agent=agent1
|
||||
)
|
||||
crew = Crew(agents=[agent1, agent2], tasks=[task], language="es")
|
||||
|
||||
assert crew.language == "es"
|
||||
|
||||
|
||||
def test_agent_language_overrides_default():
|
||||
agent_en = Agent(
|
||||
role="English Agent",
|
||||
goal="English goal",
|
||||
backstory="English backstory",
|
||||
language="en"
|
||||
)
|
||||
agent_es = Agent(
|
||||
role="Spanish Agent",
|
||||
goal="Spanish goal",
|
||||
backstory="Spanish backstory",
|
||||
language="es"
|
||||
)
|
||||
|
||||
assert agent_en.i18n.language == "en"
|
||||
assert agent_es.i18n.language == "es"
|
||||
assert "You are {role}" in agent_en.i18n.slice("role_playing")
|
||||
assert "Eres {role}" in agent_es.i18n.slice("role_playing")
|
||||
|
||||
|
||||
def test_agent_without_language_uses_default():
|
||||
agent = Agent(
|
||||
role="Test Agent",
|
||||
goal="Test goal",
|
||||
backstory="Test backstory"
|
||||
)
|
||||
assert agent.language is None
|
||||
assert agent.i18n.language == "en"
|
||||
98
lib/crewai/tests/utilities/test_i18n_multilanguage.py
Normal file
98
lib/crewai/tests/utilities/test_i18n_multilanguage.py
Normal file
@@ -0,0 +1,98 @@
|
||||
import pytest
|
||||
from crewai.utilities.i18n import I18N
|
||||
|
||||
|
||||
def test_default_language_is_english():
|
||||
i18n = I18N()
|
||||
assert i18n.language == "en"
|
||||
assert isinstance(i18n.slice("role_playing"), str)
|
||||
assert "You are {role}" in i18n.slice("role_playing")
|
||||
|
||||
|
||||
def test_explicit_english_language():
|
||||
i18n = I18N(language="en")
|
||||
assert i18n.language == "en"
|
||||
assert isinstance(i18n.slice("role_playing"), str)
|
||||
assert "You are {role}" in i18n.slice("role_playing")
|
||||
|
||||
|
||||
def test_spanish_language():
|
||||
i18n = I18N(language="es")
|
||||
assert i18n.language == "es"
|
||||
assert isinstance(i18n.slice("role_playing"), str)
|
||||
assert "Eres {role}" in i18n.slice("role_playing")
|
||||
|
||||
|
||||
def test_spanish_hierarchical_manager():
|
||||
i18n = I18N(language="es")
|
||||
role = i18n.retrieve("hierarchical_manager_agent", "role")
|
||||
goal = i18n.retrieve("hierarchical_manager_agent", "goal")
|
||||
backstory = i18n.retrieve("hierarchical_manager_agent", "backstory")
|
||||
|
||||
assert role == "Gerente del Equipo"
|
||||
assert "Gestionar el equipo" in goal
|
||||
assert "gerente experimentado" in backstory
|
||||
|
||||
|
||||
def test_spanish_errors():
|
||||
i18n = I18N(language="es")
|
||||
error = i18n.errors("tool_usage_error")
|
||||
assert "Encontré un error" in error
|
||||
|
||||
|
||||
def test_spanish_tools():
|
||||
i18n = I18N(language="es")
|
||||
delegate_work = i18n.tools("delegate_work")
|
||||
assert "Delega una tarea específica" in delegate_work
|
||||
|
||||
|
||||
def test_fallback_to_english_for_unsupported_language():
|
||||
i18n = I18N(language="fr")
|
||||
assert isinstance(i18n.slice("role_playing"), str)
|
||||
assert "You are {role}" in i18n.slice("role_playing")
|
||||
|
||||
|
||||
def test_custom_prompt_file_overrides_language():
|
||||
import os
|
||||
import tempfile
|
||||
import json
|
||||
|
||||
custom_prompts = {
|
||||
"slices": {
|
||||
"role_playing": "Custom role playing prompt"
|
||||
}
|
||||
}
|
||||
|
||||
with tempfile.NamedTemporaryFile(mode='w', suffix='.json', delete=False) as f:
|
||||
json.dump(custom_prompts, f)
|
||||
temp_file = f.name
|
||||
|
||||
try:
|
||||
i18n = I18N(prompt_file=temp_file, language="es")
|
||||
assert i18n.slice("role_playing") == "Custom role playing prompt"
|
||||
finally:
|
||||
os.unlink(temp_file)
|
||||
|
||||
|
||||
def test_retrieve_with_spanish():
|
||||
i18n = I18N(language="es")
|
||||
observation = i18n.retrieve("slices", "observation")
|
||||
assert "Observación" in observation
|
||||
|
||||
|
||||
def test_spanish_reasoning_prompts():
|
||||
i18n = I18N(language="es")
|
||||
initial_plan = i18n.retrieve("reasoning", "initial_plan")
|
||||
assert "Eres {role}" in initial_plan
|
||||
assert "profesional" in initial_plan
|
||||
|
||||
|
||||
def test_language_parameter_validation():
|
||||
i18n = I18N(language="en")
|
||||
assert i18n.language == "en"
|
||||
|
||||
i18n_es = I18N(language="es")
|
||||
assert i18n_es.language == "es"
|
||||
|
||||
i18n_pt = I18N(language="pt")
|
||||
assert i18n_pt.language == "pt"
|
||||
Reference in New Issue
Block a user