【2024最全最细Lanchain教程-8】Langchain数据库查询链

【2024最全最细Lanchain教程-7】Langchain数据增强之词嵌入、存储和检索-CSDN博客

        上几节课,我们介绍了什么是数据增强,数据增强的基本业务流程是什么样的,以及如何通过代码来实现数据增强,这节课,我们继续开始深入研究langchain的链。

        之前我们在前面的demo里,已经看到了什么链,下面就是一个最简单、可运行的链:

import langchain
import os

from langchain_openai import ChatOpenAI

# 引入模板 ChatPromptTemplate
from langchain_core.prompts import ChatPromptTemplate

api_key = os.getenv("OPENAI_API_KEY")

llm = ChatOpenAI(
    temperature=0,
    openai_api_key = os.getenv("OPENAI_API_KEY"),
    base_url = os.getenv("OPENAI_BASE_URL")
)



prompt = ChatPromptTemplate.from_messages([
    ("system", "你是一个中国历史专家."),
    ("user", "{input}")
])

chain = prompt | llm

chain.invoke({"input":"中国改革开放的总设计师是谁?"})

        prompt提示词和大语言模型llm构成了一个最简单的链。

链的类型

        链的类型大体分为基础链和工具链:

【2024最全最细Lanchain教程-8】Langchain数据库查询链_第1张图片

        上文用LCEL语法构成的链,应该是作为顺序链的一种,更多这方面的知识可以关注官网里面的说明:Chains | ️ Langchain。

        我们今天来应用和实践数据库查询链 create_sql_query_chain,这个链在我们查询数据库的时候起到重要作用。

数据库查询链create_sql_query_chain

  1. 建立一个本地的MYSQL数据库     

        按照网上的其他教程,可以自行下载和安装MYSQL数据库到本地,在创建本地测试数据的时候,可以使用chatGPT来帮你生成语句,如下图所示:

【2024最全最细Lanchain教程-8】Langchain数据库查询链_第2张图片

        包括测试数据也可以让chatGPT生成:

【2024最全最细Lanchain教程-8】Langchain数据库查询链_第3张图片

        chatGPT帮你生成的SQL语句你进入到MYSQL里执行就OK了,然后用下面的代码来连接和测试MYSQL数据库:

from langchain_community.utilities import SQLDatabase

db_user = "root"
db_password = "161212"
db_host = "127.0.0.1"
db_name = "langchain"

#注意要安装pymysql这个库

db = SQLDatabase.from_uri(f"mysql+pymysql://{db_user}:{db_password}@{db_host}/{db_name}")

print(db.dialect)
print(db.get_usable_table_names())
db.run("SELECT * FROM user;")

        注意要安装一下 pymysql这个库,否则无法建立mysql连接。建立好之后跑一下db.run("SELECT * FROM user;")可以看到数据:

【2024最全最细Lanchain教程-8】Langchain数据库查询链_第4张图片

2. 使用create_sql_query_chain来构链

        从 langchain.chains 引入 create_sql_query_chain,然后构造一个chain:

import os

from langchain.chains import create_sql_query_chain
from langchain_openai import ChatOpenAI

llm = ChatOpenAI(
    temperature=0,
    openai_api_key = os.getenv("OPENAI_API_KEY"),
    base_url = os.getenv("OPENAI_BASE_URL")
)

chain = create_sql_query_chain(llm, db)
response = chain.invoke({"question": "How many people are there in the user table?"})
response

        针对这个问题,LLM给出了正确的SQL语句:

【2024最全最细Lanchain教程-8】Langchain数据库查询链_第5张图片

3. 用 get_prompts()方法来查看langchain内置的prompt样式     

          可以用chain.get_prompts()方法来查看链的内置prompt模板template是什么样的,正是因为有了这样准确和完整的提示词工程,大语言模型才知道如果通过问题来生成SQL语句:

chain.get_prompts()[0].pretty_print()

        我把template的全文贴一下:

