将信任嵌入文本到 SQL AI 代理

126 阅读19分钟

利用可靠的 AI 代理系统为用户简化复杂的数据环境,从而做出更好的数据驱动决策​编辑

       1- 简单性在推动参与方面起着至关重要的作用(为什么)

欢迎来到雲闪世界。 数据驱动型组织已经发现了数据的巨大优势,许多组织将这些优势反映在市场优势中。根据麦肯锡的一份报告,这一价值可能反映出EBITDA 高达 25% 的增长。与此同时,其他组织在这一领域却举步维艰,尽管这并不是因为缺乏努力。 如果我们看一下一些数字,就会发现许多组织未能实现数据驱动的目标。如果数据能让你获得市场优势,那为什么大多数组织仍然落后呢? 这不是一个可以简单回答的问题,有些人认为这是一项巨大的投资,而其他人可能看不到其价值,有些人可能缺乏正确的技能。 有时,利用数据的价值会遇到一些瓶颈,可能只是数据不易供用户分析,或者用户访问数据的流程太复杂,许多人在尝试之前就放弃了,等等…… 这个清单很长,但有一些用例是我在为构建数据能力的组织工作时体验到的。这些企业已经建立了数据仓库/数据湖,但仍在努力从数据中创造价值。

“简单即是终极的复杂。” - 列奥纳多·达·芬奇

    达芬奇说得最好,简单是关键,但我们仍然看到数据用户在与复杂性作斗争。 让我们假设一家企业成功度过难关并构建了其数据平台。 数据用户面临的数据仓库和数据库由数百张表格组成,表格包含数千行和数千列。在最好的情况下,所有数据都有记录,并且有数据目录。 最糟糕的情况是,他们被困在迷宫中。你再深入一点,就能找到更多的仪表板和报告,以及几百个优先级 KPI,还有……还有……还有…… 对于紧急的决定,您很可能会尽力避免花费数小时在数据驱动价值的大海迷宫中搜索。 幸运的是,还有其他选择。 在接下来的部分中,我们将逐步了解人工智能在为用户简化数据环境的复杂性方面能带来什么。如何优化它以建立鼓励用户参与的信任度。最后,我们将提供实践教程,介绍如何构建一个功能齐全的人工智能代理系统,该系统利用 Llama3.1 8b 和 GPT-4o-mini 以简单的可配置聊天室形式提供快速可靠的结果。

2 - 决策变成对话式的(内容)

专家以其基于多年积累的经验而快速检索信息的能力而著称。你提出一个精心设计的问题,他们就会给出答案。这是一个简单、高效、快速的交易。专家会抽象出提供答案所需的所有复杂处理。

​编辑

这可能适用于数据可管理的特定领域的专家。当涉及到跨分布式集群存储的大量信息时,数据专家需要咨询其数据源系统和查询引擎来寻找答案。 现在,让我们想象一下,我们可以创建足够数量的此类专家。所有专家都可以访问组织和数据源中的数据库,全天候待命,并准备在几秒钟内根据用户输入提供答​​案。 更进一步,让这些专家讨论和分析,为您提供最佳答案。我们最终得到了一个能够满足用户按需请求的大量数据的系统。 重要的是要明白,一旦信任因素受到损害,此类系统就会失效。这里的目标是信任。信任一个能够及时向正确的人提供正确数字和答案的系统。 现在我们把这些可扩展的专家称为 AI 代理。AI 代理可以利用正确的信息、工具和指令有效地运行。 当前的问题转化为: 我们如何设计信息、工具和指令来构建一个能够有效地为数据用户服务的强大且值得信赖的系统?

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

信息、工具和说明。这些是构建有效的基于 AI 代理的解决方案时需要考虑的关键因素。

​编辑

让我们分析一下我们的形势,使事情变得更加清晰一些。 信息

  • 我们数据景观中的信息将在数据库中可用。存储为表、函数和元数据。
  • 此外,信息还来源于提示的上下文和分配给代理的工具内的其他指令。

工具

  • 我们用例上下文中的工具是为使代理能够利用特定操作而创建的功能。因此,为代理的行为增加了一层一致性。

人工智能代理

  • 代理是根据特定的背景创建的。
  • 代理人被分配了工具来实现他们的目标。
  • 代理商使用最适合其目标的选定的 LLM 模型。

为了确保高概率的代理提供一致且值得信赖的结果,需要以尽量减少幻觉并增强用户信任的方式设计上述因素。 构建系统需要我们解决阻碍用户采用人工智能来处理其数据用例的挑战。 我们需要解决的一些挑战/问题:

  • 我如何相信系统提供的数字是正确的?
  • 如何才能确保数据结果值得信赖?
  • 系统是否使用了正确的数据源?
  • 我们能否公开所使用的信息来源及其内容?
  • 结果对用户来说是否清楚?

