大模型LLM Agent在 Text2SQL 应用上的实践

news2024/12/24 3:35:01

1.前言

在上篇文章中「如何通过Prompt优化Text2SQL的效果」介绍了基于Prompt Engineering来优化Text2SQL效果的实践,除此之外我们还可以使用Agent来优化大模型应用的效果。

本文将从以下4个方面探讨通过AI Agent来优化LLM的Text2SQL转换效果。

  • 1 Agent概述
  • 2 LangChain中的Agent模块
  • 3 Agent优化Text2SQL效果的实践
  • 4 后续计划

Text2SQL 系列

  • 如何通过 Prompt 优化大模型 Text2SQL 的效果
  • 大模型LLM在 Text2SQL 上的应用实践

技术交流

技术要学会分享、交流,不建议闭门造车。一个人走的很快、一堆人可以走的更远。

建立了大模型技术交流群,大模型学习资料、数据代码、技术交流提升, 均可加知识星球交流群获取,群友已超过2000人,添加时切记的备注方式为:来源+兴趣方向,方便找到志同道合的朋友。

方式①、微信搜索公众号:机器学习社区,后台回复:技术交流
方式②、添加微信号:mlc2060,备注:技术交流

在这里插入图片描述

2. Agent概述

2.1 Agent概念

在大语言模型LLM领域中,Agent是一个人工智能系统的设计理念,它旨在模拟人类或其他智能体的行为和决策过程。Agent被设计为能够在特定环境中运作,能够感知环境状态,处理信息,制定策略,执行行动,并根据反馈调整其行为。

Agent 的本质是教大模型一些思考方法论,就好像人们已经有了知识,但可能缺乏思考的方法。因此,Agent通过一个框架传授方法论,这个框架具有一些具体模块,支持整个结构的运行。

2.2 Agent关键组件

Open AI的Lilian Weng在个人博客发表的一篇文章:LLM Powered Autonomous Agents描述了 Agent 系统的全貌:

在这里插入图片描述

图1. LLM Powered Autonomous Agents系统

Agent: 核心,理解为可以处理一些复杂操作的“代理”服务,其核心驱动力是大模型;

Tools: 提供给 Agent 的工具,例如计算、搜索网络、代码执行等;

Memory: 由数据库或者其他存储上保存交流的历史记录,防止交流过程中遗忘之前的信息;

Planning: LLM的一些能力,包括反射、目标分解、反思、思维链。

2.2.1 Planning

一个复杂的任务通常涉及多个步骤,Agent需要知道这些步骤并提前计划,类型包括:

  • 子目标和任务分解

  • 反思与改进

1. 子目标和任务分解: Agent将大型任务分解为更小、更易管理的子目标,使得能够有效地处理复杂任务。其技术研究包括:

  • 思维链(CoT;Wei等人,2022年)已成为增强模型在复杂任务上性能的标准提示技术。模型被指示“一步一步思考”,利用更多测试时间计算将困难任务分解为更小、更简单的步骤。CoT将大任务转化为多个可管理的任务,并揭示了模型思考过程的解释。

  • 思维树(ToT;Yao等人,2023年)通过在每一步探索多种推理可能性扩展了CoT。它首先将问题分解为多个思维步骤,并在每一步生成多个思想,创建一个树状结构。搜索过程可以是广度优先搜索(BFS)或深度优先搜索(DFS),每个状态由分类器(通过Prompt)或多数投票评估。

任务分解可以通过以下方式进行:

  • LLM使用简单的提示,如“Steps for X.Y.Z.”,“What are the subgoals for achieving XYZ?”

  • 使用任务特定的指令,例如用于写作“Write a story outline.”

  • 用户输入

2. 反思与改进: Agent可以对过去的行为进行自我校准和自我反思,从错误中学习并改进未来步骤,从而提高最终结果的质量。其技术研究包括:

  • ReAct(Yao等人,2023年)通过将“Acting行为”和“Reasoning推理”组合,在LLM中集成推理和行动。前者使LLM能够与外部环境交互(例如Wikipedia搜索API),而后者提示LLM生成自然语言中的推理轨迹。

ReAct提示模板包含LLM思考的明确步骤,大致格式为:

Thought: ...
Action: ...
Observation: ...
... (Repeated many times)

在这里插入图片描述

图2.ReAct模式推理轨迹

