赋能数据驱动决策:将信任嵌入到文本到 SQL AI 代理中

原文:towardsdatascience.com/embedding-trust-into-text-to-sql-ai-agents-3f15d0ddaf1a

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/f60b820bd517a4dfbb6dcd5ffe6ea272.png

什么因素是驱动用户在对话式数据驱动 AI 应用中**信任和参与度**的关键因素?

内部采用 AI 应用的组织数量不断增加,但这并不一定反映更高的用户参与度评分。AI 结果的可信度评分并未达到关键决策范围。

向这些应用中引入额外的组件对于推动用户的参与度和信任至关重要,最终将组织引向更加数据驱动的决策环境。


目录

1- 简单性在驱动参与度中扮演关键角色(为什么)

2- 决策变得对话化(是什么)

3- 建立 AI 数据应用中的信任(方法)

4 – 实践:使用 Gradio、Postgres 和 Langchain 构建数据聊天室

  • 数据库

  • 代理

  • 工具

  • 提示

  • 用户界面

  • 测试运行

总结


1- 简单性在驱动参与度中扮演关键角色(为什么)

数据驱动型组织已经发现了数据的重要益处,许多组织在市场优势中反映了这些益处。根据麦肯锡公司的一份报告,这一价值可能反映在 EBITDA 的高达 25%的增长上。同时,其他人虽然在该领域努力尝试,但并未取得显著进展。

如果我们看看一些数字,我们会发现许多组织在成为更加数据驱动型的目标上未能实现。如果数据在市场上给你带来优势,为什么大多数组织仍然落后?

这是一个不容易回答的问题,对一些人来说,它被视为巨大的投资,其他人可能看不到其价值,而有些人可能缺乏正确的技能集。

有时利用数据的价值会遇到一些瓶颈,可能是数据对用户来说并不容易获取以进行分析,或者用户访问数据的过程过于复杂,以至于很多人在尝试之前就放弃了,等等。

列表很长,但有一些用例是我为那些正在构建数据能力的组织工作所经历的。那些已经建立了数据仓库/湖但难以从数据中创造价值的企业。

“简单是最高级的复杂性。”

– 莱昂纳多·达·芬奇

达·芬奇说得最好,简单是关键,但我们仍然看到数据用户在与复杂性作斗争。

假设一家企业设法成功构建了其数据平台。

数据用户面临着由数百张表组成的数据仓库和数据库,这些表跨越数千行和列。在最佳情况下,事情是文档化的,并且已经建立了数据目录

最坏的情况下,他们陷入了一个迷宫。你深入一点,会发现更多的仪表板和报告,以及一些 100 个优先 KPI,以及……以及……以及……

对于紧急决策,你可能会尽力避免花费数小时在数据驱动的价值迷宫中搜索。

幸运的是,存在替代方案。

在接下来的章节中,我们将探讨人工智能在简化数据环境中的复杂性方面可以带来什么。它是如何被优化以建立鼓励用户参与的水平信任。最后,一个关于如何构建一个完全功能的人工智能代理系统的实战教程,该系统利用 Llama3.1 8b 和 GPT-4o-mini,通过一个简单的可配置聊天室以快速和可靠的结果形式提供答案。


2 – 决策变得对话化(关于“是什么”)

专家凭借其基于多年积累经验快速检索信息的能力而脱颖而出。你提出一个精心构思的问题,他们提供答案。简单、高效且快速的交易。专家抽象出提供答案过程中所有复杂的处理。

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/a57f47a94f2d5bd9ca58288e75397b2c.png

专家代理 – 图片由作者提供

这可能适用于数据可管理的特定领域的专家。当涉及到存储在分布式集群中的大量信息时,数据专家需要咨询他们的数据源系统和查询引擎以获取答案。

现在,让我们想象一下,我们可以创建足够可扩展数量的此类专家。他们都能访问组织内的数据库和数据源,全天候可用,并在接收到一些用户输入后几秒钟内提供答案。

再进一步,让那些专家讨论和分析提供给你的最佳答案。我们最终得到一个能够满足大量数据用户按需请求的系统。

理解这一点至关重要,即一旦系统中的信任因素受到损害,这些系统就会变得无效。这里的目的是建立信任。信任一个能够及时向正确的人提供正确数字和答案的系统。

现在,让我们将这些可扩展的专家称为人工智能代理。人工智能代理在适当的信息、工具和指令下有效运作。

我们不会深入探讨人工智能代理本身,优秀的文章详细阐述了这一点。

当前的问题可以转化为:我们如何设计信息、工具和指令,以构建一个能够有效服务数据用户的强大且值得信赖的系统?