如果我们进一步深入研究挑战,这个列表会变得更长。为了讨论的范围,我们将限制在上面要解决的挑战列表中。 下面我们来针对以上每个问题讨论一下解决策略,并为最终的实施奠定基础。 提供正确的数字意味着用户相信 AI 执行的一切都是正确的(一如既往地取决于用户的问题/提示)。 作为数据用户,如果能够满足以下条件,将会对我有所帮助:

  • 人工智能对于具体计算的内容是透明的。
  • 人工智能经过良好的训练,首先知道它是否能够回答这个问题。
  • 人工智能理解所请求的背景和数据,并拥有所有正确的信息来提供正确的结果。
  • AI 了解我的数据源,并且能够熟练地编写数据检索查询。

从工程角度来看:

  • 人工智能需要向用户解释他们的计算逻辑以及使用了哪些工具和信息。
  • 人工智能回答是否有工具和信息来回答他们的问题
  • AI 配备了限制幻觉的工具(这里我们谈论的是功能,因此限制 AI 只能使用正确的参数来调用)
  • AI 能够执行数据库中的代码和函数并检索数据(考虑到返回到用户前端的数据大小)

构建这样的应用程序可能会有一定的复杂性,但证明其价值非常重要。我们将在下一节中逐步介绍实现过程。 您可以在此处获取我们的实际实现的最终代码。

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

,我们将开发端到端的面向用户的应用程序。该解决方案的主要目标是使用户能够无缝交互,并注重简单性和信任度。

​编辑

应用环境包括:

  • 一个简单的 Gradio UI,供用户与其应用程序交互、配置和测试
  • Postgres 数据库用于存储用户希望分析的信息
  • 处理用户请求并与 AI 代理交互的后端,为他们提供实现目标所需的工具。

我们将首先列出各个组件,然后阐述如何将它们组合在一起,以构建一个以信任为中心的系统。 首先,确保您已运行 Python 3.9+,并在requirements.txt文件中安装所有必需的依赖项。

gradio 
sqlalchemy 
langchain 
langchain 
langchain-community 
psycopg2 
langchain-openai 
python-dotenv 
langchain-ollama

pip 安装-r 要求.txt

数据库

   我们将在本节中使用此设置。这很容易是任何其他类型的数据库和模式。

编辑

我们必须确保与表和列相关的所有元数据都已到位。 书籍表元数据丰富示例:

-- 图书表
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 DATE
 ); 

COMMENT ON COLUMN books.book_id IS '每本书的唯一标识符' ; COMMENT ON  COLUMN books.title IS '书名' ; COMMENT ON COLUMN books.author_id IS '引用图书作者的外键' ; COMMENT ON COLUMN books.isbn IS '国际标准书号(13 位数字)' ; COMMENT ON COLUMN books.price IS '十进制格式的图书价格' ; COMMENT ON COLUMN books.publication_date IS '图书出版日期' ; 
  

这将是向人工智能代理提供更多数据背景信息的第一步。 为了设置我们的数据库,我们将使用 Postgres docker 镜像并在本地运行它进行测试。 确保docker已安装并且在文件中定义了以下服务docker-compose.yaml。

服务:
  db:
    图像: postgres:13
    容器名称: bookstore_db
    环境:
      POSTGRES_DB: 书店
      POSTGRES_USER: 管理员
      POSTGRES_PASSWORD: 管理员密码
    端口:
      -  “5432:5432”
    卷:
      -  ./app/database /init.sql:/docker-entrypoint-initdb.d/init.sql

特工 可信 AI 代理的配置始于选择适当的模型、设计合适的提示,最后选择正确的工具。 LLM 为了演示我们的用例,我们将使用多个 LLM 来运行测试。这些将是

  • OpenAI GPT-4O-mini
  • 骆驼 3.1 8b

在项目中,AgentSetupagent.py负责使用正确的 LLM 模型设置我们的代理。

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


class  AgentSetup : 
    def  __init__ ( self, engine, llm = None , tools=[] ): 
        self.engine = engine 
        self.llm = llm或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" ) 
        # 提示在此处编辑以提高可读性
        # 您可以在 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( "未设置代理。请先调用 setup()。" ) 
        return self.agent_executor 

    def  update_llm ( self, new_llm ): 
        self.llm = new_llm 
        if self.toolkit: 
            self.toolkit.llm = new_llm
        self.setup()   # 使用新的 LLM 重新设置代理

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

<span style="background-color:#f9f9f9"><span style="color:#242424">从 langchain_openai 导入 ChatOpenAI<span style="color:#aa0d91"></span>langchain_openai<span style="color:#aa0d91">导入</span>ChatOpenAI 
llm = ChatOpenAI(model= <span style="color:#c41a16">"gpt-4o-mini"</span> ,temperature= <span style="color:#1c00cf">0</span> ,api_key=OPENAI_API_KEY)</span></span>

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

