Hello all,
I have configured a crew to "list files from a Sharepoint site, then read that file and lastly provide an executive summary. all my tools are custom and my LLM is private (Azure).
the crew woks fine except when in in the task (and some of them) I set output_pydantic to a Class to get a structured output.
there is a very similar situation from another user filed as Bug in Github([BUG] Pydantic output with azure function calling models failed with litellm auth error · Issue #1572 · crewAIInc/crewAI · GitHub) , but no solution has been provided.
Here is the out just snipet of the error:
indent preformatted text by 4 spaces
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'.
---------------------------------------------------------------------------
AuthenticationError Traceback (most recent call last)
File /opt/anaconda3/lib/python3.12/site-packages/litellm/llms/openai/openai.py:707, in OpenAIChatCompletion.completion(self, model_response, timeout, optional_params, litellm_params, logging_obj, model, messages, print_verbose, api_key, api_base, api_version, dynamic_params, azure_ad_token, acompletion, logger_fn, headers, custom_prompt_dict, client, organization, custom_llm_provider, drop_params)
706 else:
--> 707 raise e
708 except OpenAIError as e:
File /opt/anaconda3/lib/python3.12/site-packages/litellm/llms/openai/openai.py:634, in OpenAIChatCompletion.completion(self, model_response, timeout, optional_params, litellm_params, logging_obj, model, messages, print_verbose, api_key, api_base, api_version, dynamic_params, azure_ad_token, acompletion, logger_fn, headers, custom_prompt_dict, client, organization, custom_llm_provider, drop_params)
622 logging_obj.pre_call(
623 input=messages,
624 api_key=openai_client.api_key,
(...)
630 },
631 )
633 headers, response = (
--> 634 self.make_sync_openai_chat_completion_request(
635 openai_client=openai_client,
636 data=data,
637 timeout=timeout,
638 logging_obj=logging_obj,
639 )
640 )
642 logging_obj.model_call_details["response_headers"] = headers
.....
....
File /opt/anaconda3/lib/python3.12/site-packages/openai/_base_client.py:1064, in SyncAPIClient._request(self, cast_to, options, retries_taken, stream, stream_cls)
1063 log.debug("Re-raising status error")
-> 1064 raise self._make_status_error_from_response(err.response) from None
1066 return self._process_response(
1067 cast_to=cast_to,
1068 options=options,
(...)
1072 retries_taken=retries_taken,
1073 )
AuthenticationError: Error code: 401 - {'error': {'message': 'Your authentication token is not from a valid issuer.', 'type': 'invalid_request_error', 'param': None, 'code': 'invalid_issuer'}}
During handling of the above exception, another exception occurred:
OpenAIError Traceback (most recent call last)
File /opt/anaconda3/lib/python3.12/site-packages/litellm/main.py:1626, in completion(model, messages, timeout, temperature, top_p, n, stream, stream_options, stop, max_completion_tokens, max_tokens, modalities, prediction, audio, 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)
1620 logging.post_call(
1621 input=messages,
1622 api_key=api_key,
1623 original_response=str(e),
1624 additional_args={"headers": headers},
1625 )
-> 1626 raise e
1628 if optional_params.get("stream", False):
1629 ## LOGGING
....
....
43 if current_attempt < self.max_attempts:
44 return self.to_pydantic(current_attempt + 1)
---> 45 raise ConverterError(
46 f"Failed to convert text into a Pydantic model due to the following error: {e}"
47 )
ConverterError: Failed to convert text into a Pydantic model due to the following error: litellm.BadRequestError: OpenAIException - Error code: 401 - {'error': {'message': 'Your authentication token is not from a valid issuer.', 'type': 'invalid_request_error', 'param': None, 'code': 'invalid_issuer'}}
Here is the code (just part of it for simplicity):
class UseCaseSection(BaseModel):
usecase_emoji: str = Field(description="Section emoji (e.g., 🔍, 📊, 🎯)")
usecase_title: str = Field(description="Use Case title")
usecase_content: str = Field(description="Describe what the use case can deliver, execute or acomplish")
key_highlights: List[str] = Field(description="Describe benefits of Use case")
UseCaseAgent= Agent(
role="IT Use Case Analyst",
goal=("Identify and extract IT-related use cases from documeread_file_task"
"Output should be in readable markdown documents"
),
backstory=( "An expert in IT operations, familiar with networking, security,\ "
"and compliance processes. Skilled in analyzing technical documents\ "
"to extract key use cases such as device onboarding, configuration\ "
"compliance, and software upgrades.\ "
"Anything that an action or result is not Device or Network Service related, should not be included as use case.\ "
),
allow_delegation=False,
memory=memory_set, # Enable memory to store file list for Agent 2
verbose=True,
llm=bridgeit_llm
)
use_case_task = Task(
name="Use Case Identification Task",
description=(""" Read the provided document and identify IT-related use cases such as
'Device Onboarding,' 'Configuration Compliance,' 'Software Upgrade,'
or similar. Extract and provide a brief description of each use case """
),
agent=UseCaseAgent,
expected_output="A structured list of identified IT use cases with summaries.",
output_pydantic=UseCaseSection,
output_file="UseCaseReport.md",
context= [read_file_task],
sync_mode=True
)
crew = Crew(
agents=[PopulateCredentials, FileBrowser, FileReader, UseCaseAgent, SummarizationAgent, Formatter],
tasks=[assign_credentials_task, list_files_task, read_file_task,use_case_task, summarize_task, formatting_task],
manager_agent=RequestHandler,
process=Process.hierarchical,
verbose=True,
)
print("Inputs to Crew:", params_agent)
result = crew.kickoff(inputs=params_agent)
Any guidance or ideas on where the problem might reside will greatly help.
I really appreciate any help you can provide.
Adrian