编者按:这篇文章是与 Gretel 团队合作撰写的。我们对他们结合基于代理的方法、LLM 和合成数据,以实现数据库和数据仓库的自然语言查询(无需 SQL)的方法感到非常兴奋。这篇文章有一个非常有用的演练(附带代码!),将这些想法变为现实。
基于代理的方法与大型语言模型 (LLM) 相结合,正在迅速改变我们与数据库和数据仓库交互的方式。这些技术结合在一起,使您的应用程序或业务中的数据能够进行自然语言查询,无需 SQL 专业知识即可与数据交互,甚至可以促进跨不同系统的无缝查询。
在本文中,我们将通过一个示例,介绍 LangChain、LLM(无论是 Llama-2、Falcon 等开源模型,还是来自 OpenAI、Google、Anthropic 的基于 API 的模型)以及来自 Gretel 的合成数据如何结合在一起,为数据库和数据仓库中的数据的自然语言数据交互创建强大的、保护隐私的解决方案。我们将介绍诸如代理 (Agents)、LLM 链 (Chains) 和合成数据等关键概念,然后深入研究一个实际的代码示例,将这些想法变为现实。
关键技术
- LLM 链 (Chains):诸如 LangChain 等框架,用于通过将语言模型链接在一起来开发由语言模型驱动的应用程序。
- 代理 (Agents):代理使用 LLM 来决定采取哪些行动以及采取这些行动的顺序,通过迭代观察先前行动的结果来做出未来的决策。
- 具备函数意识的 LLM (Function Aware LLMs):某些较新的 LLM(如 OpenAI 的 GPT-3.5-turbo-0613 和 Google 的 PaLM text-bison)已经过微调,可以检测到何时应调用函数,并响应应传递给函数的输入。
- 合成数据:由数据感知生成模型创建的真实世界的人工版本,可以为数据提供强大的隐私保证。Gretel 提供基于 Transformer、GAN 和基于图的架构的表格数据生成模型。
- SQL 数据库:支撑您要查询的数据的骨干。今天,我们将使用 SQLite 数据库。
LangChain 中的代理 (Agent) 是什么?
某些应用程序不仅需要预定的 LLM/其他工具调用链,还需要可能未知的链,这取决于用户的输入。在这些类型的链中,有一个“代理 (agent)”可以访问一套工具——例如数学或查询 SQL 数据库的能力。根据用户输入,代理可以决定调用哪些工具(如果有)。
在底层,LangChain SQL 代理使用基于 MRKL(发音为 Miracle)的方法,并查询数据库模式和示例行,并使用这些来生成 SQL 查询,然后执行这些查询以拉取您请求的结果。
生成合成表格数据
在深入示例之前,让我们谈谈合成数据。借助 Gretel 的模型,您可以创建敏感数据的人工但统计上相似的版本。由于诸如 差分隐私 等数学支持的隐私功能,这些合成数据可以安全使用。在我们的示例中,我们将同时使用真实数据和合成数据来展示为什么在让语言模型访问敏感信息时,这种隐私至关重要。
要为此示例生成您自己的合成数据,请获取 IBM HR 员工离职数据集(或您自己的数据集)和来自 https://console.gretel.ai 的 API 密钥。您可以运行 Gretel 的 快速入门 notebook 或基于控制台的工作流程来创建数据的合成版本。
对于此示例,我使用了 Gretel Tabular DP 模型(notebook,文档),epsilon 值为 5,以实现强大的隐私保证,这非常适合受监管的环境。为了在保持隐私的同时实现最大精度,您还可以尝试 Gretel ACTGAN 模型(文档),该模型擅长处理高维表格数据,以支持机器学习和分析用例。
入门:安装
请跟随我们的完整 Colab 中的 notebook 或 GitHub。
首先,安装依赖项。
!pip install -Uqq langchain openai gretel-client
!pip install -Uqq smart_open tabulate
初始化 LangChain 代理 (Agent)
注意:请使用您的 OpenAI 密钥,该密钥应保密。
以下是初始化 LangChain 代理 (Agent) 并将其连接到您的 SQL 数据库的代码。
from langchain.agents import AgentExecutor, create_sql_agent
from langchain.agents.agent_toolkits import SQLDatabaseToolkit
from langchain.agents.agent_types import AgentType
from langchain.chat_models import ChatOpenAI
from langchain.llms.openai import OpenAI
from langchain.sql_database import SQLDatabase
def create_agent(
db_uri,
agent_type=AgentType.OPENAI_FUNCTIONS,
verbose=VERBOSE_LANGCHAIN,
temperature=0,
model="gpt-3.5-turbo-0613",
):
db = SQLDatabase.from_uri(db_uri)
toolkit = SQLDatabaseToolkit(db=db, llm=OpenAI(temperature=temperature))
return create_sql_agent(
llm=ChatOpenAI(temperature=temperature, model=model),
toolkit=toolkit,
verbose=verbose,
agent_type=agent_type,
)
在这里,我们还导入了一些示例数据集。我们将使用 IBM 员工流失 HR 数据集的真实版本和合成版本。合成版本是使用 Gretel 的 Tabular DP 模型生成的,其 (ε) Epsilon 值为 5。
# Create SQLite databases from CSV datasets
create_sqlite_db_from_csv(
SYNTHETIC_DATA, db_name="synthetic-sqlite.db", table_name="synthetic_ibm_attrition"
)
create_sqlite_db_from_csv(
REAL_DATA, db_name="real-sqlite.db", table_name="real_ibm_attrition"
)
# Create SQL agent to interact with synthetic IBM attrition data
agent_synthetic_db = create_agent("sqlite:////content/synthetic-sqlite.db")
# Create SQL agent to interact with real-world IBM attrition data
agent_real_db = create_agent("sqlite:////content/real-sqlite.db")
查询数据
首先,我们将创建一个辅助函数来比较真实数据和合成数据的输出。
def run_and_compare_queries(synthetic, real, query: str):
"""Compare outputs of Langchain Agents running on real vs. synthetic data"""
query_template = f"{query} Execute all necessary queries, and always return results to the query, no explanations or apologies please. Word wrap output every 50 characters."
result1 = synthetic.run(query_template)
result2 = real.run(query_template)
print("=== Comparing Results for Query ===")
print(f"Query: {query}")
table_data = [
{"From Agent on Synthetic DB": result1, "From Agent on Real DB": result2}
]
print(tabulate(table_data, headers="keys", tablefmt="pretty"))
示例查询
哪三个部门的员工离职率最高?
prompt = "Which 3 departments have the highest attrition rates? Return a list please."
run_and_compare_queries(synthetic=agent_synthetic_db, real=agent_real_db, query=prompt)

