【AI大模型应用开发】2.2 Function Calling连接外部世界 - 【实战】查询数据库

简介: 【AI大模型应用开发】2.2 Function Calling连接外部世界 - 【实战】查询数据库

大家好,我是【同学小张】。持续学习,持续干货输出,跟我一起学AI大模型。

上篇文章我们学习了Function Calling的基本用法,本文我们更近一步,学习下怎样利用Function Calling将大模型与数据库打通。

知识背景:我算是对数据库的SQL语句很不熟悉,只会简单的单表操作,还不熟练,每次都得查半天。现在有了大模型应用,有了Function Calling,再也不用查半天资料才写一个SQL了,还能熟练地用多表查询了!

本文实战案例来自知乎的AGI课程。

0. 封装数据库查询接口

还是先本地定义一个查询数据库的接口,该接口接收SQL数据库操作语句,然后调用执行。

# 创建数据库连接
import sqlite3
conn = sqlite3.connect(':memory:')
cursor = conn.cursor()
def ask_database(query):
    cursor.execute(query)
    records = cursor.fetchall()
    return records

1. 数据库的Functions怎么定义

示例代码:

#  描述数据库表结构
database_schema_string = """
CREATE TABLE orders (
    id INT PRIMARY KEY NOT NULL, -- 主键,不允许为空
    customer_id INT NOT NULL, -- 客户ID,不允许为空
    product_id STR NOT NULL, -- 产品ID,不允许为空
    price DECIMAL(10,2) NOT NULL, -- 价格,不允许为空
    status INT NOT NULL, -- 订单状态,整数类型,不允许为空。0代表待支付,1代表已支付,2代表已退款
    create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, -- 创建时间,默认为当前时间
    pay_time TIMESTAMP -- 支付时间,可以为空
);
"""
def get_sql_completion(messages, model="gpt-3.5-turbo-1106"):
    response = openai.chat.completions.create(
        model=model,
        messages=messages,
        temperature=0,  # 模型输出的随机性,0 表示随机性最小
        tools=[{  # 摘自 OpenAI 官方示例 https://github.com/openai/openai-cookbook/blob/main/examples/How_to_call_functions_with_chat_models.ipynb
            "type": "function",
            "function": {
                "name": "ask_database",
                "description": "Use this function to answer user questions about business. \
                            Output should be a fully formed SQL query.",
                "parameters": {
                    "type": "object",
                    "properties": {
                        "query": {
                            "type": "string",
                            "description": f"""
                            SQL query extracting info to answer the user's question.
                            SQL should be written using this database schema:
                            {database_schema_string}
                            The query should be returned in plain text, not in JSON.
                            The query should only contain grammars supported by SQLite.
                            """,
                        }
                    },
                    "required": ["query"],
                }
            }
        }],
    )
    return response.choices[0].message

重点看两个description:

(1)function 的 description:Use this function to answer user questions about business. Output should be a fully formed SQL query."

  • 要求输出必须是一个SQL语句

(2)参数的description:

f"""
SQL query extracting info to answer the user's question.
SQL should be written using this database schema:
{database_schema_string}
The query should be returned in plain text, not in JSON.
The query should only contain grammars supported by SQLite.
""",
  • 将数据库的数据结构database_schema_string放到prompt中,根据此表的数据结构写SQL语句
  • 不能返回json,而是返回字符串
  • 返回的query语句文字必须符合SQL语法

2. 可以使用了

prompt = "10月的销售额"
messages = [
    {"role": "system", "content": "基于 order 表回答用户问题"},
    {"role": "user", "content": prompt}
]
response = get_sql_completion(messages)
if response.content is None:
    response.content = ""
messages.append(response)
print("====Function Calling====")
print_json(response)
if response.tool_calls is not None:
    tool_call = response.tool_calls[0]
    if tool_call.function.name == "ask_database":
        arguments = tool_call.function.arguments
        args = json.loads(arguments)
        print("====SQL====")
        print(args["query"])
        result = ask_database(args["query"])
        print("====DB Records====")
        print(result)
        messages.append({
            "tool_call_id": tool_call.id,
            "role": "tool",
            "name": "ask_database",
            "content": str(result)
        })
        response = get_sql_completion(messages)
        print("====最终回复====")
        print(response.content)

看下运行过程,可以看到返回了正确的SQL查询语句:

(但是因为我本地没有数据库,所以没有查询到数据,返回“暂时不可用”。为了测试,你可以在本地事先生成一份demo数据,这就涉及到Python操作数据库了,有需要的话我再写个文章介绍下怎么用Python操作数据库)

3. 进阶 - 多表查询

(1)将数据表数据结构改一下,改成多张表即可

#  描述数据库表结构
database_schema_string = """
CREATE TABLE customers (
    id INT PRIMARY KEY NOT NULL, -- 主键,不允许为空
    customer_name VARCHAR(255) NOT NULL, -- 客户名,不允许为空
    email VARCHAR(255) UNIQUE, -- 邮箱,唯一
    register_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP -- 注册时间,默认为当前时间
);
CREATE TABLE products (
    id INT PRIMARY KEY NOT NULL, -- 主键,不允许为空
    product_name VARCHAR(255) NOT NULL, -- 产品名称,不允许为空
    price DECIMAL(10,2) NOT NULL -- 价格,不允许为空
);
CREATE TABLE orders (
    id INT PRIMARY KEY NOT NULL, -- 主键,不允许为空
    customer_id INT NOT NULL, -- 客户ID,不允许为空
    product_id INT NOT NULL, -- 产品ID,不允许为空
    price DECIMAL(10,2) NOT NULL, -- 价格,不允许为空
    status INT NOT NULL, -- 订单状态,整数类型,不允许为空。0代表待支付,1代表已支付,2代表已退款
    create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, -- 创建时间,默认为当前时间
    pay_time TIMESTAMP -- 支付时间,可以为空
);
"""

(2)提问

prompt = "统计每月每件商品的销售额"
# prompt = "这星期消费最高的用户是谁?他买了哪些商品? 每件商品买了几件?花费多少?"
messages = [
    {"role": "system", "content": "基于 order 表回答用户问题"},
    {"role": "user", "content": prompt}
]
response = get_sql_completion(messages)
print(response.tool_calls[0].function.arguments)

(3)运行结果,生成了正确的多表查询语句

4. 思考 - 利用大模型写数据库查询语句的Prompt

通过上面对function和参数的description描述,我们可以大体看出怎样利用大模型去写正确的SQL查询语句。

Prompt如下:

假如你是一个SQL数据库专家。请按照用户的输入生成一个SQL语句

SQL should be written using this database schema:

“”"

CREATE TABLE customers (

id INT PRIMARY KEY NOT NULL, – 主键,不允许为空

customer_name VARCHAR(255) NOT NULL, – 客户名,不允许为空

email VARCHAR(255) UNIQUE, – 邮箱,唯一

register_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP – 注册时间,默认为当前时间

);

CREATE TABLE products (

id INT PRIMARY KEY NOT NULL, – 主键,不允许为空

product_name VARCHAR(255) NOT NULL, – 产品名称,不允许为空

price DECIMAL(10,2) NOT NULL – 价格,不允许为空

);

CREATE TABLE orders (

id INT PRIMARY KEY NOT NULL, – 主键,不允许为空

customer_id INT NOT NULL, – 客户ID,不允许为空

product_id INT NOT NULL, – 产品ID,不允许为空

price DECIMAL(10,2) NOT NULL, – 价格,不允许为空

status INT NOT NULL, – 订单状态,整数类型,不允许为空。0代表待支付,1代表已支付,2代表已退款

create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, – 创建时

间,默认为当前时间

pay_time TIMESTAMP – 支付时间,可以为空 ); “”"

The query should be returned in plain text, not in JSON. The query

should only contain grammars supported by SQLite. Output should be a

fully formed SQL query.

用户输入:统计每月每件商品的销售额,包含商品名称

结果:

完美。

注意: Function Calling 不仅可以调用读函数,也能调用写函数。但官方强烈建议,在写之前,一定要有人做确认,因为大模型的结果有不确定性。


  • 大家好,我是同学小张
  • 欢迎 点赞 + 关注 👏,促使我持续学习持续干货输出
  • +v: jasper_8017 一起交流💬,一起进步💪。
  • 微信公众号也可搜【同学小张】 🙏
  • 踩坑不易,感谢关注和围观

本站文章一览:

