你是否拥有大量数据却苦于难以从中提取有价值的信息?想不想像和朋友聊天一样,用自然语言就能轻松查询数据库?SQL Agent 或许正是你需要的解决方案。本文将介绍如何使用 Agno 框架,构建一个能理解你的数据,并将自然语言转化为 SQL 查询的智能 AI Agent,最终实现与数据的高效对话。

1. Agno:构建智能多 Agent 系统的基石

Agno 作为一个全栈框架,专为构建具备记忆、知识和推理能力的多 Agent 系统而生。它简化了 AI Agent 的创建过程,无需复杂的底层代码,只需简单的配置即可搭建强大的智能体。Agno 的核心优势在于其模块化设计,允许开发者轻松集成各种功能,例如本文重点介绍的 SQL Agent。 通过 Agno,开发者可以构建一个能够理解用户意图,并将用户的自然语言问题转化为具体的 SQL 查询语句的 AI Agent,进而从数据库中提取所需的信息。 想象一下,无需编写冗长的 SQL 代码,只需一句“告诉我所有未支付的发票”,Agno 就能帮你搞定一切。

2. 数据库准备:PostgreSQL 的 Docker Compose 部署

在构建 SQL Agent 之前,我们需要准备一个数据库。本文选择 PostgreSQL 作为核心数据库,并使用 Docker Compose 进行快速部署。 Docker Compose 文件如下所示:

services:
  pgvector:
    image: agnohq/pgvector:16
    restart: unless-stopped
    ports:
      - "5432:5432"
    volumes:
      - pgdata:/var/lib/postgresql/data
    environment:
      POSTGRES_USER: ai
      POSTGRES_PASSWORD: ai
      POSTGRES_DB: ai
    networks:
      - agent-api

networks:
  agent-api:

volumes:
  pgdata:

这段配置定义了一个名为 pgvector 的服务,基于 agnohq/pgvector:16 镜像,将容器的 5432 端口映射到宿主机的 5432 端口,并将数据存储在名为 pgdata 的卷中。同时,设置了 PostgreSQL 的用户名、密码和数据库名。 通过 Docker Compose,我们可以一键启动 PostgreSQL 数据库,避免了繁琐的手动配置过程,为后续 SQL Agent 的搭建奠定了基础。

3. 数据准备:创建示例 Invoice 数据表

为了演示 SQL Agent 的功能,我们需要在 PostgreSQL 数据库中创建一些示例数据。本文创建了两个数据表:invoice_headerinvoice_item,分别用于存储发票头信息和发票明细信息。

invoice_header 表的结构如下:

