利用 Gemini 和 Qdrant 构建实时财务新闻聊天机器人

438 阅读9分钟

介绍

大多数人在考虑投资时,都会涉足房地产、共同基金、债券等领域。选择投资之前,我们都希望找到一个可靠的银行合作伙伴,特别是对于长期投资,大家都倾向于选择那些表现稳定、没有诈骗记录、并能提供良好利息与回报的银行。因此,紧跟金融新闻成了我们的必需。

想象一下,如果你能随时随地通过一个实时的金融新闻聊天机器人获取所有财经相关新闻,这听起来是不是很吸引人?现在,利用检索增强生成技术(Retrieval Augmented Generation, RAG),这一切已经成为可能。我们可以结合大型语言模型和向量数据库技术,轻松地获得我们所需的信息。

让我们来看一下如何创建一个能够实时提供准确金融信息的RAG聊天机器人。这种聊天机器人能够实时更新,因为它会不断地从最新的新闻中获取数据。

利用Gemini打造的实时金融新闻RAG聊天机器人 我们的起点是一个包含了大量印度银行金融新闻的数据集,该数据集截至2020年5月26日更新。

在正式开始前,我们首先需要准备好相关的软件依赖。

%pip install -q llama-index 'google-generativeai>=0.3.0' qdrant_client llama-index-embeddings-fastembed fastembed llama-index-llms-gemini

准备节点

由于数据集是 CSV 文件,我们加载数据。

from llama_index.core import SimpleDirectoryReader
docs = SimpleDirectoryReader("Dataset").load_data()

所有文档已准备就绪;现在,我们将句子拆分为定义的块大小。

from llama_index.core.node_parser.text import SentenceSplitter  
# Initialize the SentenceSplitter with a specific chunk size  
text_parser = SentenceSplitter(chunk_size=1024)  
text_chunks = [] # This will hold all the chunks of text from all documents  
doc_idxs = [] # This will keep track of the document each chunk came from  
for doc_idx, doc in enumerate(docs):  
# Split the current document's text into chunks  
cur_text_chunks = text_parser.split_text(doc.text)  
  
# Extend the list of all text chunks with the chunks from the current document  
text_chunks.extend(cur_text_chunks)  
  
# Extend the document index list with the index of the current document, repeated for each chunk  
doc_idxs.extend([doc_idx] * len(cur_text_chunks))

然后,我们将创建一个文本节点对象,并将元数据分配给它。我们将所有节点存储在一个节点列表中。

from llama_index.core.schema import TextNode  
nodes = [] # This will hold all TextNode objects created from the text chunks  
# Iterate over each text chunk and its index  
for idx, text_chunk in enumerate(text_chunks):  
# Create a TextNode object with the current text chunk  
node = TextNode(text=text_chunk)  
  
# Retrieve the source document using the current index mapped through doc_idxs  
src_doc = docs[doc_idxs[idx]]  
  
# Assign the source document's metadata to the node's metadata attribute  
node.metadata = src_doc.metadata  
  
# Append the newly created node to the list of nodes  
nodes.append(node)

初始化 Qdrant 向量存储

为了储存节点,我们需要一个专门的存储系统。这里,我们选用了Qdrant,一种高效的向量数据库。Qdrant拥有向量数据库所需的一切关键功能。它利用HNSW (Hierarchical Navigable Small World) 算法进行快速且精确的近似最邻近搜索,确保我们可以迅速找到最相关的数据点。Qdrant不仅支持附加信息的存储,还能通过一个简单易用的API根据这些附加信息进行筛选。它的特点包括支持Docker安装方式、向量数据的内存存储、云原生架构设计以及水平扩展能力。Qdrant使用Rust语言开发,特别实现了动态查询规划和附加信息数据的索引功能。

我们首先需要在这个向量数据库中创建一个数据集合。

from llama_index.core import VectorStoreIndex, StorageContext  
from llama_index.vector_stores.qdrant import QdrantVectorStore  
from llama_index.core import Settings  
from llama_index.core import StorageContext  
import qdrant_client  
  
# Create a local Qdrant vector store  
client = qdrant_client.QdrantClient(path="financialnews")  
vector_store = QdrantVectorStore(client=client, collection_name="collection")

Gemini嵌入和文本模型