相关文章
|
18天前
|
存储 人工智能 Cloud Native
云栖重磅|从数据到智能:Data+AI驱动的云原生数据库
在9月20日2024云栖大会上,阿里云智能集团副总裁,数据库产品事业部负责人,ACM、CCF、IEEE会士(Fellow)李飞飞发表《从数据到智能:Data+AI驱动的云原生数据库》主题演讲。他表示,数据是生成式AI的核心资产,大模型时代的数据管理系统需具备多模处理和实时分析能力。阿里云瑶池将数据+AI全面融合,构建一站式多模数据管理平台,以数据驱动决策与创新,为用户提供像“搭积木”一样易用、好用、高可用的使用体验。
云栖重磅|从数据到智能:Data+AI驱动的云原生数据库
|
20天前
|
SQL 安全 Java
MyBatis-Plus条件构造器:构建安全、高效的数据库查询
MyBatis-Plus 提供了一套强大的条件构造器(Wrapper),用于构建复杂的数据库查询条件。Wrapper 类允许开发者以链式调用的方式构造查询条件,无需编写繁琐的 SQL 语句,从而提高开发效率并减少 SQL 注入的风险。
13 1
MyBatis-Plus条件构造器:构建安全、高效的数据库查询
|
17天前
|
人工智能 运维 关系型数据库
云栖大会|数据库与AI全面融合,迈入数据智能新纪元
2024年云栖大会「数据库与AI融合」专场,来自NVIDIA、宇视科技、合思信息、杭州光云科技、MiniMax等企业的代表与阿里云瑶池数据库团队,共同分享了Data+AI全面融合的最新技术进展。阿里云发布了DMS的跨云统一开放元数据OneMeta和智能开发OneOps,推出《云数据库运维》技术图书,并介绍了PolarDB、AnalyticDB、Lindorm和Tair等产品的最新能力,展示了AI在数据库领域的广泛应用和创新。
|
17天前
|
关系型数据库 分布式数据库 数据库
云栖大会|从数据到决策:AI时代数据库如何实现高效数据管理?
在2024云栖大会「海量数据的高效存储与管理」专场,阿里云瑶池讲师团携手AMD、FunPlus、太美医疗科技、中石化、平安科技以及小赢科技、迅雷集团的资深技术专家深入分享了阿里云在OLTP方向的最新技术进展和行业最佳实践。
|
17天前
|
存储 缓存 固态存储
怎么让数据库查询更快
【10月更文挑战第28天】
25 2
|
19天前
|
存储 缓存 关系型数据库
怎么让数据库查询更快
【10月更文挑战第25天】通过以上综合的方法,可以有效地提高数据库查询的速度,提升应用程序的性能和响应速度。但在优化过程中,需要根据具体的数据库系统、应用场景和数据特点进行合理的调整和测试,以找到最适合的优化方案。
|
19天前
|
SQL Java 数据库连接
在Java应用中,数据库访问常成为性能瓶颈。连接池技术通过预建立并复用数据库连接,有效减少连接开销,提升访问效率
在Java应用中,数据库访问常成为性能瓶颈。连接池技术通过预建立并复用数据库连接,有效减少连接开销,提升访问效率。本文介绍了连接池的工作原理、优势及实现方法,并提供了HikariCP的示例代码。
32 3
|
18天前
|
监控 关系型数据库 MySQL
数据库优化:MySQL索引策略与查询性能调优实战
【10月更文挑战第27天】本文深入探讨了MySQL的索引策略和查询性能调优技巧。通过介绍B-Tree索引、哈希索引和全文索引等不同类型,以及如何创建和维护索引,结合实战案例分析查询执行计划,帮助读者掌握提升查询性能的方法。定期优化索引和调整查询语句是提高数据库性能的关键。
86 1
|
19天前
|
Java 数据库连接 数据库
深入探讨Java连接池技术如何通过复用数据库连接、减少连接建立和断开的开销,从而显著提升系统性能
在Java应用开发中,数据库操作常成为性能瓶颈。本文通过问题解答形式,深入探讨Java连接池技术如何通过复用数据库连接、减少连接建立和断开的开销,从而显著提升系统性能。文章介绍了连接池的优势、选择和使用方法,以及优化配置的技巧。
19 1
|
19天前
|
Java 数据库连接 数据库
Java连接池在数据库性能优化中的重要作用。连接池通过预先创建和管理数据库连接,避免了频繁创建和关闭连接的开销
本文深入探讨了Java连接池在数据库性能优化中的重要作用。连接池通过预先创建和管理数据库连接,避免了频繁创建和关闭连接的开销,显著提升了系统的响应速度和吞吐量。文章介绍了连接池的工作原理,并以HikariCP为例,展示了如何在Java应用中使用连接池。通过合理配置和优化,连接池技术能够有效提升应用性能。
33 1

热门文章

最新文章