AI大模型探索之路-基础篇4:彻底掌握Function函数的概念及其应用

文章目录
前言
一、Function函数特点
二、Function应用场景
三、Function参数说明
四、基于Function函数实现天气查询服务
五、基于Function函数实现数据平台查询
总结
前言
OpenAI大语言模型不仅在文本生成、翻译、问答等方面表现出色;同时引入了Function函数,通过Function函数对大模型能力进行扩展增强。本文将深入探讨Function函数的特点、功能和使用场景,让我们在开发学习中可以更好地理解和利用这一强大工具。

一、Function函数特点
Function函数是OpenAI大模型非常重要的一个功能点,它允许大模型在生成响应时,可以调用外部函数来获取回复结果。这些函数可以是任何类型的计算或数据检索操作,包括但不限于联网检索、数据库查询、复杂数学计算等。这种设计使得大模型不再局限于其内置的知识库,而是能够动态地获取和处理信息。

二、Function应用场景
1) 实时信息检索:通过Function函数,大模型可以接入互联网或其他数据源,获取最新的信息;如天气预报、股票价格查询等需要实时数据任务信息。
2)复杂计算:Function函数还可以用来执行复杂的计算任务,比如数据分析、图形渲染等。这使得模型能够在更复杂的应用场景中发挥作用。
3)代码解释与执行:通过Function函数,模型甚至可以解释和执行代码,这为开发者提供了一个强大的编程辅助工具。
4)个性化服务:Function函数还可以用来实现个性化服务,比如根据用户的特定需求生成定制化的内容。

三、Function参数说明
Function函数主要包括Function和Function_call两个参数配合使用;为了兼容后续的扩展;官网已经升级调整为tools和tool_choice,将Function调整为tools中的一种类型的工具
1)tools参数:自定义工具列表,配置自定义函数(目前Type只支持function),可以配置多个函数
2)tool_choice参数:设置是否需要大模型调用自定义的funcation函数(none/auto)
none:表示不调用自定义函数、auto:表示大模型可以自动选择生成消息或者调用函数
升级前:

#1.大模型API调用

#data = openai.ChatCompletion.create(model= GPT_MODEL,messages = messages,functions = functions,function_call = None)
data = openai.ChatCompletion.create(
            model= GPT_MODEL,
            messages = messages,
            functions = functions,
            function_call = {"name": "functionName1"}
)
#2.function函数定义
functions = [
    {
        "name": "functionName1",  # 功能的名称
        "description": "XXXX",  # 功能的描述
        "parameters": {  # 定义该功能需要的参数
           ....
        },
    },
    {
        "name": "functionName2",  # 功能的名称
        "description": "XXXX",  # 功能的描述
        "parameters": {  # 定义该功能需要的参数
           ....
        },
    },
..................
]


升级后:

#1.大模型API调用

data = client.chat.completions.create(
            model= GPT_MODEL,
            messages = messages,
            tools = tools,
            tool_choice={"type": "function", "function": {"name": "functionName1"} )


#2.function函数定义

tools = [
    {
        "type": "function", #固定设置为function,目前仅支持function
        "function": {
            "name": "functionName1",# 功能的名称
            "description": "xxxxxx",# 功能的描述
            "parameters": { # 定义该功能需要的参数
              .......
            },
        }
    },
    {
        "type": "function",
        "function": {
            "name": "functionName2",# 功能的名称
            "description": "xxxxxx",# 功能的描述
            "parameters": { # 定义该功能需要的参数
              .......
            },
        }
    },
..........................
]



四、基于Function函数实现天气查询服务
通过一个实战案例来演示如何使用Function函数实现天气查询服务。
1)环境准备pip install scipy tenacity tiktoken termcolor openai requests
2)导入依赖、定义客户端

import json
from openai import OpenAI
from tenacity import retry, wait_random_exponential, stop_after_attempt
from termcolor import colored

