微信扫码
添加专属顾问
上一章【项目实战】基于Agent的金融问答系统:RAG检索模块初建成,我们已经完成了RAG的基本流程,本章我将梳理Agent的运行框架以及介绍如何将RAG数据和SQL查询数据进行整合,实现金融问题的自主回答。
在进行Agent框架介绍之前,我们需要探讨一个核心问题,即:用户输入一个问题后,如何实现用户问题的自动查询(是SQL查询还是RAG检索) 。
关于这个问题,我们曾有一个方案如下:
• 对于用户输入的问题,是需要查询SQL,还是需要去RAG检索,我们通过一个意图识别模块来实现;
• 意图识别模块会接受用户的问题,然后将用户的问题交给大模型去分辨;
• 大模型我们提前做了sft微调(few-shot少样本训练也可以达到同样效果),让大模型知道什么样的问题属于SQL查询问题,什么样的问题属于RAG检索问题,例如: # 准备few-shot样例
examples =[
{
"inn":"我想知道东方阿尔法优势产业混合C基金,在2021年年度报告中,前10大重仓股中,有多少只股票在报告期内取得正收益。",
"out":"rag_question***我想知道东方阿尔法优势产业混合C基金,在2021年年度报告中,前10大重仓股中,有多少只股票在报告期内取得正收益。"
},
{
"inn":"森赫电梯股份有限公司产品生产材料是什么?",
"out":"rag_question***森赫电梯股份有限公司产品生产材料是什么?"
},
{
"inn":"20210930日,一级行业为机械的股票的成交金额合计是多少?取整。",
"out":"agent_question***20210930日,一级行业为机械的股票的成交金额合计是多少?取整。"
},
...
]
• 意图识别结果之后,在代码中通过if...else对识别结果进行不同类别的后续处理,如下:
if intent =="rag_question":
# 如果是RAG相关的问题
result = self.rag.get_result(question=question)
return result
elif intent =="agent_question":
# 如果是Agent相关的问题
result, result_list = self.agent.get_result(input=question)
return result
else:
# 其他类问题
result = self.chat.invoke(input=question).content
return result这一方案有个核心问题:
1. 如果意图识别错了,那么后续的处理就失效了,答案一定会错;
2. 我们固然可以给if...else...增加修正策略,比如:rag检索不到那就去sql里再查一下....但是如果我们需求很复杂呢,这个策略编写和维护成本也是指数级上升;
3. 最为重要的一点是:这种方式我觉得一点都不智能!
这种方式还是传统开发的思维:由开发者来清晰地控制着程序的每一步骤,大模型在其中只是扮演一个辅助工具角色(例如:做个问题分类)
但是,在我首次接触Agent时,Agent的自主思考和自主行动给我留下了深刻的印象,所以我决定换一种方式:使用Agent来进行用户问题的自主判断、自主解决。
在【课程总结】day30:大模型之Agent的初步了解中,我们曾初步了解Agent框架如下:
由上图可知,如果我们给Agent赋予相应的工具,那么Agent依托于大模型的思考力,可以自主开展相应的planning以及action。因此,我们首要解决如何给Agent赋予相应的工具。
因为我们的需求是查询结构化的SQL数据库和非结构化的RAG数据,所以我们需要给Agent赋予两个工具,具体如下:
代码文件及目录:app/finance_bot_ex.py
import logging
import datetime
from langgraph.prebuilt import create_react_agent
from langchain.tools.retriever import create_retriever_tool
from langchain_community.utilities importSQLDatabase
from langchain_community.agent_toolkits importSQLDatabaseToolkit
from rag.rag importRagManager
import settings
classFinanceBotEx:
def__init__(self, llm=settings.llm, chat=settings.chat, embed=settings.embed):
self.llm = llm
self.chat = chat
self.embed = embed
self.tools =[]
self.rag =RagManager(llm=llm, embed=embed)
为FinanceBotEx类添加
def init_sql_tool(self, path):
# 连接数据库
db = SQLDatabase.from_uri(f"sqlite:///{path}")
toolkit = SQLDatabaseToolkit(db=db, llm=self.llm)
sql_tools = toolkit.get_tools() # 工具
return sql_tools
说明:
• 上述函数中path用来传入SQlite数据库的路径
• 使用langchain封装的 SQLDatabase 连接数据库
• 使用langchain封装的 SQLDatabaseToolkit 得到SQL相关的工具,用以后续提供给Agent
为FinanceBotEx类添加
def init_rag_tools(self):
# 给大模型 RAG 检索器工具
retriever = self.rag.get_retriever()
retriever_tool = create_retriever_tool(
retriever=retriever,
name="rag_search",
description="按照用户的问题搜索相关的资料,对于招股书类的问题,you must use this tool!",
)
return retriever_tool说明:
• 该函数中的 self.rag 是我们封装的RAG管理类
• 通过这个管理类的get_retriever()得到RAG的检索器
• 借助langchain封装的create_retriever_tool(),将检索器创建为一个工具:
• 工具的 name 为 rag_search
• 工具的 description 用于告诉大模型,这个工具能做什么用(这一点很重要)
为FinanceBotEx类添加
def create_prompt():
system_prompt = """你是一位金融助手,可以帮助用户查询数据库中的信息。
你要尽可能的回答用户提出的问题,为了更好的回答问题,你可以使用工具进行多轮的尝试。
# 关于retriever_tool工具的使用:
1、你需要结合对检索出来的上下文进行回答问题。
2、如果你不知道答案,就说你不知道。请使用不超过三句话的简洁回答。
# 关于sql类工具的使用:
## 工具使用规则
1、你需要根据用户的问题,创建一个语法正确的SQLite查询来运行,然后查看查询的结果并返回答案。
2、除非用户指定了他们希望获得的特定数量的示例,否则总是将查询限制为最多5个结果。
3、您可以按相关列对结果进行排序,以返回数据库中最有趣的示例。
4、永远不要查询指定表的所有列以避免查询性能问题,你只查询给定问题的相关列即可。
5、你必须在执行查询之前仔细检查查询。如果执行查询时出现错误,请重新编写查询并重试。
6、请勿对数据库进行任何DML语句(INSERT,UPDATE,DELETE,DROP等)。
## 工具使用过程
1、首先,你应该始终查看数据库中的表,看看可以查询什么,这一步骤很重要,注意不要跳过。
2、然后,你应该查询最相关表的schema。
## 工具使用注意事项:
1、如果生成的SQL语句中,字段带有英文括号(),请使用双引号包裹起来,例如:收盘价(元) 双引号包裹为 "收盘价(元)"。
2、如果查询过程中SQL语句有语法错误,减少查询量,总体查询次数应控制在15次以内。
# 关于你的思考和行动过程,请按照如下格式:
问题:你必须回答的输入问题
思考:你应该总是考虑该怎么做
行动:你应该采取的行动,应该是以下工具之一:{tool_names}
行动输入:行动的输入
观察:行动的结果
... (这个思考/行动/行动输入/观察可以重复N次)
思考: 我现在知道最终答案了
最终答案:原始输入问题的最终答案
Begin!
"""
return system_prompt在准备好相应的工具以及prompt之后,创建Agent并传入提前准备好的工具和prompt。
为FinanceBotEx类添加
def init_agent(self):
# 初始化 RAG 工具
retriever_tool = self.init_rag_tools()
# 初始化 SQL 工具
sql_tools = self.init_sql_tool(settings.SQLDATABASE_URI)
# 创建系统Prompt提示语
system_prompt = self.create_prompt()
# 创建Agent
agent_executor = create_react_agent(
self.chat,
tools=[retriever_tool]+ sql_tools,
state_modifier=system_prompt
)
return agent_executor说明:
• settings.SQLDATABASE_URI 是一个本地SQLite文件的路径,我将它单独维护在app/settings.py中,方便配置的修改。
• 代码文件:app/settings.py# 连接数据库db文件的地址根据需要需要更换
SQLDATABASE_URI = os.path.join(os.getcwd(), "app/dataset/dataset/博金杯比赛数据.db")
为FinanceBotEx类添加
def handle_query(self, example_query):
# 流式处理事件
events = self.agent_executor.stream(
{"messages":[("user", example_query)]},
stream_mode="values",
)
# 打印流式事件的消息
for event in events:
event["messages"][-1].pretty_print()
return event["messages"][-1].content在test_framework.py中增加测试函数如下:
# 测试 FinanceBotEx 主流程
deftest_financebot_ex():
from finance_bot_ex importFinanceBotEx
llm, chat, embed = get_qwen_models()
financebot =FinanceBotEx(llm=llm, chat=chat, embed=embed)
example_query ="20210304日,一级行业为非银金融的股票的成交量合计是多少?取整。"
financebot.handle_query(example_query)
if __name__ =="__main__":
# test_rag()
# test_import()
test_financebot_ex()运行结果:
通过日志可以看到,Agent收到问题后,先去SQL数据库中查询看有哪些表可能有这些数据,通过返回的表信息自主实现对应的SQL语句,然后查询结果后给出答案。
如果将上面的问题变成如下问题:
example_query = "根据联化科技股份有限公司招股意见书,精细化工产品的通常利润率是多少?"
运行结果:
通过日志可以看到,Agent对于这个问题认为应该直接去RAG中搜索,所以直接调用工具rag_search。
53AI,企业落地大模型首选服务商
产品:场景落地咨询+大模型应用平台+行业解决方案
承诺:免费POC验证,效果达标后再合作。零风险落地应用大模型,已交付160+中大型企业
2026-06-03
2026-05-13
2026-05-26
2026-04-14
2026-04-20
2026-04-16
2026-05-21
2026-06-10
2026-04-27
2026-06-02
2026-07-08
2026-07-07
2026-07-07
2026-07-02
2026-06-29
2026-06-18
2026-06-11
2026-06-05
欢迎您使用【53AI 官方网站】(以下简称“本网站”或“我们”)。本《会员服务协议》(以下简称“本协议”)是您(以下简称“会员”或“用户”)与【深圳市博思协创网络科技有限公司】之间关于注册、登录及使用本网站会员服务所订立的法律协议。
在您注册或登录前,请务必审慎阅读、充分理解各条款内容,特别是免除或限制责任的条款、知识产权条款、争议解决条款等。此类条款将以加粗形式提示您注意。 当您通过微信公众号授权、手机验证码验证或其他方式成功登录本网站时,即视为您已完全理解并同意接受本协议的全部内容。
一、 定义
本网站:指由【深圳市博思协创网络科技有限公司】运营的,域名为【53ai.com】的网站及相关移动端页面。
会员服务:指本网站向注册会员提供的知识库文章查阅、内容检索及其他相关增值服务。
知识库内容:指本网站发布的包括但不限于文字、图表、数据、研究报告、行业分析等数字化内容资源。
二、 账号注册与登录
登录方式:本网站支持以下登录方式,您可根据实际情况选择:
微信公众号授权登录:您同意将您的微信OpenID信息授权给本网站,用于创建或关联会员账号。
手机验证码登录:您需提供真实有效的手机号码,并通过短信验证码完成身份验证与登录/注册。
账号安全:您的账号仅限您本人使用,禁止赠与、借用、租用、转让或售卖。因您保管不善导致的账号被盗、密码泄露等损失,由您自行承担。
实名认证:根据相关法律法规要求,我们可能要求您在特定功能下完成实名认证。如您拒绝提供,可能无法使用部分或全部服务。
未成年人保护:若您未满18周岁,请在法定监护人的陪同下阅读本协议,并在征得监护人同意后使用本服务。
三、 服务内容与规范
知识库查阅权限:会员登录后,有权按照其会员等级对应的权限范围,在线浏览、检索本网站知识库中的相关文章及内容。
服务变更:我们有权根据业务发展需要,调整、变更或终止部分服务内容,并将以网站公告、公众号消息等方式提前通知。
禁止行为:您在使用服务时不得实施以下行为:
利用技术手段批量爬取、下载、转存知识库内容;
将知识库内容用于商业目的或未经授权地向第三方传播;
干扰本网站正常运行或侵犯其他用户合法权益;
发布违法违规信息或从事违反公序良俗的活动。
四、 知识产权声明
权利归属:本网站知识库中的排版设计、软件代码等内容的知识产权均归【公司全称】或原权利人所有,受《中华人民共和国著作权法》等法律保护。
有限许可:本网站授予会员一项非独占、不可转让、不可转授权的普通许可,仅限于个人学习、研究之目的在线查阅知识库内容。
侵权追责:未经书面许可,任何单位或个人不得以任何形式复制、转载、摘编、镜像、汇编或以其他方式使用上述内容。一经发现,我们保留追究其法律责任的权利。
五、 个人信息保护
我们重视对您个人信息的保护。关于我们如何收集、使用、存储和保护您的个人信息,请单独阅读 《隐私政策》。
您通过微信公众号授权或手机号验证所提供的信息,我们将严格按照《个人信息保护法》的规定处理,仅用于身份识别、服务提供及安全验证等必要用途。
您可以随时通过网站设置或联系客服行使查阅、更正、删除个人信息及撤回授权同意的权利。
六、 免责声明
内容准确性:知识库内容仅供参考,不构成专业建议。我们不对其完整性、准确性、时效性作任何明示或暗示的保证,您应自行判断并承担使用风险。
不可抗力:因自然灾害、政策法规变化、网络故障、第三方平台接口异常(如微信接口维护、运营商短信通道故障)等不可抗力导致的服务中断或延迟,我们不承担违约责任。
第三方链接:本网站可能包含指向第三方网站的链接,该等网站的内容和服务不受我们控制,请您自行甄别风险。
七、 违约责任
如您违反本协议约定,我们有权视情节采取警告、限制功能、暂停服务、注销账号等措施,并保留要求赔偿损失的权利。
如因您的违约行为导致我们遭受行政处罚、第三方索赔或商誉损失,您应承担全部赔偿责任(包括但不限于罚款、赔偿金、律师费、公证费等)。
八、 法律适用与争议解决
本协议的订立、执行和解释均适用中华人民共和国大陆地区法律。
因本协议产生的或与本协议有关的任何争议,双方应友好协商解决;协商不成的,任何一方均可向【公司所在地】有管辖权的人民法院提起诉讼。
九、 其他
本协议构成双方就本服务达成的完整协议,取代此前任何口头或书面约定。
本协议任一条款被认定为无效或不可执行的,不影响其他条款的效力。
我们对本协议享有最终解释权,并在法律允许的范围内保留随时修改的权利。修改后的协议一经公布即生效,继续使用服务即视为同意修订内容。