ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

基于Grok API构建代购Bot:Function Calling与Link授权实战

基于Grok API构建代购Bot:Function Calling与Link授权实战 假设你是一个用户在一个购物平台上看到一个商品但你可能没有该平台的账号或者不想每次手动登录、搜索、比较、下单。此时如果有一个 Bot 能听懂你的话帮你完成从商品查询到提交订单的整条链路甚至还能关联你已有的 Link 账户完成支付授权那整个“代购”体验就会从“多平台手动切换”变成“一句话完成”。这类工具的雏形已经在很多产品里出现。基于 Grok API 的 Bot 并不只是“聊天机器人”它更像一个能调用外部工具的 Agent。而“可关联 Link 账户”这个能力本质上是把支付授权和账户联动接入了 Bot 的工具链。先说判断把“Grok Bot 可关联 Link 账户代购”做成生产级功能难点不在“接入 Grok”这一个动作而在于三件事函数调用Function Calling怎么稳定执行、Link 账户授权怎么做到安全合规、订单提交怎么保证不重复不丢单。本文会围绕这三件事从概念、流程、代码到排错完整拆解一套可运行的代购 Bot 示例。如果你是刚开始接触 AI Agent 的开发者本文会帮你搞清楚 LLM 如何与外部系统交互如果你已经在做自动化应用本文的重点则是授权联动和幂等下单这些工程细节是直接决定能不能上生产的关键。1. Grok Bot 关联 Link 账户代购到底解决什么问题先说一个容易被忽略的事实所谓“代购”在技术层面上并不是一个 AI 能单独完成的事情。一个普通用户的代购流程大概是这样的在 A 平台看到商品。去 B 平台搜索比价。登录 B 平台账号。确认商品、填写地址。跳转到支付页面完成付款。这五步里每一步都要用户手动操作。如果要做成 Bot 自动完成就需要为每一步找到对应的“执行入口”搜索靠商品 API登录靠 OAuth 授权下单靠订单接口支付靠支付网关。任何一个环节没有入口Bot 就只能停在“给用户建议”的层面。Grok Bot 在这里扮演的角色不是替代整个系统而是充当“调度大脑”。它通过 Function Calling 生成结构化的调用指令再由代码去执行真实请求。这套方案真正降低的是集成成本。传统方式做一个代购助手需要为每个平台写一套固定的命令菜单用户只能按照预设选项操作。而基于 Grok 的 Bot用户可以用自然语言表达需求模型负责把需求转换成工具调用。对比下来对比维度传统自动化脚本Grok Bot 代购方案用户输入固定命令或按钮自然语言描述工具扩展人工编排逻辑通过 Function Calling 动态调度账户授权往往需要保存密码通过 OAuth 授权码机制联动维护成本各平台逻辑耦合工具模块可独立扩展所以这篇文章要解决的核心问题是如何基于 Grok API 构建一个能理解用户意图、调用真实工具、并关联 Link 账户完成代购流程的 Bot。1.1 谁适合关注这个方案正在做 AI Agent、AI 客服或智能助理开发的工程师。需要把大模型接入电商、支付、供应链系统的后端开发者。对 Function Calling 有基本了解但想看看完整业务链路怎么落地的人。如果你只是想知道“Grok Bot 能不能帮我自动下单”那本文的价值在于让你明白自动下单不是靠模型“想出来”的而是靠一套严密的工具调用与授权协议支撑的。2. 核心概念Grok API、Function Calling 与 Link 账户授权在写代码之前先把几个容易混淆的概念讲清楚。2.1 Grok API 是什么Grok 是 xAI 推出的大语言模型产品。开发者可以通过 Grok API 在代码中调用模型能力。Grok API 的接口风格与 OpenAI API 兼容因此在 Python 中可以直接使用openai库来访问。from openai import OpenAI client OpenAI( api_key你的_XAI_API_KEY, base_urlhttps://api.x.ai/v1 )需要注意Grok API 的模型名、上下文长度和价格会随官方版本更新而调整。写代码时不要硬编码模型名最好通过环境变量配置。import os model os.getenv(GROK_MODEL, grok-2-latest)2.2 Function Calling 是什么Function Calling 是 LLM 的一种“工具调用”能力。简单说你在请求里声明一组函数模型在理解用户问题后不是直接回答而是返回一个结构化的“调用哪个函数、参数是什么”的指令由你的代码去真正执行。举个例子。用户说“帮我查一下商品 A 的价格。”传统模型会回答“好的我已经帮你查了价格是 100 元。”——但这显然是编造的。Function Calling 的流程是你在代码中定义get_product_price(product_id)函数并把函数签名传给模型。模型识别出用户想查询商品价格返回类似{name: get_product_price, arguments: {product_id: A}}的调用指令。你的代码真正调用get_product_price(A)。把查询结果返回给模型模型基于真实结果组织回答。这才是可信的 AI 自动化基础。2.3 Link 账户授权是什么“Link 账户”在本文中泛指某个购物/支付平台的用户账户体系。代购 Bot 如果要代替用户下单、支付绝不能保存用户的账号密码而是通过 OAuth 之类的授权机制让用户在平台上确认“允许该 Bot 代我执行操作”。授权流程的核心是Bot 生成一个授权请求。用户跳转到 Link 平台登录并确认授权。Link 平台返回一个临时授权码或令牌。Bot 使用该令牌调用平台的下单接口。这套机制保证了 Bot 只在用户允许的范围内、在令牌有效期内执行操作。在后面的示例中我会用 Flask 写一个 Mock Link 授权服务来演示完整流程方便你本地跑通。2.4 普通代购流程 vs Bot 代购流程普通手动流程偏体验层Bot 流程偏工程层。用一个表格对比方便理解环节手动代购Bot 代购需求表达用户自己去搜索自然语言描述商品查询手动浏览多页面调用商品查询工具账户登录输入账号密码Link OAuth 授权下单确认手动点击确认Bot 展示订单信息并请求确认支付跳转支付页面使用授权令牌调用支付接口幂等控制用户自己把握必须用订单号去重注意这里有一个核心工程原则Bot 可以自动查询但最终下单和支付必须经过用户确认并记录幂等键。这个原则不仅是安全要求也是生产系统的基本素养。3. 环境准备与前置条件本文的示例代码使用 Python后端框架选用 Flask 作为 Mock Link 账户服务。相比真实平台本地 Mock 服务能让你不依赖第三方账号就跑通整个流程。建议环境如下Python 3.10。一个 xAI API Key用于调用 Grok API。自动化环境变量管理建议使用.env文件。安装依赖openai、flask、requests、python-dotenv。安装命令pip install openai flask requests python-dotenv版本说明以上依赖以当前 PyPI 最新稳定版为准。本文重点演示通用思路版本不影响核心原理。3.1 环境变量文件创建.env文件XAI_API_KEYyour_xai_api_key_here GROK_MODELgrok-2-latest LINK_API_BASEhttp://127.0.0.1:5010LINK_API_BASE是本地 Mock Link 服务的地址。如果后续接入真实平台换成真实网关地址即可。4. 整个代购流程如何拆解在代码实现前先把流程拆成五个环节。每个环节都要明确“谁负责什么”。4.1 用户表达需求用户输入一句话比如“帮我看看商品 10086 的价格如果不超过 500 元就下单用我的 Link 账户支付。”这句输入本身包含多个意图查询商品、判断价格阈值、执行下单动作。Grok 模型要先把这些意图解析出来。4.2 Grok 生成工具调用意图这里就是 Function Calling 的用武之地。我们会给模型提供两个工具get_product_price(product_id)查询商品价格。create_order(product_id, quantity, link_token)创建订单并支付。模型会根据用户输入决定调用哪个工具、传什么参数。4.3 执行商品查询代码收到模型的调用指令后真正去调用商品查询函数。查询结果可能是 JSON 数据例如{ product_id: 10086, title: 无线蓝牙耳机, price: 299.00, currency: CNY }查询结果会作为“工具返回消息”再次传给模型。这样模型就不是凭空回答而是基于真实数据组织回复。4.4 确认订单与支付授权在真正下单前必须让用户确认。确认方式可以是 Bot 输出订单摘要等待用户回复“确认”。这一步在交易场景里不能省。同时用户需要先完成 Link 账户授权。示例中我会模拟一个授权接口返回link_token。实际项目中这里应该走完整的 OAuth 流程。4.5 下单落库与幂等下单请求需要带上一个全局唯一的幂等键比如order_req_id。这样即使网络超时后重试服务端也能识别这是同一次下单不会重复扣款。这部分是很多代购 Bot 的隐藏难点。模型再聪明也不可能自动解决重复下单问题必须由业务代码保证。5. 完整示例代码实现下面提供一套可运行的最小示例。工程目录建议如下grok-link-bot/ ├── .env ├── requirements.txt ├── bot/ │ ├── __init__.py │ ├── main.py # 主入口调用 Grok API │ ├── tools.py # 商品查询与下单工具 │ └── link_client.py # 调用 Link 服务的客户端 └── mock_link/ ├── __init__.py └── server.py # Mock Link 授权与下单服务5.1 工具函数模块bot/tools.py# 文件路径bot/tools.py import uuid from datetime import datetime # 模拟商品数据库 PRODUCTS { 10086: { title: 无线蓝牙耳机, price: 299.00, currency: CNY }, 10087: { title: 机械键盘, price: 499.00, currency: CNY } } # 模拟订单存储 ORDERS {} def get_product_price(product_id: str) - dict: 查询商品价格。 if product_id not in PRODUCTS: return {error: 商品不存在, product_id: product_id} product PRODUCTS[product_id] return { product_id: product_id, title: product[title], price: product[price], currency: product[currency] } def create_order(product_id: str, quantity: int, link_token: str) - dict: 创建订单并返回订单号。 if product_id not in PRODUCTS: return {error: 商品不存在, product_id: product_id} # 幂等键由业务方生成重复请求不会重复下单 order_req_id uuid.uuid4().hex order_id ORD datetime.now().strftime(%Y%m%d%H%M%S) product_id # 模拟校验 Link 授权令牌 if not link_token: return {error: 缺少 Link 授权令牌} # 模拟落库 order { order_id: order_id, product_id: product_id, quantity: quantity, total_amount: PRODUCTS[product_id][price] * quantity, status: CREATED } ORDERS[order_id] order return order这里需要特别说明示例中的uuid.uuid4().hex每次都会生成新的order_req_id在生产环境里应该由调用方在业务入口生成并保存重试时复用同一个值。示例只是为了演示结构真正工程化时要把它当作请求参数传入。5.2 Link 客户端模块bot/link_client.py# 文件路径bot/link_client.py import os import requests LINK_API_BASE os.getenv(LINK_API_BASE, http://127.0.0.1:5010) def authorize_link(user_id: str) - dict: 模拟用户授权 Link 账户获取访问令牌。 resp requests.post( f{LINK_API_BASE}/link/authorize, json{user_id: user_id}, timeout5 ) resp.raise_for_status() return resp.json() def get_link_token(user_id: str) - str: 获取 Link 授权令牌。 data authorize_link(user_id) return data.get(token)实际接入真实平台时这里不应直接调用“授权接口”然后拿到 token而是应该跳转到平台授权页由用户主动登录并确认授权。示例代码只是方便本地演示这是有意的简化。5.3 主程序bot/main.py# 文件路径bot/main.py import json import os from openai import OpenAI from dotenv import load_dotenv from tools import get_product_price, create_order from link_client import get_link_token load_dotenv() client OpenAI( api_keyos.getenv(XAI_API_KEY), base_urlhttps://api.x.ai/v1 ) MODEL os.getenv(GROK_MODEL, grok-2-latest) # 1. 定义函数描述 TOOLS [ { type: function, function: { name: get_product_price, description: 查询指定商品的实时价格, parameters: { type: object, properties: { product_id: { type: string, description: 商品 ID } }, required: [product_id] } } }, { type: function, function: { name: create_order, description: 根据商品 ID 和数量创建订单并使用 Link 账户令牌支付, parameters: { type: object, properties: { product_id: { type: string, description: 商品 ID }, quantity: { type: integer, description: 购买数量, default: 1 }, link_token: { type: string, description: Link 账户授权令牌 } }, required: [product_id, quantity, link_token] } } } ] def run_tool(tool_name: str, arguments: dict) - str: 执行工具调用。 if tool_name get_product_price: result get_product_price(arguments[product_id]) elif tool_name create_order: # 简化处理实际项目中应通过授权流程获取 token result create_order( product_idarguments[product_id], quantityarguments.get(quantity, 1), link_tokenarguments[link_token] ) else: result {error: f未知工具: {tool_name}} return json.dumps(result, ensure_asciiFalse) def chat_with_grok(user_input: str) - str: 与 Grok 对话支持多次工具调用。 messages [ { role: system, content: ( 你是一个代购助手。你可以查询商品价格并且可以在用户确认后 帮助用户通过 Link 账户创建订单。 创建订单前必须请用户确认订单信息。 ) }, {role: user, content: user_input} ] while True: response client.chat.completions.create( modelMODEL, messagesmessages, toolsTOOLS, tool_choiceauto ) message response.choices[0].message # 没有工具调用直接返回文本 if not message.tool_calls: return message.content # 有工具调用执行函数并追加消息 messages.append(message) for tool_call in message.tool_calls: tool_name tool_call.function.name arguments json.loads(tool_call.function.arguments) print(f[Bot] 调用工具: {tool_name}, 参数: {arguments}) tool_result run_tool(tool_name, arguments) print(f[Bot] 工具返回: {tool_result}) messages.append({ role: tool, tool_call_id: tool_call.id, content: tool_result }) if __name__ __main__: user_input 帮我查一下商品 10086 的价格 result chat_with_grok(user_input) print([Grok], result)这段代码的主循环是标准的 Agent 循环模型判断是否需要调用工具、代码执行工具、结果回传、模型继续生成。这样就能实现“Bot 先查价再根据用户回复决定是否下单”的完整对话流程。5.4 Mock Link 服务mock_link/server.py# 文件路径mock_link/server.py import time import uuid from flask import Flask, request, jsonify app Flask(__name__) # 模拟 token 存储 TOKENS {} # 模拟订单存储 ORDERS {} app.post(/link/authorize) def authorize(): 模拟用户授权 Link 账户返回短时有效的令牌。 payload request.get_json() or {} user_id payload.get(user_id, default_user) token link_ uuid.uuid4().hex expires_at int(time.time()) 3600 TOKENS[token] { user_id: user_id, expires_at: expires_at } return jsonify({ token: token, expires_at: expires_at, message: 授权成功。生产环境应跳转 OAuth 页面由用户主动确认。 }) app.post(/link/orders) def create_order(): 创建 Link 平台订单。 payload request.get_json() or {} token payload.get(token, ) order_req_id payload.get(order_req_id, ) product_id payload.get(product_id, ) quantity payload.get(quantity, 1) if token not in TOKENS: return jsonify({error: 无效的 Link 令牌}), 401 if not order_req_id: return jsonify({error: 缺少 order_req_id无法保证幂等}), 400 if order_req_id in ORDERS: return jsonify(ORDERS[order_req_id]) order { order_req_id: order_req_id, order_id: LINK_ uuid.uuid4().hex[:16].upper(), product_id: product_id, quantity: quantity, status: PAID } ORDERS[order_req_id] order return jsonify(order), 201 if __name__ __main__: app.run(host127.0.0.1, port5010, debugTrue)Mock 服务里的/link/orders接口实现了幂等逻辑同一个order_req_id重复请求会返回已存在的订单而不会创建新订单。这是生产系统必须具备的容错能力。6. 运行与验证6.1 启动 Mock Link 服务export LINK_API_BASEhttp://127.0.0.1:5010 python mock_link/server.py预期输出* Running on http://127.0.0.1:50106.2 启动 Bot保持 Mock Link 服务运行打开另一个终端python bot/main.py输入帮我查一下商品 10086 的价格预期输出类似[Bot] 调用工具: get_product_price, 参数: {product_id: 10086} [Bot] 工具返回: {product_id: 10086, title: 无线蓝牙耳机, price: 299.0, currency: CNY} [Grok] 商品 10086 的价格是 299.00 CNY商品名称是“无线蓝牙耳机”。这说明模型没有凭空回答而是先触发了工具调用再基于真实数据组织回复。6.3 模拟完整代购流程继续输入确认下单用我的 Link 账户支付买 1 件由于我们在系统提示中要求“创建订单前必须请用户确认订单信息”模型会先展示订单摘要。同时示例代码中link_token的获取被简化了。如果是在生产环境这里会触发一次 Link 授权跳转用户确认后回传令牌再发起下单。6.4 判断成功标准终端出现工具调用日志。Grok 返回的内容里包含商品真实价格。在 Mock Link 服务的控制台能看到收到的订单请求。mock_link/server.py的ORDERS字典里新增了订单记录。如果第一步就失败先检查XAI_API_KEY是否正确设置再检查LINK_API_BASE指向是否正确。7. 常见问题与排查思路问题现象可能原因排查方式解决方案调用 Grok API 报 401API Key 无效或环境变量未加载检查.env文件是否加载打印os.getenv(XAI_API_KEY)重新配置有效的 API Key模型返回空内容模型被拒绝或请求参数不正确查看上游 API 返回的完整错误信息检查模型名和工具参数 schema工具参数 JSON 解析失败模型生成的 arguments 不是合法 JSON打印原始tool_call.function.arguments增加异常处理要求模型重新生成Agent 陷入死循环工具返回结果没有推动对话前进观察工具调用次数和消息列表在循环中增加最大轮数限制Link 授权后 token 无效token 过期或未正确传递检查 Mock 服务中 TOKENS 存储确认授权流程返回的 token 已传到下单请求重复下单缺少幂等键检查订单接口是否按order_req_id去重在下单请求中强制携带全局唯一幂等键其中最容易踩坑的是“Agent 死循环”。比如拿到价格后又去下单但下单时缺少 Link 令牌工具返回错误模型看到错误又尝试重新下单循环不止。解决办法有两个一是在系统提示里写清楚“缺少授权时引导用户先完成授权而不是直接重试”二是在代码循环里加上max_iterations 5的限制。MAX_ITERATIONS 5 for _ in range(MAX_ITERATIONS): # 调用模型、执行工具的逻辑 ... else: return 操作轮数过多请重试8. 最佳实践与工程建议如果你不只是跑通示例而是打算在自己的项目里落地这套方案以下建议值得重点关注。8.1 安全边界不保存用户密码这是所有账户联动类产品的底线。Link 账户授权必须走标准 OAuth 流程Bot 只保留短期有效的访问令牌不保存用户密码。令牌过期后引导用户重新授权而不是用“记住密码”的方式绕过授权。在代码示例中Mock Link 的/link/authorize直接返回 token属于刻意简化。真实项目里要引入授权码、回调地址、令牌刷新机制。8.2 幂等设计下单前先生成请求 ID在进入下单接口之前业务层就要生成一个全局唯一的order_req_id并把它作为请求参数传给 Link 平台。这样即使网络超时导致客户端重试服务端也能识别出这是同一次下单返回原订单而不是新建订单。这条建议适用于所有涉及支付、扣减库存、创建订单的操作。8.3 超时与重试策略调用 Grok API 和外部平台接口都需要设置超时时间。建议分两级连接超时3 秒。读取超时根据接口耗时建议 10 到 30 秒。重试要配合幂等键使用。不是所有异常都能重试比如 401 授权失败就不应盲目重试而应该重新触发授权流程但 5xx 或网络超时可以重试且要限制重试次数。8.4 日志链路在 Agent 场景里日志是所有排错的基础。建议至少记录以下信息用户输入原文。模型每次返回的 tool_call 内容。工具执行结果。授权 token 的生成时间和过期时间注意脱敏不要打印完整 token。最终订单号。最好为每一次“用户会话”生成一个session_id贯穿所有日志方便排查时快速定位。8.5 合规提醒代购不是越界操作“代购 Bot”听起来自动化程度高但在真实商业环境里必须遵守各平台的开发者协议和用户授权规则。以下是几条底线只操作用户主动授权范围内的账户。不批量注册、不批量抢购、不使用脚本绕过平台反作弊机制。明确告知用户订单信息和支付金额经确认后再下单。不转售平台账号或利用非公开接口获利。把“代购”理解成“辅助用户在自己账户内完成购物”而不是“绕过平台规则的自动抢单”这样才能保证技术方案具备长期价值。8.6 生产环境的多层确认虽然 Grok 可以生成下单指令但交易类操作建议做多层确认模型输出订单摘要。用户回复确认。业务代码校验用户身份、授权状态、商品库存。调用支付接口。任何一层校验失败都不能进入下一步。9. 总结与后续学习方向本文从“Grok Bot 可关联 Link 账户代购”这个场景出发完整拆解了一套 AI Agent 代购助手的实现思路。核心结论是这类应用的真正价值不在于模型本身而在于函数调用、授权联动和幂等下单这三个工程能力。运行完本文示例后你可以继续往三个方向深入把 Mock Link 服务替换为真实平台 API重点学习标准 OAuth 授权流程。为工具调用增加更多类型的函数比如物流查询、优惠券计算、订单取消。为 Agent 循环增加记忆和上下文管理让 Bot 在多轮对话中记住用户偏好。这套代码本身还远不是生产级产品但它提供了一个可以二次开发的骨架。建议你先把本地流程跑通再逐步替换真实组件每替换一个环节都做一次完整回归确保“查询-授权-下单”链路始终可用。
返回列表