基于 LangChain 实现数据库问答机器人
一、简介
在 Retrieval 或者 ReACT 的一些场景中,常常需要数据库与人工智能结合。而 LangChain 本身就封装了许多相关的内容,在其官方文档-SQL 能力中,也有非常好的示例。
二、应用场景
在未出现人工智能,如果想要完成数据查询与数据分析的工作,则需要相关人员有相应的数据库的功底,而在 LangChain 结合大语言模型的过程中,应对这些问题则相当轻松------写清晰的提示词即可。
- 生成将基于自然语言问题运行的查询。
在传统的工作流程中,如果想要在数据库中搜索一些信息,那么就必须要掌握相应的数据库技术,比如 SQL 语句查询等,但是其本身有很高的学习成本。如果能用自然语言代替这个过程,则任何人都无需学习 SQL 语法,即可轻松进行数据的查询。
- 根据数据库数据回答问题的聊天机器人。
自然也可以做一个基于数据库信息的问答机器人,比如产品经理以及一些业务人员,也可以轻松获得数据库的信息。
- 数据分析展示面板
之前常常会通过 SQL 完成一些数据分析的工作,并通过各种样式的表格展示出来。此过程也可以通过人工智能完成。
三、实战案例
1、需求说明
- 输入查询的需求,返回查询的结果。
- 查询的结果通过自然语言表述(选做)。
2、实现思路
3、对应源码
https://python.langchain.com/v0.1/docs/use_cases/sql/quickstart/
python
from langchain_community.utilities import SQLDatabase
#通过工具链接数据库,查看数据库的信息是否整除
db = SQLDatabase.from_uri("sqlite:///Chinook.db")
print(db.dialect)
print(db.get_usable_table_names())
db.run("SELECT * FROM Artist LIMIT 10;")
执行结果:
python
from langchain_community.tools.sql_database.tool import QuerySQLDataBaseTool
from langchain_community.utilities import SQLDatabase
# 通过工具链接数据库,查看数据库的信息是否整除
db = SQLDatabase.from_uri("sqlite:///Chinook.db")
# 通过LLM 获取查询语句
from langchain.chains import create_sql_query_chain
from langchain_openai import ChatOpenAI
# 初始化大语言模型
llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0)
# 创建查询链,作用是将自然语言转换为1条sql语句
chain = create_sql_query_chain(llm, db)
# 执行链,通过自然语言进行查询
response = chain.invoke({"question": "How many employees are there"})
# 响应结果为1条sql语句
print(response)
#查询动作
print(db.run(response))
执行结果
python
SELECT COUNT("EmployeeId") AS "TotalEmployees" FROM "Employee"
[(8,)]
Execute SQL query
Now that we've generated a SQL query, we'll want to execute it. This is the most dangerous part of creating a SQL chain. Consider carefully if it is OK to run automated queries over your data. Minimize the database connection permissions as much as possible. Consider adding a human approval step to you chains before query execution (see below).
We can use the QuerySQLDatabaseTool to easily add query execution to our chain:
python
from langchain_community.tools.sql_database.tool import QuerySQLDataBaseTool
from langchain_community.utilities import SQLDatabase
# 通过工具链接数据库,查看数据库的信息是否整除
db = SQLDatabase.from_uri("sqlite:///Chinook.db")
# 通过LLM 获取查询语句
from langchain.chains import create_sql_query_chain
from langchain_openai import ChatOpenAI
# 初始化大语言模型
llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0)
# 创建查询链,作用是将自然语言转换为1条sql语句
write_query = create_sql_query_chain(llm, db)
# 执行sql语句
execute_query = QuerySQLDataBaseTool(db=db)
# 先生成一个查询语句,然后再执行query
chain = write_query | execute_query
response1=write_query.invoke({"question": "How many employees are there"})
print(f"response1的结果为:{response1}")
print('================================')
response2=chain.invoke({"question": "How many employees are there"})
print(f"response2的结果为:{response2}")
执行结果:
python
response1的结果为:SELECT COUNT("EmployeeId") AS "TotalEmployees" FROM "Employee"
================================
response2的结果为:[(8,)]
Answer the question
Now that we've got a way to automatically generate and execute queries, we just need to combine the original question and SQL query result to generate a final answer. We can do this by passing question and result to the LLM once more:
python
from operator import itemgetter
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import PromptTemplate
from langchain_core.runnables import RunnablePassthrough
from langchain_community.tools.sql_database.tool import QuerySQLDataBaseTool
from langchain_community.utilities import SQLDatabase
# 通过工具链接数据库,查看数据库的信息是否整除
db = SQLDatabase.from_uri("sqlite:///Chinook.db")
# 通过LLM 获取查询语句
from langchain.chains import create_sql_query_chain
from langchain_openai import ChatOpenAI
# 初始化大语言模型
llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0)
# 创建查询链,作用是将自然语言转换为1条sql语句
write_query = create_sql_query_chain(llm, db)
# 执行sql语句
execute_query = QuerySQLDataBaseTool(db=db)
# 先生成一个查询语句,然后再执行query
chain = write_query | execute_query
response1 = write_query.invoke({"question": "How many employees are there"})
print(f"response1的结果为:{response1}")
print('================================')
response2 = chain.invoke({"question": "How many employees are there"})
print(f"response2的结果为:{response2}")
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()
# 组成和sql相关的链
chain = (
RunnablePassthrough.assign(query=write_query).assign(
result=itemgetter("query") | execute_query
)
| answer
)
response3 = chain.invoke({"question": "How many employees are there"})
print('===================================')
print(f"response3的值为:{response3}")
执行结果: