"""一个可部署到 Hugging Face Spaces 的最小 Agent 示例。 在 Space 的 Settings -> Variables and secrets 中设置 HF_TOKEN(需要 Inference 权限)。 """ import datetime import os import gradio as gr import pytz from smolagents import CodeAgent, DuckDuckGoSearchTool, GradioUI, InferenceClientModel, tool # 在 Space 的 Settings -> Variables and secrets 中设置 HF_MODEL_ID,即可换模型而不改代码。 # 未设置时使用课程中的模型作为入门默认值。 MODEL_ID = os.getenv("HF_MODEL_ID", "Qwen/Qwen2.5-Coder-32B-Instruct") # 大多数情况不需要指定供应商;需要固定供应商时再设置 HF_PROVIDER,例如 "together"。 PROVIDER = os.getenv("HF_PROVIDER") or None @tool def get_current_time_in_timezone(timezone: str) -> str: """获取指定 IANA 时区的当前本地时间。 Args: timezone: IANA 时区名称,例如 "Asia/Shanghai" 或 "America/New_York"。 """ try: local_time = datetime.datetime.now(pytz.timezone(timezone)) return local_time.strftime("%Y-%m-%d %H:%M:%S %Z") except pytz.UnknownTimeZoneError: return f"未知时区:{timezone}。请使用 IANA 时区名,例如 Asia/Shanghai。" @tool def calculate_order_total(unit_price: float, quantity: int, discount_rate: float = 0.0) -> str: """计算订单折后总价,用于演示一个带多个参数的自定义工具。 Args: unit_price: 单件价格,必须大于或等于 0。 quantity: 购买数量,必须是非负整数。 discount_rate: 折扣率,范围为 0 到 1;例如 0.1 表示九折。 """ if unit_price < 0 or quantity < 0 or not 0 <= discount_rate <= 1: return "参数无效:价格和数量必须非负,折扣率必须介于 0 和 1。" subtotal = unit_price * quantity total = subtotal * (1 - discount_rate) return f"小计:{subtotal:.2f};折后总价:{total:.2f}。" def build_agent() -> CodeAgent: """按需创建 Agent,避免在 Space 导入模块时初始化远程模型客户端。""" token = os.getenv("HF_TOKEN") if not token: raise gr.Error("未配置 HF_TOKEN。请在 Space Settings 的 Secrets 中添加它。") model = InferenceClientModel( model_id=MODEL_ID, token=token, provider=PROVIDER, max_tokens=1024, temperature=0.2, ) web_search = DuckDuckGoSearchTool() return CodeAgent( tools=[get_current_time_in_timezone, calculate_order_total, web_search], model=model, max_steps=4, verbosity_level=1, ) if __name__ == "__main__": # GradioUI 会把工具调用、执行日志和最终答案展示到网页中。 # 每次请求重置 memory,避免公开 Space 的不同访客共享上下文。 agent = build_agent() GradioUI(agent, reset_agent_memory=True).launch()