<span style="background-color:#f9f9f9"><span style="color:#242424">docker run -d -v ollama:/root/.ollama -p 11434:11434 --name ollama ollama/ollama</span></span>

选择并运行模型

<span style="background-color:#f9f9f9"><span style="color:#242424">docker exec -it ollama ollama 运行 llama3.1 <span style="color:#5c2699">exec</span> -it ollama ollama 运行 llama3.1</span></span>

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

<span style="background-color:#f9f9f9"><span style="color:#242424"><span style="color:#aa0d91">from</span> langchain_ollama <span style="color:#aa0d91">import</span> ChatOllama 

new_llm = ChatOllama(model= <span style="color:#c41a16">"llama3.1"</span> ,温度= <span style="color:#1c00cf">0</span> )</span></span>

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

工具

编辑

添加图片注释,不超过 140 字(可选)

为代理商建立正确的工具有助于建立对我们最终结果的信任因素。 需要基本的 SQL 工具包来确保代理能够与数据库通信并检索所有元数据和查询结果。 我们将使用 Langchain 的SQL 数据库工具包。此工具包中可用的工具及其说明包括:

  • QuerySQLDataBaseTool:此工具的输入是详细且正确的 SQL 查询,输出是数据库的结果。如果查询不正确,将返回错误消息。如果返回错误,请重写查询,检查查询,然后重试。如果您遇到“字段列表”中未知列“xxxx”的问题,请使用 sql_db_schema 查询正确的表字段。
  • InfoSQLDatabaseTool:此工具的输入是逗号分隔的表列表,输出是这些表的架构和示例行。首先调用 sql_db_list_tables 确保表存在!示例输入:table1、table2、table3',
  • ListSQLDatabaseTool:用于获取指定数据库的表名的工具。
  • QuerySQLCheckerTool:检查 SQL 查询是否具有正确的语法。

虽然该工具包提供了代理与数据库交互所需的所有功能,但这并不能保证人工智能能够编写出完美的查询。当依靠自己的 SQL 知识和语法来制定正确的查询时,它仍然容易产生幻觉。 哪些工具是增加对代理商结果的信任的关键因素? 拥有领域知识的开发人员和分析师可以列出用户经常请求的数据,并开发自定义参数化数据库函数,供人工智能用作服务数据用户的工具。 这些函数将具有清晰的元数据来描述其功能和用途。 AI 代理可以使用这些功能,并根据需要根据用户请求添加所需参数。这减少了对 AI 构建全功能查询的完全依赖,并为输出引入了额外的一致性层。 可用于我们的书店数据库的函数示例和所需的函数描述。