3 – 建立人工智能数据应用中的信任(方法)

信息、工具和指令。这些是在构建有效的基于人工智能代理的解决方案时需要考虑的关键因素。

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/00d20f031a10fc23f1e1dab56fccb3b3.png

人工智能代理工作流程 – 图片由作者提供

让我们分析我们的景观,使事情更加清晰。

信息

  • 我们数据景观中的信息将在数据库中可用。存储为表格、函数和元数据。

  • 信息还来源于提示的上下文以及分配给代理的工具中的其他指令。

工具

  • 在我们的用例背景下,工具是为使代理能够用于特定行动而创建的函数。因此,为代理的行为添加了一层一致性。

人工智能代理

  • 代理是以特定的背景创建的。

  • 代理被分配工具以实现其目标。

  • 代理使用最适合其目标的选定的 LLM 模型。

为了确保具有高概率的代理提供一致且值得信赖的结果,上述因素需要以最小化幻觉并促进用户信任的方式设计。

构建系统需要我们解决阻碍用户采用人工智能解决其数据用例的挑战。

我们需要解决的某些挑战/问题:

  • 我如何相信系统提供的是正确的数字?

  • 我们能做些什么来确保数据结果是值得信赖的?

  • 系统是否使用了正确的数据源?

  • 我们能否使使用的来源及其内容透明?

  • 结果对用户来说是否清晰?

如果我们进一步深入挑战,列表会变得更长。为了我们讨论的范围,我们将限制在上面的挑战列表中。

让我们讨论上述每个问题的解决方案策略,并为最终实施奠定基础。

提供正确的数字意味着用户有信心,无论人工智能执行了什么,都是正确的(始终依赖于用户的提问/提示)。

作为数据用户,如果:

  • 人工智能对其计算的确切内容是透明的。

  • 人工智能经过良好训练,知道它是否首先能够回答问题。

  • 人工智能理解请求的上下文和数据,并拥有所有正确信息以提供正确的结果。

  • 人工智能理解我的数据源,并且擅长编写查询以检索数据。

从工程角度的翻译:

  • 人工智能需要向用户解释他们的计算逻辑以及使用了哪些工具和信息。

  • 人工智能响应它是否有工具和信息来回答他们的问题

  • 人工智能配备了限制幻觉的工具(这里我们谈论的是函数,因此限制人工智能只能使用正确的参数调用)

  • 人工智能能够执行数据库中的代码和函数,并检索数据(考虑返回给用户前端的数据大小)

构建这样的应用程序可能具有一两个复杂度级别,但证明其价值很重要。我们将在下一节逐步介绍实现过程。

您可以在这里获取我们动手实现的最终代码。


实践操作:使用 Gradio、Postgres 和 Langchain 构建数据聊天室

在本节中,我们开发我们的端到端用户界面应用程序。解决方案的主要目标是使用户能够无缝交互,重点是简单性和信任。

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/af3b7bd9653ce8687b222b6e29905472.png

应用程序工作流程 – 作者图片

应用程序景观包括:

  • 一个简单的 Gradio 用户界面,用户可以通过它进行交互、配置和测试他们的应用程序

  • 一个 Postgres 数据库用于存储用户希望分析的信息

  • 一个后端处理用户请求并与 AI 代理交互,为它们提供完成目标所需的工具。

我们将首先列出组件,并说明它们是如何一起构建一个以信任为中心的系统。

