ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

深入浅出Function Calling③-零基础保姆级教程

2026/8/25 13:31:18 拓冰建站 浏览量
深入浅出Function Calling③-零基础保姆级教程 第 5 章工程细节 —— 让工具调用达到生产级5.1 工具描述写作军规模型乱调工具时90% 先改这里军规BadGood说清何时用查天气查询城市当前实时天气。用户问天气/气温/穿衣/带伞时使用历史天气不支持参数给格式与示例城市城市中文名如北京。用户未提及城市时先追问不要猜测划清边界无只支持数学表达式不含变量/函数日期计算请改用 date_diff 工具定义返回无返回格式城市: 天气 温度失败时返回以天气查询失败开头的错误说明补一条系统提示词侧的黄金句式你已经在用了涉及 X 的问题必须使用工具禁止凭记忆回答/心算——把该用工具时不用的漏调率打下来。5.2 用 Pydantic 自动生成 Schema少写 30 行样板手写 JSON Schema 又长又易错。Pydantic 的model_json_schema()一键生成class WeatherArgs(BaseModel): 查询指定城市的当前实时天气。用户询问天气/气温/穿衣建议时使用。 city: str Field(..., description城市中文名如北京) def pydantic_to_tool(model_cls) - dict: schema model_cls.model_json_schema() return {type: function, function: { name: schema.get(title, model_cls.__name__).lower(), description: model_cls.__doc__.strip(), parameters: {type: object, properties: schema[properties], required: schema.get(required, [])}}}LangChaintool装饰器把这一步也自动化了读函数签名docstring 直接生成——你现在已看穿它的全部魔法。5.3 敏感操作先申请人来批准绝不允许模型直调退款/转账/删除/群发类函数。生产范式——工具只返回待确认单真执行等人点头def request_refund(order_id: str, amount: float) - str: 发起退款申请。注意本工具只创建待确认的申请单不会直接扣款。 if amount 2000: return f已创建退款申请单 R-{order_id}金额{amount}元超过阈值已转人工审核模型无权继续操作。 return f已创建退款申请单 R-{order_id}{amount}元。请向用户复述金额并获得明确同意后调用 confirm_refund 工具。这就是human-in-the-loop的最小实现。5.4 其余四条速记工具结果限长return result[:2000]或先摘要——工具灌爆上下文是 Agent 变笨主因第 2 批 17.5。工具历史要不要长留本轮任务内必须留模型靠它推理跨任务的旧 tool 消息可在历史裁剪时优先清退信息密度低、体积大。幂等设计查询类随便重试写操作类下单要防重复执行——传入唯一请求号。给工具也加超时requests.get(..., timeout10)你已在做慢工具会卡死整个循环。第 6 章错误处理、重试与成本控制6.1 SDK 异常家族对号入座表import openai try: r client.chat.completions.create(modelMODEL, messagesmessages, timeout30) except openai.AuthenticationError: # 401Key错误/被吊销 → 查 .env不要重试 ... except openai.RateLimitError: # 429限流/欠费 → 指数退避重试见下 ... except openai.BadRequestError as e: # 400参数错/上下文超限 → 修请求别重试 ... # 报错含 context length 字样 → 该裁历史了 except openai.APITimeoutError: # 超时 → 可重试 ... except openai.APIConnectionError: # 网络不通 → 可重试 ... except openai.APIStatusError as e: # 5xx 服务端故障 → 退避重试 print(e.status_code, e.response)分两类记该重试的429/超时/网络/5xx——问题在环境与不该重试的401/400——问题在你重试一百次也一样。6.2 重试双方案方案 A · SDK 自带最省事处理网络类错误client OpenAI(api_key..., base_url..., max_retries2, timeout30.0)方案 B · tenacity 装饰器可精确控制哪些异常、退避曲线01 教程 17.2 装饰器知识变现# pip install tenacity from tenacity import retry, stop_after_attempt, wait_exponential_jitter, retry_if_exception_type retry(retryretry_if_exception_type((openai.RateLimitError, openai.APITimeoutError, openai.APIConnectionError, openai.APIStatusError)), waitwait_exponential_jitter(initial1, max30), # 指数退避随机抖动 stopstop_after_attempt(4)) def safe_chat(messages, **kw): return client.chat.completions.create(modelMODEL, messagesmessages, **kw)为什么要抖动jitter并发的 100 个请求同时 429、又同时在第 2 秒重试 集体二次撞墙各自随机等待错峰重试才是解。这是面试429 怎么处理的满分尾句。6.3 成本记账器挂进综合项目class CostTracker: # 价格随行就市以官网为准单位元/百万token PRICES {deepseek-chat: (2.0, 8.0)} # (输入, 输出) 量级示意 def __init__(self): self.prompt_tokens self.completion_tokens self.calls 0 def record(self, usage, model: str deepseek-chat): self.calls 1 self.prompt_tokens usage.prompt_tokens self.completion_tokens usage.completion_tokens def report(self, model: str deepseek-chat) - str: pin, pout self.PRICES[model] cost self.prompt_tokens/1e6*pin self.completion_tokens/1e6*pout return (f调用{self.calls}次 | 输入{self.prompt_tokens} f输出{self.completion_tokens} tokens | 约 ¥{cost:.4f})省钱三板斧回顾稳定前缀吃缓存DeepSeek 响应里的prompt_cache_hit_tokens字段能直接看到命中量好奇就打出来、历史裁剪、小任务用小模型。