使用Llama Index调用OpenAI工具时遇TypeError: 'ChatCompletionMessageToolCall'不可下标访问
问题描述
我正在遵循Llama Index的文档开发,但文档似乎已过时(LLM领域这种情况很普遍)。我查了OpenAI文档,没找到合适的API,可能漏了内容?
运行main.py时输出如下:
Hello! How can I assist you today? Traceback (most recent call last): File "/Users/me/Documents/openai-agent/main.py", line 80, in <module> print(agent.chat("What is 2123 * 215123")) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/me/Documents/openai-agent/main.py", line 54, in chat function_message = self._call_function(tool_call) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/me/Documents/openai-agent/main.py", line 62, in _call_function id_ = tool_call["id"] ~~~~~~~~~^^^^^^ TypeError: 'ChatCompletionMessageToolCall' object is not subscriptable
相关代码:
from typing import Sequence, List from dotenv import load_dotenv import json from llama_index.llms.openai import OpenAI from llama_index.core.llms import ChatMessage from llama_index.core.tools import BaseTool, FunctionTool import nest_asyncio nest_asyncio.apply() load_dotenv() def multiply(a: int, b: int) -> int: """Multiplies two integers and returns the result integer""" return a * b multiply_tool = FunctionTool.from_defaults(fn=multiply) def add(a: int, b: int) -> int: """Adds two integers and returns the result integer""" return a + b add_tool = FunctionTool.from_defaults(fn=add) class MyOpenAIAgent: def __init__( self, tools: Sequence[BaseTool] = [], llm: OpenAI = OpenAI(temperature=0, model="gpt-3.5-turbo-0613"), chat_history: List[ChatMessage] = [], ) -> None: self._llm = llm self._tools = {tool.metadata.name: tool for tool in tools} self._chat_history = chat_history def reset(self) -> None: self._chat_history = [] def chat(self, message: str) -> str: chat_history = self._chat_history chat_history.append(ChatMessage(role="user", content=message)) tools = [ tool.metadata.to_openai_tool() for _, tool in self._tools.items() ] ai_message = self._llm.chat(chat_history, tools=tools).message additional_kwargs = ai_message.additional_kwargs chat_history.append(ai_message) tool_calls = ai_message.additional_kwargs.get("tool_calls", None) # parallel function calling is now supported if tool_calls is not None: for tool_call in tool_calls: function_message = self._call_function(tool_call) chat_history.append(function_message) ai_message = self._llm.chat(chat_history).message chat_history.append(ai_message) return ai_message.content def _call_function(self, tool_call: dict) -> ChatMessage: id_ = tool_call["id"] function_call = tool_call["function"] tool = self._tools[function_call["name"]] output = tool(**json.loads(function_call["arguments"])) return ChatMessage( name=function_call["name"], content=str(output), role="tool", additional_kwargs={ "tool_call_id": id_, "name": function_call["name"], }, ) if __name__ == "__main__": agent = MyOpenAIAgent(tools=[multiply_tool, add_tool]) print(agent.chat("Hi")) print(agent.chat("What is 2123 * 215123"))
调用工具时触发上述TypeError,请问该如何解决?
解决方案
错误核心原因是:当前使用的Llama Index版本中,tool_call不再是字典类型,而是ChatCompletionMessageToolCall对象,不能通过下标([])访问属性,需改用点属性访问。
修改步骤
- 调整
_call_function方法
将字典下标访问改为点属性访问,且arguments已自动解析为字典,无需json.loads:
def _call_function(self, tool_call) -> ChatMessage: id_ = tool_call.id function_call = tool_call.function tool = self._tools[function_call.name] output = tool(**function_call.arguments) return ChatMessage( name=function_call.name, content=str(output), role="tool", additional_kwargs={ "tool_call_id": id_, "name": function_call.name, }, )
- 优化
chat方法中tool_calls的获取逻辑
新版本中ai_message直接提供tool_calls属性,无需从additional_kwargs读取:
def chat(self, message: str) -> str: chat_history = self._chat_history chat_history.append(ChatMessage(role="user", content=message)) tools = [ tool.metadata.to_openai_tool() for _, tool in self._tools.items() ] ai_message = self._llm.chat(chat_history, tools=tools).message chat_history.append(ai_message) # 直接从ai_message获取tool_calls tool_calls = ai_message.tool_calls if tool_calls is not None: for tool_call in tool_calls: function_message = self._call_function(tool_call) chat_history.append(function_message) ai_message = self._llm.chat(chat_history).message chat_history.append(ai_message) return ai_message.content
改动说明
- 属性访问方式变化:
ChatCompletionMessageToolCall对象将id、function作为实例属性,用.代替[]访问 arguments无需JSON解析:已自动转为字典,省去json.loads步骤tool_calls获取路径优化:直接从ai_message.tool_calls读取,避免依赖过时的additional_kwargs结构
内容的提问来源于stack exchange,提问作者somethingsomethingswift
相关产品推荐
相关产品推荐