You are a MySQL expert. Given an input question, first create a syntactically correct MySQL query to run, then look at the results of the query and return the answer to the input question.
Unless the user specifies in the question a specific number of examples to obtain, query for at most {top_k} results using the LIMIT clause as per MySQL. You can order the results to return the most informative data in the database.
Never query for all columns from a table. You must query only the columns that are needed to answer the question. Wrap each column name in backticks (`) to denote them as delimited identifiers.
Pay attention to use only the column names you can see in the tables below. Be careful to not query for columns that do not exist. Also, pay attention to which column is in which table.
Pay attention to use CURDATE() function to get the current date, if the question involves "today".

Use the following format:

Question: Question here
SQLQuery: SQL Query to run
SQLResult: Result of the SQLQuery
Answer: Final answer here

Only use the following tables:
{table_info}

Question: {input}

  4. 构造另外一个链来执行上一个链生成SQL

         我们可以从langchain_community.tools.sql_database.tool引入一个 QuerySQLDataBaseTool 来执行 write_query 这个链生成的SQL语句,具体如下:

from langchain_community.tools.sql_database.tool import QuerySQLDataBaseTool

execute_query = QuerySQLDataBaseTool(db=db)
write_query = create_sql_query_chain(llm, db)
chain = write_query | execute_query
chain.invoke({"question": "user表里有多少个admin用户?"})

          这里有两个链,第一个链chain由write_query和execute_query组成,chain调用invoke方法提出问题,这个问题作为input输入给 write_query,​​write_query是第二个链,它使用之前构造好的模型 llm 和数据库 db ,生成了正确的SQL语句 ,通过 chain链传递给了 execute_query 进行执行,执行结果为:

【2024最全最细Lanchain教程-8】Langchain数据库查询链_第6张图片

        就是说,user表里有四个用户是admin用户。

5. 构造一个链来回答用户的问题

       得到了SQL结果我们还是不满意,我们希望应用可以最终回答用户的问题,我们还需要构造一个链来进行回答:

from operator import itemgetter

from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import PromptTemplate
from langchain_core.runnables import RunnablePassthrough

answer_prompt = PromptTemplate.from_template(
"""Given the following user question, corresponding SQL query, and SQL result, answer the user question. 用中文回答最终答案

Question: {question}
SQL Query: {query}
SQL Result: {result}
Answer: """
)


answer = answer_prompt | llm | StrOutputParser()

        这个链的prompt模板很重要,这个模板需要有三个参数输入,一个是用户最初的问题question,一个是​​write_query生成的SQL语句,一个是execute_query生成的结果,基于这三个参数,answer链才可以回答最后的问题。

6. 构造最后一个FINAL链来把上述流程串起来

        上面的流程已经很清晰了,但是我们还需要最后一个final链把这些流程串起来,形成最后一个链:

final_chain = (
    RunnablePassthrough.assign(query=write_query).assign(result=itemgetter("query") | execute_query)
    | answer
)

final_chain.invoke({"question": "user表里有多少个admin用户?"})

        final_chain里面的RunnablePassthrough方法我们之前在【2024最全最细Lanchain教程-7】Langchain数据增强之词嵌入、存储和检索-CSDN博客 里遇到过,他的作用是接收和传递参数。在这里他先接收 write_query链处理的结果赋值给 query("SELECT COUNT(*) FROM `user` WHERE `role` = 'admin'") , query是一个 键值对{“query”:"SELECT COUNT(*) FROM `user` WHERE `role` = 'admin"}。然后又用itemgetter把query的值赋给 result ,然后把result传给 execute_query去执行,执行的结果([(4,)])传给 answer链去解答。最后得到最终的答案:

【2024最全最细Lanchain教程-8】Langchain数据库查询链_第7张图片

     至此,完成了全部流程,不仅给出了正确的答案而且还是通过自然语言来妥善回答了用户的问题。

本教学演示代码已上传github: https://github.com/jerry1900/jupyter

本教学有B站视频,欢迎大家捧场:【2024最全最细】langchain之数据库查询_哔哩哔哩_bilibili

        
 

你可能感兴趣的:(langchain,ai,数据库,chatgpt)