在金融服务行业,投资组合经理和研究分析师努力筛选大量数据,以在投资中获得竞争优势,做出明智的决策需要访问最相关的数据,并能够快速合成和解释这些数据。
传统上,卖方分析师和基本投资组合经理会专注于一小部分公司,仔细检查财务报表、盈利通知和公司文件。通过系统分析更大的交易领域的金融文档可以发现更多见解。由于此类任务的技术和算法难度,直到最近,只有成熟的量化交易公司才能对广泛的交易领域的转录进行系统分析。
与大型语言模型(LLM)在金融 NLP 任务中的功能相比,使用传统自然语言处理(NLP)方法(如词袋、情感字典和词统计)完成这些任务的性能通常低于大型语言模型(LLM)。此外,LLM还在医学文档理解、新闻文章摘要和法律文档检索等领域展示了出色的性能。
借助 AI 和 NVIDIA 技术,卖方分析师、基础交易员和零售交易员可以显著加速其研究工作流程,从金融文档中提取更细致入微的见解,并覆盖更多的公司和行业。通过采用这些先进的 AI 工具,金融服务部门可以增强数据分析能力,节省时间并提高投资决策的准确性。根据 NVIDIA 2024 金融服务业 AI 现状 调查报告,37% 的受访者正在探索用于报告生成、合成和投资研究的生成式 AI 和 LLM,以减少重复性手动工作。
在本文中,我们将向您展示一个端到端演示,介绍如何构建 AI 助手,以使用 NVIDIA NIM 推理微服务从收益电话会议成绩单中提取见解,从而实现一个 检索增强生成(RAG) 系统。我们将重点介绍如何利用先进的 AI 技术加速工作流程,发现隐藏的见解,并最终增强金融服务行业的决策流程。
使用 NIM 分析收益电话记录的转录
收益电话会议尤其是投资者和分析师的重要来源,为公司提供了沟通重要财务和业务信息的平台,这些电话会议提供了有关行业、公司产品、竞争对手以及最重要的业务前景的见解。
通过分析收益电话会议成绩单,投资者可以收集有关公司未来收益和估值的宝贵信息。收益电话会议成绩单已成功用于生成 Alpha 二十多年来。有关更多详细信息,请参阅自然语言处理 – 第一部分:基础知识和自然语言处理 – 第二部分:股票选择。
第 1 步:数据
在此演示中,我们使用 2016 年至 2020 年期间 NASDAQ 财报电话会议的成绩单进行分析。这份财报电话会议成绩单数据集可从 Kaggle 下载。
在评估中,我们使用了由 10 家公司组成的子集,然后随机选择了 63 份文稿进行手动注释。对于所有文稿,我们回答了以下问题:
- 公司的主要收入来源是什么?在过去一年中,这些来源有何变化?
- 公司的主要成本构成是什么?在报告期间,这些成本构成有何波动?
- 有哪些资本支出?这些支出如何支持公司的发展?
- 执行了哪些分红或股票回购?
- 成绩单中提到了哪些重大风险?
这总共会生成 315 个问答对,全都是使用结构化的JSON 格式回答的。例如:
问题:公司的主要收入来源是什么?在过去一年中,这些来源有何变化?
答案:
{
"Google Search and Other advertising": {
"year_on_year_change": "-10%",
"absolute_revenue": "21.3 billion",
"currency": "USD"
},
"YouTube advertising": {
"year_on_year_change": "6%",
"absolute_revenue": "3.8 billion",
"currency": "USD"
},
"Network advertising": {
"year_on_year_change": "-10%",
"absolute_revenue": "4.7 billion",
"currency": "USD"
},
"Google Cloud": {
"year_on_year_change": "43%",
"absolute_revenue": "3 billion",
"currency": "USD"
},
"Other revenues": {
"year_on_year_change": "26%",
"absolute_revenue": "5.1 billion",
"currency": "USD"
}
}
使用 JSON 可以在不依赖主观语言理解方法的情况下评估模型性能,这些方法如 LLM 作为判断,可能会在评估中引入不必要的偏差。
第 2 步:NVIDIA NIM
此演示使用 NVIDIA NIM,这是一套旨在加速企业 生成式 AI 部署的微服务。有关更多详细信息,请参阅 NVIDIA NIM 提供用于大规模部署 AI 模型的优化推理微服务。NIM 支持各种 AI 模型(包括 NVIDIA 优化的社区和商业合作伙伴模型),可确保利用行业标准 API 在本地或云端进行无缝、可扩展的 AI 推理。
准备投入生产时,NIM 只需一个命令即可部署,以便使用标准 API 和几行代码轻松集成到企业级 AI 应用程序中。基于包括 NVIDIA TensorRT、TensorRT-LLM 和 PyTorch 等推理引擎在内的可靠基础构建,NIM 旨在基于底层硬件提供出色的开箱即用性能,从而实现无缝 AI 推理。同时,具有 NIM 的自托管模型支持保护客户和企业数据,这是 RAG 应用程序的常见要求。
第 3 步:在 NVIDIA API 目录上设置
可以使用 NVIDIA API 目录访问 NIM。只需注册 NVIDIA API 密钥(在 API 目录中,单击“获取 API 密钥”即可进行设置:API catalog)。在本文中,我们将其存储在环境变量中:
export NVIDIA_API_KEY=YOUR_KEY
LangChain 提供了一个便于 NGC 集成的软件包。本教程将使用端点运行嵌入、重新排序和聊天模型,以 NIM 为对象。要重现代码,您需要安装以下 Python 依赖项:
langchain-nvidia-ai-endpoints==0.1.2
faiss-cpu==1.7.4
langchain==0.2.5
unstructured[all-docs]==0.11.2
第 4 步:使用 NIM 构建 RAG 管道
RAG 是一种通过将从大型语料库中检索相关文档与文本生成相结合来增强语言模型的方法。
RAG 的第一步是向量化您的文档集合。这包括将一系列文档拆分成较小的块,然后使用 Embedder 模型将每个块转换为神经网络嵌入(向量),最后将其存储在一个 向量数据库。 我们将针对每个收益调用转录执行此操作:
import os
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.document_loaders import TextLoader
from langchain.vectorstores import FAISS
from langchain_nvidia_ai_endpoints import NVIDIAEmbeddings
# Initialise the embedder that converts text to vectors
transcript_embedder = NVIDIAEmbeddings(model='nvidia/nv-embed-v1',
truncate='END'
)
# The document we will be chunking and vectorizing
transcript_fp = "Transcripts/GOOGL/2020-Feb-03-GOOGL.txt"
raw_document = TextLoader(transcript_fp).load()
# Split the document into chunks of 1500 characters each
text_splitter = RecursiveCharacterTextSplitter(chunk_size=3000,
chunk_overlap=200)
documents = text_splitter.split_documents(raw_document)
# Vectorise each chunk into a separate entry in the database
vectorstore = FAISS.from_documents(documents, transcript_embedder)
vector_store_path = "vector_db/google_transcript_2020_feb.pkl"
try:
os.remove(vector_store_path)
except OSError:
pass
vectorstore.save_local(vector_store_path)
构建矢量化数据库后,最简单的 RAG 流程如下所示:
- 用户输入查询。例如输入“What are the company’s main revenue sources?”
- The embedder 模型将查询嵌入到向量中,然后通过矢量化的文档数据库搜索最相关的 Top-K 块(例如 Top-30)。
- 然后,重新排序模型(也称为交叉编码器)会输出每个查询文档对的相似度分数。此外,元数据还可用于帮助提高重新排序步骤的准确性。此分数用于重新排序嵌入程序根据与用户查询的相关性检索的 Top-K 文档,然后可以应用进一步的过滤,仅保留 Top-N(例如 Top-10)文档。
- 然后,最相关的 Top-N 文档与用户查询一起传递到 LLM。检索到的文档用作模型的答案的背景,以便奠定基础。

