使用 LangChain 和 Llama 3.1 查询你的 PostgreSQL 数据库:探索 LLMs — 2
7 个月前
在我们之前的博客文章中,我们讨论了如何通过输入自然语言文本来生成和执行数据库查询。在今天的博客文章中,我们将尝试将查询的输出再次传递给大型语言模型(LLM),以生成同样是自然语言的结果。
如果你是这个系列的新读者,可以先查看 这篇文章 以获取更多背景信息。
让我们开始编码吧!
第0步 — 之前的代码
我们将在之前博客文章的基础上构建这个功能,因此以下部分将保持相对相似。
from langchain_community.llms import Ollama
llm = Ollama(model = "llama3.1")
from langchain_community.utilities import SQLDatabase
from langchain.chains import create_sql_query_chain
from langchain_core.prompts import PromptTemplate
db = SQLDatabase.from_uri("postgresql://abouzuhayr:@localhost:5432/postgres")
write_query = create_sql_query_chain(llm=llm, db=db)
第1步:定义答案提示模板
我们将定义一个提示模板,用于生成最终的用户答案。
from langchain_core.prompts import PromptTemplate
answer_prompt = PromptTemplate.from_template(
"""根据以下用户问题、相应的SQL查询和SQL结果,回答用户问题。
问题: {question}
SQL 查询: {query}
SQL 结果: {result}
答案: """
)
PromptTemplate
是一种结构化输入的方式,我们将提供给 LLM。它允许我们定义一个带有占位符(如 {question}
、{query}
和 {result}
)的模板,这些占位符将在执行时用实际值填充。这有助于 LLM 理解上下文并生成准确的响应。
第2步:为 write_query_with_question
创建可运行组件
接下来,我们需要创建一个组件,从用户的问题生成 SQL 查询,并将问题传递给后续使用。我们将定义一个函数并用 RunnableLambda
包装它:
from langchain.schema.runnable import RunnableLambda
# 创建一个可运行的组件,包装 write_query 并传递问题
def write_query_with_question(inputs):
response = write_query.invoke(inputs)
return {'response': response, 'question': inputs['question']}
write_query_runnable = RunnableLambda(write_query_with_question)
理解 RunnableLambda
RunnableLambda
允许我们包装一个简单的 Python 函数,以便它可以作为我们 LangChain 链中的一个组件使用。这使得它与其他链元素兼容,并确保数据在它们之间顺畅流动。
在这个例子中,write_query_with_question
:
- 调用
write_query
链(从问题生成 SQL 查询)。 - 返回一个字典,包含
write_query
的响应和原始问题。
第3步:提取并执行 SQL 查询
现在,我们将定义一个函数,从 LLM 的响应中提取 SQL 查询并在我们的数据库中执行它:
import re
# 定义提取和执行 SQL 查询的函数
def extract_and_execute_sql(inputs):
# 提取响应文本和问题
response = inputs.get('response', '')
question = inputs.get('question', '')
# 定义正则表达式模式以匹配 SQL 查询
pattern = re.compile(r'SQLQuery:s*(.*)')
# 在响应中搜索模式
match = pattern.search(response)
if match:
# 提取匹配的 SQL 查询
sql_query = match.group(1).strip()
# 使用自定义逻辑执行查询
result = db.run(sql_query)
# 返回链中下一步所需的信息
return {
"question": question,
"query": sql_query,
"result": result
}
else:
return {
"question": question,
"query": None,
"result": "在响应中未找到 SQL 查询。"
}
这个函数:
- 使用正则表达式从 LLM 的响应中提取 SQL 查询。
- 在数据库中执行 SQL 查询。
- 返回问题、提取的 SQL 查询和查询结果。
用 RunnableLambda
包装 extract_and_execute_sql
我们用 RunnableLambda
包装 extract_and_execute_sql
函数,以便它可以包含在我们的链中:
# 用 RunnableLambda 包装你的函数
extract_and_execute = RunnableLambda(extract_and_execute_sql)
同样,RunnableLambda
使我们的自定义函数与链兼容,将其视为可运行的组件。
构建链
现在,我们将组件组装成一个链:
from langchain_core.output_parsers import StrOutputParser
# 创建链
chain = (
write_query_runnable
| extract_and_execute
| answer_prompt
| llm
| StrOutputParser()
)
链是如何工作的?
这个链由几个组件组成,使用 |
操作符连接在一起,表示数据从一个组件流向下一个组件。
write_query_runnable
:从用户的问题生成 SQL 查询并传递问题。extract_and_execute
:从响应中提取 SQL 查询并在数据库中执行。answer_prompt
:将输入(问题、SQL 查询和结果)格式化为 LLM 的提示。llm
:语言模型根据提示生成自然语言答案。StrOutputParser()
:将 LLM 的输出解析为字符串以供最终展示。
可视化数据流
输入:{"question": "总共有多少员工?"}
在 write_query_runnable
之后:
- 生成 SQL 查询。
- 输出:
{'response': '...SQLQuery: SELECT COUNT(*) FROM employees;', 'question': '总共有多少员工?'}
在 extract_and_execute
之后:
- 提取并执行 SQL 查询。
- 输出:
{'question': '总共有多少员工?', 'query': 'SELECT COUNT(*) FROM employees;', 'result': '42'}
在 answer_prompt
之后:
- 格式化 LLM 的提示。
- 输出:填充占位符的格式化字符串。
在 llm
之后:
- 生成自然语言答案。
- 输出:
'总共有 42 名员工。'
在 StrOutputParser()
之后:
- 将输出解析为字符串。
- 最终输出:
'总共有 42 名员工。'
调用链
我们现在可以使用链来处理问题:
# 用你的问题调用链
response = chain.invoke({"question": "总共有多少员工?"})
# 打印最终答案
print(response)
这将输出:
总共有 5 名员工。
结论
通过利用 LangChain 的链式能力,我们可以构建一个模块化和可扩展的应用程序,处理自然语言问题,生成和执行 SQL 查询,并以用户友好的格式返回结果。使用 PromptTemplate
和 RunnableLambda
使我们能够创建可重用的组件,轻松集成到链中。
关键要点
PromptTemplate
:通过定义带有占位符的模板,帮助结构化 LLM 的输入。RunnableLambda
:包装自定义函数,使其与 LangChain 的链兼容,将其视为可运行的组件。- 链式处理:通过将组件连接在一起,我们可以创建逐步处理数据的复杂工作流。
在我们下一个博客文章中,我们将探讨如何为我们的聊天机器人添加记忆,使其在回答问题时能够保留上下文,从而使使用体验更加有趣!
在此之前,祝你编码愉快!
等等,你就这样离开而不分享你的智慧吗?🤔
等等!在你再次潜入代码深渊或开始将更多函数串联在一起之前,让我们聊聊吧!如果这篇文章让你发笑、思考或质疑我的理智(都是有效的反应),为什么不点个赞呢?👍
记住,每次你留下评论:
- 一只虫子就会长出翅膀 🐛➡️🦋
- 程序员的咖啡变成代码 ☕➡️💻
- 无限循环找到尽头 🔄➡️🏁
而且,老实说,我的代码需要所有的帮助。😅
FluxAI 中文
© 2025. All Rights Reserved