普通视图

发现新文章,点击刷新页面。
昨天 — 2026年5月9日首页

大模型和function calling分别是如何工作的

作者 review44543
2026年5月9日 18:02

以一个表处理为例:

github地址:github.com/YueJingGe/p…

用大模型处理表格

描述:有一个本周饮品销量小表,希望大模型输出按饮品汇总销量的列表,以及销量最高的饮品是什么

代码示例+运行结果

image.png

核心思想

当你把表格 用 df.to_string() 转成文本,然后放进 prompt 里时,大模型(如通义千问、GPT-4)会做这几步:

  • 1、阅读理解:识别出这是一个三列表格,理解列名含义(“饮品”“销量_杯”“门店”)。
  • 2、信息提取:逐行读取数据,记住每行对应关系。
  • 3、简单计算:将“美式”的两行销量 30 和 12 相加,得到 42;将“拿铁”的 18 单独作为总和;将“橙汁”的 12 作为总和。
  • 4、格式组织:按要求的格式输出“美式:42,拿铁:18,橙汁:12”。   这些能力完全来自大模型自身的训练——它在海量数据中学到了如何理解文本表格、如何进行基本的聚合计算(求和、计数等)、如何比较大小。你不需要额外实现任何逻辑,只要把表格文本喂给模型,它就能尝试回答。  

技术架构图

image.png

局限性

虽然模型能处理简单的表格问答,但有以下问题:

  • 1、计算错误:当表格行数多、数字复杂(如带小数、需加权平均),或者需要多步运算(先分组再排序再筛选),模型容易算错或遗漏。
  • 2、上下文长度:表格太大(比如1000行),放进 prompt 可能超过模型的 token 限制,或导致注意力分散、遗漏关键信息。
  • 3、不确定性:同一个表格问同一个问题,模型可能给出略有差异的答案(因为生成有随机性)。
  • 4、无法执行复杂逻辑:比如“找出销量最高的门店,再列出该门店销量前两名的饮品”,这类需要多步条件筛选和排序的任务,模型往往做不好。  

Function Calling + 大模型处理表

首先,Function calling(也称工具调用)不是让模型直接分析表格,而是让模型决定去调用一个外部工具(比如写好的 Python 函数) 来精确处理表格,再把工具返回的结果整理成自然语言回答。

描述:有一个本周饮品销量小表,希望大模型输出按饮品汇总销量的列表,以及销量最高的饮品是什么,以及哪个门店销量最高

典型流程:

用户问:“按饮品汇总销量。”
模型看到可用的函数列表,比如 compute_groupby_sum(column, group_by)。
模型不自己计算,而是输出一个函数调用指令:compute_groupby_sum(column="销量_杯", group_by="饮品")。
你的程序拦截这个指令,让 Python 后端实际执行 df.groupby("饮品")["销量_杯"].sum(),拿到精确结果 {"美式":42, "拿铁":18, "橙汁":12}。
你的程序把这个结果送回模型,模型再组织成一句人话:“美式共卖出42杯,拿铁18杯,橙汁12杯。”

代码示例

import os
import json
import pandas as pd
from openai import OpenAI
from dotenv import load_dotenv

load_dotenv()
client = OpenAI(
    api_key=os.getenv('DASHSCOPE_API_KEY'),
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
)

# ---------- 定义真实的数据查询函数(后端执行) ----------
# 使用 pandas 创建数据表
df = pd.DataFrame({
    "饮品": ["美式", "拿铁", "橙汁", "美式"],
    "销量_杯": [30, 18, 12, 12],
    "门店": ["A店", "A店", "B店", "B店"],
})