向量存储空间和节点都已经准备就绪,但是向量存储并不会直接接收节点。它们需要的是嵌入向量,为此,我们在这里采用了Gemini嵌入模型。我们打算使用Gemini大语言模型(LLM),它是一个功能强大的多模态模型系列。Gemini模型建立在Transformer架构之上,并在TPU(张量处理单元)上进行了训练,擅长执行多种任务,如内容摘要、阅读理解以及针对具体任务进行的细微调整。它还支持多种语言、处理长文本、编程、复杂的逻辑推理、数学问题解答,以及自然不必说的,处理多种模态的数据。

接下来,我们需要启用Google API密钥,你可以通过访问Google AI Studio来申请获取。这个密钥是我们连接和使用Google提供的AI服务的通行证。

%env GOOGLE_API_KEY = "your-api-key"  
import os  
GOOGLE_API_KEY = "your-api-key" # add your GOOGLE API key here  
os.environ["GOOGLE_API_KEY"] = GOOGLE_API_KEY

现在,使用 API 密钥,我们将使用 Llamaindex 设置中的 FastEmbed 嵌入模型和 Gemini LLM 生成嵌入。

from llama_index.embeddings.fastembed import FastEmbedEmbedding  
embed_model = FastEmbedEmbedding(model_name="BAAI/bge-small-en-v1.5")  
for node in nodes:  
node_embedding = embed_model.get_text_embedding(  
node.get_content(metadata_mode="all")  
)  
node.embedding = node_embedding  
from llama_index.llms.gemini import Gemini  
Settings.embed_model = embed_model  
Settings.llm = Gemini(model="models/gemini-pro")  
Settings.transformations = [SentenceSplitter(chunk_size=1024)]  
storage_context = StorageContext.from_defaults(vector_store=vector_store)  
index = VectorStoreIndex(  
nodes=nodes,  
storage_context=storage_context,  
transformations=Settings.transformations,  
)

向量存储保存在存储上下文中,并且索引已使用它和节点初始化。

HyDE 查询转换

现在,我们将使用响应生成器和向量检索器启动向量查询引擎。向量检索器在已包含索引的向量索引检索器中启动。响应生成器使用用户查询和一组给定的文本片段从 LLM 生成响应。响应生成器的输出是一个响应对象。

from llama_index.core import get_response_synthesizer  
from llama_index.core.query_engine import RetrieverQueryEngine  
from llama_index.core.retrievers import VectorIndexRetriever  
vector_retriever = VectorIndexRetriever(index=index, similarity_top_k=2)  
response_synthesizer = get_response_synthesizer()  
vector_query_engine = RetrieverQueryEngine(  
retriever=vector_retriever,  
response_synthesizer=response_synthesizer,  
)

我们将采用 HyDE 查询转换器进行高级检索。HyDE(假设文档嵌入)在大语言模型中促进了零次提示,通过指令来进行遵循。它生成一个假设文档,封装相关文本模式,将它们转换为嵌入向量,并对它们求平均值以创建一个嵌入。此过程通过文档嵌入空间中的向量相似性识别相应的实际嵌入,直接获得所需文档,而无需执行查询输入和从大型数据库中获取文档的检索步骤。

HyDE 查询转换有助于直接简洁地提供响应。

from llama_index.core.indices.query.query_transform import HyDEQueryTransform  
from llama_index.core.query_engine import TransformQueryEngine  
hyde = HyDEQueryTransform(include_original=True)  
hyde_query_engine = TransformQueryEngine(vector_query_engine, hyde)

利用 Gradio UI 实现聊天机器人

对于部署一个聊天机器人,我们将使用 Gradio。

def queries(query_str):  
response = hyde_query_engine.query(query_str)  
return str(response)  
import gradio as gr  
import os  
gr.close_all()  
with gr.Blocks(theme=gr.themes.Soft()) as demo:  
gr.Markdown(  
"""  
# Welcome to Gemini-Powered Stock Predictor RAG Chatbot!  
""")  
chatbot = gr.Chatbot()  
msg = gr.Textbox()  
clear = gr.ClearButton([msg, chatbot])  
def respond(message, chat_history):  
bot_message = queries(message)  
chat_history.append((message, bot_message))  
return "", chat_history  
msg.submit(respond, [msg, chatbot], [msg, chatbot])  
  
