pydantic-ai
pydantic-ai copied to clipboard
An assistant message with 'tool_calls' must be followed by tool messages
A weird error is showing on an agent that runs multiple times in parallel
research_agent = Agent(
model="openai:gpt-4o-mini",
name="research_agent",
deps_type=ResearchDependencies,
result_type=ResearchResult,
retries=3,
)
Error message
Error code: 400 - {'error': {'message': "An assistant message with 'tool_calls' must be followed by tool messages responding to each 'tool_call_id'. The following tool_call_ids did not have response messages: call_peVwb5yZhjdZ3xtJZAX8dDRV", 'type': 'invalid_request_error', 'param': 'messages', 'code': None}}
any idea why it could happen?
I think this might be fixed in the latest pydantic-ai, what version are you using?
If it's still occurring with the latest version, I would need an MRE to be able to look into this further.
I think this might be fixed in the latest pydantic-ai, what version are you using?
If it's still occurring with the latest version, I would need an MRE to be able to look into this further.
I was on 0.0.15 and was getting the same error. I've upgraded to 0.0.16 and it appears to be fixed.
I keep on getting this error as well, seems volatile.
Using pydantic-ai 0.0.17.
Downgraded to 0.0.16 and still have the same experience. For some cases it works, others it fails, only difference is the input_data per row in the dataframe. The input data is not the problem as this runs on langchain and has sufficient volume.
Errors:
Error code: 400 - {'error': {'message': "An assistant message with 'tool_calls' must be followed by tool messages responding to each 'tool_call_id'. The following tool_call_ids did not have response messages: call_8DeVnHtAruahS0pOkggrfUkA", 'type': 'invalid_request_error', 'param': 'messages', 'code': None}}
Error code: 400 - {'error': {'message': "An assistant message with 'tool_calls' must be followed by tool messages responding to each 'tool_call_id'. The following tool_call_ids did not have response messages: call_qO2nOccG4MBRyx1OOdql3YgA", 'type': 'invalid_request_error', 'param': 'messages', 'code': None}}
Code below:
from typing_extensions import NotRequired, TypedDict
from pydantic import Field
import pandas as pd
import numpy as np
from src.utils import load_yaml_from_file
from src.utils_ai import *
from schemas.gpt.animal import Animal
from pydantic import BaseModel
from pydantic_ai import RunContext, ModelRetry
from pydantic_ai.settings import ModelSettings
class ThemeCount(TypedDict):
theme: Annotated[str, Field(description="The specific theme")]
count: Annotated[int, Field(description="Number of times this theme appears")]
class AnimalThemes(TypedDict):
themes: Annotated[List[ThemeCount], Field(
description="The underlying themes associated with this animal and their counts"
)]
count: Annotated[int, Field(description="Number of times this animal appears")]
class AnimalStats(TypedDict):
total_count: Annotated[int, Field(description="Total number of animals in this category")]
animals: Annotated[Dict[str, AnimalThemes], Field(
description="Dictionary mapping animals to their themes and counts"
)]
class Animal(TypedDict):
positive_animals: Annotated[AnimalStats, Field(
description="Statistics and details for positively mentioned animals"
)]
negative_animals: NotRequired[Annotated[AnimalStats, Field(
description="Statistics and details for negatively mentioned animals"
)]]
# CONFIGURE AGENT
extract_config = load_yaml_from_file("prompts/sys-extract-analytics.yml")
model_settings = ModelSettings(
temperature=extract_config['model_temperature']
)
model_provider_name = extract_config['model_provider_name']
model_type = extract_config['model_type']
if model_provider_name == 'openai':
model_name = f"{model_provider_name}:{model_type}"
else:
model_name = model_type
model_name = cast(KnownModelName, model_name)
class InputData(BaseModel):
survey_question: str
answers: str
analytics_agent = Agent(
model=model_name,
system_prompt=extract_config['prompt'],
retries=10,
result_type=Animal,
deps_type=InputData,
model_settings=model_settings
)
@analytics_agent.system_prompt
def add_input_data(ctx: RunContext[InputData]) -> str:
return f"Questions asked: {ctx.deps.survey_question}, Answers: {ctx.deps.answers}"
@analytics_agent.result_validator
def validate_result(ctx: RunContext[None], result: Animal) -> Animal:
try:
if result['negative_animals']['total_count'] == 0 and result['positive_animals']['total_count'] == 0:
raise ModelRetry(
"No analytics returned, reflect on what went wrong and correct it, there is underlying data to construct an analysis from."
)
except (KeyError, TypeError) as e:
raise ModelRetry(
"Invalid result structure. Please ensure both positive and negative animals are included with their counts."
)
return result
user_prompt = load_yaml_from_file("prompts/user-animal.yml")['prompt']
df = pd.read_csv("data/gpt-input.csv")
df['success'] = 0
out_df = pd.DataFrame()
for row_index, row in df.iterrows():
if row['success'] == 0:
report_name = row['report_name']
report_section_name = row['report_section_name']
input_data = InputData(survey_question=row['question_and_previous_question'], answers=row['data'])
try:
response = analytics_agent.run_sync(user_prompt=user_prompt, deps=input_data)
tmp_df = pd.DataFrame(flatten_animal_data(response.data))
tmp_df['report_name'] = report_name
tmp_df['report_section_name'] = report_section_name
out_df = pd.concat([out_df, tmp_df], axis=0)
df.loc[row_index, 'success'] = 1
except Exception as e:
print(f"Failed for {report_name}:{report_section_name} with error: {e}")```
This issue is stale, and will be closed in 3 days if no reply is received.
I also keep seeing this on 0.0.19. It is not consistent. I see it on 1 out of 3 runs.
I got same. in 0.0.17 and 0.0.19
Seeing the same, v0.0.20 for what I would expect to be a simple straightforward use case.
some_agent = Agent(
'openai:gpt-4o',
deps_type=InputType,
result_type=ActionsDict,
system_prompt=prompt,
tools=[]
)
and variants (without deps_type, without tools, simplified ActionsDict pydantic, etc).
Same here for v0.0.20
def change_language(conversation: ConversationParts) -> LanguageChangeResponse:
change_language_agent = Agent(
'openai:gpt-4o',
result_type=Language,
system_prompt=CHANGE_LANGUAGE_PROMPT,
)
return change_language_agent.run_sync(str(conversation)).data
Very strange, it is not happening in other agents that I have in the same project, just in this one
Adding parallel_tool_calls=False in the model_settings in the Agent definition on v0.0.20 seems to fix the problem.
model_settings=dict(parallel_tool_calls=False)
Maybe just one more data point, I also encounter this primarily when running Agent.run_sync with nested result_type models, only when using OpenAI LLMs (not when using Anthropic LLMs). model_settings=dict(parallel_tool_calls=False) does indeed help.
Same, it feels like nested result_type calls with OpenAI LLMs are more likely to cause issues.
I am using version 0.0.24 and noticed this error as well.
In my case, it was caused by the agent calling a tool that was not defined. I forgot the tool name in the prompt but didn't provide the tool to the agent.
The minimal repro looks like this:
def calculate(text: str) -> str:
return f"Calculated: {text}"
model = OpenAIModel("gpt-4o-mini", openai_client=client)
agent = Agent(
model,
tools=[calculate],
system_prompt="Check the user question, if the user is asking for help you MUST call the tool `validate_query`",
)
result = await agent.run("How you can help me?")
assert result is not None
There must be a tool assigned to the agent otherwise, the agent will not try to call it.
Another reason is that when the tool call is valid in the model's view, but invalid in pydantic_ai's view, pydantic_ai will append a plain text error message, not a tool result message.
e.g. https://github.com/pydantic/pydantic-ai/blob/dfc919c686212b92e45069a926e6cd37be74ca3f/pydantic_ai_slim/pydantic_ai/_agent_graph.py#L484
Seeing the same error. Could it be because of parallel tool calls as shown here https://github.com/langchain-ai/langchain/discussions/23733
Can someone in this long issue give me an MRE that I reproduce?