GPT_MODEL = "gpt-3.5-turbo-0613"
client = OpenAI()

#client.models.list()



3)请求封装
定义一个函数chat_completion_request,主要用于发送 聊天补全 请求到OpenAI服务器

def chat_completion_request(messages, tools=None, tool_choice=None, model=GPT_MODEL):
    try:
        response = client.chat.completions.create(
            model=model,
            messages=messages,
            tools=tools,
            tool_choice=tool_choice,
        )
        return response
    except Exception as e:
        print("Unable to generate ChatCompletion response")
        print(f"Exception: {e}")
        return e



4)定义打印函数
定义一个函数pretty_print_conversation,用于打印消息对话内容

def pretty_print_conversation(messages):

    # 为不同角色设置不同的颜色
    role_to_color = {
        "system": "red",
        "user": "green",
        "assistant": "blue",
        "function": "magenta",
    }

    # 遍历消息列表
    for message in messages:
            # 如果消息的角色是"system",则用红色打印“content”
            if isinstance(message, dict) and message["role"] == "system":
                print(colored(f"system: {message['content']}\n", role_to_color[message["role"]]))
            # 如果消息的角色是"user",则用绿色打印“content”
            elif isinstance(message, dict) and message["role"] == "user":
                print(colored(f"user: {message['content']}\n", role_to_color[message["role"]]))
            # 如果消息的角色是"assistant",并且消息中包含"function_call",则用蓝色打印"function_call"
            elif hasattr(message, 'role') and message.role == "assistant" and message.function_call:
                print(colored(f"assistant: {message.function_call}\n", role_to_color[message.role]))
            # 如果消息的角色是"assistant",但是消息中不包含"function_call",则用蓝色打印“content”
            elif hasattr(message, 'role') and message.role == "assistant" and not message.function_call:
                print(colored(f"assistant: {message.content}\n", role_to_color[message.role]))
            elif isinstance(message, dict) and message["role"] == "function":
            # 如果消息的角色是"function",则用品红色打印“function”
                print(colored(f"function ({message['name']}): {message['content']}\n", role_to_color[message["role"]]))



5)自定义函数查询某地天气
定义一个tools 的工具集(函数列表),包含2个为function函数,这两个函数分别定义了相关功能的参数

# 第一个字典定义了一个名为"get_current_weather"的函数
tools = [
    {
        "type": "function",
        "function": {
            "name": "get_current_weather",# 函数的名称
            "description": "Get the current weather",# 函数的描述
            "parameters": {# 定义该函数需要的参数
                "type": "object",
                "properties": {# 参数的属性
                    "location": {# 地点参数
                        "type": "string",# 参数类型为字符串
                        "description": "The city and state, e.g. San Francisco, CA",# 参数的描述
                    },
                    "format": {# 温度单位参数
                        "type": "string",# 参数类型为字符串
                        "enum": ["celsius", "fahrenheit"],# 摄氏度,华氏 参数的取值
                        "description": "The temperature unit to use. Infer this from the users location.",# 参数的描述
                    },
                },
                "required": ["location", "format"],# 该函数需要的必要参数
            },
        }
    },
    # 第二个字典定义了一个名为"get_n_day_weather_forecast"的函数
    {
        "type": "function",
        "function": {
            "name": "get_n_day_weather_forecast",
            "description": "Get an N-day weather forecast",
            "parameters": {
                "type": "object",
                "properties": {
                    "location": {
                        "type": "string",
                        "description": "The city and state, e.g. San Francisco, CA",
                    },
                    "format": {
                        "type": "string",
                        "enum": ["celsius", "fahrenheit"],
                        "description": "The temperature unit to use. Infer this from the users location.",
                    },
                    "num_days": {
                        "type": "integer",
                        "description": "The number of days to forecast",
                    }
                },
                "required": ["location", "format", "num_days"]
            },
        }
    },
]



