Function Calling进行Mysql数据库查询

技术定义与核心价值

Function Calling(函数调用)是MySQL数据库查询优化的核心方法论之一,指通过预定义的存储过程(Stored Procedure)或自定义函数(User-Defined Function)执行数据操作,实现业务逻辑与数据库操作的深度耦合。相较于传统SQL语句拼接,其核心价值体现在:

  1. 逻辑封装‌:将高频查询、复杂计算封装为可复用的函数模块,例如通过CREATE PROCEDURE定义多表联查逻辑,或使用CREATE FUNCTION实现税率计算等业务规则;
  2. 性能优化‌:预编译的存储过程减少SQL解析开销,结合参数化查询降低网络传输负载;
  3. 安全增强‌:通过权限隔离(如GRANT EXECUTE ON PROCEDURE)控制敏感数据访问,规避SQL注入风险。

应用场景与演进方向
在传统企业系统中,Function Calling常用于财务报表生成、数据清洗等批处理任务。随着AI技术发展,其与自然语言处理(NLP)的结合成为新趋势:通过语义解析引擎将用户提问(如“显示本月华东区销售额”)转换为函数调用指令(如CALL get_region_sales('East', CURRENT_MONTH)),驱动智能数据分析Agent自动响应。

总结
Function Calling通过标准化、模块化的数据库操作接口,显著提升系统健壮性与开发效率。未来在低代码平台与AI代理的驱动下,其“声明式调用+自动化执行”的特性将进一步降低数据库交互门槛,成为企业数据架构升级的关键技术支点。

一、定义Mysql表结构以及查询

进行表结构的定义以及mysql数据库的连接以及查询

table_sql = """

CREATE TABLE `user_info` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '角色id',
  `role` varchar(255) DEFAULT NULL COMMENT '角色简称',
  `name` varchar(255) DEFAULT NULL COMMENT '姓名',
  `wuqi` varchar(255) DEFAULT NULL COMMENT '武器',
  `fashu` varchar(255) DEFAULT NULL COMMENT '法术',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8;

"""

# 数据库连接配置
config = {
    'host':'localhost',
    'user':'root',
    'password':'123456',
    'database':'sys'
}

def mysql_query(query:str):
    # 获取数据库连接
    try:
        db = pymysql.connect(**config)
        cursor = db.cursor()
        cursor.execute(query)
        result = cursor.fetchall()
        return result
    except Exception as e:
        print(f"Error connecting to database: {e}")
        return ""    
def get_query_result(tool_name,tool_args):
    if tool_name == "mysql_query":
        sql = tool_args["query"]
        print(sql)
        result = mysql_query(sql)
        print(f'执行结果是:{result}')
        return str(result)
    else:
        return "未知的函数"

二、定义functions

functions = [{
            "type": "function",
            "function": {
                "name": "mysql_query",
                "description": "使用此功能回答用户有关业务的问题。输出应该是完整形式的SQL查询",
                "parameters": {
                    "type": "object",
                    "properties": {
                        "query": {
                            "type": "string",
                            "description": f"""
                            SQL查询提取信息以回答用户的问题.
                            SQL应该使用此数据库模式编写:
                            {table_sql}
                            该查询应该以纯文本形式返回,而不是以JSON形式返回.
                            查询应仅包含Mysql支持的语法.
                            """,
                        }
                    },
                    "required": ["query"],
                }
            }
        }]

三、定义OpenAI以及模型工具调用

1、进行模型定义

client = OpenAI(
    api_key = os.getenv("DMX_OPENAI_API_KEY"),
    base_url = os.getenv("DMX_BASE_URL")
)

def get_sql_completion(messages, model="gpt-3.5-turbo"):
    try:
        response = client.chat.completions.create(
            model=model,
            messages=messages,
            temperature=0,
            tools= functions,
            tool_choice = "auto"
        )
        return response.choices[0].message
    except ValueError as e:
        print(f"模型处理数据异常:{str(e)}")

2、定义提示词以及message参数,并对第一次的执行结果进行封装

rompt = "孙悟空有什么武器和法术";

messages = [
    {"role": "system", "content": "你是一个数据分析师,基于数据库的数据回答问题"},
    {"role": "user", "content": prompt}
]

first_response = get_sql_completion(messages)
if first_response:
    messages.append(first_response)

    # 注意第一次的结果也要塞入
    tool_calls = first_response.tool_calls
    if tool_calls is not None:
        for tool_call in tool_calls:
            tool_name = tool_call.function.name
            tool_args = json.loads(tool_call.function.arguments)
            # 解析后的结果塞入
            messages.append({
                "role": "tool",
                "content": get_query_result(tool_name,tool_args),
                "tool_call_id": tool_call.id
            })
            
# 第二次请求
second_response = get_sql_completion(messages)
print("*****************************************")
print(second_response.content)

四、运行结果

以上结果运行了三次,三次都是不一样的,所以还有待于进行微调,不过这里只是demo演示,了解其运行过程。

五、扩展与思考

1、上面的例子是一个表的,那么对于三个表、多个表呢

只要在table_sql中加入对应的表接口就可以了

table_sql = """

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、这个例子中数据库采用的是mysql,那么sqllite、ES、mongoDB集成也和这类似,只是修改对应的查询就可以了。不过现在已经有成熟的框架去调用了,可以不用fun_call去处理了,这里只是了解其原理。比如基于SQLDatabase+langchain+mysql搭建智能sql查询_langchain sqldatabasechain-CSDN博客这个例子中就是基于langchain框架进行数据处理的。

这个是function calling基本的用法,以及多工具调用实例,可以参考

大语言模型function calling的基本用法-CSDN博客

### 如何在DeepSeek中使用Java进行函数调用 当涉及到在DeepSeek环境中通过Java实现函数调用来操作大型语言模型(LLM)节点时,最佳实践建议采用注册连接的方式传递必要的配置信息给目标函数[^1]。为了使这些连接能够被正确识别并应用到LLM节点上,在编写Java代码时应当遵循特定的设计模式。 对于希望集成外部服务如数据库查询功能的情况,可以通过定义接口来封装数据访问逻辑,并利用依赖注入机制将具体的实现类提供给需要执行远程过程调用的组件[^2]。这种方式不仅有助于解耦业务逻辑和服务层之间的关系,同时也简化了测试流程以及后续维护工作。 下面是一个简单的例子展示如何创建一个接受已注册连接作为参数的方法: ```java public class FunctionCaller { private final ConnectionManager connectionManager; public FunctionCaller(ConnectionManager connectionManager){ this.connectionManager = connectionManager; } /** * Demonstrates how a function call might be made using an injected connection. */ public void performFunctionCall(String functionName, Map<String,Object> parameters) { try (Connection conn = connectionManager.getConnection()) { // Assuming there's a method to prepare and execute calls against the provided connection object CallResult result = conn.execute(functionName, parameters); System.out.println("Execution completed successfully."); System.out.println(result.getResponse()); } catch (Exception e) { System.err.println("Failed to execute function " + functionName); throw new RuntimeException(e); } } } ``` 在这个案例里,`performFunctionCall` 方法接收两个参数:一个是表示要调用的功能名称字符串;另一个则是包含所有所需输入参数的地图结构。而实际用于通信的对象则由 `connectionManager.getConnection()` 提供,这使得我们可以轻松切换不同的底层实现而不必修改高层的应用程序代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值