crewAIInc / crewAI

Framework for orchestrating role-playing, autonomous AI agents. By fostering collaborative intelligence, CrewAI empowers agents to work together seamlessly, tackling complex tasks.
https://crewai.com
MIT License
20.94k stars 2.9k forks source link

[BUG] After upgrading to latest version of crewAI the code doesn't work anymore. #1333

Closed manili closed 1 month ago

manili commented 1 month ago

Description

I'm using Colab to test crewAI and after upgrading to 0.60.0 using the following code:

!pip install 'crewai[tools]'==0.60.0

The following code does not work anymore:

import os
from crewai import Agent, Task, Crew, Process
# from crewai_tools import SerperDevTool

os.environ["OPENAI_API_KEY"] = "xxxxxxxxxxxxxxxxx"
os.environ["OPENAI_API_BASE"] = 'https://api.sambanova.ai/v1/'
os.environ["OPENAI_MODEL_NAME"] = 'Meta-Llama-3.1-8B-Instruct'

researcher = Agent(
  role='Senior Research Analyst',
  goal='Uncover cutting-edge developments in AI and data science',
  backstory="""You work at a leading tech think tank.
  Your expertise lies in identifying emerging trends.
  You have a knack for dissecting complex data and presenting actionable insights.""",
  verbose=True,
  allow_delegation=False,
)

writer = Agent(
  role='Tech Content Strategist',
  goal='Craft compelling content on tech advancements',
  backstory="""You are a renowned Content Strategist, known for your insightful and engaging articles.
  You transform complex concepts into compelling narratives.""",
  verbose=True,
  allow_delegation=True
)

task1 = Task(
  description="""Conduct a comprehensive analysis of the latest advancements in AI in 2024.
  Identify key trends, breakthrough technologies, and potential industry impacts.""",
  expected_output="Full analysis report in bullet points",
  agent=researcher
)

task2 = Task(
  description="""Using the insights provided, develop an engaging blog
  post that highlights the most significant AI advancements.
  Your post should be informative yet accessible, catering to a tech-savvy audience.
  Make it sound cool, avoid complex words so it doesn't sound like AI.""",
  expected_output="Full blog post of at least 4 paragraphs",
  agent=writer
)

crew = Crew(
  agents=[researcher, writer],
  tasks=[task1, task2],
  verbose=True,
  process = Process.sequential
)

result = crew.kickoff()

print("######################")
print(result)

The code was working perfectly fine before upgrading to this version (tonight).

Steps to Reproduce

N/A

Expected behavior

N/A

Screenshots/Code snippets

BadRequestError: litellm.BadRequestError: OpenAIException - Unknown model: gpt-4o

Operating System

Other (specify in additional context)

Python Version

3.10

crewAI Version

0.60.0

crewAI Tools Version

0.60.0

Virtual Environment

Venv

Evidence

I'm encountering the following error:

# Agent: Senior Research Analyst
## Task: Conduct a comprehensive analysis of the latest advancements in AI in 2024.
  Identify key trends, breakthrough technologies, and potential industry impacts.

Give Feedback / Get Help: https://github.com/BerriAI/litellm/issues/new
LiteLLM.Info: If you need to debug this error, use `litellm.set_verbose=True'.

Give Feedback / Get Help: https://github.com/BerriAI/litellm/issues/new
LiteLLM.Info: If you need to debug this error, use `litellm.set_verbose=True'.

Give Feedback / Get Help: https://github.com/BerriAI/litellm/issues/new
LiteLLM.Info: If you need to debug this error, use `litellm.set_verbose=True'.

Give Feedback / Get Help: https://github.com/BerriAI/litellm/issues/new
LiteLLM.Info: If you need to debug this error, use `litellm.set_verbose=True'.

Give Feedback / Get Help: https://github.com/BerriAI/litellm/issues/new
LiteLLM.Info: If you need to debug this error, use `litellm.set_verbose=True'.

Give Feedback / Get Help: https://github.com/BerriAI/litellm/issues/new
LiteLLM.Info: If you need to debug this error, use `litellm.set_verbose=True'.

# Agent: Senior Research Analyst
## Task: Conduct a comprehensive analysis of the latest advancements in AI in 2024.
  Identify key trends, breakthrough technologies, and potential industry impacts.

Give Feedback / Get Help: https://github.com/BerriAI/litellm/issues/new
LiteLLM.Info: If you need to debug this error, use `litellm.set_verbose=True'.

Give Feedback / Get Help: https://github.com/BerriAI/litellm/issues/new
LiteLLM.Info: If you need to debug this error, use `litellm.set_verbose=True'.

Give Feedback / Get Help: https://github.com/BerriAI/litellm/issues/new
LiteLLM.Info: If you need to debug this error, use `litellm.set_verbose=True'.

Give Feedback / Get Help: https://github.com/BerriAI/litellm/issues/new
LiteLLM.Info: If you need to debug this error, use `litellm.set_verbose=True'.

Give Feedback / Get Help: https://github.com/BerriAI/litellm/issues/new
LiteLLM.Info: If you need to debug this error, use `litellm.set_verbose=True'.

Give Feedback / Get Help: https://github.com/BerriAI/litellm/issues/new
LiteLLM.Info: If you need to debug this error, use `litellm.set_verbose=True'.