CREATE TABLE invoice_header (
    invoice_id UUID PRIMARY KEY,
    invoice_number VARCHAR(50) NOT NULL UNIQUE,
    customer_id UUID NOT NULL,
    customer_name VARCHAR(100) NOT NULL,
    invoice_date DATE NOT NULL,
    due_date DATE NOT NULL,
    total_amount NUMERIC(15, 2) NOT NULL,
    status VARCHAR(20) NOT NULL CHECK (status IN ('DRAFT', 'ISSUED', 'PAID', 'CANCELLED')),
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

invoice_item 表的结构如下:

CREATE TABLE invoice_item (
    item_id UUID PRIMARY KEY,
    invoice_id UUID NOT NULL,
    product_code VARCHAR(50) NOT NULL,
    product_name VARCHAR(100) NOT NULL,
    quantity INTEGER NOT NULL CHECK (quantity > 0),
    unit_price NUMERIC(12, 2) NOT NULL CHECK (unit_price >= 0),
    discount NUMERIC(5, 2) DEFAULT 0 CHECK (discount >= 0),
    total_price NUMERIC(15, 2) NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (invoice_id) REFERENCES invoice_header(invoice_id) ON DELETE CASCADE
);

接下来,我们插入一些示例数据:

-- Invoice 1 - ISSUED
INSERT INTO invoice_header (
    invoice_id, invoice_number, customer_id, customer_name, invoice_date, due_date, total_amount, status
) VALUES (
    '11111111-1111-1111-1111-111111111111',
    'INV-20240601-001',
    'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa',
    'PT Nusantara Jaya',
    '2024-06-01',
    '2024-06-15',
    1350000.00,
    'ISSUED'
);

INSERT INTO invoice_item (
    item_id, invoice_id, product_code, product_name, quantity, unit_price, discount, total_price
) VALUES
('22222222-2222-2222-2222-222222222222', '11111111-1111-1111-1111-111111111111', 'PRD001', 'Printer LaserJet HP', 1, 1000000.00, 0, 1000000.00),
('33333333-3333-3333-3333-333333333333', '11111111-1111-1111-1111-111111111111', 'PRD002', 'Tinta Printer HP 680', 2, 150000.00, 0, 300000.00),
('44444444-4444-4444-4444-444444444444', '11111111-1111-1111-1111-111111111111', 'PRD003', 'Kabel USB 2.0', 1, 50000.00, 0, 50000.00);

-- Invoice 2 - DRAFT with discount
INSERT INTO invoice_header (
    invoice_id, invoice_number, customer_id, customer_name, invoice_date, due_date, total_amount, status
) VALUES (
    '55555555-5555-5555-5555-555555555555',
    'INV-20240602-002',
    'bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb',
    'CV Sumber Makmur',
    '2024-06-02',
    '2024-06-30',
    890000.00,
    'DRAFT'
);

INSERT INTO invoice_item (
    item_id, invoice_id, product_code, product_name, quantity, unit_price, discount, total_price
) VALUES
('66666666-6666-6666-6666-666666666666', '55555555-5555-5555-5555-555555555555', 'PRD004', 'Monitor LG 24"', 1, 1500000.00, 30.00, 1050000.00),
('77777777-7777-7777-7777-777777777777', '55555555-5555-5555-5555-555555555555', 'PRD005', 'Mouse Wireless Logitech', 2, 200000.00, 10.00, 360000.00);

-- Invoice 3 - PAID
INSERT INTO invoice_header (
    invoice_id, invoice_number, customer_id, customer_name, invoice_date, due_date, total_amount, status
) VALUES (
    '88888888-8888-8888-8888-888888888888',
    'INV-20240520-003',
    'cccccccc-cccc-cccc-cccc-cccccccccccc',
    'UD Toko Maju',
    '2024-05-20',
    '2024-06-05',
    135000.00,
    'PAID'
);

INSERT INTO invoice_item (
    item_id, invoice_id, product_code, product_name, quantity, unit_price, discount, total_price
) VALUES
('99999999-9999-9999-9999-999999999999', '88888888-8888-8888-8888-888888888888', 'PRD006', 'Pulpen Pilot G2', 10, 15000.00, 10.00, 135000.00);

-- Invoice 4 - CANCELLED
INSERT INTO invoice_header (
    invoice_id, invoice_number, customer_id, customer_name, invoice_date, due_date, total_amount, status
) VALUES (
    'aaaa1111-aaaa-aaaa-aaaa-aaaaaaaaaaaa',
    'INV-20240525-004',
    'dddddddd-dddd-dddd-dddd-dddddddddddd',
    'CV Indo Supply',
    '2024-05-25',
    '2024-06-10',
    0.00,
    'CANCELLED'
);

这些数据模拟了四张发票的信息,包括已开具 (ISSUED)、草稿 (DRAFT)、已支付 (PAID) 和已取消 (CANCELLED) 等不同状态,以及对应的客户信息、产品信息、数量、单价和折扣等。 有了这些示例数据,我们就可以测试 SQL Agent 的查询能力,例如查询特定客户的未支付发票,或者查询某段时间内的销售额等。

4. 创建 AI Agent:使用 Agno 定义 SQL Agent

接下来,我们使用 Agno 框架创建一个 SQL Agent。创建一个名为 main.py 的文件,并将以下代码复制到该文件中:

from dotenv import load_dotenv
from agno.agent import Agent
from agno.tools.sql import SQLTools
from agno.models.openai import OpenAIChat
from agno.memory.agent import AgentMemory
from agno.memory.db.postgres import PgMemoryDb
from agno.storage.postgres import PostgresStorage
from textwrap import dedent
from agno.tools.thinking import ThinkingTools
from agno.playground import Playground, serve_playground_app

load_dotenv()

db_url = "postgresql+psycopg2://ai:ai@localhost:5432/ai"

agent_sql = Agent(
    name="SQL Agent",
    model=OpenAIChat(id="gpt-4.1"),
    tools=[
        SQLTools(db_url=db_url),
        ThinkingTools(add_instructions=True)
    ],
    memory=AgentMemory(
        db=PgMemoryDb(
            table_name="agent_memory",
            db_url=db_url,
        ),
        create_user_memories=True,
        update_user_memories_after_run=True,
        create_session_summary=True,
        update_session_summary_after_run=True,
    ),
    storage=PostgresStorage(
        table_name="agent_sessions", db_url=db_url, auto_upgrade_schema=True
    ),
    add_history_to_messages=True,
    num_history_responses=3,
    add_datetime_to_instructions=True,
    markdown=True,
    add_state_in_messages=True,
    enable_agentic_memory=True,
    show_tool_calls=True,
    description=dedent(
        """\
        I am Emma, a specialized Data Agent focused on converting natural language queries and reasoning into SQL queries.

        I excel at:
        - Transforming natural language questions into SQL queries
        - Understanding database schema and relationships
        - Providing clear explanations of the SQL queries I generate
        - Helping users get the data they need through SQL

        I will help you interact with databases through natural language and generate accurate SQL queries.
    """
    ),
    instructions=dedent(
        """\
        As a SQL Agent, I will help you analyze and process data through careful reasoning. Follow these steps:

        1. Initial Analysis:
        - First, I will thoroughly analyze the request using systematic reasoning
        - Break down complex queries into smaller, manageable components
        - Identify key data points and relationships needed
        - Consider edge cases and potential data limitations

        2. Reasoning Process:
        - Think step by step about what needs to be done
        - Consider multiple approaches to solve the problem
        - Evaluate the pros and cons of each approach
        - Document my thought process clearly

        3. Query Construction:
        - Based on the analysis, construct appropriate SQL queries
        - Validate query logic before execution
        - Consider query performance and optimization
        - Test for edge cases and potential errors

        4. Result Analysis:
        - Carefully examine the query results
        - Verify if the results match the expected outcome
        - Look for any anomalies or unexpected patterns
        - Consider if additional analysis is needed

        5. Explanation and Documentation:
        - Provide clear explanations of my reasoning process
        - Document why certain approaches were chosen
        - Explain any assumptions made
        - Highlight important findings and insights

        6. Quality Assurance:
        - Double-check all calculations and logic
        - Verify data consistency
        - Ensure explanations are clear and complete
        - Suggest potential follow-up analyses

        Additional Information:
        - You are interacting with the user_id: {current_user_id}
        - Always show your reasoning process before executing any query
        - Document each step of your thought process clearly
    """
    ),
)

app = Playground(
    agents=[
        agent_sql
    ]).get_app()

if __name__ == "__main__":
    serve_playground_app("main:app", port=7777, reload=True)

这段代码定义了一个名为 “SQL Agent” 的 AI Agent,并配置了以下关键组件:

  • Model: 使用 OpenAI 的 gpt-4.1 模型,负责理解自然语言并生成 SQL 查询。
  • Tools: 包含了 SQLToolsThinkingToolsSQLTools 用于连接数据库并执行 SQL 查询,ThinkingTools 帮助 AI Agent 进行推理和规划。
  • Memory: 使用 AgentMemory 管理 AI Agent 的记忆,包括用户记忆和会话总结,提高 AI Agent 的上下文理解能力。
  • Storage: 使用 PostgresStorageAI Agent 的会话信息存储到 PostgreSQL 数据库中,实现持久化存储。
  • Instructions: 定义了 AI Agent 的角色和行为规范,例如 “仔细分析请求”、”逐步思考”、”构建合适的 SQL 查询” 等,引导 AI Agent 正确执行任务。

通过这段代码,我们定义了一个具备自然语言理解、SQL 查询和记忆功能的智能 SQL Agent

5. 运行 AI Agent:使用 Agno Playground 进行交互

定义好 SQL Agent 后,我们可以使用 Agno Playground 进行交互。在终端中运行以下命令:

python main.py

这将启动一个本地 Web 服务器,并在浏览器中打开 Agno Playground。在 Playground 中,你可以像和朋友聊天一样,用自然语言向 SQL Agent 提问。

例如,你可以提问:

  • “Show me all issued invoices.”(显示所有已开具的发票)
  • “What is the total amount of draft invoices?”(草稿发票的总金额是多少?)
  • “Which customer has the highest total invoice amount?”(哪个客户的发票总金额最高?)

SQL Agent 将会自动将你的问题转化为 SQL 查询,并从数据库中提取相应的信息,最终以自然语言的形式返回给你。

6. 部署 Agent UI:更友好的用户界面

为了提供更友好的用户界面,你可以使用 Agno 提供的 Agent UI 示例。Agent UI 是一个美观、开源的界面,可以让你更方便地与 AI Agent 进行交互。 你可以参考 Agno 官方文档中的步骤,下载并运行 Agent UI 示例,并将 API Endpoint 连接到你刚刚创建的 SQL Agent。 通过 Agent UI,你可以更加直观地查看 AI Agent 的思考过程、生成的 SQL 查询以及查询结果,从而更好地理解 AI Agent 的工作原理。

7. 实际应用案例:提升数据分析效率

SQL Agent 在实际应用中具有广泛的应用前景。例如,在财务领域,财务人员可以使用 SQL Agent 快速查询各种财务报表,例如资产负债表、利润表和现金流量表,而无需编写复杂的 SQL 查询语句。 在销售领域,销售人员可以使用 SQL Agent 快速查询客户的购买记录、销售额和利润率,从而更好地了解客户的需求,并制定更有效的销售策略。 在运营领域,运营人员可以使用 SQL Agent 快速查询各种运营指标,例如用户活跃度、转化率和留存率,从而更好地了解产品的运营状况,并进行相应的优化。

例如,假设你是某电商平台的运营人员,你需要了解过去一个月内用户购买最多的商品是什么。你可以直接问 SQL Agent:”What are the top 10 most purchased products in the last month?” SQL Agent 会自动将这个问题转化为 SQL 查询语句,并从数据库中提取相应的信息,最终以列表的形式返回给你,包括商品名称和购买数量。 通过 SQL Agent,你可以快速获取所需的信息,而无需花费大量时间编写和执行 SQL 查询,从而大大提升了工作效率。

8. 优化 SQL Agent:提升准确性和效率

为了提升 SQL Agent 的准确性和效率,我们可以采取以下一些优化措施:

  • 优化数据库 schema: 合理设计数据库 schema,例如使用适当的数据类型、添加索引和外键等,可以提高 SQL 查询的效率。
  • 提供更详细的 instructions: 尽可能提供更详细的 instructions,例如明确 AI Agent 的角色、行为规范和约束条件等,可以引导 AI Agent 正确执行任务。
  • 添加更多示例数据: 提供更多的示例数据,可以帮助 AI Agent 更好地理解数据库 schema 和数据之间的关系,从而提高 SQL 查询的准确性。
  • 使用更强大的模型: 使用更强大的语言模型,例如 GPT-4 Turbo,可以提高 AI Agent 的自然语言理解能力和 SQL 查询生成能力。
  • 引入知识图谱: 引入知识图谱,可以将数据库中的实体和关系以图的形式表示出来,从而帮助 AI Agent 更好地理解数据之间的关联,提高 SQL 查询的准确性和效率。

例如,如果你的数据库中包含大量的文本数据,你可以使用文本向量化技术,将文本数据转化为向量形式,并使用向量数据库进行存储。然后,你可以使用 SQL Agent 进行语义搜索,例如 “find all products that are similar to ‘iPhone 15′”,SQL Agent 会自动将你的问题转化为向量查询语句,并从向量数据库中提取相应的信息。

9. 未来展望:更多 Agent 的可能性

Agno 不仅可以用于构建 SQL Agent,还可以用于构建各种其他类型的 AI Agent,例如:

  • 文档 Agent: 可以用于分析和处理各种文档,例如 PDF 文件、Word 文档和 Markdown 文件。
  • 客服 Agent: 可以用于自动回复客户的问题,并提供相关的帮助信息。
  • 销售 Agent: 可以用于自动跟踪潜在客户,并提供个性化的销售建议。
  • 内容创作 Agent: 可以用于自动生成各种内容,例如文章、博客和社交媒体帖子。

Agno 的灵活性和可扩展性为 AI Agent 的应用提供了无限的可能性。 随着大模型技术的不断发展,AI Agent 将会在越来越多的领域发挥重要作用,例如自动化、智能化和个性化等。

总结:

通过 Agno 框架,我们可以轻松构建一个智能 SQL Agent,实现与数据库的高效对话。这个 AI Agent 可以理解自然语言,将用户的提问转化为 SQL 查询,并从数据库中提取所需的信息。未来,我们可以探索更多 Agent 的可能性,让 AI Agent 在各个领域发挥更大的价值。你觉得下一个应该尝试构建什么类型的 Agent 呢?欢迎在评论区留下你的建议。感谢你的阅读,我们下篇文章再见!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注