LangChain-v0.2文档翻译:2.7、教程-在SQL数据上构建一个问答系统

  1. 介绍
  2. 教程
    2.1. 构建一个简单的 LLM 应用程序
    2.2. 构建一个聊天机器人
    2.3. 构建向量存储库和检索器
    2.4. 构建一个代理
    2.5. 构建检索增强生成 (RAG) 应用程序
    2.6. 构建一个会话式RAG应用程序
    2.7. 在SQL数据上构建一个问答系统(点击查看原文

基于 SQL 数据构建问答系统

使大型语言模型(LLM)查询结构化数据与查询非结构化文本数据有质的不同。在后者中,通常生成可以针对向量数据库搜索的文本,而结构化数据的方法通常是让LLM编写并在DSL(例如SQL)中执行查询。在本指南中,我们将介绍在数据库中创建表格数据上的问答系统的基本方法。我们将涵盖使用链(chains)和代理(agents)的实现。这些系统将允许我们询问数据库中的数据并得到自然语言答案。两者之间的主要区别在于,我们的代理可以根据需要多次循环查询数据库以回答问题。

⚠️ 安全提示 ⚠️

构建SQL数据库的问答系统需要执行模型生成的SQL查询。这样做存在固有风险。确保您的数据库连接权限始终尽可能地限定在链/代理的需求范围内。这将减轻但不会消除构建模型驱动系统的风险。有关一般安全最佳实践的更多信息,请参阅此处。

架构

在高层次上,这些系统的步骤是:

  1. 将问题转换为DSL查询:模型将用户输入转换为SQL查询。
  2. 执行SQL查询:执行查询。
  3. 回答问题:模型使用查询结果响应用户输入。

注意,查询CSV数据可以遵循类似的方法。有关详细信息,请参见我们关于CSV数据上问答的指南。
在这里插入图片描述

安装

首先,获取所需的包并设置环境变量:

%pip install --upgrade --quiet langchain langchain-community langchain-openai

我们将在本指南中使用OpenAI模型。

import getpass
import os

os.environ["OPENAI_API_KEY"] = getpass.getpass()

# 注释掉下面的代码以使用LangSmith。不是必需的。
# os.environ["LANGCHAIN_API_KEY"] = getpass.getpass()
# os.environ["LANGCHAIN_TRACING_V2"] = "true"

下面的例子将使用SQLite连接和Chinook数据库。按照这些安装步骤在同一目录中创建Chinook.db

  • 将此文件保存为Chinook.sql
  • 运行sqlite3 Chinook.db
  • 运行.read Chinook.sql
  • 测试SELECT * FROM Artist LIMIT 10;

现在,Chinook.db在目录中,我们可以使用SQLAlchemy驱动的SQLDatabase类与之交互:

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;")
sqlite
['Album', 'Artist', 'Customer', 'Employee', 'Genre', 'Invoice', 'InvoiceLine', 'MediaType', 'Playlist', 'PlaylistTrack', 'Track']
"[(1, 'AC/DC'), (2, 'Accept'), (3, 'Aerosmith'), (4, 'Alanis Morissette'), (5, 'Alice In Chains'), (6, 'Antônio Carlos Jobim'), (7, 'Apocalyptica'), (8, 'Audioslave'), (9, 'BackBeat'), (10, 'Billy Cobham')]"

太好了!我们现在有一个可以查询的SQL数据库。现在让我们尝试将其连接到LLM。

链(Chains)

链(即 LangChain Runnable的组合)支持步骤可预测的应用程序。我们可以创建一个简单的链,它接受一个问题并执行以下操作:

  • 将问题转换为SQL查询;
  • 执行查询;
  • 使用结果回答原始问题。

有些场景不受这种安排的支持。例如,该系统将为任何用户输入执行SQL查询 - 即使是"hello"。重要的是,正如我们将在下面看到的,一些问题需要多个查询才能回答。我们将在代理部分解决这些场景。

将问题转换为SQL查询

SQL链或代理的第一步是将用户输入转换为SQL查询。LangChain提供了一个内置的链来进行此操作:create_sql_query_chain

  • OpenAI
pip install -qU langchain-openai
import getpass
import os

os.environ["OPENAI_API_KEY"] = getpass.getpass()

from langchain_openai import ChatOpenAI

llm = ChatOpenAI(model="gpt-3.5-turbo-0125")
from langchain.chains import create_sql_query_chain

chain = create_sql_query_chain(llm, db)
response = chain.invoke({"question": "How many employees are there"})
response
'SELECT COUNT("EmployeeId") AS "TotalEmployees" FROM "Employee"
LIMIT 1;'

我们可以执行查询以确保它有效:

db.run(response)

‘[(8,)]’

我们可以查看LangSmith跟踪以更好地了解此链正在做什么。我们还可以直接检查链的提示。查看提示(如下),我们可以看到它是:

  • 特定于方言。在这种情况下,它明确引用 SQLite。
  • 具有所有可用表的定义。
  • 每个表有三行示例。

这种技术受到诸如此类的论文的启发,这些论文建议显示示例行并明确表名可以提高性能。我们还可以像这样检查完整的提示:

chain.get_prompts()[0].pretty_print()
您是一位SQLite专家。根据输入的问题,首先创建一个语法正确的SQLite查询来运行,然后查看查询结果并返回输入问题的答案。
除非用户在问题中指定了要获取的示例数量,否则按SQLite的规定使用LIMIT子句查询最多5个结果。您可以按相关列对结果进行排序,以返回数据库中最有趣的示例。
永远不要查询表中的所有列。您必须只查询回答该问题所需的列。将每个列名称用双引号括起来以表示它们为分隔标识符。
注意只使用您在下面表格中看到的列名称。注意不要查询不存在的列。还要注意哪个列在哪个表中。
注意使用date('now')函数获取当前日期,如果问题涉及"今天"。

使用以下格式:

问题:问题在这里
SQL查询:要运行的SQL查询
SQL结果:SQL查询的结果
答案:最终答案在这里

只使用以下表:
\[33;1m\[1;3m{table_info}\[0m

问题:\[33;1m\[1;3m{input}\[0m

执行SQL查询

现在我们已经生成了一个SQL查询,我们将想要执行它。**这是创建SQL链中最危险的部分。**仔细考虑是否可以在您的数据上运行自动化查询。尽可能减少数据库连接权限。考虑在执行查询前在链中添加人工审批步骤(见下文)。

我们可以使用QuerySQLDatabaseTool轻松地将查询执行添加到我们的链中:

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": "How many employees are there"})

回答问题

现在我们已经找到了一种自动生成和执行查询的方法,我们只需要将原始问题和SQL查询结果结合起来生成最终答案。我们可以通过再次将问题和结果传递给LLM来做到这一点:

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: """
)

chain = (
    RunnablePassthrough.assign(query=write_query).assign(
        result=itemgetter("query") | execute_query
    )
    | answer_prompt
    | llm
    | StrOutputParser()
)

chain.invoke({"question": "How many employees are there"})
'There are a total of 8 employees.'

让我们回顾一下上述LCEL中发生了什么。假设这个链被调用了。

  • 在第一个RunnablePassthrough.assign之后,我们有一个可运行的组件,包含两个元素:

{"question": question, "query": write_query.invoke(question)}

其中write_query将生成一个SQL查询以回答该问题。

  • 在第二个RunnablePassthrough.assign之后,我们添加了第三个元素"result",包含execute_query.invoke(query),其中query是在前一步计算的。
  • 这三个输入被格式化成提示并传递到LLM。
  • StrOutputParser()提取输出消息的字符串内容。

注意,我们正在组合LLM、工具、提示和其他链,但由于每个都实现了Runnable接口,它们的输入和输出可以以合理的方式绑定在一起。

下一步

对于更复杂的查询生成,我们可能想要创建少量示例提示或添加查询检查步骤。有关此类高级技术和更多信息,请查看:

  • 提示策略:高级提示工程技术。
  • 查询检查:添加查询验证和错误处理。
  • 大型数据库:处理大型数据库的技术。

代理(Agents)

LangChain有一个SQL代理,它提供了一种比链更灵活的与SQL数据库交互的方式。使用SQL代理的主要优点是:

  • 它可以基于数据库的架构以及数据库的内容(如描述特定表)回答问题。
  • 它可以通过运行生成的查询,捕获跟踪并正确重新生成它来从错误中恢复。
  • 它可以按需查询数据库,直到回答用户问题为止。
  • 它将通过仅从相关表中检索架构来节省令牌。

要初始化代理,我们将使用SQLDatabaseToolkit创建一组工具:

  • 创建和执行查询
  • 检查查询语法
  • 检索表描述
  • ……等等
from langchain_community.agent_toolkits import SQLDatabaseToolkit

toolkit = SQLDatabaseToolkit(db=db, llm=llm)

tools = toolkit.get_tools()

tools
[QuerySQLDataBaseTool(description="Input to this tool is a detailed and correct SQL query, output is a result from the database. If the query is not correct, an error message will be returned. If an error is returned, rewrite the query, check the query, and try again. If you encounter an issue with Unknown column 'xxxx' in 'field list', use sql_db_schema to query the correct table fields.", db=langchain_community.utilities.sql_database.SQLDatabase object at 0x113403b50),
 InfoSQLDatabaseTool(description='Input to this tool is a comma-separated list of tables, output is the schema and sample rows for those tables. Be sure that the tables actually exist by calling sql_db_list_tables first! Example Input: table1, table2, table3', db=langchain_community.utilities.sql_database.SQLDatabase object at 0x113403b50),
 ListSQLDatabaseTool(db=langchain_community.utilities.sql_database.SQLDatabase object at 0x113403b50),
 QuerySQLCheckerTool(description='Use this tool to double check if your query is correct before executing it. Always use this tool before executing a query with sql_db_query!', db=langchain_community.utilities.sql_database.SQLDatabase object at 0x113403b50, llm=ChatOpenAI(client=openai.resources.chat.completions.Completions object at 0x115b7e890, async_client=openai.resources.chat.completions.AsyncCompletions object at 0x115457e10, temperature=0.0, openai_api_key=SecretStr('**********'), openai_proxy='')]

系统提示

我们还想为我们的代理创建一个系统提示。这将包括如何行为的指令。

from langchain_core.messages import SystemMessage

SQL_PREFIX = """
You are an agent designed to interact with a SQL database.
Given an input question, create a syntactically correct SQLite query to run, then look at the results of the query and return the answer.
Unless the user specifies a specific number of examples they wish to obtain, always limit your query to at most 5 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 the relevant columns given the question.
You have access to tools for interacting with the database.
Only use the below tools. Only use the information returned by the below tools to construct your final answer.
You MUST double check your query before executing it. If you get an error while executing a query, rewrite the query and try again.

DO NOT make any DML statements (INSERT, UPDATE, DELETE, DROP etc.) to the database.

To start you should ALWAYS look at the tables in the database to see what you can query.
Do NOT skip this step.
Then you should query the schema of the most relevant tables.
"""

system_message = SystemMessage(content=SQL_PREFIX)

初始化代理

首先,获取所需包LangGraph

%pip install --upgrade --quiet langgraph

我们将使用预构建的LangGraph代理来构建我们的代理

from langchain_core.messages import HumanMessage
from langgraph.prebuilt import chat_agent_executor

agent_executor = chat_agent_executor.create_tool_calling_executor(
    llm, tools, messages_modifier=system_message
)

考虑代理如何响应以下问题:

for s in agent_executor.stream(
    {"messages": [HumanMessage(content="Which country's customers spent the most?")]}
):
    print(s)
    print("----")
{'agent': {'messages': [AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_vnHKe3oul1xbpX0Vrb2vsamZ', 'function': {'arguments': '{"query":"SELECT c.Country, SUM(i.Total) AS Total_Spent FROM customers c JOIN invoices i ON c.CustomerId = i.CustomerId GROUP BY c.Country ORDER BY Total_Spent DESC LIMIT 1"}', 'name': 'sql_db_query'}, 'type': 'function'}]}, response_metadata={'token_usage': {'completion_tokens': 53, 'prompt_tokens': 557, 'total_tokens': 610}, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': 'fp_3b956da36b', 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-da250593-06b5-414c-a9d9-3fc77036dd9c-0', tool_calls=[{'name': 'sql_db_query', 'args': {'query': 'SELECT c.Country, SUM(i.Total) AS Total_Spent FROM customers c JOIN invoices i ON c.CustomerId = i.CustomerId GROUP BY c.Country ORDER BY Total_Spent DESC LIMIT 1'}, 'id': 'call_vnHKe3oul1xbpX0Vrb2vsamZ'}]}]} 
----
{'action': {'messages': [ToolMessage(content='Error: (sqlite3.OperationalError) no such table: customers\n[SQL: SELECT c.Country, SUM(i.Total) AS Total_Spent FROM customers c JOIN invoices i ON c.CustomerId = i.CustomerId GROUP BY c.Country ORDER BY Total_Spent DESC LIMIT 1]\n(Background on this error at: https://sqlalche.me/e/20/e3q8)', name='sql_db_query', id='1a5c85d4-1b30-4af3-ab9b-325cbce3b2b4', tool_call_id='call_vnHKe3oul1xbpX0Vrb2vsamZ')]}} 
----
{'agent': {'messages': [AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_pp3BBD1hwpdwskUj63G3tgaQ', 'function': {'arguments': '{}', 'name': 'sql_db_list_tables'}, 'type': 'function'}]}, response_metadata={'token_usage': {'completion_tokens': 12, 'prompt_tokens': 699, 'total_tokens': 711}, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': 'fp_3b956da36b', 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-04cf0e05-61d0-4673-b5dc-1a9b5fd71fff-0', tool_calls=[{'name': 'sql_db_list_tables', 'args': {}, 'id': 'call_pp3BBD1hwpdwskUj63G3tgaQ'}]}]} 
----
{'action': {'messages': [ToolMessage(content='Album, Artist, Customer, Employee, Genre, Invoice, InvoiceLine, MediaType, Playlist, PlaylistTrack, Track', name='sql_db_list_tables', id='c2668450-4d73-4d32-8d75-8aac8fa153fd', tool_call_id='call_pp3BBD1hwpdwskUj63G3tgaQ')]}} 
----
{'agent': {'messages': [AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_22Asbqgdx26YyEvJxBuANVdY', 'function': {'arguments': '{"query":"SELECT c.Country, SUM(i.Total) AS Total_Spent FROM Customer c JOIN Invoice i ON c.CustomerId = i.CustomerId GROUP BY c.Country ORDER BY Total_Spent DESC LIMIT 1"}', 'name': 'sql_db_query'}, 'type': 'function'}]}, response_metadata={'token_usage': {'completion_tokens': 53, 'prompt_tokens': 744, 'total_tokens': 797}, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': 'fp_3b956da36b', 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-bdd94241-ca49-4f15-b31a-b7c728a34ea8-0', tool_calls=[{'name': 'sql_db_query', 'args': {'query': 'SELECT c.Country, SUM(i.Total) AS Total_Spent FROM Customer c JOIN Invoice i ON c.CustomerId = i.CustomerId GROUP BY c.Country ORDER BY Total_Spent DESC LIMIT 1'}, 'id': 'call_22Asbqgdx26YyEvJxBuANVdY'}]}]} 
----
{'action': {'messages': [ToolMessage(content='[(\'USA\', 523.0600000000003)]', name='sql_db_query', id='f647e606-8362-40ab-8d34-612ff166dbe1', tool_call_id='call_22Asbqgdx26YyEvJxBuANVdY')]}} 
----
{'agent': {'messages': [AIMessage(content='Customers from the USA spent the most, with a total amount spent of $523.06.', response_metadata={'token_usage': {'completion_tokens': 20, 'prompt_tokens': 819, 'total_tokens': 839}, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': 'fp_3b956da36b', 'finish_reason': 'stop', 'logprobs': None}, id='run-92e88de0-ff62-41da-8181-053fb5632af4-0')]}} 
----

请注意,代理执行多个查询,直到它拥有所需的信息:

  1. 列出可用表;
  2. 检索三个表的架构;
  3. 通过联接操作查询多个表。

然后,代理可以使用最终查询的结果来生成对原始问题的答复。

代理也可以类似地处理定性问题:

for s in agent_executor.stream(
    {"messages": [HumanMessage(content="Describe the playlisttrack table")]}
):
    print(s)
    print("----")
{'agent': {'messages': [AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_WN0N3mm8WFvPXYlK9P7KvIEr', 'function': {'arguments': '{"table_names":"playlisttrack"}', 'name': 'sql_db_schema'}, 'type': 'function'}]}, response_metadata={'token_usage': {'completion_tokens': 17, 'prompt_tokens': 554, 'total_tokens': 571}, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': 'fp_3b956da36b', 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-be278326-4115-4c67-91a0-6dc97e7bffa4-0', tool_calls=[{'name': 'sql_db_schema', 'args': {'table_names': 'playlisttrack'}, 'id': 'call_WN0N3mm8WFvPXYlK9P7KvIEr'}]}]} 
----
{'action': {'messages': [ToolMessage(content="Error: table_names {'playlisttrack'} not found in database", name='sql_db_schema', id='fe32b3d3-a0ad-4802-a6b8-87a2453af8c2', tool_call_id='call_WN0N3mm8WFvPXYlK9P7KvIEr')]}} 
----
{'agent': {'messages': [AIMessage(content='I apologize for the error. Let me first check the available tables in the database.', additional_kwargs={'tool_calls': [{'id': 'call_CzHt30847ql2MmnGxgYeVSL2', 'function': {'arguments': '{}', 'name': 'sql_db_list_tables'}, 'type': 'function'}]}, response_metadata={'token_usage': {'completion_tokens': 30, 'prompt_tokens': 592, 'total_tokens': 622}, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': 'fp_3b956da36b', 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-f6c107bb-e945-4848-a83c-f57daec1144e-0', tool_calls=[{'name': 'sql_db_list_tables', 'args': {}, 'id': 'call_CzHt30847ql2MmnGxgYeVSL2'}]}]} 
----
{'action': {'messages': [ToolMessage(content='Album, Artist, Customer, Employee, Genre, Invoice, InvoiceLine, MediaType, Playlist, PlaylistTrack, Track', name='sql_db_list_tables', id='a4950f74-a0ad-4558-ba54-7bcf99539a02', tool_call_id='call_CzHt30847ql2MmnGxgYeVSL2')]}} 
----
{'agent': {'messages': [AIMessage(content='The database contains a table named "PlaylistTrack". Let me retrieve the schema and sample rows from the "PlaylistTrack" table.', additional_kwargs={'tool_calls': [{'id': 'call_wX9IjHLgRBUmxlfCthprABRO', 'function': {'arguments': '{"table_names":"PlaylistTrack"}', 'name': 'sql_db_schema'}, 'type': 'function'}]}, response_metadata={'token_usage': {'completion_tokens': 44, 'prompt_tokens': 658, 'total_tokens': 702}, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': 'fp_3b956da36b', 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-e8d34372-1159-4654-a185-1e7d0cb70269-0', tool_calls=[{'name': 'sql_db_schema', 'args': {'table_names': 'PlaylistTrack'}, 'id': 'call_wX9IjHLgRBUmxlfCthprABRO'}]}]} 
----
{'action': {'messages': [ToolMessage(content="
CREATE TABLE \"PlaylistTrack\" (\n\
\t\"PlaylistId\" INTEGER NOT NULL, \n\
\t\"TrackId\" INTEGER NOT NULL, \n\
\tPRIMARY KEY (\"PlaylistId\", \"TrackId\"), \n\
\tFOREIGN KEY(\"TrackId\") REFERENCES \"Track\" (\"TrackId\"), \n\
\tFOREIGN KEY(\"PlaylistId\") REFERENCES \"Playlist\" (\"PlaylistId\")\n\
)\n\
/*\n\
3 rows from PlaylistTrack table:\n\
PlaylistId\tTrackId\n\
1\t3402\n\
1\t3389\n\
1\t3390\n\
*/", name='sql_db_schema', id='f6ffc37a-188a-4690-b84e-c9f2c78b1e49', tool_call_id='call_wX9IjHLgRBUmxlfCthprABRO')]}} 
----
{'agent': {'messages': [AIMessage(content='The \"PlaylistTrack\" table has the following schema:\n\n- PlaylistId: INTEGER (NOT NULL)\n- TrackId: INTEGER (NOT NULL)\n- Primary Key: (PlaylistId, TrackId)\n- Foreign Key: TrackId references Track(TrackId)\n- Foreign Key: PlaylistId references Playlist(PlaylistId)\n\nHere are 3 sample rows from the \"PlaylistTrack\" table:\n1. PlaylistId: 1, TrackId: 3402\n2. PlaylistId: 1, TrackId: 3389\n3. PlaylistId: 1, TrackId: 3390\n\nIf you have any specific questions or queries regarding the \"PlaylistTrack\" table, feel free to ask!', response_metadata={'token_usage': {'completion_tokens': 145, 'prompt_tokens': 818, 'total_tokens': 963}, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': 'fp_3b956da36b', 'finish_reason': 'stop', 'logprobs': None}, id='run-961a4552-3cbd-4d28-b338-4d2f1ac40ea0-0')]}} 
----

处理高基数列

为了过滤包含专有名词的列,如地址、歌曲名称或艺术家,我们首先需要双重检查拼写以便正确过滤数据。

我们可以通过创建一个包含数据库中所有不同专有名词的向量存储来实现这一点。然后,代理每次用户在问题中包含专有名词时,都可以查询该向量存储,以找到该词的正确拼写。这样,代理可以在构建目标查询之前确保它理解用户所指的实体。

首先我们需要我们想要的每个实体的唯一值,为此我们定义一个解析结果为元素列表的函数:

import ast
import re

def query_as_list(db, query):
    res = db.run(query)
    res = [el for sub in ast.literal_eval(res) for el in sub if el]
    res = [re.sub(r"\b\d+\b", "", string).strip() for string in res]
    return list(set(res))

artists = query_as_list(db, "SELECT Name FROM Artist")
albums = query_as_list(db, "SELECT Title FROM Album")
albums[:5]
['Big Ones', 
 'Cidade Negra - Hits', 
 'In Step', 
 'Use Your Illusion I', 
 'Voodoo Lounge']

使用这个函数,我们可以创建一个检索工具,代理可以自行执行。

from langchain.agents.agent_toolkits import create_retriever_tool
from langchain_community.vectorstores import FAISS
from langchain_openai import OpenAIEmbeddings

vector_db = FAISS.from_texts(artists + albums, OpenAIEmbeddings())
retriever = vector_db.as_retriever(search_kwargs={"k": 5})
description = """
Use to look up values to filter on. Input is an approximate spelling of the proper noun, output is 
valid proper nouns. Use the noun most similar to the search.
"""
retriever_tool = create_retriever_tool(
    retriever,
    name="search_proper_nouns",
    description=description,
)

让我们尝试一下:

print(retriever_tool.invoke("Alice Chains"))
Alice In Chains
Alanis Morissette
Pearl Jam
Pearl Jam
Audioslave

这样,如果代理确定需要基于类似"Alice Chains"的艺术家编写过滤器,它首先可以使用检索工具来观察列的相关值。

将这些组合起来:

system = """
You are an agent designed to interact with a SQL database.
Given an input question, create a syntactically correct SQLite query to run, then look at the results of the query and return the answer.
Unless the user specifies a specific number of examples they wish to obtain, always limit your query to at most 5 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 the relevant columns given the question.
You have access to tools for interacting with the database.
Only use the given tools. Only use the information returned by the tools to construct your final answer.
You MUST double check your query before executing it. If you get an error while executing a query, rewrite the query and try again.

DO NOT make any DML statements (INSERT, UPDATE, DELETE, DROP etc.) to the database.

You have access to the following tables: {table_names}

If you need to filter on a proper noun, you must ALWAYS first look up the filter value using the "search_proper_nouns" tool!
Do not try to guess at the proper name - use this function to find similar ones.
""".format(
    table_names=db.get_usable_table_names()
)

system_message = SystemMessage(content=system)

agent = chat_agent_executor.create_tool_calling_executor(
    llm, tools, messages_modifier=system_message
)

for s in agent.stream(
    {"messages": [HumanMessage(content="How many albums does alis in chain have?")]}
):
    print(s)
    print("----")

{'agent': {'messages': [AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_r5UlSwHKQcWDHx6LrttnqE56', 'function': {'arguments': '{"query":"SELECT COUNT(*) AS album_count FROM Album WHERE ArtistId IN (SELECT ArtistId FROM Artist WHERE Name = \\'Alice In Chains\\')"}', 'name': 'sql_db_query'}, 'type': 'function'}]}, response_metadata={'token_usage': {'completion_tokens': 40, 'prompt_tokens': 612, 'total_tokens': 652}, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': 'fp_3b956da36b', 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-548353fd-b06c-45bf-beab-46f81eb434df-0', tool_calls=[{'name': 'sql_db_query', 'args': {'query': "SELECT COUNT(*) AS album_count FROM Album WHERE ArtistId IN (SELECT ArtistId FROM Artist WHERE Name = 'Alice In Chains')"}, 'id': 'call_r5UlSwHKQcWDHx6LrttnqE56'}]}]} 
----
{'action': {'messages': [ToolMessage(content='[(1,)]', name='sql_db_query', id='093058a9-f013-4be1-8e7a-ed839b0c90cd', tool_call_id='call_r5UlSwHKQcWDHx6LrttnqE56')]}} 
----
{'agent': {'messages': [AIMessage(content='Alice In Chains has 11 albums.', response_metadata={'token_usage': {'completion_tokens': 9, 'prompt_tokens': 665, 'total_tokens': 674}, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': 'fp_3b956da36b', 'finish_reason': 'stop', 'logprobs': None}, id='run-f804eaab-9812-4fb3-ae8b-280af8594ac6-0')]}} 
----

如我们所见,代理使用search_proper_nouns工具来检查如何正确地为此特定艺术家查询数据库。


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值