首先,确保您正在运行 Python 3.9+,并在[requirements.txt](https://github.com/Husseinjd/data-chat-rooms/blob/main/requirements.txt)文件中安装所有必需的依赖项。

gradio
sqlalchemy
langchain
langchain
langchain-community
psycopg2
langchain-openai
python-dotenv
langchain-ollama
pip install -r requirements.txt

数据库

对于我们的用例,我们构建了一个简单的书店 Postgres 数据库。您可以在[init.sql](https://github.com/Husseinjd/data-chat-rooms/blob/main/app/database/init.sql)脚本中找到所有需要的表和数据。我们将在本节中使用这个设置。这可以很容易地是任何其他类型的数据库和模式。

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/ecec4aa8de1ce9539a2f7823385a69d9.png

我们必须确保所有与表和列相关的元数据都已就绪。

示例:为书籍表增强元数据:

-- Books table
CREATE TABLE books (
    book_id SERIAL PRIMARY KEY,
    title VARCHAR(200) NOT NULL,
    author_id INTEGER REFERENCES authors(author_id),
    isbn VARCHAR(13) UNIQUE,
    price DECIMAL(10, 2),
    publication_date DATE
);

COMMENT ON COLUMN books.book_id IS 'Unique identifier for each book';
COMMENT ON COLUMN books.title IS 'Title of the book';
COMMENT ON COLUMN books.author_id IS 'Foreign key referencing the author of the book';
COMMENT ON COLUMN books.isbn IS 'International Standard Book Number (13 digits)';
COMMENT ON COLUMN books.price IS 'Price of the book in decimal format';
COMMENT ON COLUMN books.publication_date IS 'Date when the book was published';

这将是向 AI 代理提供更多数据上下文的第一步。

为了设置我们的数据库,我们将使用 Postgres docker 镜像并在本地运行它进行测试。

确保已安装 Docker,并在docker-compose.yaml文件中定义以下服务。

services:
  db:
    image: postgres:13
    container_name: bookstore_db
    environment:
      POSTGRES_DB: bookstore
      POSTGRES_USER: admin
      POSTGRES_PASSWORD: adminpassword
    ports:
      - "5432:5432"
    volumes:
      - ./app/database/init.sql:/docker-entrypoint-initdb.d/init.sql

代理

配置受信任的 AI 代理从选择合适的模型、设计合适的提示,并最终选择正确的工具开始。

LLM

为了展示我们的用例,我们将与多个 LLM 一起运行我们的测试。这些 LLM 将是

  • OpenAI gpt-4o-mini

  • LLama 3.1 8b

在项目中,AgentSetup [agent.py](https://github.com/Husseinjd/data-chat-rooms/blob/main/app/agent/agent.py)负责使用正确的 LLM 模型设置我们的代理。

from langchain_community.utilities import SQLDatabase
from langchain_community.agent_toolkits.sql.toolkit import SQLDatabaseToolkit
from langchain import hub
from langchain_core.prompts.prompt import PromptTemplate
from langgraph.prebuilt import create_react_agent
from langchain_openai import ChatOpenAI
from app.config import OPENAI_API_KEY

class AgentSetup:
    def __init__(self, engine, llm = None, tools=[]):
        self.engine = engine
        self.llm = llm or ChatOpenAI(
            model="gpt-4o-mini", temperature=0, api_key=OPENAI_API_KEY
        )
        self.tools = tools
        self.agent_executor = None
        self.toolkit = None

    def setup(self):
        db = SQLDatabase(self.engine)
        self.toolkit = SQLDatabaseToolkit(db=db, llm=self.llm)

        prompt_template = hub.pull("langchain-ai/sql-agent-system-prompt")
        # prompt redacted here for better readability
        # you can find the full version in the repo.
        function_prompt_addition = """"""

        prompt_template = PromptTemplate(
            input_variables=["dialect", "top_k"], template=function_prompt_addition
        )

        tools =  self.toolkit.get_tools() + self.tools

        self.agent_executor = create_react_agent(
            self.llm,
            tools,
            state_modifier=prompt_template.format(dialect="POSTGRESQL", top_k=5),
        )

    def get_agent(self):
        if not self.agent_executor:
            raise ValueError("Agent not set up. Call setup() first.")
        return self.agent_executor

    def update_llm(self, new_llm):
        self.llm = new_llm
        if self.toolkit:
            self.toolkit.llm = new_llm
        self.setup()  # Re-setup the agent with the new LLM

对于使用 OpenAI LLM 设置 Langchain,我们添加以下内容:

 from langchain_openai import ChatOpenAI
 llm = ChatOpenAI(model="gpt-4o-mini", temperature=0, api_key=OPENAI_API_KEY)

要使用 LLama3.1,我们下载并运行 docker 镜像,最后运行选定的模型

docker run -d -v ollama:/root/.ollama -p 11434:11434 --name ollama ollama/ollama

选择并运行模型

docker exec -it ollama ollama run llama3.1

使用以下代码片段连接到 ollama:

from langchain_ollama import ChatOllama

new_llm = ChatOllama(model="llama3.1",temperature=0)

代码片段被组合在最终的UI 模块中。

工具

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/1371a937f9187f063504bde1cb02b034.png

数据库工具 – 图片由作者提供

为代理建立正确的工具有助于建立对我们最终结果的信任因素。

基本 SQL 工具包是必需的,以确保代理能够与数据库通信并检索所有元数据和查询结果。

我们将使用 Langchain 的SQL 数据库工具包。此工具包内可用的工具及其描述包括:

  • QuerySQLDataBaseTool:此工具的输入是一个详细且正确的 SQL 查询,输出是数据库的结果。如果查询不正确,将返回错误消息。如果返回错误,请重写查询,检查查询,然后重试。如果您遇到“在字段列表中未知列‘xxxx’”的问题,请使用 sql_db_schema 查询正确的表字段。

  • InfoSQLDatabaseTool:此工具的输入是一个以逗号分隔的表列表,输出是这些表的架构和样本行。请确保通过调用 sql_db_list_tables 首先确认表的存在!示例输入:table1, table2, table3′,

  • ListSQLDatabaseTool:用于获取指定数据库的表名的工具。

  • QuerySQLCheckerTool:检查 SQL 查询是否有正确的语法。

虽然工具包为代理与数据库交互提供了所有必需的功能,但这并不能保证 AI 会编写无瑕疵的查询。当依赖其自身的 SQL 知识和语法来制定正确查询时,它仍然容易产生幻觉。

哪些工具将是增加对代理结果信任的关键因素?

具有领域知识的开发人员和分析师可以列出用户频繁请求的数据,并为 AI 开发自定义参数化数据库函数,作为 AI 作为工具为数据用户提供服务的工具。

这些函数将具有描述其功能和使用的清晰元数据。

AI 代理可以使用这些函数,并根据用户请求添加所需的参数。这减少了完全依赖 AI 构建完全功能的查询,并为输出引入了额外的致性层。

一个可用于我们的书店数据库的函数示例及其所需的功能描述。

CREATE OR REPLACE FUNCTION public.get_books_by_year(year_param integer)
 RETURNS TABLE(title character varying, author_name character varying, publication_date date)
 LANGUAGE plpgsql
AS $function$
BEGIN
    RETURN QUERY
    SELECT b.title, a.name AS author_name, b.publication_date
    FROM books b
    JOIN authors a ON b.author_id = a.author_id
    WHERE EXTRACT(YEAR FROM b.publication_date) = year_param
    ORDER BY b.publication_date;
END;
$function$

COMMENT ON FUNCTION public.get_books_by_year(integer) IS 'This function returns all books published in a specific year.';

应用程序将包含引入函数作为工具的代码

from sqlalchemy import text

class DatabaseFunctions:
    def __init__(self, engine):
        self.engine = engine
    def get_all_functions(self):
        query = text("""
            SELECT 
                p.proname AS routine_name,
                pg_catalog.pg_get_functiondef(p.oid) AS routine_definition,
                d.description AS routine_comment
            FROM 
                pg_catalog.pg_proc p
            LEFT JOIN 
                pg_catalog.pg_namespace n ON n.oid = p.pronamespace
            LEFT JOIN 
                pg_catalog.pg_description d ON d.objoid = p.oid
            WHERE 
                n.nspname = 'public'
            ORDER BY 
                p.proname
        """)
        with self.engine.connect() as connection:
            result = connection.execute(query)
            return [
                {
                    "function_name": row[0],
                    "function_code": row[1],
                    "description": row[2],
                }
                for row in result
            ]
    def add_function(self, name, code, description):
        with self.engine.connect() as connection:
            connection.execute(text(code))
            comment_sql = f"COMMENT ON FUNCTION {name} IS '{description}';"
            connection.execute(text(comment_sql))
            connection.commit()
    def delete_function(self, name):
        with self.engine.connect() as connection:
            drop_sql = f"DROP FUNCTION IF EXISTS {name};"
            connection.execute(text(drop_sql))
            connection.commit()

提示

提示在引导 LLM 行为中起着重要作用。一个精心设计的提示可以使 LLM 理解任务并按指示处理请求。提示必须确保以下内容:

  • 使用特定的 SQL 数据库方言

  • 返回的结果数量

  • 可用工具

  • 所需输出格式

  • 查询的构建和执行

将上述要求翻译成提示:

"""
 You are an agent designed to interact with a SQL database.

Given an input question, check whether the question can be answered by 
a function already available or create a syntactically correct {dialect} 
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 {top_k} 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 functions in the database and then tables to see what you can use to query.
Do NOT skip this step. 

Then you should construct the right query whether you chose a function 
to run or build your own query.

Those functions should always take precedence to use and execute over 
building your own query and running. 

Decide correctly whether to choose the function or build your own query. 

If you choose a function make sure to build the sql query to execute 
the function correctly and get the results.

In order to execute a function run an sql like SELECT <columns> 
from <function_name(param)>

At the end of the result provide information. 
The result should be structured in json format.

It should include all the columns and results, 
in addition to the approach used with three potential values (FUNCTION or QUERY or None) 
(FUNCTION if function is used, QUERY if own query is used). 

The approach result should be also included in the json, 
in addition to the function name used.

Your last answer should only be a valid json and nothing else. in the following format: 

    {{
      "results": [
      {{
        "col1": val1,
        "col2": val2,
        "col3": val3,
        ...
      }}
    ],
    "approach": "FUNCTION or QUERY or NONE",
    "function_used": "<function name>",
    "query": <final using function or not used to retrieve the final results>
    }}
    """

此外,对于最佳实践语句,如“不要执行任何 DML 语句”,可以通过限制对数据库的写权限来缓解。

Gradio UI

UI 界面保持简单,包含 4 个标签页,分别用于数据库连接配置、创建函数以及添加带有 gradio 聊天界面的少量示例。

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/c8f5d5f043b40cc4ceab05ba9a2c0723.png

UI 界面 – 作者图像

在成功连接到数据库后,所有可用的函数都被加载为我们的应用程序的工具,并准备好供用户查询。添加了一些示例函数来测试我们的应用程序。

  • get_books_by_year(int)

  • get_customer_order_history(int)

将所有内容整合在一起,我们现在正在使用一个完全功能的 AI 代理,它可以利用其工具与数据库交互,读取其元数据,并构建具有函数执行能力的查询。

我们现在已准备好测试我们的应用程序。

测试运行

我们将运行多个提示,使用 LLM 模型,每个模型都期望采取我们应用程序的不同方法。

要运行应用程序,请确保数据库已设置

docker-compose up

然后启动 gradio 应用程序

python -m app.main

提示 1:预期功能利用率

在这个提示中,我们期望我们的代理能够认识到他们可以使用函数而不是构建他们的查询。

查询: 获取 1997 年的书籍

gpt-4o-mini 响应:

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/7dfe53b82e5a871e11e4986eef90a0db.png

gpt-4o-mini 响应 1 – 作者生成的图像

llama3.1 8b 响应:

使用 llama 3.1,我需要几个提示,但它仍然依赖于使用其生成的查询。这可以通过使用 70b 版本或采取更直接的方法来指导它使用特定的函数来缓解,如下所示

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/4cb2bed43d29f888e9467f60b814e14f.png

llama3.1 响应 1 – 作者生成的图像

输出分析:

对用户输入的响应包括额外的组件,以确保关于结果信任级别的完全透明度。AI 的答案被包裹在一个可信标签和查看原始 SQL 代码及使用的函数。

当 AI 代理使用特定函数检索最终答案时,应用可信标签。这为用户提供了一个额外的信心层。

提示 2:基于数据库元数据的查询预期构建

查询:订单总数是多少?

gpt-4o-mini 响应:

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/7756400016f83971b9d7d596713e0610.png

Response 2 gpt-4o-mini – 由作者生成的图像

llama3.1 8b 响应:

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/50523d51d1510f36fcbe97a64f9f5950.png

Response 2 llama3.1 – 由作者生成的图像

输出分析

当涉及到构建 SQL 以响应用户查询时,两者都正确地做出了响应。随着数据库数据模型变得越来越复杂,需要专门的 SQL 微调模型或更大的通用模型来维持响应质量。

完整应用程序可在此处测试更多与您的数据相关的示例。


摘要

在文本到 SQL 应用程序中构建额外的一致性层有助于降低失去用户信任的风险。我们展示了如何将功能作为工具融入,以及一些示例,有助于减少对 AI 构建查询逻辑的完全依赖,从而增加错误的可能性。此外,我们引入了带有可信标签和附加信息的视觉提示,使用户能够在评估最终结果时处于主导地位。

数据驱动型组织依赖用户对其数据资产的使用进行决策。对话式人工智能提供的无缝和简单交互,加上信任因素,鼓励增加数据参与度。应用程序通过简单的聊天界面访问大量公司数据,使组织更接近实现其数据驱动目标。


喜欢这个故事吗?

  • 订阅 以在发布新故事时获得通知。

  • 欢迎您通过**领英**联系我。


参考文献

对人工智能的信任 – KPMG 全球

麦肯锡全球调查 | 麦肯锡公司

洞察力影响:创建和维持数据驱动型商业增长 | 麦肯锡

[公司努力成为数据驱动型企业的努力失败 (hbr.org)]([`hbr.org/2019/02/companies-are-failing-in-their-efforts-to-become-data-driven#::text=72%25%20of%20survey%20participants%20report,competing%20on%20data%20and%20analytics.))(https://hbr.org/2019/02/companies-are-failing-in-their-efforts-to-become-data-driven#::text=72%25%20of%20survey%20participants%20report,competing%20on%20data%20and%20analytics.))

为什么成为数据驱动型企业如此困难? (hbr.org)`

LangChain

Ollama

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值