使用图表和幻灯片放映
Claude 非常擅长处理图表、图形和更广泛的幻灯片放映。根据您的用例,您可以利用一些技巧和窍门。本示例将向您展示使用 Claude 处理这些材料的常见模式。
图表和图形
在大多数情况下,将 Claude 与图表和图形结合使用非常简单。让我们逐步介绍如何摄取它们并将它们传递给 Claude,以及一些改进结果的常用技巧。
摄取和调用 Claude API
将图表和图形传递给 Claude 的最佳方法是利用其视觉能力和 PDF 支持功能。也就是说,给 Claude 提供图表或图形的 PDF 文档,以及有关它的文本问题。
目前,只有 claude-3-5-sonnet-20241022
支持 PDF 功能。由于该功能仍处于测试阶段,因此您需要为其提供 pdfs-2024-09-25
测试版标头。
# 安装并创建 Anthropic 客户端。
%pip install anthropic
import base64
from anthropic import Anthropic
# 尽管 PDF 支持仍处于测试阶段,但您必须提供正确的测试版标头
client = Anthropic(default_headers={
"anthropic-beta": "pdfs-2024-09-25"
}
)
# 目前,只有 claude-3-5-sonnet-20241022 支持 PDF
MODEL_NAME = "claude-3-5-sonnet-20241022"
# 创建一个有用的辅助函数。
def get_completion(messages):
response = client.messages.create(
model=MODEL_NAME,
max_tokens=8192,
temperature=0,
messages=messages
)
return response.content[0].text
# 首先,我们需要一个 PDF。我们将使用位于 cvna_2021_annual_report.pdf 的 .pdf 文档。
# 首先读取 PDF 并将其编码为 base64。
with open("./documents/cvna_2021_annual_report.pdf", "rb") as pdf_file:
binary_data = pdf_file.read()
base_64_encoded_data = base64.b64encode(binary_data)
base64_string = base_64_encoded_data.decode('utf-8')
让我们看看如何将此文档与简单问题一起传递给模型。
messages = [
{
"role": 'user',
"content": [
{"type": "document", "source": {"type": "base64", "media_type": "application/pdf", "data": base64_string}},
{"type": "text", "text": "这个文档里有什么?用一句话回答。"}
]
}
]
print(get_completion(messages))
这是来自 Carvana 2021 年年度报告的一页,显示了四个关键指标:零售销量、总收入、年末总市场和汽车自动售货机,所有这些指标都显示出从 2014 年到 2021 年的显著增长。
这很不错!现在让我们问一些更有用的问题。
questions = [
"CVNA 2020 年的收入是多少?",
"自 2014 年以来,Carvana 增加了多少个市场?",
"2016 年每零售单位的销售收入是多少?"
]
for index, question in enumerate(questions):
messages = [
{
"role": 'user',
"content": [
{"type": "document", "source": {"type": "base64", "media_type": "application/pdf", "data": base64_string}},
{"type": "text", "text": question}
]
}
]
print(f"\n----------问题 {index+1}----------")
print(get_completion(messages))
----------问题 1---------- 根据显示总收入(百万美元)的图表,Carvana 2020 年的收入为 55.87 亿美元(或约 55.9 亿美元)。
----------问题 2---------- 根据“年末总市场”图表,Carvana 于 2014 年开始有 4 个市场,到 2021 年增长到 311 个市场。因此,自 2014 年以来,Carvana 增加了 307 个市场(311 - 4 = 307 个额外市场)。
----------问题 3---------- 我来为您计算一下:
2016 年收入:3.65 亿美元 2016 年零售销量:18,761 台
3.65 亿美元 ÷ 18,761 台 = 19,455 美元/台(四舍五入到最接近的美元)
因此,在 2016 年,Carvana 的每零售单位销售收入约为 19,455 美元。
如您所见,Claude 能够回答有关图表和图形的相当详细的问题。但是,有一些技巧可以帮助您充分利用它。
- 有时 Claude 的算术能力会碍事。您会注意到,如果您对上述第三个问题进行采样,它有时会输出不正确的最终答案,因为它会弄乱算术。请考虑为 Claude 提供计算器工具,以确保它不会犯这类错误。
- 对于非常复杂的图表和图形,我们可以要求 Claude “首先描述您在文档中看到的每个数据点”,以此来引发类似于传统思维链的改进。
- Claude 有时会难以处理依赖多种颜色来传达信息的图表,例如具有多个分组的组合条形图。要求 Claude 首先使用 HEX 代码识别图表中的颜色可以提高其准确性。
幻灯片放映
既然我们知道 Claude 是图表和图形的专家,那么将其扩展到图表和图形的真正归宿——幻灯片放映——是合乎逻辑的!
幻灯片是许多领域(包括金融服务)的关键信息来源。虽然您可以使用 PyPDF 等包从幻灯片中提取文本,但它们繁重的图表/图形特性通常会使此方法效果不佳,因为模型会难以访问它们实际需要的信息。
PDF 支持功能可以很好地替代此功能。它在处理 PDF 文档时同时使用提取的文本和视觉元素。在本节中,我们将介绍如何将 PDF 文档用于 Claude 来查看幻灯片放映,以及如何处理此方法的一些常见陷阱。
将典型的幻灯片放映放入 Claude 的最佳方法是将其下载为 PDF 并直接提供给 Claude。
# 以与之前相同的方式打开多页 PDF 文档。
with open("./documents/twilio_q4_2023.pdf", "rb") as pdf_file:
binary_data = pdf_file.read()
base_64_encoded_data = base64.b64encode(binary_data)
base64_string = base_64_encoded_data.decode('utf-8')
# 现在我们将文档直接传递给 Claude。请注意,Claude 将处理文档的文本和视觉元素。
question = "Twilio 2023 财年的同比收入增长是多少?"
content = [
{"type": "document", "source": {"type": "base64", "media_type": "application/pdf", "data": base64_string}},
{"type": "text", "text": question}
]
messages = [
{
"role": 'user',
"content": content
}
]
print(get_completion(messages))
根据演示文稿中显示的财务业绩,Twilio 2023 财年的同比增长收入增长为 9%。这可以在“公司整体业绩亮点”部分找到,其中显示 2023 财年收入增长为 9%。
这种方法是一个很好的起点,并且对于某些用例而言,它提供了最佳性能。但是,存在一些限制。
- 您在请求中包含的文档总数最多只能包含 100 页(我们打算随着时间的推移增加此限制)。
- 如果您将幻灯片内容用作 RAG 的一部分,将多模态 PDF 引入嵌入可能会导致问题
幸运的是,我们可以利用 Claude 的视觉能力来获得比普通 PDF 文本提取更好的幻灯片放映文本表示。
我们发现最好的方法是要求 Claude 顺序地从头到尾叙述演示文稿,将当前幻灯片和之前的叙述传递给它。让我们看看如何操作。
# 定义一个用于叙述我们幻灯片放映的提示。我们会根据演示文稿的性质调整此提示,但基本结构保持不变。
prompt = """
您是 Twilio 的首席财务官,正在叙述您的 2023 年第四季度财报演示文稿。
已向您提供整个财报演示文档。
请像演示者一样,从 Twilio 的 2023 年第四季度财报开始叙述此演示文稿。如果您不确定某个缩写词的确切含义,请不要提及它。
不要遗漏任何细节,因为您的一些观众有视力障碍,所以如果您不叙述每个数字,他们将不知道该数字。
请按以下结构组织您的回复:
<narration>
<page_narration id=1>
[您对第 1 页的叙述]
</page_narration>
<page_narration id=2>
[您对第 2 页的叙述]
</page_narration>
... 以此类推,涵盖每一页
</narration>
请对每一页都提供极其详细的描述,确保您描述了所有出现的视觉元素和数字。一次性显示完整回复。
"""
messages = [
{
"role": 'user',
"content": [
{"type": "document", "source": {"type": "base64", "media_type": "application/pdf", "data": base64_string}},
{"type": "text", "text": prompt}
]
}
]
# 现在我们使用提示来叙述整个演示文稿。请注意,这可能需要几分钟才能运行(通常最多 10 分钟)。
completion = get_completion(messages)
import re
# 接下来,我们将使用正则表达式解析 Claude 的回复
pattern = r"<narration>(.*?)</narration>"
match = re.search(pattern, completion.strip(), re.DOTALL)
if match:
narration = match.group(1)
else:
raise ValueError("无法获取叙述。可能是因为模型响应被截断。")
现在我们有了基于文本的叙述(虽然不完美,但相当不错),我们可以将此演示文稿用于任何仅文本的工作流。包括向量搜索!
作为最后的健全性检查,让我们在仅叙述的设置中问几个问题!
questions = [
"第四季度总收入中,细分业务线的收入占多大百分比?",
"季度收入的增长率是在增加还是在减少?只给一个答案。",
"截至 2023 年 12 月 31 日的年度收购收入是多少(包括负收入)?"
]
for index, question in enumerate(questions):
prompt = f"""您是一位专业的财务分析师,正在分析 Twilio 财报电话会议的文字记录。
这是文字记录:
<transcript>
{narration}
</transcript>
请回答以下问题:
<question>
{question}
</question>"""
messages = [
{
"role": 'user',
"content": [
{"type": "text", "text": prompt}
]
}
]
print(f"\n----------问题 {index+1}----------")
print(get_completion(messages))
----------问题 1---------- 我来计算一下:
2023 年第四季度细分收入:7500 万美元 2023 年第四季度总收入:10.76 亿美元
7500 万美元 ÷ 10.76 亿美元 = 0.0697 或约 7%
因此,细分业务线约占 Twilio 2023 年第四季度总收入的 7%。
----------问题 2---------- 减少。文字记录显示,2023 年第四季度的收入增长率为 5%(同比增长),而 2023 年全年的收入增长率为 9%(同比增长),这表明增长率正在放缓。此外,2024 年第一季度的预测甚至更低的增长率(同比增长 2-3%),证实了下降趋势。
----------问题 3---------- 我来帮助计算一下 2023 年的收购收入。
从文字记录中我们可以看到:
- 2023 年总收入:41.54 亿美元
- 2023 年有机收入:41.46 亿美元
因此,收购收入为: 总收入 - 有机收入 = 41.54 亿美元 - 41.46 亿美元 = 800 万美元
因此,截至 2023 年 12 月 31 日的年度收购收入为 800 万美元。
这可以通过总收入增长率(9%)和有机收入增长率(10%)之间的差异也表明收购的贡献很小来验证。
看起来不错!有了这些技巧,您就可以开始将模型应用于像幻灯片这样的图表和图形密集型内容了。