上面是一个例子。问题是:除了Apple Remote之外,还有什么设备可以控制 Apple Remote 最初设计用于交互的程序吗?

然后 ReAct 就会一步步拆开,第一个 Thought:需要查找 Apple Remote原生的交互程序;然后进行一个 Action,去 google 找这个问题答案。然后进行下一个 Thought:Apple remote 是一个控制媒体的程序,需要查找其他可以控制媒体中心的程序,然后继续下一个 Action:找不到;然后继续 Thought:找其他相关的;然后找到了。把找到的信息填入到最后一个 Thought,得到最终答案。

所以 ReAct 是通过外部工具和反复查找匹配得到最终答案的过程。

这样似乎给我们打开了一个新的解决问题的路径。利用 LLM 的拆解问题的能力,在中间过程投喂信息。人工参与确认是否正确,直至找到人类认可的答案。‍

  • Reflexion(Shinn & Labash,2023年)是一个框架,为Agent配备动态记忆和自我反思能力,以提高推理技能。遵循ReAct的设置,在每次动作a后,Agent计算一个启发式h,并根据自我反思结果选择是否重置环境以开始新的试验。

在这里插入图片描述

图3. Reflexion框架示意图

  • Chain of Hindsight(CoH;Liu等人,2023年)其思想是在上下文中呈现顺序改进的输出历史,并训练模型跟随趋势生成更好的输出。算法蒸馏(AD;Laskin等人,2023年)将相同的想法应用于强化学习任务中的跨情节轨迹,其中算法被封装在长历史条件策略中。考虑到Agent与环境互动多次,并且在每个情节中Agent都会变得更好一点,AD连接这一学习历史并将其输入到模型中。因此,我们应该期望下一个预测动作比之前的试验表现更好。

在这里插入图片描述

图4. 算法蒸馏(AD)工作原理示意图

2.2.2 Memory

Memory可以定义为获取、存储、保持和随后检索信息的过程。Memory类型如下:

(1) 感觉Memory:这是Memory的最早阶段,表示为原始输入(包括文本、图像或其他模态)的Embedding表示。

(2) 短期Memory:认为所有在上下文学习(见Prompt Engineering)中利用的都是模型的短期Memory来学习;是短暂和有限的,因为它受到Transformer上下文窗口长度的限制。

(3) 长期Memory:这为Agent提供了在长时间内保留和回溯(无限)信息的能力,通常利用外部向量存储和快速检索实现。

2.2.3 Tools

Agent可以调用外部API获取模型权重中缺失的额外信息(通常在预训练后难以更改),包括当前信息、代码执行能力、访问专有信息源等。

Tools使用意味着Agent能够识别和利用外部资源(如API、数据库或其他模型)来增强其解决问题的能力。这可能包括学习如何调用适当的API获取额外信息、从数据库中检索相关数据或组合多个模型的输出以生成更全面的答案。通过这种方式,Tools使用使Agent能够适应不断变化的环境和任务需求,提高其灵活性和效率。

MRKL(Karpas等人,2022年),“Modular Reasoning, Knowledge and Language”, MRKL系统包含一组“专家”模块,而LLM作为路由器,将请求路由到最适合的专家模块。这些模块可以是神经网络(例如深度学习模型)或调用模块(例如数学计算器、货币转换器、天气API)。

我们熟悉的ChatGPT插件和OpenAI API函数调用是LLM与工具增强的好例子。这些工具允许LLM访问额外的信息源和计算能力,从而扩大其解决问题的能力范围。

3. LangChain中的Agent模块

3.1 Agent模块概述

在LangChain的Agents这个模块中,Agent 类型有多个,包括:Zero-shot ReAct、Conversational 以及 Plan-and-execute等。其中ReAct就是所谓Reasoning + Acting 模式,把复杂问题拆开,有些缺少的内容通过工具从外部获取,然后补充到问题回答里。

那么LangChain 是怎么实现的呢?

LangChain设置了两种模式:

(1)Action Agents,就是下一步的动作由上一步的输出决定

(2)Plan-and-execute Agents,就是计划好所有的步骤,然后顺序执行

在执行过程中, Agent可以调用一些 tools,来辅助过程。例如 google 搜索、语音识别、文件处理、python执行等等。tools 就是给Agent配备了一些工具箱ToolKit。

