跳到文章正文
Grok 实用教程

Grok函数调用怎么接入?只读库存查询、参数校验与工具结果回传

用xAI Responses API定义只读库存工具,演示模型请求、本地白名单校验、call_i…

希望Grok回答库存,不能只在提示词里写“你连接了仓库”。Function Calling让模型请求调用工具,由你的程序执行并回传结果。本教程用一份写死的虚构库存表跑通消息协议,重点检查参数和结果对应关系,不接订单系统,不下单、不锁库存,也不展示不存在的真实供应状态。

第一步:理解谁真正执行工具

官方流程是定义名称、描述与参数Schema,随请求提供工具;模型返回function_call,应用执行本地逻辑,再用function_call_output继续对话。工具定义只是声明接口,模型并不会凭空获得数据库连接。执行权限、参数校验和异常处理都要由你的应用负责。

示例需要Python requests、xAI官方API密钥与可用模型权限,密钥放在XAI_API_KEY环境变量。下面可能产生API费用,代码用于教学,没有替你执行真实调用。数据明确写为演示,不要求读取用户电脑或生产系统,也不把第三方聊天会员视为API凭据。

第二步:用白名单实现只读工具

import os, json, requests
s = requests.Session()
s.headers["Authorization"] = "Bearer " + os.environ["XAI_API_KEY"]
url = "https://api.x.ai/v1/responses"
tools = [{"type": "function", "name": "get_demo_stock",
    "description": "读取虚构练习库存,不代表真实库存,不产生订单。",
    "parameters": {"type": "object", "properties": {
        "sku": {"type": "string", "enum": ["DEMO_A", "DEMO_B"]}},
        "required": ["sku"], "additionalProperties": False}}]
stock = {"DEMO_A": 12, "DEMO_B": 0}
def query(payload):
    r = s.post(url, json={"model": "grok-4.7", "tools": tools, **payload}, timeout=120)
    r.raise_for_status()
    return r.json()
data = query({"input": [{"role": "user", "content":
    "请查询DEMO_A和DEMO_B的演示库存。必须标明数据为虚构练习;不要下单或承诺发货。"}]})
used = 0
for turn in range(3):
    calls = [x for x in data.get("output", []) if x.get("type") == "function_call"]
    if not calls:
        break
    outputs = []
    for call in calls:
        try:
            args = json.loads(call["arguments"])
            if call["name"] != "get_demo_stock" or not isinstance(args, dict):
                raise ValueError("未知工具或参数类型")
            if set(args) != {"sku"} or not isinstance(args["sku"], str) or args["sku"] not in stock:
                raise ValueError("SKU不在白名单")
            result = {"sku": args["sku"], "stock": stock[args["sku"]],
                      "is_demo": True, "source": "本地虚构练习表"}
            used += 1
        except (ValueError, KeyError, TypeError) as error:
            result = {"error": str(error), "is_demo": True}
        outputs.append({"type": "function_call_output", "call_id": call["call_id"],
                        "output": json.dumps(result, ensure_ascii=False)})
    data = query({"previous_response_id": data["id"], "input": outputs})
if any(x.get("type") == "function_call" for x in data.get("output", [])):
    raise RuntimeError("达到轮次上限,停止并检查工具调用")
print("已执行的有效演示查询数:", used)
for item in data.get("output", []):
    for part in item.get("content", []):
        if part.get("type") == "output_text":
            print(part.get("text", ""))
if used == 0:
    print("未执行有效工具查询,回答不能视为已核验库存。")

Schema中的枚举帮助模型选择SKU,但程序仍在本地检查工具名、参数类型、额外字段和SKU范围。不能用模型提供的字符串直接拼接SQL、执行命令或动态调用任意函数。这里只有两条只读演示记录,失败返回错误,不允许猜测库存或自动改成另一个商品。

第三步:正确回传所有调用结果

同一响应可能请求多个工具调用,示例先收集全部结果,再一起继续请求。每个输出用原call_id关联对应调用,用previous_response_id接续上下文;不靠数组顺序猜测对应关系。库存为零是有效业务结果,与参数错误或工具执行失败要分别表示。

代码限制最多三轮工具往返,仍有新调用就停止检查,避免没有终点的费用和重试。实际生产还应限制单轮调用数、请求频率和总预算;这些是应用控制,不能只在提示词里写一句“不要调用太多”就视为实现。

第四步:用确定结果检验整个链路

运行自己的小样本后,对照本地表确认DEMO_A为12、DEMO_B为0,回答必须说明虚构数据,不得出现发货承诺。观察有效工具查询数,模型没有调用工具时不能把回答算作查库成功;若调用结果与最终文字不同,应先定位消息回传和模型总结的差异。

请只根据工具返回回答:SKU、演示库存、是否为演示、数据来源。工具报错就说明无法确认,不引用模型常识补库存,不生成订单、发货时间或采购建议。

还应在本地单测式地尝试未知SKU、额外字段和非法JSON,确认校验会返回错误而不访问其他资源。这里的练习不需要真实库存凭据。接入生产前再为当前用户校验可查询范围、数据时效与审计记录,权限不能由模型自己决定。

第五步:保留最小排查材料

遇到401或403先查密钥与模型权限,遇到工具报错查参数和函数实现,遇到回答不符查call_id与原始返回。日志保留请求标识和错误类别即可,不应打印密钥或完整敏感业务资料。验收标准是请求、执行、回传、总结四个环节都可追溯,而不是模型偶然答中了两条数字。

官方资料

资料核对日期:2026年10月24日。

本文地址:https://www.163264.com/17892