function calling 流程和案例

流程

以下是openai的代码,使用阿里云等其他模型需要调整

大模型选择

有些小模型不支持function call,如qwen2.5-7b-instruct 不支持function calling, qwen2.5-72b-instruct 支持

0 函数定义和编写工具说明(tools)

sunwukong_tool = StructuredTool.from_function(
    func=get_weather,
    name=get_weather.__name__ ,  # 保持名称一致性
    description="查询天气,输入必须是英文名,中国的城市需要用对应城市的英文名称代替,例如如果需要查询北京市天气,则loc参数需要输入'Beijing';,示例输入:'Beijing'"
)

1. 第一次调用大模型

除了发送询问消息外,还要带上 自定义函数列表。 大模型判断当需要调用外部函数的时候,会根据函数的说明寻找合适的函数。

messages=[
    {"role": "system", "content": "数据集data:%s,数据集以字符串形式呈现" % df_str},
    {"role": "user", "content": "请在数据集data上执行孙悟空算法"}
]
response = client.chat.completions.create(
        model="gpt-3.5-turbo",
        messages=messages,
        tools=tools, 
        tool_choice="auto",  //让大模型决定是否需要调用外部自定义函数
    )

first_response = response.choices[0].message

2. 解析调用返回值,判断response的 tool_calls 是否有值,如果有值说明需要调用外部函数

tool_calls = response.choices[0].message.tool_calls
 
for tool_call in tool_calls:
    function_name = tool_call.function.name
    function_to_call = available_tools[function_name]
    function_args = json.loads(tool_call.function.arguments)
    function_response = function_to_call(**function_args)

3. 追加 第一次模型返回结果消息

messages.append(first_response)

4. 追加 外部函数的调用结果

messages.append(
        {
            "tool_call_id": tool_call.id,
            "role": "tool",
            "name": function_name,
            "content": function_response,
        }
)

5. 再一次请求大模型

示例代码

以下使用阿里云大模型function calling 代码示例

import os
import numpy as np
import pandas as pd 
import json
import io
from langchain_core.tools import StructuredTool
from openai import OpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
from langchain_core.messages import AIMessage
from langchain_core.messages import SystemMessage, HumanMessage, ToolMessage

import os



def sunwukong_function(data):
    """
    孙悟空算法函数,该函数定义了数据集计算过程
    :param data: 必要参数,表示带入计算的数据表,用字符串进行表示
    :return:sunwukong_function函数计算后的结果,返回结果为表示为JSON格式的Dataframe类型对象
    """
    data = io.StringIO(data)
    df_new = pd.read_csv(data, sep='\s+', index_col=0)
    res = df_new * 10
    return json.dumps(res.to_string())

df = pd.DataFrame({'x1':[1, 2], 'x2':[3, 4]})
df_str = df.to_string()
print(df_str)
result_json=sunwukong_function(df_str)
print(result_json)

# sunwukong={
#         "type": "function",
#         "function": {"name": "sunwukong_processor",
#                       "description": "用于执行孙悟空算法函数,定义了一种特殊的数据集计算过程",
#                       "parameters": {"type": "object",
#                                      "properties": {"data": {"type": "string",
#                                                              "description": "执行孙悟空算法的数据集"},
#                                                    },
#                                      "required": ["data"],
#                                     },
#                      }
#     }

    # 注册函数
# sunwukong_tool = StructuredTool.from_function(func=sunwukong_function,name="sunwukong_processor", description=sunwukong['function']['description'])

sunwukong_tool = StructuredTool.from_function(
    func=sunwukong_function,
    name=sunwukong_function.__name__ ,  # 保持名称一致性
    description="执行孙悟空算法处理表格数据,输入必须是以空格或制表符分隔的字符串,示例输入:'x1 x2\\n0 1 3\\n1 2 4'"
)


def create_llm() -> ChatOpenAI:
    """创建并返回配置好的大模型实例"""
    return ChatOpenAI(
        api_key=os.getenv("DASHSCOPE_API_KEY") or "your_api_key_here",
        base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
        model="qwen2.5-72b-instruct",
    )
# message_history = [
#         SystemMessage(content=f"数据集data:{dataset_str},数据集以字符串形式呈现"),
#         HumanMessage(content="请用孙悟空算法处理这个数据集")
#     ]



messages=[
    {"role": "system", "content": "数据集data:%s,数据集以字符串形式呈现" % df_str},
    {"role": "user", "content": "请在数据集data上执行孙悟空算法"}
]

def build_chain_withtool(prompt_template):
    # 定义提示模板
   

    
    # 创建LLM实例并绑定工具
    llm = create_llm()
    
    # 构建处理链:提示词 -> 绑定工具的模型
    return prompt_template | llm.bind_tools(tools=[sunwukong_tool],tool_choice="auto")

def build_chain(prompt_template):
    # 定义提示模板
    # prompt_template = ChatPromptTemplate.from_messages([
    #     ("system", "数据集data:{dataset},数据集以字符串形式呈现"),
    #     ("human", "{user_query}"),
    # ])

    
    # 创建LLM实例并绑定工具
    llm = create_llm()
    
    # 构建处理链:提示词 -> 绑定工具的模型
    return prompt_template | llm


def main():
   

    prompt_template = ChatPromptTemplate.from_messages([
        ("system", "数据集data:{dataset},数据集以字符串形式呈现"),
        ("human", "{user_query}"),
    ])

    # 示例数据集
    sample_df = pd.DataFrame({'x1': [1, 2], 'x2': [3, 4]})
    dataset_str = sample_df.to_string()
    
     # 初始化消息历史
    message_history = [
        SystemMessage(content=f"数据集data:{dataset_str},数据集以字符串形式呈现"),
        HumanMessage(content="请用孙悟空算法处理这个数据集")
    ]

    # 构建对话链
    chain = build_chain_withtool(prompt_template)
    
    # 执行调用
    first_response = chain.invoke({
        "dataset": dataset_str,
        "user_query": "请用孙悟空算法处理这个数据集"
    })

    print("完整响应对象:\n", first_response)    
    message_history.append(first_response)  # 追加AIMessage

    
    
    if isinstance(first_response, AIMessage):
        raw_calls = first_response.additional_kwargs.get("tool_calls", [])
        for call in raw_calls:
            func_name = call["function"]["name"]
            args = json.loads(call["function"]["arguments"])
            if func_name == sunwukong_function.__name__ :
                func_args = sunwukong_function(args["data"])
                tool_result =  json.loads(func_args)
                print("最终结果:", tool_result)  # 解析JSON输出
            

                message_history.append(
                    ToolMessage(
                        content=tool_result,
                        name=func_name,
                        tool_call_id=call["id"]
                    )
                )
    
                # 第二次调用:传递完整历史
                final_prompt = ChatPromptTemplate.from_messages(message_history)
                final_chain = build_chain(final_prompt)
                final_response = final_chain.invoke({})  # 无输入变量
                print("最终回复:", final_response.content)
                

if __name__ == "__main__":
    
    main()

参考资料

posted @ 2025-03-26 10:43  向着朝阳  阅读(243)  评论(0)    收藏  举报