请注意,可以进行修改以提高模型的答案准确性,但现在我们将继续使用最简单的稳健方法。
请考虑以下用户查询和所需的 JSON 格式:
question = "What are the company’s primary revenue streams and how have they changed over the past year?"
json_template = """
{"revenue_streams": [
{
"name": "<Revenue Stream Name 1>",
"amount": <Current Year Revenue Amount 1>,
"currency": "<Currency 1>",
"percentage_change": <Change in Revenue Percentage 1>
},
{
"name": "<Revenue Stream Name 2>",
"amount": <Current Year Revenue Amount 2>,
"currency": "<Currency 2>",
"percentage_change": <Change in Revenue Percentage 2>
},
// Add more revenue streams as needed
]
}
"""
user_query = question + json_template
将使用 JSON 模板,以便在管道后续阶段,LLM 知道输出答案时使用有效的 JSON,而非纯文本。如步骤 1 中所述,使用 JSON 可以以客观方式自动评估模型答案。如果首选更具对话式的风格,则可以删除该选项。
要使用户查询符合上下文,请初始化 Embedder 和 Reranker,以便检索相关文档并对其进行排序:
from langchain_nvidia_ai_endpoints import NVIDIARerank
from langchain.retrievers.contextual_compression import ContextualCompressionRetriever
# How many retrieved documents to keep at each step
top_k_documents_retriever = 30
top_n_documents_reranker = 5
# Initialie retriever for vector database
retriever = vectorstore.as_retriever(search_type='similarity',
search_kwargs={'k': top_k_documents_retriever})
# Add a reranker to reorder documents by relevance to user query
reranker = NVIDIARerank(model="ai-rerank-qa-mistral-4b",
top_n=top_n_documents_reranker)
retriever = ContextualCompressionRetriever(base_compressor=reranker,
base_retriever=retriever)
# Retrieve documents, rerank them and pick top-N
retrieved_docs = retriever.invoke(user_query)
# Join all retrieved documents into a single string
context = ""
for doc in retrieved_docs:
context += doc.page_content + "\n\n"
然后,在检索相关文档时,可以将它们与用户查询一起传递给 LLM。我们使用的是Llama 3 70B NIM:
from langchain_nvidia_ai_endpoints import ChatNVIDIA
PROMPT_FORMAT = """"
Given the following context:
####################
{context}
####################
Answer the following question:
{question}
using the following JSON structure:
{json_template}
For amounts don't forget to always state if it's in billions or millions and "N/A" if not present.
Only use information and JSON keys that are explicitly mentioned in the transcript.
If you don't have information for any of the keys use "N/A" as a value.
Answer only with JSON. Every key and value in the JSON should be a string.
"""
llm = ChatNVIDIA(model="ai-llama3-70b",
max_tokens=600,
temperature=0
)
llm_input = PROMPT_FORMAT.format(**{"context": context,
"question": question,
"json_template": json_template
})
answer = llm.invoke(llm_input)
print(answer.content)
运行此代码将生成针对用户查询的 JSON 结构化答案。现在可以轻松修改代码,以读取多个文稿并回答不同的用户查询。
第 5 步:评估
要评估检索步骤的性能,请使用前面描述的带注释的问答对,将真值 JSON 与预测的 JSON 逐键进行比较,考虑以下真值示例:
"Google Cloud": {
"year_on_year_change": "43%",
"absolute_revenue": "3 billion",
"currency": "N/A"
}
预测如下所示:
"Google Cloud": {
"year_on_year_change": "43%",
"absolute_revenue": "N/A",
"currency": "USD"
}
三种可能的结果是:
- 真阳性(TP): 真值和预测匹配,没有要提取的值。对于上一个示例,prediction for
year_on_year_change
是 TP。 - 误报(FP):真值为
“N/A”
,换言之,没有要提取的值,但预测会产生一个值的幻觉;例如,在前面的示例中,货币预测就是 FP。 - 假阴性(FN):真值存在,但预测未能捕获该值。在上一个示例中,prediction for
absolute_revenue
是 FP。
测量这些结果后,接下来计算以下三个主要指标:
- 回想率 = TP/ (TP + FN):高回想率意味着我们的模型会返回越来越多的相关结果。
- 精度 = TP/(TP+FP):我们的模型返回的相关结果与无关结果的比率越高,精度就越高。
- F1 分数 = (2 * 精度 * 召回) / (精度 + 召回):F1 分数是精度和召回的调和平均值。
在对某些属性进行字符串比较时,用户可能希望在匹配非数字值方面保持部分灵活性。例如,考虑有关收入来源的问题,其中一个真实答案是“数据中心”,模型输出“数据中心”。精确匹配评估会将其视为不匹配。要在这种情况下实现更可靠的评估,请使用 Python 默认的 difflib
进行模糊匹配。
import difflib
def get_ratio_match(gt_string, pred_string):
if len(gt_string) < len(pred_string):
min_len = len(gt_string)
else:
min_len = len(pred_string)
matcher = difflib.SequenceMatcher(None, gt_string, pred_string, autojunk=False)
_, _, longest_match = matcher.find_longest_match(0, min_len, 0, min_len)
# Return the ratio of match with ground truth
return longest_match / min_len
对于评估,如果字符串属性的相似度比高于 90%,则将其视为匹配。
表 1 根据我们的手动标注数据显示了两个常用开源模型系列(Mistral AI Mixtral 模型和 Meta Llama 3 模型)的结果对于这两个模型系列,降低参数数量会导致性能明显下降访问 NVIDIA API 目录,体验这些 NIM。
方法 | F1 | 精度 | 回顾 | |
Llama 3 70B | 84.4% | 91.3% | 78.5% | |
Llama 3 8B | 75.8% | 85.2% | 68.2% | |
Mixtral 8x22B | 回复在简体中文中,不加解释。 | 84.4% | 91.9% | 78.0% |
Mixtral 8x7B Reply in Simplified Chinese 以无解释. |
62.2% | 80.2% | 50.7% |
Mixtral-8x22B 的性能似乎与 Llama 3 70B 大致相当。但是,对于这两个模型系列而言,减少参数数量确实会导致性能显著下降,其中 Recall 的下降最为明显。这经常出现一个权衡,即在选择更高的准确性与更高的硬件要求之间。
在大多数情况下,可以通过使用特定领域的数据微调 Embedder、Reranker 或 LLM(在本例中,使用通话记录),在不增加参数数量的情况下提高模型的准确性。
Embedder 外形小巧,因此微调速度最快,且最具成本效益。有关详细说明,请参阅 NVIDIA NeMo 文档。此外,NVIDIA NeMo 简化并提高了微调有效版本 LLM 的效率。
用户的主要影响
此演示旨在从收益电话会议成绩单中提取见解。通过利用先进的 AI 技术,如 NIM,现在可以快速准确地从收益电话会议成绩单中检索信息。该 AI 产品在最密集的文档和数据分析过程中为多种类金融研究人员、分析师、顾问和基础投资组合经理提供帮助,使金融专业人员能够将更多时间用于战略决策或与客户沟通。
例如,在资产管理领域,投资组合经理可以使用该助手快速合成大量收益调用中的见解,从而改进投资策略和结果。在保险行业,AI 助手可以分析公司报告中的财务状况和风险因素,从而改进承销和风险评估流程。在基础交易和零售交易中,该助手可以帮助系统信息提取,以确定市场趋势和情绪变化,从而为未来交易使用更详细的信息。
即使在银行业,它也可以通过分析潜在贷款接收者的收益调用来评估其财务稳定性。最终,这项技术提高了效率、准确性和做出数据驱动决策的能力,为用户在各自市场中提供竞争优势。
访问 NVIDIA API 目录,查看所有可用的 NIM,并尝试 LangChain 的便捷集成,看看什么方法最适合您自己的数据。