修复LangChain调用MistralAI Agent多轮对话的400错误
错误信息
HTTPStatusError: Error response 400 while fetching https://api.mistral.ai/v1/chat/completions: {"object":"error","message":"Expected last role User or Tool (or Assistant with prefix True) for serving but got assistant","type":"invalid_request_message_order","param":null,"code":"3230"}
During task with name 'model' and id '61e16c9d-830c-9496-12da-acafb10a9a50'
用户代码
from langchain.chat_models import init_chat_model model = init_chat_model( "mistralai:mistral-small-latest", temperature=0.7, timeout=10, max_tokens=1000 ) from langchain.agents import create_agent agent = create_agent( model = model, system_prompt = system_prompt, tools = [get_user_location, get_weather_for_location], context_schema = Context, response_format = ResponseFormat, checkpointer = checkpointer ) def invoke_agent_stateful(agent, user_input: str, user_id: str): config = {"configurable": {"thread_id": f"{user_id}"}} response = agent.invoke( {"messages": [{"role": "user", "content": f"{user_input}"}]}, config=config, context=Context(user_id=user_id) ) return response['structured_response'] invoke_agent_stateful(agent, user_input="what is the weather?", user_id="1") # 首次调用输出正常 invoke_agent_stateful(agent, user_input="where am i?", user_id="1") # 调用出现错误
问题根源
Mistral API要求对话历史的角色顺序必须严格交替(User ↔ Assistant),或在工具调用场景下遵循User → Tool → Assistant的顺序。第二次调用时,对话历史的最后一条重复出现了Assistant角色,导致API返回格式错误。
修复方案
1. 保留完整Agent响应,确保状态正确更新
你的函数只返回了结构化响应,但Agent的完整输出包含更新对话历史的关键信息。修改函数,让checkpointer自动处理状态更新:
def invoke_agent_stateful(agent, user_input: str, user_id: str): config = {"configurable": {"thread_id": f"{user_id}"}} # 保留完整响应,确保checkpointer正确保存对话状态 full_response = agent.invoke( {"messages": [{"role": "user", "content": f"{user_input}"}]}, config=config, context=Context(user_id=user_id) ) # 按需提取结构化响应 return full_response['structured_response']
2. 显式包装Agent的消息历史管理
如果checkpointer配置存在问题,显式用RunnableWithMessageHistory包装Agent,确保对话历史顺序正确:
from langchain_core.runnables.history import RunnableWithMessageHistory from langchain_core.chat_history import InMemoryChatMessageHistory # 内存存储对话历史,实际场景可替换为数据库等持久化方案 chat_history_store = {} def get_session_history(session_id: str): if session_id not in chat_history_store: chat_history_store[session_id] = InMemoryChatMessageHistory() return chat_history_store[session_id] # 用消息历史包装Agent agent_with_history = RunnableWithMessageHistory( agent, get_session_history, input_messages_key="messages", history_messages_key="history", ) def invoke_agent_stateful(agent, user_input: str, user_id: str): config = {"configurable": {"session_id": f"{user_id}"}} response = agent_with_history.invoke( {"messages": [{"role": "user", "content": f"{user_input}"}]}, config=config, context=Context(user_id=user_id) ) return response['structured_response']
3. 验证对话历史格式
在调用前可以打印当前对话历史,确认角色顺序是否正确:
# 示例:获取并打印对话历史 history = get_session_history("1") print([msg.dict() for msg in history.messages])
确保输出的角色顺序是user → assistant → user...,没有连续的assistant角色。
内容的提问来源于stack exchange,提问作者Gokul Krishna Balaji