demo.launch(share=True)

开始提问

问题 1

告诉我所有关于诈骗的新闻。

  • PNB 诈骗余波:普遍存在的谨慎心理和飙升的保费打击贸易融资
  • 随着 NCLT 禁止 60 多个实体出售资产,PNB 诈骗余波扩大
  • PNB 诈骗:CBI 逮捕尼拉夫·莫迪和梅洛·乔克西公司 4 名官员
  • PNB 诈骗:法院对尼拉夫·莫迪和乔克西发布不可保释逮捕证
  • PNB 行长苏尼尔·梅塔承认 LoUs 骗局中有员工勾结
  • 尼拉夫·莫迪案件:CBI 找回 LoU 文件,逮捕另一名 PNB 高管
  • 价值 57.16 亿卢比的资产和 2011 年 3 月发行的第一批 LoU 被扣押:ED 关于 PNB 诈骗
  • “说明诈骗如何发生”:CVC 要求 PNB 和财政部在 10 天内提交报告
  • PNB 欺诈案:国会表示将反对国有银行私有化
  • PNB 欺诈:政府认为 RBI 可能无法确保有效监管?
  • 7 家国有银行股票因 1140 亿卢比的 PNB 欺诈案而创下 52 周新低
  • 周一 PNB 暴跌 7%;市值在四次交易中暴跌 1097.5 亿卢比
  • 财政部表示,对于真正的交易,PNB 必须承担责任
  • 尼拉夫·莫迪 PNB 欺诈:劳尔表示,莫迪总理的沉默表明了他的忠诚
  • 尼拉夫·莫迪 PNB 欺诈:维杰·阿加瓦尔将成为潜逃钻石商的律师
  • 在 PNB 欺诈之前:尼拉夫·莫迪和乔克西使 18 名商人、24 家公司破产
  • 尼拉夫·莫迪 PNB 诈骗:CBI 封锁了孟买银行的 Brady House 分行
  • 曾经是旁遮普邦骄傲的 PNB 现在在印度成为 WhatsApp 表情包的主题
  • 睁一只眼闭一只眼:18 亿美元的 PNB 欺诈完全没有被注意到
  • 银行工会希望 CBI 调查 PNB 欺诈,声称 RBI 作为监管机构失败了
  • CBI 质询尼拉夫·莫迪的 CFO 维普尔·安巴尼;搜查 PNB 孟买分行
  • PNB 诈骗:珠宝商预计会有更多人员伤亡和更严厉的法规
  • 价值 1140 亿卢比的 PNB 诈骗:为什么诈骗者更喜欢使用承兑函(Letter of Undertaking (LoU))

问题 2

有关 RBI 的最新消息是什么?

印度储备银行再次推迟了印度会计准则的推出,等待对银行法的修正。

问题 3

你能告诉我所有与房屋贷款有关的新闻吗?

  • 贷款利率下调促进了房屋贷款市场的余额转账
  • 利率下调后,巴罗达银行看好更大的房屋贷款份额
  • 巴罗达银行以 8.35% 的利率提供最低的房屋贷款利率
  • 印度国家银行推出“我们的家”活动,提供新的房屋贷款
  • 银行下调贷款利率,房屋贷款借款人将受益
  • 印度国家银行将贷款利率下调 90 个基点,房屋和汽车贷款将变得更便宜

问题 4

告诉我有关 Yes Bank 诈骗的新闻。

印度储备银行在印度银行发现了超过 4.5 亿美元的额外不良贷款。印度储备银行评估的非执行资产总额比印度银行截至 2019 年 11 月 20 日披露的金额高出 4.57 亿美元。

问题 5

有关 NBFC 的最新消息是什么?

有关 NBFC 的最新消息是,RBI 放宽了银行向 NBFC 和住房金融公司发放更多贷款的规范。RBI 将单一借款人敞口限额提高至银行资本的 15%。

结论

借助金融新闻数据集,构建了一个实时的金融新闻 RAG 聊天机器人,这是一个有益的历程。现在你了解到你可以轻松地向聊天机器人询问有关银行的问题,并即刻获得答案!现在是时候由你制作自己的聊天机器人了。希望你读完这篇博文之后有所收获。