3.2 Agent示例

示例的代码如下:

# 设置一个搜索工具
search = SerpAPIWrapper()
tools = [
    Tool(
        name = "Current Search",
        func=search.run,
        description="useful for when you need to answer questions about current events or the current state of the world"
    ),
   
]

# 提供交互中的“memory”存储
memory = ConversationBufferMemory(memory_key="chat_history")

# 设置 agent chain
llm=OpenAI(temperature=0)
agent_chain = initialize_agent(tools, llm, agent=AgentType.CONVERSATIONAL_REACT_DESCRIPTION, verbose=True, memory=memory)

执行提问:

agent_chain.run(input="whats the current temperature in pomfret?")

执行结果如下:

> Entering new AgentExecutor chain...

Thought: Do I need to use a tool? Yes
Action: Current Search
Action Input: Current temperature in Pomfret
Observation: Partly cloudy skies. High around 70F. Winds W at 5 to 10 mph. Humidity41%.
Thought: Do I need to use a tool? No
AI: The current temperature in Pomfret is around 70F with partly cloudy skies and winds W at 5 to 10 mph. The humidity is 41%.

> Finished chain.

'The current temperature in Pomfret is around 70F with partly cloudy skies and winds W at 5 to 10 mph. The humidity is 41%.'

上面代码逻辑还是比较清楚,设置工具,设置 chain。运行之后,会出现Thought->Action->Observation的模式。这就是上面所说的"ReAct"模式。

3.3 ReAct模式解析

在执行run之后,LangChain会按照模型来顺序执行,这里是默认AI Agent执行模型,根据返回结果执行下一步。

这里会有一个疑问,为什么提交到LLM之后,可以返回Thought->Action->Observation 的模式?奥秘还是在提示(Prompt)模板上。

在使用agent=AgentType.CONVERSATIONAL_REACT_DESCRIPTION之后,Prompt就会被格式化成如下这样:

"Have a conversation with a human, answering the following questions as best you can. You have access to the following tools: 
Search: useful for when you need to answer questions about current events.
Use the following format: 
Question: the input question you must answer 
Thought: you should always think about what to do 
Action: the action to take, should be one of [Search] 
Action Input: the input to the action
Observation: the result of the action 
... (this Thought/Action/Action Input/Observation can repeat N times) 
Thought: I now know the final answer 
Final Answer: the final answer to the original input question Begin!"

在提示模板里面,说明了需要按照 Search、Question、Thought、Action这种模式来回答,还告诉LLM,可以使用Search这个工具,之后LLM按照要求回答,LangChain就可以按照格式返回获取对应的Thought。然后可以提供新的工具或者与用户的交互输入,形成新的提示词再继续提交给LLM,直至获得最终结果。

这种做法打开了新的一扇窗,当下流行的AutoGPT、BabyAGI也是类似的机制。

4. Agent优化Text2SQL效果的实践

4.1 现有问题

依然以上篇文中的数据库Chinook为例,需求为统计“连续两个月都下订单的客户有哪些?”,示例代码可参考上文。

结果如下:

在这里插入图片描述

可以看出生成的SQL不准确,只统计了最近两个月中都下订单的客户,和统计需求不相符。那如何解决这个问题?

4.2 Agent解决方案

LangChain的SQL Agent提供一种比SQLDatabaseChain更灵活的与SQL数据库交互的方式。

使用SQL Agent的主要优点是:

(1)可以根据Database Schema和数据库的内容(如描述特定的表)回答问题;

(2)可以通过运行生成的查询、捕获回溯并正确的重新生成,以此来纠错。

我们可以使用create_sql_agent函数来初始化SQL Agent。此Agent包含SQLDatabaseToolkit,其中包含用于执行以下操作的工具:

  • 创建和执行查询

  • 检查SQL查询语法

  • 检索表的描述

示例代码如下:

from langchain.agents import create_sql_agent
from langchain.agents.agent_toolkits import SQLDatabaseToolkit

# from langchain.agents import AgentExecutor
from langchain.agents.agent_types import AgentType

db = SQLDatabase.from_uri("sqlite:///xxx/Chinook.db")

agent_executor = create_sql_agent(
    llm=OpenAI(temperature=0),
    toolkit=SQLDatabaseToolkit(db=db, llm=OpenAI(temperature=0)),
    verbose=True,
    agent_type=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
)