def get_sales_summary(by: str = "饮品"):
    """
    获取销量汇总数据。
    by: 分组依据,目前支持 "饮品" 或 "门店"
    """
    if by == "饮品":
        grouped = df.groupby("饮品")["销量_杯"].sum().reset_index()
        grouped = grouped.sort_values("销量_杯", ascending=False)
        # 转为字典列表,方便模型阅读
        result = grouped.to_dict(orient="records")
    elif by == "门店":
        grouped = df.groupby("门店")["销量_杯"].sum().reset_index()
        grouped = grouped.sort_values("销量_杯", ascending=False)
        result = grouped.to_dict(orient="records")
    else:
        result = {"error": f"不支持的聚合方式: {by}"}
    return json.dumps(result, ensure_ascii=False)

def get_top_sales(by: str = "饮品"):
    """获取销量冠军"""
    if by == "饮品":
        grouped = df.groupby("饮品")["销量_杯"].sum()
        top_item = grouped.idxmax()
        top_value = int(grouped.max())
        return json.dumps({"冠军": top_item, "销量": top_value}, ensure_ascii=False)
    elif by == "门店":
        grouped = df.groupby("门店")["销量_杯"].sum()
        top_item = grouped.idxmax()
        top_value = int(grouped.max())
        return json.dumps({"冠军": top_item, "销量": top_value}, ensure_ascii=False)
    else:
        return json.dumps({"error": f"不支持的冠军查询: {by}"})