# Agent: Senior Research Analyst
## Task: Conduct a comprehensive analysis of the latest advancements in AI in 2024.
  Identify key trends, breakthrough technologies, and potential industry impacts.

Give Feedback / Get Help: https://github.com/BerriAI/litellm/issues/new
LiteLLM.Info: If you need to debug this error, use `litellm.set_verbose=True'.

Give Feedback / Get Help: https://github.com/BerriAI/litellm/issues/new
LiteLLM.Info: If you need to debug this error, use `litellm.set_verbose=True'.

Give Feedback / Get Help: https://github.com/BerriAI/litellm/issues/new
LiteLLM.Info: If you need to debug this error, use `litellm.set_verbose=True'.

Give Feedback / Get Help: https://github.com/BerriAI/litellm/issues/new
LiteLLM.Info: If you need to debug this error, use `litellm.set_verbose=True'.

Give Feedback / Get Help: https://github.com/BerriAI/litellm/issues/new
LiteLLM.Info: If you need to debug this error, use `litellm.set_verbose=True'.

Give Feedback / Get Help: https://github.com/BerriAI/litellm/issues/new
LiteLLM.Info: If you need to debug this error, use `litellm.set_verbose=True'.

---------------------------------------------------------------------------
BadRequestError                           Traceback (most recent call last)
[/usr/local/lib/python3.10/dist-packages/litellm/llms/OpenAI/openai.py](https://localhost:8080/#) in completion(self, model_response, timeout, optional_params, logging_obj, model, messages, print_verbose, api_key, api_base, acompletion, litellm_params, logger_fn, headers, custom_prompt_dict, client, organization, custom_llm_provider, drop_params)
    906                     else:
--> 907                         raise e
    908         except OpenAIError as e:

43 frames
[/usr/local/lib/python3.10/dist-packages/litellm/llms/OpenAI/openai.py](https://localhost:8080/#) in completion(self, model_response, timeout, optional_params, logging_obj, model, messages, print_verbose, api_key, api_base, acompletion, litellm_params, logger_fn, headers, custom_prompt_dict, client, organization, custom_llm_provider, drop_params)
    824                         headers, response = (
--> 825                             self.make_sync_openai_chat_completion_request(
    826                                 openai_client=openai_client,

[/usr/local/lib/python3.10/dist-packages/litellm/llms/OpenAI/openai.py](https://localhost:8080/#) in make_sync_openai_chat_completion_request(self, openai_client, data, timeout)
    682         except Exception as e:
--> 683             raise e
    684 

[/usr/local/lib/python3.10/dist-packages/litellm/llms/OpenAI/openai.py](https://localhost:8080/#) in make_sync_openai_chat_completion_request(self, openai_client, data, timeout)
    671         try:
--> 672             raw_response = openai_client.chat.completions.with_raw_response.create(
    673                 **data, timeout=timeout

[/usr/local/lib/python3.10/dist-packages/openai/_legacy_response.py](https://localhost:8080/#) in wrapped(*args, **kwargs)
    349 
--> 350         return cast(LegacyAPIResponse[R], func(*args, **kwargs))
    351 

[/usr/local/lib/python3.10/dist-packages/openai/_utils/_utils.py](https://localhost:8080/#) in wrapper(*args, **kwargs)
    273                 raise TypeError(msg)
--> 274             return func(*args, **kwargs)
    275 

[/usr/local/lib/python3.10/dist-packages/openai/resources/chat/completions.py](https://localhost:8080/#) in create(self, messages, model, frequency_penalty, function_call, functions, logit_bias, logprobs, max_completion_tokens, max_tokens, n, parallel_tool_calls, presence_penalty, response_format, seed, service_tier, stop, stream, stream_options, temperature, tool_choice, tools, top_logprobs, top_p, user, extra_headers, extra_query, extra_body, timeout)
    703         validate_response_format(response_format)
--> 704         return self._post(
    705             "/chat/completions",

[/usr/local/lib/python3.10/dist-packages/openai/_base_client.py](https://localhost:8080/#) in post(self, path, cast_to, body, options, files, stream, stream_cls)
   1259         )
-> 1260         return cast(ResponseT, self.request(cast_to, opts, stream=stream, stream_cls=stream_cls))
   1261 

[/usr/local/lib/python3.10/dist-packages/openai/_base_client.py](https://localhost:8080/#) in request(self, cast_to, options, remaining_retries, stream, stream_cls)
    936     ) -> ResponseT | _StreamT:
--> 937         return self._request(
    938             cast_to=cast_to,

[/usr/local/lib/python3.10/dist-packages/openai/_base_client.py](https://localhost:8080/#) in _request(self, cast_to, options, remaining_retries, stream, stream_cls)
   1040             log.debug("Re-raising status error")
-> 1041             raise self._make_status_error_from_response(err.response) from None
   1042 

BadRequestError: Unknown model: gpt-4o

During handling of the above exception, another exception occurred:

OpenAIError                               Traceback (most recent call last)
[/usr/local/lib/python3.10/dist-packages/litellm/main.py](https://localhost:8080/#) in completion(model, messages, timeout, temperature, top_p, n, stream, stream_options, stop, max_completion_tokens, max_tokens, presence_penalty, frequency_penalty, logit_bias, user, response_format, seed, tools, tool_choice, logprobs, top_logprobs, parallel_tool_calls, deployment_id, extra_headers, functions, function_call, base_url, api_version, api_key, model_list, **kwargs)
   1395                 )
-> 1396                 raise e
   1397 

[/usr/local/lib/python3.10/dist-packages/litellm/main.py](https://localhost:8080/#) in completion(model, messages, timeout, temperature, top_p, n, stream, stream_options, stop, max_completion_tokens, max_tokens, presence_penalty, frequency_penalty, logit_bias, user, response_format, seed, tools, tool_choice, logprobs, top_logprobs, parallel_tool_calls, deployment_id, extra_headers, functions, function_call, base_url, api_version, api_key, model_list, **kwargs)
   1368             try:
-> 1369                 response = openai_chat_completions.completion(
   1370                     model=model,

[/usr/local/lib/python3.10/dist-packages/litellm/llms/OpenAI/openai.py](https://localhost:8080/#) in completion(self, model_response, timeout, optional_params, logging_obj, model, messages, print_verbose, api_key, api_base, acompletion, litellm_params, logger_fn, headers, custom_prompt_dict, client, organization, custom_llm_provider, drop_params)
    913             error_text = getattr(e, "text", str(e))
--> 914             raise OpenAIError(
    915                 status_code=status_code, message=error_text, headers=error_headers

OpenAIError: Unknown model: gpt-4o

During handling of the above exception, another exception occurred:

BadRequestError                           Traceback (most recent call last)
[/usr/local/lib/python3.10/dist-packages/litellm/utils.py](https://localhost:8080/#) in wrapper(*args, **kwargs)
    979             # MODEL CALL
--> 980             result = original_function(*args, **kwargs)
    981             end_time = datetime.datetime.now()

[/usr/local/lib/python3.10/dist-packages/litellm/main.py](https://localhost:8080/#) in completion(model, messages, timeout, temperature, top_p, n, stream, stream_options, stop, max_completion_tokens, max_tokens, presence_penalty, frequency_penalty, logit_bias, user, response_format, seed, tools, tool_choice, logprobs, top_logprobs, parallel_tool_calls, deployment_id, extra_headers, functions, function_call, base_url, api_version, api_key, model_list, **kwargs)
   2823         ## Map to OpenAI Exception
-> 2824         raise exception_type(
   2825             model=model,

[/usr/local/lib/python3.10/dist-packages/litellm/utils.py](https://localhost:8080/#) in exception_type(model, original_exception, custom_llm_provider, completion_kwargs, extra_kwargs)
   8195             setattr(e, "litellm_response_headers", litellm_response_headers)
-> 8196             raise e
   8197         else:

[/usr/local/lib/python3.10/dist-packages/litellm/utils.py](https://localhost:8080/#) in exception_type(model, original_exception, custom_llm_provider, completion_kwargs, extra_kwargs)
   6521                         exception_mapping_worked = True
-> 6522                         raise BadRequestError(
   6523                             message=f"{exception_provider} - {message}",

BadRequestError: litellm.BadRequestError: OpenAIException - Unknown model: gpt-4o

During handling of the above exception, another exception occurred:

BadRequestError                           Traceback (most recent call last)
[<ipython-input-2-cebbbee08ec0>](https://localhost:8080/#) in <cell line: 76>()
     74 
     75 # Get your crew to work!
---> 76 result = crew.kickoff()
     77 
     78 print("######################")

[/usr/local/lib/python3.10/dist-packages/crewai/crew.py](https://localhost:8080/#) in kickoff(self, inputs)
    464 
    465         if self.process == Process.sequential:
--> 466             result = self._run_sequential_process()
    467         elif self.process == Process.hierarchical:
    468             result = self._run_hierarchical_process()

[/usr/local/lib/python3.10/dist-packages/crewai/crew.py](https://localhost:8080/#) in _run_sequential_process(self)
    572     def _run_sequential_process(self) -> CrewOutput:
    573         """Executes tasks sequentially and returns the final output."""
--> 574         return self._execute_tasks(self.tasks)
    575 
    576     def _run_hierarchical_process(self) -> CrewOutput:

[/usr/local/lib/python3.10/dist-packages/crewai/crew.py](https://localhost:8080/#) in _execute_tasks(self, tasks, start_index, was_replayed)
    669 
    670                 context = self._get_context(task, task_outputs)
--> 671                 task_output = task.execute_sync(
    672                     agent=agent_to_use,
    673                     context=context,

[/usr/local/lib/python3.10/dist-packages/crewai/task.py](https://localhost:8080/#) in execute_sync(self, agent, context, tools)
    189     ) -> TaskOutput:
    190         """Execute the task synchronously."""
--> 191         return self._execute_core(agent, context, tools)
    192 
    193     @property

[/usr/local/lib/python3.10/dist-packages/crewai/task.py](https://localhost:8080/#) in _execute_core(self, agent, context, tools)
    245         self.processed_by_agents.add(agent.role)
    246 
--> 247         result = agent.execute_task(
    248             task=self,
    249             context=context,

[/usr/local/lib/python3.10/dist-packages/crewai/agent.py](https://localhost:8080/#) in execute_task(self, task, context, tools)
    192             if self._times_executed > self.max_retry_limit:
    193                 raise e
--> 194             result = self.execute_task(task, context, tools)
    195 
    196         if self.max_rpm and self._rpm_controller:

[/usr/local/lib/python3.10/dist-packages/crewai/agent.py](https://localhost:8080/#) in execute_task(self, task, context, tools)
    192             if self._times_executed > self.max_retry_limit:
    193                 raise e
--> 194             result = self.execute_task(task, context, tools)
    195 
    196         if self.max_rpm and self._rpm_controller:

[/usr/local/lib/python3.10/dist-packages/crewai/agent.py](https://localhost:8080/#) in execute_task(self, task, context, tools)
    191             self._times_executed += 1
    192             if self._times_executed > self.max_retry_limit:
--> 193                 raise e
    194             result = self.execute_task(task, context, tools)
    195 

[/usr/local/lib/python3.10/dist-packages/crewai/agent.py](https://localhost:8080/#) in execute_task(self, task, context, tools)
    180 
    181         try:
--> 182             result = self.agent_executor.invoke(
    183                 {
    184                     "input": task_prompt,

[/usr/local/lib/python3.10/dist-packages/crewai/agents/crew_agent_executor.py](https://localhost:8080/#) in invoke(self, inputs)
     87 
     88         self.ask_for_human_input = bool(inputs.get("ask_for_human_input", False))
---> 89         formatted_answer = self._invoke_loop()
     90 
     91         if self.ask_for_human_input:

[/usr/local/lib/python3.10/dist-packages/crewai/agents/crew_agent_executor.py](https://localhost:8080/#) in _invoke_loop(self, formatted_answer)
    160                 return self._invoke_loop(formatted_answer)
    161             else:
--> 162                 raise e
    163 
    164         self._show_logs(formatted_answer)

[/usr/local/lib/python3.10/dist-packages/crewai/agents/crew_agent_executor.py](https://localhost:8080/#) in _invoke_loop(self, formatted_answer)
    109                         stop=self.stop if self.use_stop_words else None,
    110                         callbacks=self.callbacks,
--> 111                     ).call(self.messages)
    112 
    113                     if not self.use_stop_words:

[/usr/local/lib/python3.10/dist-packages/crewai/llm.py](https://localhost:8080/#) in call(self, messages)
     11 
     12     def call(self, messages: List[Dict[str, str]]) -> Dict[str, Any]:
---> 13         response = completion(
     14             stop=self.stop, model=self.model, messages=messages, num_retries=5
     15         )

[/usr/local/lib/python3.10/dist-packages/litellm/utils.py](https://localhost:8080/#) in wrapper(*args, **kwargs)
   1065                     ):
   1066                         kwargs["num_retries"] = num_retries
-> 1067                         return litellm.completion_with_retries(*args, **kwargs)
   1068                 elif (
   1069                     isinstance(e, litellm.exceptions.ContextWindowExceededError)

[/usr/local/lib/python3.10/dist-packages/litellm/main.py](https://localhost:8080/#) in completion_with_retries(*args, **kwargs)
   2855             reraise=True,
   2856         )
-> 2857     return retryer(original_function, *args, **kwargs)
   2858 
   2859 

[/usr/local/lib/python3.10/dist-packages/tenacity/__init__.py](https://localhost:8080/#) in __call__(self, fn, *args, **kwargs)
    473         retry_state = RetryCallState(retry_object=self, fn=fn, args=args, kwargs=kwargs)
    474         while True:
--> 475             do = self.iter(retry_state=retry_state)
    476             if isinstance(do, DoAttempt):
    477                 try:

[/usr/local/lib/python3.10/dist-packages/tenacity/__init__.py](https://localhost:8080/#) in iter(self, retry_state)
    374         result = None
    375         for action in self.iter_state.actions:
--> 376             result = action(retry_state)
    377         return result
    378 

[/usr/local/lib/python3.10/dist-packages/tenacity/__init__.py](https://localhost:8080/#) in exc_check(rs)
    416                 retry_exc = self.retry_error_cls(fut)
    417                 if self.reraise:
--> 418                     raise retry_exc.reraise()
    419                 raise retry_exc from fut.exception()
    420 

[/usr/local/lib/python3.10/dist-packages/tenacity/__init__.py](https://localhost:8080/#) in reraise(self)
    183     def reraise(self) -> t.NoReturn:
    184         if self.last_attempt.failed:
--> 185             raise self.last_attempt.result()
    186         raise self
    187 

[/usr/lib/python3.10/concurrent/futures/_base.py](https://localhost:8080/#) in result(self, timeout)
    449                     raise CancelledError()
    450                 elif self._state == FINISHED:
--> 451                     return self.__get_result()
    452 
    453                 self._condition.wait(timeout)

[/usr/lib/python3.10/concurrent/futures/_base.py](https://localhost:8080/#) in __get_result(self)
    401         if self._exception:
    402             try:
--> 403                 raise self._exception
    404             finally:
    405                 # Break a reference cycle with the exception in self._exception

[/usr/local/lib/python3.10/dist-packages/tenacity/__init__.py](https://localhost:8080/#) in __call__(self, fn, *args, **kwargs)
    476             if isinstance(do, DoAttempt):
    477                 try:
--> 478                     result = fn(*args, **kwargs)
    479                 except BaseException:  # noqa: B902
    480                     retry_state.set_exception(sys.exc_info())  # type: ignore[arg-type]

[/usr/local/lib/python3.10/dist-packages/litellm/utils.py](https://localhost:8080/#) in wrapper(*args, **kwargs)
   1090                     ):  # make it easy to get to the debugger logs if you've initialized it
   1091                         e.message += f"\n Check the log in your dashboard - {liteDebuggerClient.dashboard_url}"
-> 1092             raise e
   1093 
   1094     @wraps(original_function)

[/usr/local/lib/python3.10/dist-packages/litellm/utils.py](https://localhost:8080/#) in wrapper(*args, **kwargs)
    978                     print_verbose(f"Error while checking max token limit: {str(e)}")
    979             # MODEL CALL
--> 980             result = original_function(*args, **kwargs)
    981             end_time = datetime.datetime.now()
    982             if "stream" in kwargs and kwargs["stream"] is True:

[/usr/local/lib/python3.10/dist-packages/litellm/main.py](https://localhost:8080/#) in completion(model, messages, timeout, temperature, top_p, n, stream, stream_options, stop, max_completion_tokens, max_tokens, presence_penalty, frequency_penalty, logit_bias, user, response_format, seed, tools, tool_choice, logprobs, top_logprobs, parallel_tool_calls, deployment_id, extra_headers, functions, function_call, base_url, api_version, api_key, model_list, **kwargs)
   2822     except Exception as e:
   2823         ## Map to OpenAI Exception
-> 2824         raise exception_type(
   2825             model=model,
   2826             custom_llm_provider=custom_llm_provider,

[/usr/local/lib/python3.10/dist-packages/litellm/utils.py](https://localhost:8080/#) in exception_type(model, original_exception, custom_llm_provider, completion_kwargs, extra_kwargs)
   8194         if exception_mapping_worked:
   8195             setattr(e, "litellm_response_headers", litellm_response_headers)
-> 8196             raise e
   8197         else:
   8198             for error_type in litellm.LITELLM_EXCEPTION_TYPES:

[/usr/local/lib/python3.10/dist-packages/litellm/utils.py](https://localhost:8080/#) in exception_type(model, original_exception, custom_llm_provider, completion_kwargs, extra_kwargs)
   6520                     if original_exception.status_code == 400:
   6521                         exception_mapping_worked = True
-> 6522                         raise BadRequestError(
   6523                             message=f"{exception_provider} - {message}",
   6524                             llm_provider=custom_llm_provider,

BadRequestError: litellm.BadRequestError: OpenAIException - Unknown model: gpt-4o

Possible Solution

Downgrade to the previous version.

Additional context

N/A

giandre commented 1 month ago

I have similar issues with all my previous code with crewai. I ended up sticking with 0.41.0 version so things will continue to work. I have no idea how to fix it.

strikeoncmputrz commented 1 month ago

I am encountering the same issue with gpt-4o being called despite defining an LLM in my crew method. The only working Agent is my manager_llm. I assume that it is now necessary to define the LLM on a per agent basis. Is that correct?

    @crew
    def crew(self) -> Crew:
        """Creates the WriteEssay crew"""
        return Crew(
            agents=self.agents, # Automatically created by the @agent decorator
            tasks=self.tasks, # Automatically created by the @task decorator
            llm="openai/LoneStriker_Hermes-3-Llama-3.1-70B-6.0bpw-h6-exl2_main",
            function_calling_llm="openai/LoneStriker_Hermes-3-Llama-3.1-70B-6.0bpw-h6-exl2_main",
            manager_llm="openai/LoneStriker_Hermes-3-Llama-3.1-70B-6.0bpw-h6-exl2_main",
            process=Process.hierarchical,
            #process=Process.sequential,
            #planning=True,
            planning_llm="openai/LoneStriker_Hermes-3-Llama-3.1-70B-6.0bpw-h6-exl2_main",
            memory=True,
            verbose=True,
            share_crew=False,
            output_log_file=get_log_file_name(),
            # Need to set embedder based on what is being hosted by Infinity-Embeddings
            embedder={
                "provider": "openai",
                "config":{
                        "model": 'BAAI/bge-small-en-v1.5'
                }
            }
        )
theCyberTech commented 1 month ago

https://docs.crewai.com/how-to/LLM-Connections/

olafgeibig commented 1 month ago

I must also chime in here. Making LiteLLM the only way to provide an LLM is a very poor decision for multiple reasons.

First of all its a huge breaking change. All my crews don't work anymore. Okay this can be solved with some editing monkey job, but the worst is that it seems I can't use JSON output with models other than OpenAI via their OpenAI compatible API.

With the previous version I could use output_json with deepseek-chat on tasks. I just need to used an OpenAI chat client configured with deepseek like that:

llm = ChatOpenAI(
    model="deepseek-chat", 
    api_key=DEEPSEEK_API_KEY, 
    base_url="https://api.deepseek.com/v1",
    temperature=0.0
)
note_task = Task(
    description="shortened for brevity",
    agent=writer_agent,
    expected_output="a note that is the filled template",
    output_json=Note,
    output_file="note.json",
) 

This code results in valid JSON file. With the new version I managed to use deepseek-chat with the OpenAI API, but the JSON serialisation gives an error now.

load_dotenv()
os.environ["OPENAI_API_KEY"] = os.getenv("DEEPSEEK_API_KEY")
os.environ["OPENAI_API_BASE"] = 'https://api.deepseek.com/v1/'

writer_agent = Agent(
    role='Note writer',
    goal='Write personal notes using a specified template.',
    backstory='I am a note writer with a great skill to write personal notes.',
    verbose=True,
    llm="openai/deepseek-chat",
    allow_delegation=False,
    tools=[]
)

note_task = Task(
    description="shortened for brevity",
    agent=writer_agent,
    expected_output="a note that is the filled template",
    output_json=Note,
)

Error:

pydantic_core._pydantic_core.ValidationError: 1 validation error for TaskOutput
json_dict
  Input should be a valid dictionary [type=dict_type, input_value='```json\n{\n    "title":...g and support."\n}\n```', input_type=str]
    For further information visit https://errors.pydantic.dev/2.8/v/dict_type

Using llm="deepseek/deepsekk-chat" also does not support JSON output. It seems it doesn't use deepseeks JSON output of their propretary API. Same Pydantic error because the json is surrounded by markdoiwn quotes, means no JSON mode.

Moreover there is now no control over LLM parameters like temperature anymore. Why not leaving the exiting llm parameter and add a new one for LiteLLM like llm_name?

Update: LiteLLM doesn't even support function calling for Anthropic models: https://docs.litellm.ai/docs/completion/input

strikeoncmputrz commented 1 month ago

https://docs.crewai.com/how-to/LLM-Connections/

Thanks for sharing the applicable documentation. Even when assigning all my agents an explicit LLM Crew was still attempting to use GPT-4o. I will also set the environment variable I guess.

joaomdmoura commented 1 month ago

Hey there, catching up to this! This is great feedback!

Good point @olafgeibig on maybe support multiple ways to provide an LLM, and honestly that will be way easier to do now that we removed langchain!

Other than LangChain and LLama-Index, is that other major providers we should consider adding that we might be missing out?

olafgeibig commented 1 month ago

@joaomdmoura good to know that you removed LangChain. Now I can turn off the LangChain instrumentor in my tracing. I must admit that I didn't read the changelog. I see, so you replaced the LangChain LLM support with LiteLLM. Now I understand. I agree that LiteLLM was probably the best option to support many LLMs without building on top of a framework.

Regarding the number of supported LLM APIs there is probably nothing comparable to LangChain and LlamaIndex. I find the new ell framework a very fresh approach to developing with LLMs, but it's very young and only supports OpenAI and Anthropic. https://docs.ell.so/index.html

There are many model providers, routers like openrouter or self hosted LLMs that offer an OpenAI compatible API. For instance LiteLLM is not utliizing the structured output and function calling of DeepSeek's proprietary API, but DeepSeek's OpenAI compatible endpoint is offering that. It would be some relief if crewAI would at least allow using the OpenAI client for crews and agents. That would be probably the easiest way to ease the pain expressed here in this issue.

olafgeibig commented 1 month ago

Update. I managed to make it work with the LiteLLM solution for OpenAI compatible APIs.

Additionally I needed to add the JSON schema of the Pydantic object to the task description. Somehow I though that this happening already under the hood of crewAI. At least deepseek-chat needs that to get it right.

load_dotenv()
os.environ["OPENAI_API_KEY"] = os.getenv("DEEPSEEK_API_KEY")
os.environ["OPENAI_API_BASE"] = 'https://api.deepseek.com/v1'

writer_agent = Agent(
    role='Note writer',
    goal='Write personal notes using a specified template.',
    backstory='I am a note writer with a great skill to write personal notes.',
    verbose=True,
    llm="openai/deepseek-chat",
    allow_delegation=False,
    tools=[]
)

note_task = Task(
    description=f"""
    Create a note about the resource Pydantic using the note template.
    The note shall contain a general section explaining the resource and its concepts and a multiple themed section with important links to websites.
    Adhere to this schema: {Note.model_json_schema()}
    """,
    agent=writer_agent,
    expected_output="a note that is the filled template",
    output_pydantic=Note,
)    

crew = Crew(
    agents=[writer_agent],
    tasks=[note_task],
    verbose=True
)

crew_output = crew.kickoff()
print(f"Crew: {crew_output}")
print(f"Pydantic: {note_task.output.pydantic}")

Still I don't like about this solution that I need to overwrite the OPENAI_API_KEY in the environment, but at least it works.

BTW, the tasks doc looks a bit weird and contains contradictory information regarding task parameters: https://docs.crewai.com/core-concepts/Tasks/

Kingbadger3d commented 1 month ago

Why, Just Why?. There was no need to make this change to LiteLLM so breaking, yet you did it anyway. Yet Langchain worked as expected and had more features? If changing LLM system why didnt you at least go for something more production oriented like vLLM?. odd decisions, that mean we all have to rewrite huge amounts to just get back to a working condition to have less features?.

theCyberTech commented 1 month ago

Why, Just Why?. There was no need to make this change to LiteLLM so breaking, yet you did it anyway. Yet Langchain worked as expected and had more features? If changing LLM system why didnt you at least go for something more production oriented like vLLM?. odd decisions, that mean we all have to rewrite huge amounts to just get back to a working condition to have less features?.

Curious as to why you think there was no need o make this change?

LiteLLM and vLLM do not have the same main purpose so that so it would not make sense to do that. You can integrate vLLM through LiteLLM already.

Also there is nothing stopping you from using Langchain / llamaindex still.

Let me know if you need help with anything

joaomdmoura commented 1 month ago

@olafgeibig This is a good suggestion, we can still add support to LangChain Model definition without need to bring back their executor now, so this is good, I'm already working on it.

Hey @Kingbadger3d appreciate the messages, I'm sorry you are experiment so much pain from the upgrade. If you want, it might be easier to hold on upgrading while we bring more providers including langchain for model connections. We needed to remove this because langchain was slowing down our ability to add some major new features and would break on some of their updates.

TarcisioAmaral commented 1 month ago

Can someone help me out? man i feel lost. i using CrewAI for build a crew with 'crew.py', 'main.py', 'agents.yaml' and 'tasks.yaml' to configurate and put what do u want, but a get only errors, i read documentation but still i don't get it how realy works. I start with crewai about 2 mounth, i already run some crews but after this version i get lost. there is some model, workflow with this new version and LiteLLM? And some visual feedback, i tink that could be better understanding to the documentarion and also a workflow for the people like me who jump into CrewAI now

joaomdmoura commented 1 month ago

Hey @TarcisioAmaral how much can you share about specific errors you are getting and your specific setup?

This doc page should give you instructions to get a working setup.

The major thing changing in this version was the we removed the LangChain Agent Executor, allowing us to write our own, what gave us more control and the ability to build features we were not able before, so all the remaining features should still work the same, but I would love to dig into specific problems to learn if there are bugs we should fix.

The main change required in your actual code is that now instead of passing the LangChain model definition to your agents you could pass a string like gpt-4o-mini and it will use LiteLLM behind the scenes to do the LLM calls. We will bring back support for the LangChain models without bringing back their executor though to make it easier for people to use the new versions, migrating from older ones in existing projects.

TarcisioAmaral commented 1 month ago

Opa @joaomdmoura. Shure. Is "UnicodeDecodeError", i got but the Output of the terminal here below. Few friends and i pass throught the same problem, we learning crewai with Luan(Brazilian Power hehe). If u can help me gonna be amazing. Gonna read this Doc learn more about.

File "", line 1, in File "C:\Users\Oasis\OneDrive\AI\OrNexus\Python\criador_ofertas\src\criador_ofertas\main.py", line 22, in run crew_instance = CriadorOfertasCrew() ^^^^^^^^^^^^^^^^^^^^ File "C:\Users\Oasis\AppData\Local\pypoetry\Cache\virtualenvs\criador-ofertas-EbYFKUVs-py3.12\Lib\site-packages\crewai\project\crew_base.py", line 29, in init self.agents_config = self.load_yaml(agents_config_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\Oasis\AppData\Local\pypoetry\Cache\virtualenvs\criador-ofertas-EbYFKUVs-py3.12\Lib\site-packages\crewai\project\crew_base.py", line 39, in load_yaml return yaml.safe_load(file) ^^^^^^^^^^^^^^^^^^^^ File "C:\Users\Oasis\AppData\Local\pypoetry\Cache\virtualenvs\criador-ofertas-EbYFKUVs-py3.12\Lib\site-packages\yaml__init__.py", line 125, in safe_load return load(stream, SafeLoader) ^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\Oasis\AppData\Local\pypoetry\Cache\virtualenvs\criador-ofertas-EbYFKUVs-py3.12\Lib\site-packages\yaml__init.py", line 79, in load loader = Loader(stream) ^^^^^^^^^^^^^^ File "C:\Users\Oasis\AppData\Local\pypoetry\Cache\virtualenvs\criador-ofertas-EbYFKUVs-py3.12\Lib\site-packages\yaml\loader.py", line 34, in init Reader.init(self, stream) File "C:\Users\Oasis\AppData\Local\pypoetry\Cache\virtualenvs\criador-ofertas-EbYFKUVs-py3.12\Lib\site-packages\yaml\reader.py", line 85, in init__ self.determine_encoding() File "C:\Users\Oasis\AppData\Local\pypoetry\Cache\virtualenvs\criador-ofertas-EbYFKUVs-py3.12\Lib\site-packages\yaml\reader.py", line 124, in determine_encoding self.update_raw() File "C:\Users\Oasis\AppData\Local\pypoetry\Cache\virtualenvs\criador-ofertas-EbYFKUVs-py3.12\Lib\site-packages\yaml\reader.py", line 178, in update_raw data = self.stream.read(size) ^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\Oasis\AppData\Local\Programs\Python\Python312\Lib\encodings\cp1252.py", line 23, in decode return codecs.charmap_decode(input,self.errors,decoding_table)[0] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UnicodeDecodeError: 'charmap' codec can't decode byte 0x8d in position 172: character maps to An error occurred while running the crew: Command '['poetry', 'run', 'run_crew']' returned non-zero exit status 1.

joaomdmoura commented 1 month ago

Hey folks, spent the day today working on a new LLM class that will be introduced in the next version to address all the concerns in this issue, open for feedback before we cut the verison.

New docs, still not live: (https://github.com/crewAIInc/crewAI/blob/main/docs/core-concepts/LLMs.md) Some high level description bellow:

Default

By default, crewAI uses the gpt-4o-mini model.

Using Env Vars

It uses environment variables if no LLM is specified:

String Identifier

Aiming at simplicity and supporting who update to version 0.61.0

agent = Agent(llm="gpt-4o", ...)

LLM Instance

List of more providers.

from crewai import LLM

llm = LLM(model="gpt-4", temperature=0.7)
agent = Agent(llm=llm, ...)

LLM Configuration Options

This new LLM class allow you to use an big array of attributes.

Parameter Type Description
model str The name of the model to use (e.g., "gpt-4", "gpt-3.5-turbo", "ollama/llama3.1", more providers)
timeout float, int Maximum time (in seconds) to wait for a response
temperature float Controls randomness in output (0.0 to 1.0)
top_p float Controls diversity of output (0.0 to 1.0)
n int Number of completions to generate
stop str, List[str] Sequence(s) to stop generation
max_tokens int Maximum number of tokens to generate
presence_penalty float Penalizes new tokens based on their presence in the text so far
frequency_penalty float Penalizes new tokens based on their frequency in the text so far
logit_bias Dict[int, float] Modifies likelihood of specified tokens appearing in the completion
response_format Dict[str, Any] Specifies the format of the response (e.g., {"type": "json_object"})
seed int Sets a random seed for deterministic results
logprobs bool Whether to return log probabilities of the output tokens
top_logprobs int Number of most likely tokens to return the log probabilities for
base_url str The base URL for the API endpoint
api_version str The version of the API to use
api_key str Your API key for authentication

Example:

llm = LLM(
    model="gpt-4",
    temperature=0.8,
    max_tokens=150,
    top_p=0.9,
    frequency_penalty=0.1,
    presence_penalty=0.1,
    stop=["END"],
    seed=42,
    base_url="https://api.openai.com/v1",
    api_key="your-api-key-here"
)
agent = Agent(llm=llm, ...)

Using Ollama (Local LLMs)

crewAI supports using Ollama for running open-source models locally:

  1. Install Ollama: ollama.ai
  2. Run a model: ollama run llama2
  3. Configure agent:
    agent = Agent(
    llm=LLM(model="ollama/llama3.1", base_url="http://localhost:11434"),
    ...
    )

Changing the Base API URL

You can change the base API URL for any LLM provider by setting the base_url parameter:

llm = LLM(
    model="custom-model-name",
    base_url="https://api.your-provider.com/v1",
    api_key="your-api-key"
)
agent = Agent(llm=llm, ...)
joaomdmoura commented 1 month ago

@TarcisioAmaral your problem seems to be unrelated, but looking at the error message, it indicates a problem with character encoding when trying to read a YAML file.

In an attempt to fix it I push a change to master that forcer the utf-8 encoding and it will be live in the next version, it should help with it.

But I also recommend checking the YAML file for any unusual or non-printable characters. You might need to remove or replace problematic characters.

olafgeibig commented 1 month ago

@joaomdmoura I think this is a very good approach. It will return full control over the LLM client parameters to developers. I think this is an easy to apply change that will deliver great benefits.

Just one more question. I did not read all of the related code but I noticed Converter.is_gpt() is used to decide if certain advanced features of OpenAI models are used by crewAI. I think this simple check of the model name does exclude models with an OpenAI compatible API that also offer these advanced features.

A much more fine-grained check would be possible by inspecting LiteLLM's supported model features provided by a LiteLLM function:

litellm.get_supported_openai_params("openrouter/qwen/qwen-2.5-72b-instruct") 

Example response:

['temperature', 'top_p', 'frequency_penalty', 'presence_penalty', 'repetition_penalty', 'seed', 'max_tokens', 'logit_bias', 'logprobs', 'top_logprobs', 'response_format', 'stop', 'tools', 'tool_choice']
joaomdmoura commented 1 month ago

Good call, def something we could add, I think the main thing that is used for is to know if it should use actually tool calling or not but will do a pass on it

joaomdmoura commented 1 month ago

new version is out v0.63.1 env vars should work again, also ability to control all different attribute for the LLM using the LLM class, if this is still an issue let us know and we can re-open it :)