You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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对象,不能通过下标([])访问属性,需改用点属性访问。

修改步骤

  1. 调整_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,
        },
    )
  1. 优化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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 21:26:27