# ---------- 定义工具描述(给大模型看的说明书) ----------
tools = [
    {
        "type": "function",
        "function": {
            "name": "get_sales_summary",
            "description": "按饮品或门店获取销量汇总,返回排序后的列表",
            "parameters": {
                "type": "object",
                "properties": {
                    "by": {
                        "type": "string",
                        "enum": ["饮品", "门店"],
                        "description": "分组维度,例如'饮品'或'门店'"
                    }
                },
                "required": ["by"]
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "get_top_sales",
            "description": "获取销量冠军(销量最高的饮品或门店)",
            "parameters": {
                "type": "object",
                "properties": {
                    "by": {
                        "type": "string",
                        "enum": ["饮品", "门店"],
                        "description": "冠军类型,例如'饮品'或'门店'"
                    }
                },
                "required": ["by"]
            }
        }
    }
]

# ---------- 主对话循环 ----------
def ask_with_function_calling(user_question):
    messages = [{"role": "user", "content": user_question}]
    
    # 第一次调用:让模型判断是否需要调用函数
    first_response = client.chat.completions.create(
        model="qwen-plus",  # 或 qwen-turbo
        messages=messages,
        tools=tools,
        tool_choice="auto",
    )
    response_message = first_response.choices[0].message
    messages.append(response_message)
    
    # 模型要求调用函数吗?
    if response_message.tool_calls:
        for tool_call in response_message.tool_calls:
            func_name = tool_call.function.name
            func_args = json.loads(tool_call.function.arguments)
            print(f"🔧 模型调用: {func_name}, 参数: {func_args}")
            
            # 执行真实的 Python 函数
            if func_name == "get_sales_summary":
                result = get_sales_summary(**func_args)
            elif func_name == "get_top_sales":
                result = get_top_sales(**func_args)
            else:
                result = json.dumps({"error": "未知函数"})
            
            # 将工具结果加入对话
            messages.append({
                "role": "tool",
                "tool_call_id": tool_call.id,
                "content": result,
            })
        
        # 第二次调用:模型根据工具结果生成最终回答
        second_response = client.chat.completions.create(
            model="qwen-plus",
            messages=messages,
        )
        final_answer = second_response.choices[0].message.content
        return final_answer
    else:
        # 没有工具调用,直接返回模型回答
        return response_message.content

# ---------- 运行示例 ----------
if __name__ == "__main__":
    # 问题1:按饮品汇总销量
    q1 = "按饮品汇总销量,并告诉我销量最高的饮品是什么"
    print(f"🙋 用户: {q1}")
    ans1 = ask_with_function_calling(q1)
    print(f"🤖 AI: {ans1}\n")
    
    # 问题2:销量冠军门店
    q2 = "哪个门店的销量最高?"
    print(f"🙋 用户: {q2}")
    ans2 = ask_with_function_calling(q2)
    print(f"🤖 AI: {ans2}\n")

运行结果:

image.png

核心思想

核心思想就是:

1、你给模型预定义一组函数,告诉模型这些函数能做什么。

2、用户问自然语言问题,比如“按饮品汇总销量,然后自然地说出来”。

3、大模型自己决定该不该调用函数、调用哪个函数、传什么参数。

4、模型返回的不是最终答案,而是一个函数调用指令(例如 get_sales_summary(by='drink'))。

5、你的代码收到这个指令后,实际去执行 pandas 计算(或查数据库、调API等),然后把精确的计算结果再发回给模型。

6、模型根据结果生成最终的自然语言回答。

整个过程中,模型在主动决策“我需要调用工具来帮忙”,而不仅仅是接收现成数据。

技术架构图

image.png

总结

不用 Function Calling 的时候主要是依赖大模型本身的语言理解和推理能力,适合你完全清楚要算什么的场景,代码简单高效。

用 Function Calling是作为一种“增强手段”来提升准确性和能力上限,适合搭建对话式数据分析助手,用户可以随意提问,模型自动选择合适的函数去执行。

深入学习

Function Calling 官方资料:

阿里云百炼平台:搜索“阿里云百炼 Function Call”,参考官方文档。

社区博客:搜索“超实用!用 FunctionCall 实现快递 AI 助手”,了解用它构建真实 AI 助手的详细步骤。

CSDN 博客:搜索“通义千问的 Function Call”,更直观地理解整个实现流程。

昨天以前首页

基于 Cursor 实现智能代码审查skill

作者 review44543
2026年4月27日 18:08

方法一:用 Cursor Rules (.cursorrules)快速体验效果

文件位置:在项目根目录创建 .cursorrules 文件。

定义规则:在其中明确你的审查标准和偏好。

## 项目概述
- 这是一个基于 React + JavaScript 的前端项目。
- 优先使用函数式组件和 Hooks。

## 目录边界
; - 只允许修改:src/、components/、utils/ 下的文件。
; - 禁止修改:node_modules/、.next/、dist/ 等构建产物目录。

## 代码规范
- 使用 `const` 或 `let`,禁止 `var`。
- 统一为项目其它文件的“有分号”风格
- 统一引号为双引号

## 安全红线
- 禁止使用 `dangerouslySetInnerHTML`,除非配合 DOMPurify 使用。
- 禁止将 API 密钥、Token 等硬编码在代码中。

## 输出要求
- 在进行代码审查时,先输出审查计划。
- 按 "严重程度(高/中/低)" 列出问题,并提供修复建议。

测试

要确保 .cursorrules 生效,可以分三步来验证:

1、验证加载状态:在 Cursor 的设置里找到 Rules 选项卡,如果能看到你的 .cursorrules 文件在列表中,就说明它已经被成功加载了。

2、使用明确的测试指令:不要空泛地提问,要用自然但具体的语言,直接要求 AI 在代码中执行你设定的规则。例如:

如果规则要求“不能使用 var”,你可以指示 AI:“根据项目规范,将所有 var 声明替换为 const 或 let。”

如果规则定义了“组件 Props 必须有类型”,可以要求:“给 UserProfile 组件添加缺失的 Props 类型定义。”

3、通过实战测试验证:可以故意在一个小文件里写一段“违规”代码,然后用 Cmd/Ctrl + K 或 Cursor Chat,指示 AI 帮你修复。如果 AI 按规则要求修改了代码,就说明规则生效了。

结果如下: image.png

方法二:用 cursor 内置 “AI审查” (Agent Review)快速体验效果

在 AI 生成代码的 Diff 视图中:通常会有一个 Agent Review 的入口,如下图:

image.png

点击自动 review 代码。

❌
❌