在与大语言模型交互时,我们常常会遇到一个问题:直接让模型执行数学计算,或者包含数学运算的复杂问题。尤其是高精度或复杂运算时,结果往往不准确。例如,直接询问模型“计算 124342314 / 4324 并保留 6 位小数”,可能会得到一个近似值,甚至是错误的答案。这是因为大语言模型更擅长语言理解和生成,而非精确的数值计算。

不过,许多现代大模型接口(如 OpenAI 的 API)提供了 Function Calling 功能,允许我们在提示词中定义工具,通过生成代码并在本地执行来解决计算问题。本文将以 OpenAI 接口为例,展示如何利用 Function Calling 设计一个生成 Python 代码的工具,计算 124342314 / 4324 并保留 6 位小数,最终返回准确结果。国内的DeepSeek也提供了这一功能,不过目前的版本不稳地,官方接口文档说下个版本修复。

有人说为啥不使用深度推理,深度推理结果会准确。是的,不过在实际的业务场景中,使用接口调用推理模型,效率有点太低,远远不如使用这一工具,即使需要调用两次接口,使用成本还是比推理模型低的。


实现思路

  1. 定义工具:创建一个名为 generate_python_code 的工具,描述其功能为“生成并执行 Python 代码以完成计算任务”。
  2. 提示模型:在提示词中明确问题,并要求模型调用工具生成代码。
  3. 本地执行:接收模型生成的代码,在本地运行,得到计算结果。
  4. 返回结果:将结果传递回模型,生成最终回答。

代码实现

以下是一个完整的 Python 示例

1. 配置 OpenAI API

首先,确保你已安装 OpenAI 的 Python 库并获取了 API Key:

pip install openai

然后导入库并配置客户端:

import openai import json from openai import OpenAI 
client = OpenAI(api_key="your_openai_api_key")

2. 定义工具

我们定义一个工具 generate_python_code,用于生成 Python 代码:

tools = [
    {
        "type": "function",
        "function": {
            "name": "generate_python_code",
            "description": "根据任务需求生成可执行的 Python 代码来完成计算,并返回结果。",
            "parameters": {
                "type": "object",
                "properties": {
                    "code": {
                        "type": "string",
                        "description": "可执行的 Python 代码,返回计算结果"
                    }
                },
                "required": ["code"]
            }
        }
    }
]

3. 发送提示词并调用工具

构造一个提示词,要求模型计算 124342314 / 4324 并保留 6 位小数:

messages = [
    {
        "role": "user",
        "content": "请计算 124342314 / 4324,结果保留 6 位小数。"
    }
]

response = client.chat.completions.create(
    model="gpt-4o",  # 确保使用支持 Function Calling 的模型
    messages=messages,
    tools=tools,
    tool_choice="auto"
)

4. 处理模型返回的工具调用

模型会返回一个工具调用请求,我们提取生成的代码并在本地执行:

response_message = response.choices[0].message
tool_calls = response_message.tool_calls

if tool_calls:
    for tool_call in tool_calls:
        if tool_call.function.name == "generate_python_code":
            # 解析生成的代码
            function_args = json.loads(tool_call.function.arguments)
            code = function_args["code"]
            print(f"模型生成的代码:\n{code}")

            # 在本地执行代码
            try:
                local_vars = {}
                exec(code, {}, local_vars)
                result = local_vars.get("result", "未定义 result 变量")
                print(f"本地计算结果: {result}")
            except Exception as e:
                result = f"代码执行错误: {str(e)}"

模型生成以下代码(这个是不固定的,模型会自己写代码,使用的变量名以及变量数量可以在tools的参数里定义):

result = round(124342314 / 4324, 6)

本地执行后,result 将是 28756.316836

5. 将结果返回给模型

将计算结果追加到对话中,让模型生成最终回答:

messages.append({
    "role": "tool",
    "content": str(result),
    "tool_call_id": tool_call.id
})

final_response = client.chat.completions.create(
    model="gpt-4-turbo",
    messages=messages
)

final_answer = final_response.choices[0].message.content
print(f"最终回答: {final_answer}")

模型会返回:

计算结果为 28756.316836

完整代码(DeepSeek使用方法基本一致,不过目前在第二次提交给接口时返回的内容是空的,官方正在修复。。。)

以下是整合后的完整代码:

import openai
import json
from openai import OpenAI

client = OpenAI(api_key="your_openai_api_key")

tools = [
    {
        "type": "function",
        "function": {
            "name": "generate_python_code",
            "description": "根据任务需求生成可执行的 Python 代码来完成计算,并返回结果。",
            "parameters": {
                "type": "object",
                "properties": {
                    "code": {
                        "type": "string",
                        "description": "可执行的 Python 代码,返回计算结果"
                    }
                },
                "required": ["code"]
            }
        }
    }
]

def calculate_with_function_calling(prompt):
    messages = [{"role": "user", "content": prompt}]
    
    # 第一次调用,生成工具调用
    response = client.chat.completions.create(
        model="gpt-4-turbo",
        messages=messages,
        tools=tools,
        tool_choice="auto"
    )
    
    response_message = response.choices[0].message
    tool_calls = response_message.tool_calls
    
    if tool_calls:
        for tool_call in tool_calls:
            if tool_call.function.name == "generate_python_code":
                function_args = json.loads(tool_call.function.arguments)
                code = function_args["code"]
                print(f"模型生成的代码:\n{code}")
                
                # 本地执行代码
                try:
                    local_vars = {}
                    exec(code, {}, local_vars)
                    result = local_vars.get("result", "未定义 result 变量")
                    print(f"本地计算结果: {result}")
                except Exception as e:
                    result = f"代码执行错误: {str(e)}"
                
                # 将结果返回给模型
                messages.append({
                    "role": "tool",
                    "content": str(result),
                    "tool_call_id": tool_call.id
                })
    
    # 第二次调用,生成最终回答
    final_response = client.chat.completions.create(
        model="gpt-4o",
        messages=messages
    )
    return final_response.choices[0].message.content

# 测试
prompt = "请计算 124342314 / 4324,结果保留 6 位小数。"
result = calculate_with_function_calling(prompt)
print(f"最终回答: {result}")

优势与局限性

优势

  1. 高精度:通过本地执行代码,避免了模型的“猜测”行为。

  2. 灵活性:工具可以扩展到更复杂的计算或数据处理任务。

  3. 可控性:开发者可以在本地验证代码安全性。

局限性

  1. 依赖模型生成正确代码:如果模型生成的代码有误(例如忘记 round),结果仍可能错误。

  2. 本地执行风险:需要确保代码安全,避免恶意代码注入。

  3. 性能开销:两次 API 调用和本地执行增加了延迟。


总结(欢迎访问我的博客:https://he-via.xyz/)

通过 OpenAI 的 Function Calling 功能,我们可以轻松解决大模型在计算问题上的准确性缺陷。以 124342314 / 4324 为例,利用工具生成 Python 代码并本地执行,不仅保证了结果精确到 6 位小数,还展示了 Function Calling 的强大潜力。这种方法特别适合需要精确计算或逻辑推理的场景,是提示工程与代码执行的完美结合。

未来,你可以进一步优化工具定义,加入更多参数(如精度控制),或扩展到其他领域(如数据分析)。欢迎在评论区分享你的实践经验!

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