6)函数调用:咨询今天天气

messages = []
messages.append({"role": "system", "content": "Don't make assumptions about what values to plug into functions. Ask for clarification if a user request is ambiguous."})
messages.append({"role": "user", "content": "What's the weather like today"})
chat_response = chat_completion_request(
    messages, tools=tools
)
assistant_message = chat_response.choices[0].message
messages.append(assistant_message)
#assistant_message
# 打印助手的回复消息
pretty_print_conversation(messages)



7)函数调用:回复当前地点

messages.append({"role": "user", "content": "I'm in ShenZhen, China."})
#大模型自己选择是否使用函数
#chat_response = chat_completion_request(messages, tools=tools)
#强制使用函数
chat_response = chat_completion_request(messages, tools=tools, tool_choice={"type": "function", "function": {"name": "get_current_weather"}})
assistant_message = chat_response.choices[0].message
messages.append(assistant_message)
#assistant_message
# 打印助手的回复消息
pretty_print_conversation(messages)



8)设置问答样例,用于咨询未来5天的天气

messages = []
messages.append({"role": "system", "content": "Don't make assumptions about what values to plug into functions. Ask for clarification if a user request is ambiguous."})
messages.append({"role": "user", "content": "what is the weather going to be like in Glasgow, Scotland over the next x days"})
chat_response = chat_completion_request(
    messages, tools=tools
)
assistant_message = chat_response.choices[0].message
messages.append(assistant_message)
#assistant_message
# 打印助手的回复消息
pretty_print_conversation(messages)


9)咨询未来5天天气

messages = []
messages.append({"role": "system", "content": "Don't make assumptions about what values to plug into functions. Ask for clarification if a user request is ambiguous."})
messages.append({"role": "user", "content": "Give me a weather report for Toronto, Canada."})
chat_response = chat_completion_request(
    messages, tools=tools, tool_choice={"type": "function", "function": {"name": "get_n_day_weather_forecast"}}
)
chat_response.choices[0].message



五、基于Function函数实现数据平台查询
1)定义数据库信息

import sqlite3

conn = sqlite3.connect("data/chinook.db")
print("Opened database successfully")



2)定义获取数据库信息的函数
首先定义三个函数get_table_names、get_column_names和get_database_info,用于从数据库连接对象中获取数据库的表名、表的列名以及整体数据库的信息;作为大模型的知识背景进行使用

def get_table_names(conn):
    """返回一个包含所有表名的列表"""
    table_names = []  # 创建一个空的表名列表
    # 执行SQL查询,获取数据库中所有表的名字
    tables = conn.execute("SELECT name FROM sqlite_master WHERE type='table';")
    # 遍历查询结果,并将每个表名添加到列表中
    for table in tables.fetchall():
        table_names.append(table[0])
    return table_names  # 返回表名列表


def get_column_names(conn, table_name):
    """返回一个给定表的所有列名的列表"""
    column_names = []  # 创建一个空的列名列表
    # 执行SQL查询,获取表的所有列的信息
    columns = conn.execute(f"PRAGMA table_info('{table_name}');").fetchall()
    # 遍历查询结果,并将每个列名添加到列表中
    for col in columns:
        column_names.append(col[1])
    return column_names  # 返回列名列表


def get_database_info(conn):
    """返回一个字典列表,每个字典包含一个表的名字和列信息"""
    table_dicts = []  # 创建一个空的字典列表
    # 遍历数据库中的所有表
    for table_name in get_table_names(conn):
        columns_names = get_column_names(conn, table_name)  # 获取当前表的所有列名
        # 将表名和列名信息作为一个字典添加到列表中
        table_dicts.append({"table_name": table_name, "column_names": columns_names})
    return table_dicts  # 返回字典列表
# 获取数据库信息,并存储为字典列表
database_schema_dict = get_database_info(conn)