创建 或替换函数public.get_books_by_year(year_param integer )
 返回 表(title character  variations , author_name character  variations , 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  '此函数返回特定年份出版的所有书籍。' ;

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

从sqlalchemy导入文本

类 DatabaseFunctions:
    def  __init__(self,engine):
        self.engine = engine 
    def  get_all_functions(self):
        query = text(""" 
            SELECT 
                p.proname AS router_name,
                pg_catalog.pg_get_functiondef(p.oid)AS router_definition,
                d.description AS router_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 
        """)
        使用self.engine.connect()作为连接:
            result = connection.execute(query)
            返回[ 
                { 
                    "function_name":row[ 0 ],
                    "function_code":row[ 1 ], 
                    "description" : row[ 2 ], 
                } 
                for row in result 
            ] 
    def  add_function ( self, name, code, description ):
        使用self.engine.connect()作为连接:
            connection.execute(text(code)) 
            comment_sql = f"对函数{name}的评论是 ' {description} ';"
             connection.execute(text(comment_sql)) 
            connection.commit() 
    def  delete_function ( self, name ):
        使用self.engine.connect()作为连接:
            drop_sql = f"如果存在{name} ,则删除函数;"
             connection.execute(text(drop_sql)) 
            connection.commit()

迅速的 提示在指导 LLM 行为方面起着重要作用。精心设计的提示可使 LLM 理解任务并按照指示处理请求。提示必须确保以下几点:

  • 使用特定的 SQL 数据库方言
  • 返回结果数
  • 要使用的工具
  • 所需输出格式
  • 查询的构建和执行

将上述要求转化为提示:

“”“
您是设计用于与 SQL 数据库交互的代理。

给定一个输入问题,检查该问题是否可以通过
已有函数回答,或者创建一个语法正确的 {dialect}
查询来运行,然后查看查询结果并返回答案。

除非用户指定他们希望获得的特定数量的示例,否则
请始终将查询限制为最多 {top_k} 个结果。

您可以按相关列对结果进行排序,以返回
数据库中最有趣的示例。

切勿查询特定表中的所有列,
只询问给定问题的相关列。

您可以使用与数据库交互的工具。

仅使用以下工具。

仅使用以下工具返回的信息来构建
最终答案。

执行查询之前,您必须仔细检查查询。

如果在执行查询时出现错误,请重写查询并重试。

请勿对数据库执行任何 DML 语句(INSERTUPDATEDELETEDROP 等)。

首先,您应该始终查看数据库中的函数,然后查看表,以了解可以使用哪些内容进行查询。
不要跳过此步骤。然后,无论您选择运行

函数还是构建自己的查询,都应该构建正确的查询。这些函数应始终优先于构建和运行自己的查询。正确决定是选择函数还是构建自己的查询。如果选择函数,请确保构建 SQL 查询以正确执行函数并获取结果。为了执行函数,请运行 SQL,例如 SELECT <columns> from <function_name(param)>在结果末尾提供信息。结果应采用 JSON 格式。它应包括所有列和结果,以及具有三个潜在值(FUNCTION 或 QUERY 或 None)的方法(如果使用函数则为 FUNCTION,如果使用自己的查询则为 QUERY)。除了使用的函数名称之外,方法结果也应包含在 JSON 中。您的最后一个答案应该只是一个有效的 JSON,而不能包含其他任何内容。格式如下:    {{       "results": [       {{         "col1": val1,         "col2": val2,         "col3": val3,         ...       }}     ],     "approach": "FUNCTION or QUERY or NONE",     "function_used": "<function name>",
    "query": <最终使用函数或者不用来检索最终结果> 
    }} 
    """

此外,对于最佳实践声明(例如不要执行任何 DML 语句),可以通过限制对数据库的写权限来缓解。 Gradio 用户界面 用户界面保持简单,有 4 个选项卡,包含数据库连接配置、创建功能以及使用 gradio 聊天界面添加一些示例。

编辑

添加图片注释,不超过 140 字(可选)

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

  • 获取年份的书籍(int)
  • 获取客户订单历史记录(int)

总而言之,我们现在正在使用一个功能齐全的 AI 代理,它能够使用其工具与数据库交互、读取其元数据并构建具有功能执行功能的查询。

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

测试运行

我们将对两种 LLM 模型运行多个提示,每种提示都有望针对我们的应用程序所采用的不同方法。 要运行该应用程序,请确保数据库已设置

docker-compose up

然后启动 gradio 应用程序
python -m app.main主要

提示 1:预期的功能使用情况 在这个提示中,我们希望我们的代理认识到他们可以使用函数而不是构建他们的查询。 查询: 获取 1997 年的书籍 gpt-4o-mini 响应:

编辑

llama3.1 8b 响应:

使用 llama 3.1,我输入了几个提示,但它仍然使用其生成的查询。可以通过使用 70b 版本或采用更直接的方法来指示它使用特定函数来缓解此问题,如下所示

编辑

添加图片注释,不超过 140 字(可选)

输出分析: 对用户输入的响应包括附加组件,以确保结果的信任级别完全透明。AI 的答案带有“受信任”标签,并可查看使用的原始 SQL 代码和函数。 当 AI 代理使用特定功能检索最终答案时,会应用可信标签。这为用户提供了对结果的额外信心。 提示 2:基于数据库元数据的查询预期构造 查询:订单总数是多少? gpt-4o-mini 响应:

编辑

添加图片注释,不超过 140 字(可选)

llama3.1 8b 响应:

编辑

添加图片注释,不超过 140 字(可选)

输出分析 在构建 SQL 以响应用户查询时,两者都能够正确响应。随着数据库数据模型变得越来越复杂,将需要专门的 SQL 微调模型或更大的通用模型来保持响应质量。 完整的应用程序可在此处获取,以使用您的数据测试更多示例。

概括 在 Text-to-SQL 应用程序中构建额外的一致性层有助于降低失去用户信任的风险。我们展示了如何将函数作为工具,以及一些示例,有助于减少完全依赖 AI 来构建其查询逻辑,从而增加出错的可能性。此外,我们还引入了带有可信标签和附加信息的视觉队列,使用户能够自主评估他们对最终结果的信心。 数据驱动型组织依靠用户利用其数据资产进行决策。对话式人工智能提供的无缝和简单交互,加上信任因素,鼓励增加数据参与度。该应用程序在简单的聊天界面中访问大量公司数据,使组织更接近实现其数据驱动型目标。

感谢关注雲闪世界。(Aws解决方案架构师vs开发人员&GCP解决方案架构师vs开发人员)

 订阅频道(t.me/awsgoogvps_…)
TG交流群(t.me/awsgoogvpsHost)