执行提问:

agent_executor.run("在订单表中,连续两个月都下订单的客户有哪些?")

结果如下:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

效果: 生成的SQL基本满足我们的需求。

我们可以进一步通过LangSmith trace查看AgentExecutor执行过程:

在这里插入图片描述

5.后续计划

本文介绍了通过Agent来优化Text2SQL生成结果的案例,通过SQLDatabaseToolkit工具与Database进行交互,LLM按照要求回答,LangChain可以按照格式返回获取对应的Thought,然后可以提供新的工具或者与用户的交互输入,形成新的提示词再继续提交给LLM,直至获得最终结果。总的来说,Agent提供了一种新的方法来优化LLM在Text2SQL应用上的效果。通过Thought->Action->Observation,我们可以step by step分解问题,借助LLM更好地理解用户的查询,从而提高查询的准确性和效率。但仍然存在一些技术挑战需要克服,包括上下文长度限制、长期规划和任务分解的复杂性,以及自然语言接口的可靠性问题,后续持续更新。这些问题的解决将进一步推动Agent在LLM应用中的发展和效率提升。

参考文献:

https://lilianweng.github.io/posts/2023-06-23-agent

https://python.langchain.com/docs/modules/agents

https://python.langchain.com/docs/integrations/toolkits/sql_database

https://python.langchain.com/docs/use_cases/qa_structured/sql

https://zhuanlan.zhihu.com/p/643799381

https://zhuanlan.zhihu.com/p/664281311

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1375829.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

内网穿透的应用-使用Docker部署开源建站工具—Halo,并实现个人博客公网访问

文章目录 1. Docker部署Halo1.1 检查Docker版本如果未安装Docker可参考已安装Docker步骤:1.2 在Docker中部署Halo 2. Linux安装Cpolar2.1 打开服务器防火墙2.2 安装cpolar内网穿透 3. 配置Halo个人博客公网地址4. 固定Halo公网地址 本篇文章介绍如何在CentOS下使用D…

2023年北邮渣硕的暑期秋招总结

背景 实验室一般是在研究生二年级的时候会放实习,在以后的日子就是自己完成毕业工作要求,基本上不再涉及实验室的活了,目前是一月份也是开始准备暑期实习的好时间。实验室每年这个时候都会有学长学姐组织暑期实习经验分享,本着不…

Nginx配置反向代理实例二

Mac 安装Nginx教程 Nginx配置反向代理实例一 提醒一下:下面实例讲解是在Mac系统演示的; 反向代理实例二实现的效果 使用nginx 反向代理,根据访问的地址跳转到不同端口的服务中 nginx 监听端口为81; 访问地址1:http:/…

ptaR7-6/zzuli2106 有去有回

题目 输入n个整数,第一趟按从左到右间隔k个数取数据,然后第二趟再从右到左间隔k-1个数取余下的数,如果数据没有取完,下一趟再间隔k-2个从左到右取数据,如此反复,直到所有的数据取完为止。注意:…

API设计:从基础到优秀实践

在这次深入探讨中,我们将深入了解API设计,从基础知识开始,逐步进阶到定义出色API的最佳实践。 作为开发者,你可能对许多这些概念很熟悉,但我将提供详细的解释,以加深你的理解。 API设计:电子商…

2024年 最新 iPhone手机 历代机型、屏幕尺寸、纵横比、分辨率 整理

🎬 博客主页:https://xiaoy.blog.csdn.net 🎥 本文由 呆呆敲代码的小Y 原创,首发于 CSDN🙉 🎄 学习专栏推荐:Unity系统学习专栏 🌲 游戏制作专栏推荐:游戏制作 &…

css3边框与圆角

css3边框与圆角 前言边框的三要素边框的三要素小属性 四个方向的边框四个方向边框的三要素小属性 去掉边框利用边框制作三角形圆角 border-radius单独设置四个圆角小属性百分比为单位 盒子阴影阴影延展内阴影多阴影 结语 前言 在网页设计中,边框与圆角不仅仅是简单…

强化学习求解TSP(七):Qlearning求解旅行商问题TSP(提供Python代码)

一、Qlearning简介 Q-learning是一种强化学习算法,用于解决基于奖励的决策问题。它是一种无模型的学习方法,通过与环境的交互来学习最优策略。Q-learning的核心思想是通过学习一个Q值函数来指导决策,该函数表示在给定状态下采取某个动作所获…