合成数据集和真实数据集的结果非常相似,这让我们对合成数据的可靠性充满信心。
整个数据集中,按 10 年增量划分的年龄分布是什么?
prompt = "Show me a distribution of ages by 10 year increments. Return in list format please."
run_and_compare_queries(synthetic=agent_synthetic_db, real=agent_real_db, query=prompt)

同样,合成数据集和真实数据集之间的分布也显着相似。
哪个部门的员工通勤距离家最远?
prompt = "Which department travels the furthest from home?"
run_and_compare_queries(synthetic=agent_synthetic_db, real=agent_real_db, query=prompt)

在这种情况下,我们得到了完全匹配的结果。
隐私的重要性:重新识别攻击示例
在这里,我们演示了一个“重新识别攻击”,即使在去标识化的数据集中,漏洞也可能允许攻击者通过组合已知属性来重新识别个人。此类风险强调了共享剥离了直接标识符但包含属性的数据的危险性,当这些属性组合在一起时,可能会导致识别——例如,在下面的示例中,攻击者知道某人的年龄、性别和部门的组合。
合成数据可以防止个人信息的直接链接,因为输出中没有记录是基于单个用户的数据,从而有效地阻止了重新识别攻击并维护了隐私。
prompt = "Is there an employee who is Age 46, Female, and who works in Human Resources. If so, what is their monthly income, performance rating, and years since their last promotion?"
run_and_compare_queries(synthetic=agent_synthetic_db, real=agent_real_db, query=prompt)

结论
通过使用合成数据,您不仅可以保护隐私,还可以获得可操作的见解——这对于任何数据驱动型组织都至关重要。当您将此与基于代理的方法和大型语言模型相结合时,您将为更多更好的利益相关者协作打开大门。无需 SQL 专业知识;只需使用自然语言即可与组织各个级别的数据进行交互。
这种可扩展的解决方案使数据访问民主化,并迎来智能、注重隐私的数据交互的新时代。对于渴望在当今以数据为中心的世界中保持竞争优势的企业而言,采用这些技术不仅仅是一种选择;这是必须的。
如果您准备提升您的数据水平,请立即注册 Gretel 并开始合成。