解决AttributeError: 'AIMessage' object has no attribute 'strip' | 豆包MarsCode AI刷题

242 阅读5分钟

一、快速解决 AttributeError: 'AIMessage' object has no attribute 'strip'

博主在学习LangChain实战课第4课:Langchain的输出解析部分时直接复制了课程提供的代码,并将模型换成了国内可以使用的ChatGLM后,遇到了AttributeError: 'AIMessage' object has no attribute 'strip' 的错误,意思是我们传递给 output_parser.parse 的对象 output 是一个 AIMessage 对象,而不是预期的str字符串对象。如图所示。

image.png 下面是替换的代码,将原代码中的

# 获取模型的输出
output = model.invoke(input)
# 解析模型的输出
parsed_output = output_parser.parse(output)

替换成

# 获取模型的输出
output = model.invoke(input)
output_content = output.content
# 解析模型的输出(这是一个字典结构)
parsed_output = output_parser.parse(output_content)

就能实现正常的运行了,结果如下,非常的nice

image.png

二、原理解析

下面根据大模型的回答,结合控制台的输出给大家详细阐述一下原因。

您好!很高兴听到您已经取得了一些进展,并且发现了关键步骤 output_content = output.content 的重要性。让我详细分析一下为什么这一步骤能够解决您的问题,以及背后的原因和机制。

问题背景回顾

在您的原始代码中,您试图通过以下方式解析模型的输出:

parsed_output = output_parser.parse(output)

然而,这导致了以下错误:

AttributeError: 'AIMessage' object has no attribute 'strip'

这个错误表明,您传递给 output_parser.parse 的对象 output 是一个 AIMessage 对象,而不是预期的字符串。

为什么 output.content 是关键

1. 理解 model.invoke(input) 的返回值(即output)

在使用 LangChain 或类似的库调用语言模型时,model.invoke(input) 方法通常会返回一个包含模型响应的对象。这些响应对象不仅包含生成的文本,还可能包含其他元数据,例如生成时间、使用的模型版本等。

具体到您的情况,ChatZhipuAI 模型的 invoke 方法返回的是一个 AIMessage 对象。这个对象的结构可能如下:

class AIMessage:
    def __init__(self, content, other_metadata):
        self.content = content
        # 其他属性
  • content 属性:包含模型生成的实际文本内容,这是您需要解析的部分。
  • 其他属性:可能包括模型生成时间、token 使用量等。
  • 实际下,output输出如下:

content='json\n{\n\t"description": "50元,玫瑰的浪漫,爱情的物语。珍爱每一份深情,让这束玫瑰为您诉说无尽爱意。",\n\t"reason": "这个文案强调了玫瑰作为爱情象征的重要性,同时突出了价格优势,以吸引消费者的注意力。通过使用\'浪漫\'和\'爱意\'这样的词汇,增强了文案的情感吸引力,使得潜在顾客感受到购买这束玫瑰的价值不仅仅是花朵本身,更是一份深厚的情感表达。"\n}\n' response_metadata={'token_usage': {'completion_tokens': 103, 'prompt_tokens': 97, 'total_tokens': 200}, 'model_name': 'glm-4', 'finish_reason': 'stop'} id='run-1443ed20-ce5f-4c94-bbf4-bce50506084c-0'

content='json\n{\n\t"description": "清新脱俗,30元即可拥抱高雅百合,为生活添一抹纯美诗意。",\n\t"reason": "这个文案强调了百合花的高雅和价格的亲民,同时传达了购买鲜花能带来的生活品质提升,‘清新脱俗’和‘纯美诗意’两个词组旨在唤起人们对美好生活的向往。"\n}\n' response_metadata={'token_usage': {'completion_tokens': 83, 'prompt_tokens': 95, 'total_tokens': 178}, 'model_name': 'glm-4', 'finish_reason': 'stop'} id='run-3c01ef0a-1334-46c6-98c5-0d6b337f394d-0'

content='json\n{\n\t"description": "仅需20元,将爱与敬意融入一束温馨的康乃馨,为特殊之人送上不凡之情。",\n\t"reason": "这个文案突出了康乃馨的价格优势,同时强调了它作为表达爱与敬意的载体,能够传递深厚的情感,吸引顾客为之买单。"\n}\n' response_metadata={'token_usage': {'completion_tokens': 72, 'prompt_tokens': 96, 'total_tokens': 168}, 'model_name': 'glm-4', 'finish_reason': 'stop'} id='run-e7fca1c4-74fc-4241-8a2c-f128048001a2-0'

发现除了我们需要的content外,还存在大量的其它参数,而在output这里,实际上我们只需要处理content这部分内容就能完成输出的解析,其它信息是冗余的,所以这就是为什么只需要取出content的原因。

2. StructuredOutputParser.parse 的预期输入

StructuredOutputParser.parse 方法设计用于接收一个 字符串 作为输入,并将其解析为结构化的数据(例如字典或特定的格式)。它依赖于输入文本的格式来提取所需的信息。

当您将一个 AIMessage 对象直接传递给 parse 方法时,Python 尝试在该对象上调用 strip 方法(这是字符串对象的一个常用方法),但 AIMessage 对象本身并没有 strip 方法,这就导致了 AttributeError

3. 提取 content 属性解决问题

通过访问 output.content,您从 AIMessage 对象中提取出了模型生成的实际文本字符串:

output_content = output.content

然后,将这个字符串传递给 parse 方法:

parsed_output = output_parser.parse(output_content)

这样,parse 方法接收到的是预期的字符串输入,能够正常工作,并按照定义的 ResponseSchema 解析出所需的结构化数据。