对git中tag, branch的重新理解

1. 问题背景 项目中之前一个tag(v1.0)打错了,想删除它,但我们从此tag v1.0中迁出新建分支Branch_v1.0,在此分支下修复了bug,想重新打一个tag v1.0,原来的tag v1.0可以删除掉吗? 错误的理解&am…

SQL-分组查询

目录 DQL-分组查询 分组查询注意事项: DQL- 排序查询 🎉欢迎您来到我的MySQL基础复习专栏 ☆* o(≧▽≦)o *☆哈喽~我是小小恶斯法克🍹 ✨博客主页:小小恶斯法克的博客 🎈该系列文章专栏:重拾MySQL &…

RT-Thread入门笔记4-跑马灯线程实例

RT-Thread操作系统是基于线程调度的多任务系统。 线程状态切换 调度过程是一种完全抢占式的基于优先级的调度算法。 支持8/32/256优先级,其中0表示最高,7/31/255表示最低。最低优先级7/31/255优先级用于空闲线程。 支持以相同优先级运行的线程。 共享时…

【AI视野·今日NLP 自然语言处理论文速览 第七十二期】Mon, 8 Jan 2024

AI视野今日CS.NLP 自然语言处理论文速览 Mon, 8 Jan 2024 Totally 17 papers 👉上期速览✈更多精彩请移步主页 Daily Computation and Language Papers DeepSeek LLM: Scaling Open-Source Language Models with Longtermism Authors DeepSeek AI Xiao Bi, Deli Ch…

jupyter notebook 配置conda 虚拟环境python

conda创建python环境 conda create -n openvoice python3.9 激活环境 source activate openvoice 在虚拟环境中安装ipykernel pip install ipykernel 添加虚拟环境进到 jupyter notebook python -m ipykernel install --user --name openvoice --display-name openvoice …

修改idea或者pycharm或者android studio的快捷键,快速跳转到行尾

ctrl enter这个快捷键是idea默认配置的,就是将光标所在的行切一刀,并且换到下一行。但是在我的开发习惯里面不怎么使用ctrl enter这个快捷键, 反而开发java或者flutter软件需要快速跳转到行尾添加分号 ; ,但是使用end键脱离了我…

C++进阶(三)多态

📘北尘_:个人主页 🌎个人专栏:《Linux操作系统》《经典算法试题 》《C》 《数据结构与算法》 ☀️走在路上,不忘来时的初心 文章目录 一、多态的概念1、概念 二、多态的定义及实现1、多态的构成条件2、虚函数3、虚函数的重写4、C…

groovy XmlParser 递归遍历 xml 文件,修改并保存

使用 groovy.util.XmlParser 解析 xml 文件,对文件进行修改(新增标签),然后保存。 是不是 XmlParser 没有提供方法遍历每个节点,难道要自己写? 什么是递归? 不用说,想必都懂得~ …

ERROR in Plugin “react“ was conflicted .... 天坑留念-turborepo、eslint plugin

前两天项目代码拉下来,装完依赖启动的时候直接报错: [eslint] Plugin "react" was conflicted between ".eslintrc.js eslint-config-custom eslint-config-alloy/react" and "BaseConfig D:\pan\erp\test\business-servic…

Java21 如何使用switch case

1. Java8 和 Java21 Java8 引入字符串和枚举 Java21 可以返回值, yield关键字, switch 表达式, 模式匹配, null值处理 2. 代码案例 1. Java8 public static void java8() {String day "tuesday";switch (day) {case "monday":System.out.println("w…

vue3+vite+ts+pinia新建项目(略详细版)

1、新建项目 npm create vite@latest 2、安装依赖 yarn add vue-router yarn add -D @types/node vite-plugin-pages sass sass-loader 3、配置别名 //vite.config.ts import { defineConfig } from vite import path from node:path export default defineConfig({ plu…

基于ssm快餐店点餐结算系统的设计与实现+vue论文

摘 要 传统办法管理信息首先需要花费的时间比较多,其次数据出错率比较高,而且对错误的数据进行更改也比较困难,最后,检索数据费事费力。因此,在计算机上安装快餐店点餐结算系统软件来发挥其高效地信息处理的作用&…