AI大模型应用开发-用LangChain构建PAL应用:SQL的生成与执行
PAL(Program-Aided Language models) 思想成为大模型 Agent 领域的重要范式。核心思路是 LLM 只负责语言任务,复杂的逻辑/计算交由程序执行。
通过合理设计 prompt,模型生成代码/SQL/逻辑描述,外部程序再执行,得到结果后反馈给 LLM,LLM 再生成最终答案。
本文将通过一个 LangChain + MySQL + Postgres Checkpoint 实例,完整演示 PAL 的设计流程,帮助大家理解和复现。
项目结构
.
├── llm_env.py # 初始化 LLM
└── main.py # PAL 交互主流程
llm_env.py:初始化 LLM
from langchain.chat_models import init_chat_model
llm = init_chat_model("gpt-4o-mini", model_provider="openai")
简单封装一个 LLM 对象,这里用 gpt-4o-mini
,通过 llm_env.llm
调用。
main.py:PAL 主流程
导入库 & 初始化
import os
import sys
sys.path.append(os.getcwd())
from langchain_community.utilities import SQLDatabase
from langchain_core.prompts import ChatPromptTemplate
from langchain_community.tools.sql_database.tool import QuerySQLDatabaseTool
from langgraph.graph import START, StateGraph
from langgraph.checkpoint.postgres import PostgresSaver
import time
from typing import TypedDict, Annotated
from llm_set import llm_env
llm = llm_env.llm
亮点:
用
StateGraph
组织整个流程用
PostgresSaver
持久化 checkpoint,方便中断恢复
初始化 MySQL 数据库
db = SQLDatabase.from_uri(
"mysql+pymysql://root:123456@localhost:3306/javademo",
engine_args={"pool_size": 5, "max_overflow": 10},
)
数据库连接,示例用 javademo
库,用户可根据实际修改。
State 定义
class State(TypedDict):
"""State for the demo."""
question: str
query: str
result: str
answer: str
approved: bool
定义流程中的共享变量,典型 PAL 模式的中间态。
Prompt 设计
system_message = """
Given an input question, create a syntactically correct {dialect} query to
run to help find the answer. Unless the user specifies in his question a
specific number of examples they wish to obtain, always limit your query to
at most {top_k} results. You can order the results by a relevant column to
return the most interesting examples in the database.
Never query for all the columns from a specific table, only ask for a the
few relevant columns given the question.
Pay attention to use only the column names that you can see in the schema
description. Be careful to not query for columns that do not exist. Also,
pay attention to which column is in which table.
Only use the following tables:
{table_info}
"""
user_prompt = "Question:{input}"
query_prompt_template = ChatPromptTemplate(
[("system", system_message), ("human", user_prompt)],
)
亮点:
系统提示明确要求 安全、规范 的 SQL
限定
top_k
结果避免
SELECT *
LLM 生成 SQL
class QueryOutput(TypedDict):
"""Generated the SQL query."""
query: Annotated[str, "Syntactically valid SQL query."]
def write_query(state: State):
"""Generate SQL query to fetch information."""
prompt = query_prompt_template.invoke(
{
"dialect": db.dialect,
"top_k": 5,
"table_info": db.get_table_info(),
"input": state["question"],
}
)
structured_llm = llm.with_structured_output(QueryOutput)
result = structured_llm.invoke(prompt)
return {"query": result["query"]}
PAL 核心步骤 1
LLM 不直接回答问题,而是生成 SQL 查询。
用户确认
def wait_for_user_approve(state: State):
"""Pause here and wait for user approval before executing query."""
try:
user_approval = input("Do you want to go to execute query? (yes/no): ")
except Exception:
user_approval = "no"
if user_approval.lower() == "yes":
return {
"query": state["query"],
"approved": True,
}
else:
return {
"query": state["query"],
"approved": False,
}
用户确认 SQL 是否执行,保证安全性 —— 很关键。
执行 SQL
def excute_query(state: State):
"""Execute the SQL query and return the result."""
if state["approved"]:
execute_query_tool = QuerySQLDatabaseTool(db=db)
return {"result": execute_query_tool.invoke(state["query"])}
else:
return {"result": "excute denied."}
PAL 核心步骤 2
SQL 执行交给程序完成,LLM 不直接操作数据库。
回答用户
def generate_answer(state: State):
"""Answer question using retrieved information as context."""
if state["approved"]:
prompt = (
"Given the following user question, corresponding SQL query, "
"and SQL result, answer the user question.\n\n"
f'Question: {state["question"]}\n'
f'SQL Query: {state["query"]}\n'
f'SQL Result: {state["result"]}'
)
response = llm.invoke(prompt)
return {"answer": response.content}
else:
prompt = f'{"同意" if state["approved"] else "拒绝"} 用户拒绝当前执行'
response = llm.invoke(prompt)
return {"answer": response.content}
PAL 核心步骤 3
LLM 根据 SQL 结果生成最终自然语言答案。
流程图
graph_builder = StateGraph(State).add_sequence(
[write_query, wait_for_user_approve, excute_query, generate_answer]
)
graph_builder.add_edge(START, "write_query")
用 LangGraph 编排整个 PAL 流程。
持久化 checkpoint + 启动循环
DB_URI = "postgresql://postgres:123456@localhost:5432/langchaindemo?sslmode=disable"
with PostgresSaver.from_conn_string(DB_URI) as checkpointer:
checkpointer.setup()
input_thread_id = input("输入thread_id:")
time_str = time.strftime("%Y%m%d", time.localtime())
config = {"configurable": {"thread_id": f"{time_str}-{input_thread_id}-agent-demo"}}
graph = graph_builder.compile(checkpointer=checkpointer)
print("输入问题,输入 exit 退出。")
while True:
query = input("你: ")
if query.strip().lower() == "exit":
break
response = graph.invoke(
{"question": query},
config,
)
print(response)
Checkpoint 存入 Postgres
用户可断点续跑
CLI 交互友好
总结:PAL 模式的好处
1.LLM 不做逻辑执行,只负责「写程序」
2.复杂逻辑交给程序完成,结果回传给 LLM
3.SQL 查询避免安全风险
4.有明确「用户确认」步骤
5.checkpoint 持久化,支持中断恢复
运行效果示例
AI大模型应用开发-用LangChain构建PAL应用:SQL的生成与执行的更多相关文章
- AI大模型学习了解
# 百度文心 上线时间:2019年3月 官方介绍:https://wenxin.baidu.com/ 发布地点: 参考资料: 2600亿!全球最大中文单体模型鹏城-百度·文心发布 # 华为盘古 上线时 ...
- 华为高级研究员谢凌曦:下一代AI将走向何方?盘古大模型探路之旅
摘要:为了更深入理解千亿参数的盘古大模型,华为云社区采访到了华为云EI盘古团队高级研究员谢凌曦.谢博士以非常通俗的方式为我们娓娓道来了盘古大模型研发的"前世今生",以及它背后的艰难 ...
- 保姆级教程:用GPU云主机搭建AI大语言模型并用Flask封装成API,实现用户与模型对话
导读 在当今的人工智能时代,大型AI模型已成为获得人工智能应用程序的关键.但是,这些巨大的模型需要庞大的计算资源和存储空间,因此搭建这些模型并对它们进行交互需要强大的计算能力,这通常需要使用云计算服务 ...
- 无插件的大模型浏览器Autodesk Viewer开发培训-武汉-2014年8月28日 9:00 – 12:00
武汉附近的同学们有福了,这是全球第一次关于Autodesk viewer的教室培训. :) 你可能已经在各种场合听过或看过Autodesk最新推出的大模型浏览器,这是无需插件的浏览器模型,支持几十种数 ...
- zz独家专访AI大神贾扬清:我为什么选择加入阿里巴巴?
独家专访AI大神贾扬清:我为什么选择加入阿里巴巴? Natalie.Cai 拥有的都是侥幸,失去的都是人生 关注她 5 人赞同了该文章 本文由 「AI前线」原创,原文链接:独家专访AI大神贾扬清:我 ...
- DeepSpeed Chat: 一键式RLHF训练,让你的类ChatGPT千亿大模型提速省钱15倍
DeepSpeed Chat: 一键式RLHF训练,让你的类ChatGPT千亿大模型提速省钱15倍 1. 概述 近日来,ChatGPT及类似模型引发了人工智能(AI)领域的一场风潮. 这场风潮对数字世 ...
- [web建站] 极客WEB大前端专家级开发工程师培训视频教程
极客WEB大前端专家级开发工程师培训视频教程 教程下载地址: http://www.fu83.cn/thread-355-1-1.html 课程目录:1.走进前端工程师的世界HTML51.HTML5 ...
- HBase实践案例:知乎 AI 用户模型服务性能优化实践
用户模型简介 知乎 AI 用户模型服务于知乎两亿多用户,主要为首页.推荐.广告.知识服务.想法.关注页等业务场景提供数据和服务, 例如首页个性化 Feed 的召回和排序.相关回答等用到的用户长期兴趣特 ...
- 搭乘“AI大数据”快车,肌肤管家,助力美业数字化发展
经过疫情的发酵,加速推动各行各业进入数据时代的步伐.美业,一个通过自身技术.产品让用户变美的行业,在AI大数据的加持下表现尤为突出. 对于美妆护肤企业来说,一边是进入存量市场,一边是疫后的复苏期,一边 ...
- 千亿参数开源大模型 BLOOM 背后的技术
假设你现在有了数据,也搞到了预算,一切就绪,准备开始训练一个大模型,一显身手了,"一朝看尽长安花"似乎近在眼前 -- 且慢!训练可不仅仅像这两个字的发音那么简单,看看 BLOOM ...
随机推荐
- 深入理解Hadoop读书笔记-2
背景 公司的物流业务系统目前实现了使用storm集群进行过门事件的实时计算处理,但是还有一个需求,我们需要存储每个标签上传的每条明细数据,然后进行定期的标签报表统计,这个是目前的实时计算框架无法满足的 ...
- Java WatchService监控指定路径下的文件新增、删除和修改(子文件夹、指定文件类型)
WatchService 是 Java NIO 包 (java.nio.file) 中提供的一个用于监控文件系统变化的 API.它允许应用程序监听目录中的文件创建.修改和删除事件. 基本原理 Watc ...
- day11”函数“入门
函数 函数的作⽤ 函数的使⽤步骤 函数的参数作⽤ 函数的返回值作⽤ 函数的说明⽂档 函数嵌套 函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段. 函数能提高应用的模块性,和代码的重复利 ...
- 使用Python可视化磁场
引言 随着科学技术的发展,物理学中的很多概念变得越来越复杂,但我们可以利用 Python 这一强大的工具,将一些抽象的物理现象变得更加直观易懂.今天,我们将以"磁场可视化"为主题, ...
- CSharp_base
C# 基础篇 枚举(enum) 枚举是一个被命名的整形常量的集合 用于表示: 状态 类型 申明枚举:创建一个自定义的枚举类型 申明枚举变量:使用申明的自定义的枚举类型,来创建一个枚举变量 语法 //语 ...
- java中堆污染(heap pollution)以及@SafeVarargs注解使用
什么是堆污染 heap pollution 堆污染发生在使用可变参数(varargs)或泛型时,将不兼容的类型插入到一个泛型对象中.这会导致在运行时尝试访问这些对象时发生 ClassCastExcep ...
- jdk源码目录说明
- 操作系统综合题之“采用实时调度,可调度的限制条件和可调度的最大X值是是多少ms的CPU时间”
一.问题:单处理器情况下,m个周期性实时进程,若进程i处理时间为Ci,周期时间为Pi < (1 ≤ i ≤ m) 1.要使系统可调度的限制条件什么? 2.设置一个实时系统使用了4个周期事件,其周 ...
- js操作session
// 保存数据到sessionStorage sessionStorage.setItem('key', 'value'); // 从sessionStorage获取数据 sessionStorage ...
- RPC实战与核心原理之分布式环境下如何快速定位问题
分布式环境下如何快速定位 回顾 如何建立可靠的安全体系,关键点就是"鉴权",我们可以通过统一的鉴权服务动态生成秘钥,提高 RPC 调用的安全性. 分布式环境下定位问题有哪些困难 举 ...