# 将数据库信息转换为字符串格式,方便后续使用
database_schema_string = "\n".join(
    [
        f"Table: {table['table_name']}\nColumns: {', '.join(table['column_names'])}"
        for table in database_schema_dict
    ]
)
database_schema_string


3)自定义Function函数
定义 functions让 GPT 模型帮我们构造一个完整的 SQL 查询

# 定义一个功能列表,其中包含一个功能字典,该字典定义了一个名为"ask_database"的功能,用于回答用户关于音乐的问题
tools = [
    {
        "type": "function",
        "function": {
            "name": "ask_database",
            "description": "Use this function to answer user questions about music. Input 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.
                                """,
                    }
                },
                "required": ["query"],
            },
        }
    }
]



4)定义SQL执行函数
用于根据大模型返回的SQL,执行查询操作

def ask_database(conn, query):
    """使用 query 来查询 SQLite 数据库的函数。"""
    try:
        results = str(conn.execute(query).fetchall())  # 执行查询,并将结果转换为字符串
    except Exception as e:  # 如果查询失败,捕获异常并返回错误信息
        results = f"query failed with error: {e}"
    return results  # 返回查询结果


def execute_function_call(message):
    """执行函数调用"""
    # 判断功能调用的名称是否为 "ask_database"
    if message.tool_calls[0].function.name == "ask_database":
    #if message["function_call"]["name"] == "ask_database":
        # 如果是,则获取功能调用的参数,这里是 SQL 查询
        #query = json.loads(message["function_call"]["arguments"])["query"]
        query = json.loads(message.tool_calls[0].function.arguments)["query"]
        # 使用 ask_database 函数执行查询,并获取结果
        results = ask_database(conn, query)
    else:
        # 如果功能调用的名称不是 "ask_database",则返回错误信息
        #results = f"Error: function {message['function_call']['name']} does not exist"
        results = f"Error: function {message.tool_calls[0].function.name} does not exist"
    return results  # 返回结果


5)调用大模型API获取查询SQL

# 创建一个空的消息列表
messages = []

# 向消息列表中添加一个系统角色的消息,内容是 "Answer user questions by generating SQL queries against the Chinook Music Database."
messages.append({"role": "system", "content": "Answer user questions by generating SQL queries against the Chinook Music Database."})

# 向消息列表中添加一个用户角色的消息,内容是 "Hi, who are the top 5 artists by number of tracks?"
## 根据曲目数量排名前五的艺术家是谁?
messages.append({"role": "user", "content": "Hi, who are the top 5 artists by number of tracks?"})

# 使用 chat_completion_request 函数获取聊天响应
chat_response = chat_completion_request(messages, tools)

# 从聊天响应中获取助手的消息
assistant_message = chat_response.choices[0].message
#查看大模型,调用自定义函数生成的SQL
#print(assistant_message)


6)根据大模型返回的SQL, 执行查询操作获取结果

# 将助手的消息添加到消息列表中
assistant_message.content = str(assistant_message.tool_calls[0].function)
messages.append({"role": assistant_message.role, "content": assistant_message.content})

# 如果助手的消息中有功能调用
if assistant_message.tool_calls:
    # 使用 execute_function_call 函数执行功能调用,并获取结果
    results = execute_function_call(assistant_message)
    #print(results)
    # 将功能的结果作为一个功能角色的消息添加到消息列表中
    messages.append({"role": "function", "tool_call_id": assistant_message.tool_calls[0].id, "name": assistant_message.tool_calls[0].function.name, "content": results})

# 使用 pretty_print_conversation 函数打印对话
pretty_print_conversation(messages)



总结
Function函数为OpenAI大模型提供了强大的扩展能力,使其能够在更广泛的应用场景中发挥作用。通过Function函数,大模型可以动态地获取和处理信息,从而为用户提供更加丰富和个性化的服务。希望这篇文章能帮助你更好地理解和使用Function函数,发挥大模型的全部潜力。
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值